[
  {
    "path": ".gitignore",
    "content": "# macos #\n*/.DS_Store\n.DS_Store\n\n*.class\n\n# Mobile Tools for Java (J2ME)\n.mtj.tmp/\n\n# Package Files #\n*.jar\n*.war\n*.ear\n\n# virtual machine crash logs, see http://www.java.com/en/download/help/error_hotspot.xml\nhs_err_pid*\n\n# idea #\n*.iml\n\n# sh and bat #\n/latte\n/latte.bat\nbuild/*\n\n# gradle #\n.gradle/*\n"
  },
  {
    "path": "LICENSE",
    "content": "The MIT License (MIT)\n\nCopyright (c) 2016 KuiGang Wang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# Latte-Lang\n\n[![Join the chat at https://gitter.im/latte-lang/Lobby](https://badges.gitter.im/latte-lang/Lobby.svg)](https://gitter.im/latte-lang/Lobby?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge)\n\n<img src =\"http://latte-lang.org/static/Latte-lang-logo-large.png\" width=50px>\n\nLatte is a JVM language. It's highly readable and extensible.\n\n[Syntax Mannual (NEW)](https://github.com/wkgcass/Latte-lang/blob/master/mannual-zh.md)  \n[Latte WebSite](http://latte-lang.org/)\n\n`Atom` Extensions :\n\n[atom-latte-lang-highlighting](https://atom.io/packages/Atom-Latte-lang-Highlighting)  \n[atom-latte-lang-ide](https://atom.io/packages/atom-latte-lang-ide)\n\n`Gradle` Plugin :\n\n[latte-gradle-plugin](#gradle-plugin)\n\n## 中文版戳[这里](#readme-ch)\n\n### Latte supports\n\n* Operator Binding\n* DSL\n* Data Class\n* Pattern Matching\n* Inner Method\n* Lambda and High-Order Function\n* JSON Literal\n* Regular Expression\n* Read Eval Print Loop\n* Compiling to JavaScript\n* Latte Gradle Plugin\n* JSR 223\n* many other features\n\n`Latte` is based on java 6. It's compiled to JVM byte code, and can collaborate with any java library.\n\n# How to build\n\n`JDK 1.6` or higher is the only thing required.\n\nThe project is managed by `Gradle`, you can use `Gradle 2.12` (or higher) to build automatically  \nA build script is also provided.\n\nclone the repository, and run\n\n\t./build.py\n\nYou will get a shell scripts. The shell scripts can help you run the `repl`.\n\n>The build script does not support windows. Please follow the order (latte-[class-recorder | compiler | gradle-plugin | library | build]) to run `gradle clean latteBuild` in each directory, then extract `build/distributions/latte-${version}.zip` in module `latte-build`, the shell script is in the `bin` directory.\n\n\nrun:\n\n\t./latte\n\nthen the [REPL](https://github.com/wkgcass/Latte-lang/blob/master/latte-build/src/main/java/lt/repl/REPL.java) starts\n\n\tWelcome to Latte lang\n\tType in expressions and double Enter to have them evaluated.\n\tType :help for more information.\n\tfor syntax help, please visit https://github.com/wkgcass/Latte-lang/\n\n    lt> 1+1\n      |\n    res0 : java.lang.Integer = 2\n\n    lt>\n\n# Compile `lt` Files\n\nThere are two ways of compiling `lt` files\n\n* use program command\n\n\t\tlatte -c <source-directory>\n\n\tthe detailed commands and options can be found in\n\n\t\tlatte -help\n\nor:\n\n* start the `REPL` interpreter, and construct a `Compiler`\n\n\t\tcompiler = Compiler()\n\n\tuse `>>` operator to specify output directory\n\n\t\tcompiler >> '...'\n\t\t// or\n\t\tcompiler >> File('...')\n\n\tuse `+` operator to add class-path\n\n\t\tcompiler + '...'\n\n\tuse `compile MAP` to specify source codes to be compiled and start compiling\n\n\t\tcompiler compile ['fileName':FileObject]\n\n\tusually `filesInDirectory('...', regex)` is used, e.g.\n\n\t\tcompiler compile filesInDirectory('...', '.\\*\\\\.lt'.r)\n\n\tthese method invocations can be chained up\n\n\t\tCompiler() + '...cp...' >> '...output...' compile filesInDirectory('...source...', '.\\*\\\\.lt'.r)\n\n\tYou can write a `script` to configure the settings. Check [build.lts.template](https://github.com/wkgcass/Latte-lang/blob/master/latte-compiler/src/main/resources/build.lts.template) for more info.\n\n# Scripts\n\n* you can run a script directly\n\n\t\tlatte -s script-location script-arguments...\n\nor:\n\n* start the `REPL` interpreter  \n\ttype `:script <script file>` and Enter\n\n\tthen use `script run` or `script run ['string array']` to run the script\n\n# JSR 223\n\nLatte-lang supports JSR 223 specification. Use `getEngineByName(\"Latte-lang\")` to retrieve the scripting engine.  \n\n```java\nScriptEngine engine = new ScriptEngineManager().getEngineByName(\"Latte-lang\");\nObject result = engine.eval(\"a = 1 + 3\");\nSystem.out.println(engine.get(\"a\"));\n```\n\nSince Latte-lang is a compiling language, and it's directly compiled to JVM byte code, you could even use the scripting engine in Latte source codes.\n\n```\nengine = ScriptEngineManager().getEngineByName(\"Latte-lang\")\nresult = engine eval \"a = 1 + 3\"\n.println result\n.println engine.a\n```\n\n<h1 id='gradle-plugin'>Gradle Plugin</h1>\n\nA plugin for `Gradle` is provided, which helps you compile latte source codes.\n\n### How to use\n\n### step1\n\nadd the plugin configuration:\n\n```groovy\nbuildscript {\n    dependencies {\n        classpath 'org.latte-lang:latte-gradle-plugin:$VERSION'\n    }\n}\n\napply plugin: 'latte'\n\nsourceSets {\n    main {\n        java\n        latte.srcDirs = ['src/main/latte']\n        resources\n    }\n    test {\n        java\n        latte\n        resources\n    }\n}\n\nlatteConfig {\n    afterJava = true\n    afterGroovy = false\n    fastFail = false\n}\n```\n\n> all configurations are optional\n\nThe plugin adds `compileLatte` and `compileTestLatte` tasks, where `compileLatte` is before `classes` task, and `compileTestLatte` is before `testClasses` task\n\n### step2\ncreate a folder named `latte` in the same parent directory. The directory tree should be:\n\n\tsrc\n\t├── main\n\t│   ├── java\n\t│   │   └── \\*.java    ; java source\n\t│   ├── latte\n\t│   │   └── \\*.lt      ; latte source\n\t│   └── resources\n\t│       │── \\*.lts     ; latte scripts\n\t│       └── other resources\n\t└── test\n\t    ├── java\n\t    │   └── \\*.java\n\t    ├── latte\n\t    │   └── \\*.lt\n\t    └── resources\n\t        ├── \\*.lts\n\t        └── other resources\n\n### step3\nrun\n\n\tgradle clean jar\n\n# Syntax\n\nvisit the [Latte WebSite](http://latte-lang.org/)\n\nor read the [mannual](https://github.com/wkgcass/Latte-lang/blob/master/mannual-zh.md)\n\n<h1 id='readme-ch'>中文版 Chinese Version README</h1>\n\nLatte是一种JVM编程语言。 它非常可读，同时也非常可扩展。\n\n[语法规则](https://github.com/wkgcass/Latte-lang/blob/master/mannual-zh.md)  \n[Latte 主页](http://latte-lang.org/)\n\n`Atom`上的扩展插件:\n\n[atom-latte-lang-highlighting](https://atom.io/packages/Atom-Latte-lang-Highlighting)  \n[atom-latte-lang-ide](https://atom.io/packages/atom-latte-lang-ide)\n\n`Gradle` Plugin :\n\n[latte-gradle-plugin](#gradle-plugin-ch)\n\n### Latte 支持如下功能\n\n* 运算符绑定\n* DSL\n* Data Class\n* 模式匹配\n* 内部方法\n* Lambda 和 高阶函数\n* JSON 字面量\n* 正则表达式\n* Read Eval Print Loop\n* 编译到JavaScript\n* Latte Gradle Plugin\n* JSR 223\n* 许多其它特性\n\n`Latte`基于java6。它被编译到JVM字节码，可以与任何Java类库完美互通。\n\n# 如何构建工程\n\n环境仅仅需要 `JDK 1.6` 或更高\n\n本工程使用 `Gradle` 进行管理，所以您也可以使用 `Gradle 2.12`(或更高) 进行自动Build  \n此外还提供了一个Build脚本\n\nclone这个仓库,然后执行\n\n\t./build.py\n\n你将会获取一个shell脚本, shell脚本可以快捷地开启`repl`.\n\n>构建脚本不支持windows，请按latte-[class-recorder | compiler | gradle-plugin | library | build]顺序依次进入目录执行`gradle clean latteBuild`，并解压`latte-build`模块的`build/distributions/latte-${version}.zip`，其中的bin目录为shell脚本。\n\n执行:\n\n\t./latte\n\n接着, [REPL](https://github.com/wkgcass/Latte-lang/blob/master/latte-build/src/main/java/lt/repl/REPL.java) 将开始运行\n\n\tWelcome to Latte lang\n\tType in expressions and double Enter to have them evaluated.\n\tType :help for more information.\n\tfor syntax help, please visit https://github.com/wkgcass/Latte-lang/\n\n    lt> 1+1\n      |\n    res0 : java.lang.Integer = 2\n\n    lt>\n\n# 编译 `lt` 文件\n\n* 使用程序命令\n\n\t\tlatte -c <source-directory>\n\n\t详细的命令与选项可以这样找到\n\n\t\tlatte -help\n\n或者:\n\n* 开启`REPL`, 然后构造一个`Compiler`\n\n\t\tcompiler = Compiler()\n\n\t使用 `>>` 运算符来指定编译输出目录\n\n\t\tcompiler >> '...'\n\t\t// or\n\t\tcompiler >> File('...')\n\n\t使用 `+` 运算符来添加 class-path\n\n\t\tcompiler + '...'\n\n\t使用 `compile MAP` 来确定源代码并立即开始编译\n\n\t\tcompiler compile ['fileName':FileObject]\n\n\t通常来说会使用 `filesInDirectory('...', regex)`, e.g.\n\n\t\tcompiler compile filesInDirectory('/Users/me/src', '.\\*\\\\.lt'.r)\n\n\t这些方法调用可以被串联起来\n\n\t\tCompiler() + '...cp...' >> '...output...' compile filesInDirectory('...source...', '.\\*\\\\.lt'.r)\n\n\t您可以编写一个脚本 `script` 来配置这些属性。查看 [build.lts.template](https://github.com/wkgcass/Latte-lang/blob/master/latte-compiler/src/main/resources/build.lts.template) 以获取更多信息。\n\n# Scripts\n\n* 你可以直接运行脚本\n\n\t\tlatte -s script-file-path script-arguments...\n\n或者：\n\n*  开启 `REPL` 解释器  \n\t输入 `:script <script file>` 并回车\n\n\t然后使用 `script run` 或者 `script run ['string array']` 来运行这个脚本\n\n# JSR 223\n\nLatte-lang支持JSR223规范。使用`getEngineByName(\"Latte-lang\")`来获取`ScriptEngine`。\n\n```java\nScriptEngine engine = new ScriptEngineManager().getEngineByName(\"Latte-lang\");\nObject result = engine.eval(\"a = 1 + 3\");\nSystem.out.println(engine.get(\"a\"));\n```\n\n由于Latte-lang是一种编译型语言，并且它直接编译到JVM字节码，所以你甚至可以在Latte源代码中使用脚本引擎。\n\n```\nengine = ScriptEngineManager().getEngineByName(\"Latte-lang\")\nresult = engine eval \"a = 1 + 3\"\n.println result\n.println engine.a\n```\n\n<h1 id='gradle-plugin-ch'>Gradle 插件</h1>\n\n提供了一个`Gradle`的插件， 这个插件可以用来编译和运行`latte`源文件和脚本（script）。\n\n### 如何使用\n\n### step1\n\n添加如下gradle plugin配置：\n\n```groovy\nbuildscript {\n    dependencies {\n        classpath 'org.latte-lang:latte-gradle-plugin:$VERSION'\n    }\n}\n\napply plugin: 'latte'\n\nsourceSets {\n    main {\n        java\n        latte.srcDirs = ['src/main/latte']\n        resources\n    }\n    test {\n        java\n        latte\n        resources\n    }\n}\n\nlatteConfig {\n    afterJava = true\n    afterGroovy = false\n    fastFail = false\n}\n```\n\n> 所有的配置项都是可选的\n\n插件添加了 `compileLatte` 和 `compileTestLatte` 任务。`compileLatte` 在 `classes` 任务之前, `compileTestLatte` 在 `testClasses` 任务之前\n\n### step2\n在同一个上级目录中创建名称为`latte`的目录。目录结构树应当为：\n\n\tsrc\n\t├── main\n\t│   ├── java\n\t│   │   └── \\*.java    ; java source\n\t│   ├── latte\n\t│   │   └── \\*.lt      ; latte source\n\t│   └── resources\n\t│       │── \\*.lts     ; latte scripts\n\t│       └── other resources\n\t└── test\n\t    ├── java\n\t    │   └── \\*.java\n\t    ├── latte\n\t    │   └── \\*.lt\n\t    └── resources\n\t        ├── \\*.lts\n\t        └── other resources\n\n### step3\n运行\n\n\tgradle clean jar\n\n# 语法\n\n您可以从这两个地方获取语法规则\n\n[语法规则](https://github.com/wkgcass/Latte-lang/blob/master/mannual-zh.md)\n\n[Latte 主页](http://latte-lang.org/)\n"
  },
  {
    "path": "TODO.md",
    "content": "# Latte-lang TODOs\n\n## Modularization /2016-10-23\n\nlatte-compiler can be divided into 4 parts:\n\n* latte-compiler-scanner-parser takes string input and produce AST\n* latte-compiler-semantic takes AST and produce bytecode-like semantic objects\n* latte-compiler-code-gen produce bytecode\n* latte-compiler contains Latte lang, repl and other runtime necessary dependencies\n\n## Value Available Assurance /2016-10-16\n\nSome language support `null safety` (e.g. Kotlin). Latte would support a better value assurance. However, when calling a java method, there's no guarantee that the result would be safe. So Latte don't provide checking for methods outside, only checking inside the method.\n\nWhen defining a method, let each param be `null safe` or `value available` or `no assurance` as default.\n\n* ~~add new modifier for variables (`notnull`, `notempty`. The first only checks null/Unit, the second cast the value to bool can check the result).~~ / 2016-10-18 **DONE**\n* ~~implement the modifiers for params and return values~~ / 2016-10-18 **DONE**\n* ~~implement the modifiers for local variables~~ / 2016-10-22 **DONE**\n* ~~implement the modifiers for fields~~ /2016-10-18 **REMOVED**\n\n## Performance and Accuracy 1 /2016-10-15\n\nThere are multiple things can be refactored, especially the lambda expression.\nFirst step would be these tasks:\n\n* ~~`val` variable types can be predicted. (EASY)~~ / 2016-10-16 **DONE**\n* ~~when generating lambda expression, non-accessible variables (those with an invalid name) can be ignored. (HARD)~~ / 2016-10-23 **DONE**\n* scanner can be refactored. (HARD)\n* ~~step 1 should be refactored. first retrieve all packages that's defined in source code, then check import. (MEDIUM)~~ / 2016-10-16 **DONE**\n* ~~scan class path to see whether a package exist. (EASY)~~ / 2016-10-16 **DONE**\n\n## Full Function Support /2016-10-14\n\nThe current `function type` support is not good enough. Any thing that is invokable should be seen as a function.\n\nHere's the what to do:\n\n* ~~remove inner method, replace with lambda (EASY)~~ /2016-10-16 **REMOVE** methods are methods, they divide from functions\n\n  a method can be directly accessed without `(...)` to have it invoked, but a function is passed as a variable.\n  they are not the same\n\n* ~~use `fun` as modifier when defining methods (just like kotlin) (EASY)~~ /2016-10-16 **DONE** but instead of `fun`, we use `def`\n\n  the functions shoud be considered differently from methods.  \n  and now statements like `def m=1` can be used. `def m=1`,`def m:int=1`,`def m:int |- ...`,`def m:int`,`def m |- ...`,`def m`\n\n* ~~constructor as a function, when calling the function, a new object would be returned (MEDIUM)~~ **REMOVE**\n* ~~method as a function, when calling the function, the method would be invoked (MEDIUM)~~ **REMOVE**\n* bind argument to function, which generates a new function (HARD)\n"
  },
  {
    "path": "build.py",
    "content": "#!/usr/bin/python\n# -*- coding: utf-8 -*-\n\nimport os\nimport sys\nimport time\nfrom subprocess import Popen, PIPE\nimport zipfile\nimport platform\nimport getpass\n\nGRADLE_CMD = 'gradle'\nACTION = 'build'\nALLOWED_ACTIONS = ['build', 'test', 'deploy']\nBUILD_MODULES = ['latte-class-recorder', 'latte-compiler', 'latte-gradle-plugin', 'latte-library', 'latte-build']\nDEPLOY_USER = ''\nDEPLOY_PASS = ''\n\nJAVA_MIN_VERSION = '1.6'\nGRADLE_MIN_VERSION = '2.12'\nPACK_ZIP_DIR = 'latte-build/build/distributions/'\nVERSION_FILE = 'latte-build/src/main/resources/version'\n\ndef log(s):\n    print s\n\ndef javaVersion():\n    try:\n        ps = Popen('java -version'.split(' '), stdout=PIPE, stderr=PIPE)\n    except:\n        return ''\n    lines = ps.stderr.readlines()\n    if len(lines) == 0:\n        return ''\n    ver = lines[0].strip()\n    starter = 'java version \\\"'\n    if ver[0:len(starter)] == starter:\n        ver = ver[len(starter):-1]\n        while '_' in ver:\n            ver = ver[0:ver.find('_')]\n        return ver\n    else:\n        return ''\n\ndef gradleVersion():\n    try:\n        ps = Popen((GRADLE_CMD + ' --version').split(' '), stdout=PIPE, stderr=PIPE)\n    except:\n        return ''\n    lines = ps.stdout.readlines()\n    if len(lines) < 3:\n        return ''\n    ver = lines[2].strip()\n    starter = 'Gradle '\n    if ver[0:len(starter)] == starter:\n        ver = ver[len(starter):]\n        return ver\n    else:\n        return ''\n\ndef compareVersionLt(a, b):\n    aa = a.split('.')\n    bb = b.split('.')\n    i = 0\n    while i < len(aa) and i < len(bb):\n        ia = int(aa[i])\n        ib = int(bb[i])\n        i += 1\n        if ia > ib:\n            return False\n        elif ia == ib:\n            continue\n        else:\n            return True\n    return False\n\ndef check():\n    # check java version\n    jVer = javaVersion()\n    if jVer == '':\n        log('Java not found')\n        return False\n    if compareVersionLt(jVer, JAVA_MIN_VERSION):\n        log('Java version is %s, but %s or higher required' % (str(jVer), str(JAVA_MIN_VERSION)))\n        return False\n\n    # check gradle version\n    gVer = gradleVersion()\n    if gVer == '':\n        log('Gradle not found [' + GRADLE_CMD + ']')\n        return False\n    if compareVersionLt(gVer, GRADLE_MIN_VERSION):\n        log('Gradle version is %s, but %s or higher required' % (str(gVer), str(GRADLE_MIN_VERSION)))\n        return False\n\n    # get version\n    versionFile = open(VERSION_FILE, 'r')\n    version = versionFile.readline().strip()\n    versionFile.close()\n    log('--- current version is [%s] ---' % (version))\n\n    return True\n\ndef execute(cmd):\n    exportStr = 'export'\n    env = {}\n    env['BUILD_ACTION'] = ACTION.lower()\n    if DEPLOY_USER and DEPLOY_PASS:\n        env['DEPLOY_USER'] = DEPLOY_USER\n        env['DEPLOY_PASS'] = DEPLOY_PASS\n    s = ''\n    for k in env:\n        s += (exportStr + ' ' + k + '=' + env[k] + '\\n')\n    return 0 == os.system(s + cmd)\n\ndef buildModule(module):\n    log('--- Start to build module [%s] ---' % (module))\n    return execute('cd %s\\n%s clean latteBuild' % (module, GRADLE_CMD))\n\ndef build():\n    for m in BUILD_MODULES:\n        if not buildModule(m):\n            return False\n    return True\n\ndef unixLink(script):\n    # some file system do not support `ln`\n    # so we create a new shell script\n    # which redirect all input arguments to dest script\n    f = open('latte', 'w')\n    f.write('basepath=$(cd `dirname $0`; pwd)\\n')\n    f.write('$basepath/' + script + ' \"$@\"\\n')\n    f.close()\n    # and chmox +x to both the scripts\n    return \\\n    (0 == os.system('chmod +x latte')) and \\\n    (0 == os.system('chmod +x ' + script))\n\ndef scripts():\n    # unzip the latte.jar\n    zipF = None\n    for f in os.listdir(PACK_ZIP_DIR):\n        if f[-4:] == '.zip':\n            zipF = f\n            break\n    if not zipF:\n        log('distribution zip file not found')\n        return False\n    theFile = zipfile.ZipFile(PACK_ZIP_DIR + zipF, 'r')\n    for filename in theFile.namelist():\n        theFile.extract(filename, \"./build/\")\n\n    # link the scripts\n    script = 'build/' + zipF[0:-4] + '/bin/latte'\n\n    if unixLink(script):\n        return True\n    else:\n        log('Create shortcut script failed')\n        return False\n\ndef performModule(module):\n    log('--- Start to build module [%s] ---' % (module))\n    return execute('cd %s\\n%s clean latte%s' % (module, GRADLE_CMD, ACTION))\n\ndef perform():\n    for m in BUILD_MODULES:\n        if not performModule(m):\n            return False\n    return True\n\ndef start():\n    if ACTION == 'Deploy':\n        global DEPLOY_USER\n        global DEPLOY_PASS\n        DEPLOY_USER = raw_input('user: ')\n        DEPLOY_PASS = getpass.getpass('pass: ')\n\n    log('============================')\n    log( ACTION + ' Start')\n    log('============================')\n    startTime = time.time()\n\n    res = check() and perform()\n    if ACTION == 'Build':\n        scripts()\n\n    endTime = time.time()\n    if res:\n        log('============================')\n        log( ACTION + ' Successful')\n        log('============================')\n        log('Total time: %.3f secs' % (endTime - startTime))\n    else:\n        log('============================')\n        log( ACTION + ' Failed')\n        log('============================')\n\ndef assertNotLast(argv, i):\n    if len(argv) > i + 1:\n        return\n    raise Exception('command not complete')\n\ndef extractArgs():\n    if len(sys.argv) == 1:\n        return {}\n\n    global GRADLE_CMD\n    global ACTION\n    global BUILD_MODULES\n\n    index = 1\n    while index < len(sys.argv):\n        cmd = sys.argv[index]\n        if cmd == '--gradle' or cmd == '-g':\n            assertNotLast(sys.argv, index)\n            index = index + 1\n            GRADLE_CMD = sys.argv[index]\n\n        elif cmd == '--action' or cmd == '-a':\n            assertNotLast(sys.argv, index)\n            index = index + 1\n            ACTION = sys.argv[index]\n\n        elif cmd == '--modules' or cmd == '-m':\n            assertNotLast(sys.argv, index)\n            index = index + 1\n            BUILD_MODULES = sys.argv[index].split(',')\n\n        else:\n            raise Exception('unknown arg [' + cmd + ']')\n        index = index + 1\n\nif __name__ == \"__main__\":\n    if len(sys.argv) == 2 and ((sys.argv[1] == '-h') or (sys.argv[1] == '--help')):\n        log('''./build.py [-g|--gradle gradle-command-name]\n           [-a|--action %s]\n           [-m|--modules module-name1,module-name2,...]''' % ('|'.join(ALLOWED_ACTIONS)))\n        exit()\n    try:\n        extractArgs()\n        if ACTION in ALLOWED_ACTIONS:\n            ACTION = ACTION[0:1].upper() + ACTION[1:]\n            start()\n        else:\n            log('Unknown action [' + ACTION + ']')\n    except Exception, e:\n        log(str(e))\n"
  },
  {
    "path": "latte-build/.gitignore",
    "content": ".gradle/*\n.idea/*\nbuild/*\n*.ipr\n*.iws\nout/*\n"
  },
  {
    "path": "latte-build/build.gradle",
    "content": "def VERSION_FILE = file('src/main/resources/version')\nBufferedReader br = new BufferedReader(new FileReader(VERSION_FILE))\ndef VERSION = br.readLine().trim()\nbr.close()\n\ndef ACTION = System.getenv(\"BUILD_ACTION\")\n\ngroup 'org.latte-lang'\nversion VERSION\n\napply plugin: 'java'\napply plugin: 'idea'\napply plugin: 'application'\napply plugin: 'maven'\nif ('deploy' == ACTION) {\n    apply plugin: 'signing'\n}\napply plugin: LatteBuild\n\nmainClassName = 'lt.repl.Entry'\napplicationName = 'latte'\n\nsourceCompatibility = 1.6\ntargetCompatibility = 1.6\n[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\nconfigurations {\n    provided\n}\n\nsourceSets {\n    main.compileClasspath += configurations.provided\n    test.compileClasspath += configurations.provided\n    test.runtimeClasspath += configurations.provided\n}\n\nrepositories {\n    mavenLocal()\n    mavenCentral()\n}\n\nuploadArchives {\n    repositories {\n        mavenDeployer {\n            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n            def deploy_user = System.getenv('DEPLOY_USER')\n            def deploy_pass = System.getenv('DEPLOY_PASS')\n\n            repository(url: \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\") {\n                authentication(userName: deploy_user, password: deploy_pass)\n            }\n\n            pom.project {\n                name 'latte-build'\n                packaging 'jar'\n                description 'The project is to build the latte-lang modules into one, and provide command line support.'\n                url 'http://latte-lang.org'\n                scm {\n                    url 'https://github.com/wkgcass/Latte-lang'\n                    connection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                    developerConnection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                }\n                licenses {\n                    license {\n                        name 'MIT LICENSE'\n                        url 'https://github.com/wkgcass/Latte-lang/blob/master/LICENSE/'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'wkgcass'\n                        email 'wkgcass@hotmail.com'\n                    }\n                }\n            }\n        }\n    }\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    classifier = 'sources'\n    from sourceSets.main.allSource\n}\n\nartifacts {\n    archives jar\n    archives javadocJar\n    archives sourcesJar\n}\n\njavadoc {\n    options {\n        encoding 'UTF-8'\n        charSet 'UTF-8'\n    }\n}\n\nif (null == ACTION) {\n    jar {\n        manifest {\n            attributes(\"Manifest-Version\": 1.0,\n                       \"Main-Class\": \"lt.repl.Entry\")\n        }\n        from { configurations.compile.collect { it.isDirectory() ? it : zipTree(it) } }\n        into('assets') {\n            from 'assets'\n        }\n    }\n}\n\nif ('deploy' == ACTION) {\n    signing {\n        sign configurations.archives\n    }\n}\n\ndependencies {\n    compile group: 'org.latte-lang', name: 'latte-compiler', version: VERSION\n    compile group: 'org.latte-lang', name: 'latte-library', version: VERSION\n    provided group: 'jline', name: 'jline', version: '2.14.5'\n}\n\nclass LatteBuild implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def latteBuild = project.task('latteBuild')\n        latteBuild.dependsOn project.tasks['install']\n\n        project.task('latteTest') // do nothing\n\n        def latteDeploy = project.task('latteDeploy')\n        latteDeploy.dependsOn project.tasks['uploadArchives']\n    }\n}\n"
  },
  {
    "path": "latte-build/settings.gradle",
    "content": "rootProject.name = 'latte-build'\n\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/CtrlCHandler.java",
    "content": "package lt.repl;\n\n/**\n * handle ctrl-c (INT) event\n */\npublic interface CtrlCHandler {\n        interface ExitCallback {\n                void exit();\n        }\n\n        void setExitCallback(ExitCallback exitCallback);\n\n        void setAlert(Runnable alert);\n\n        void handle();\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/CtrlCHandlerImpl.java",
    "content": "package lt.repl;\n\nimport sun.misc.Signal;\nimport sun.misc.SignalHandler;\n\n/**\n * handle ctrl-c (INT) event\n */\npublic class CtrlCHandlerImpl implements CtrlCHandler {\n        private Runnable alert = null;\n        private ExitCallback exitCallback = null;\n        private final IO io;\n        private int count;\n\n        public CtrlCHandlerImpl(IO io) {\n                this.io = io;\n        }\n\n        @Override\n        public void setExitCallback(final ExitCallback exitCallback) {\n                this.exitCallback = exitCallback;\n        }\n\n        @Override\n        public void setAlert(Runnable alert) {\n                this.alert = alert;\n        }\n\n        @Override\n        public void handle() {\n                ++count;\n                if (count == 2) {\n                        io.out.println();\n                        exitCallback.exit();\n                } else {\n                        io.out.println(\"\\n(To exit, press ^C again or type :q)\");\n                        if (alert != null) {\n                                alert.run();\n                        }\n                        new Thread(new Runnable() {\n                                @Override\n                                public void run() {\n                                        try {\n                                                Thread.sleep(1000);\n                                        } catch (InterruptedException e) {\n                                                e.printStackTrace(io.err);\n                                        }\n                                        count = 0;\n                                }\n                        }).start();\n                }\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/Entry.java",
    "content": "package lt.repl;\n\nimport lt.compiler.SyntaxException;\nimport lt.repl.scripting.EvalEntry;\nimport lt.util.Utils;\n\nimport java.io.*;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.util.ArrayList;\nimport java.util.Arrays;\nimport java.util.List;\n\npublic class Entry {\n        public static void main(String[] args) throws Exception {\n                if (args == null || args.length > 0) {\n                        runCommands(args);\n                } else {\n                        StringReader reader;\n                        try {\n                                Class.forName(\"jline.console.ConsoleReader\"); // check exists\n                                reader = (StringReader) Class.forName(\"lt.repl.JLineStringReader\")\n                                        .getConstructor().newInstance();\n                        } catch (ClassNotFoundException ignore) {\n                                reader = new SimpleStringReader();\n                        }\n\n                        REPL repl = new REPL(reader, new IO(System.in, System.out, System.err),\n                                new CtrlCHandler.ExitCallback() {\n                                        @Override\n                                        public void exit() {\n                                                System.exit(0);\n                                        }\n                                });\n                        repl.handleCtrlC();\n                        repl.start();\n                }\n        }\n\n        /**\n         * run the program with arguments\n         *\n         * @param args arguments\n         */\n        private static void runCommands(String[] args) throws Exception {\n                String command = args[0];\n                if (command.equals(\"help\") || command.equals(\"-help\") || command.equals(\"--help\") || command.equals(\"-h\") || command.equals(\"/h\") || command.equals(\"/help\")) {// help\n                        System.out.println(\"\" +\n                                \"usage: -s <script-location> [arguments [,...]]\\n\" +\n                                \"       -c <source-directory> [-r] [-o <output-directory>] [-cp <classpath[:...]>]\\n\" +\n                                \"       ClassName [-cp <classpath[:...]>]\\n\" +\n                                \"       -gb <project-directory>\\n\" +\n                                \"       -repl\\n\" +\n                                \"       -v | -version\\n\" +\n                                \"       -e <statements>\\n\" +\n                                \"\\n\" +\n                                \"-s       Specify the script location and run the script\\n\" +\n                                \"-c       Specify the source file directory and compile *.lt files\\n\" +\n                                \"-r       [option] Add sub directory files to compiling list.\\n\" +\n                                \"-o       [option] Specify the output directory. (the source-directory/target/classes/ as default)\\n\" +\n                                \"-cp      [option] The classpath. use ':' to separate the class-paths\\n\" +\n                                \"-repl    Start the repl (or run the program with 0 arguments)\\n\" +\n                                \"-gb      Generate build.lts and run.lts in the given directory\\n\" +\n                                \"-e       Evaluate the given statement and print the result\\n\" +\n                                \"-version Show current version\\n\");\n\n                } else if (command.equals(\"-v\") || command.equals(\"-version\")) {\n                        System.out.println(\"Latte-lang \" + VersionRetriever.version());\n\n                } else if (command.equals(\"-s\")) {// run scripts\n                        // -s ?\n                        if (args.length < 2) {\n                                System.err.println(\"invalid command -s. the script file location should be specified\\n\" +\n                                        \"see --help\");\n                                return;\n                        }\n                        String path = args[1];\n                        File f = new File(path);\n                        ScriptCompiler s = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n                        try {\n                                ScriptCompiler.Script script = s.compile(f);\n                                String[] scriptArgs = new String[args.length - 2];\n                                System.arraycopy(args, 2, scriptArgs, 0, args.length - 2);\n                                script.run(scriptArgs);\n                        } catch (Throwable e) {\n                                if (e instanceof SyntaxException) {\n                                        System.err.println(\"[ERROR] \" + e.getMessage());\n                                } else {\n                                        e.printStackTrace();\n                                }\n                        }\n\n                } else if (command.equals(\"-c\")) {// compile\n                        // -c ?\n                        if (args.length < 2) {\n                                System.err.println(\"invalid command -c. the source directory should be specified\\n\" +\n                                        \"see --help\");\n                                return;\n                        }\n                        String sourceDir = args[1].trim();\n                        if (sourceDir.endsWith(File.separator)) {\n                                sourceDir = sourceDir.substring(0, sourceDir.length() - File.separator.length());\n                        }\n\n                        boolean recursive = false;\n                        String outputDir = sourceDir + File.separator + \"target\" + File.separator + \"classes\";\n                        List<URL> classPaths = new ArrayList<URL>();\n\n                        for (int i = 2; i < args.length; ++i) {\n                                String cmd = args[i];\n                                if (cmd.equals(\"-r\")) {\n                                        recursive = true;\n\n                                } else if (cmd.equals(\"-o\")) {\n                                        if (args.length - 1 == i) {\n                                                System.err.println(\"invalid option -o. the output directory should be specified\");\n                                                System.err.println(\"see --help\");\n                                                return;\n                                        }\n                                        outputDir = args[++i];\n\n                                } else if (cmd.equals(\"-cp\")) {\n                                        if (args.length - 1 == i) {\n                                                System.err.println(\"invalid option -cp. the class-path should be specified\");\n                                                System.err.println(\"see --help\");\n                                                return;\n                                        }\n                                        String[] class_paths = args[++i].split(\":\");\n                                        for (String class_path : class_paths) {\n                                                try {\n                                                        classPaths.add(new URL(new File(class_path).toURI().toString()));\n                                                } catch (MalformedURLException e) {\n                                                        System.err.println(\"[ERROR] \" + e.getMessage());\n                                                        return;\n                                                }\n                                        }\n\n\n                                } else {\n                                        System.err.println(\"unknown option \" + cmd);\n                                        System.err.println(\"see --help\");\n                                        return;\n                                }\n                        }\n\n                        Compiler compiler = new Compiler();\n                        File outputDirFile = new File(outputDir);\n                        if (!outputDirFile.exists()) //noinspection ResultOfMethodCallIgnored\n                                outputDirFile.mkdirs();\n                        compiler.config.result.outputDir = outputDirFile;\n                        compiler.config.classpath = classPaths;\n\n                        try {\n                                compiler.compile(Utils.filesInDirectory(sourceDir, \".*\\\\.(lt|latte)\", recursive));\n                        } catch (Exception e) {\n                                if (e instanceof SyntaxException) {\n                                        System.err.println(\"[ERROR] \" + e.getMessage());\n                                } else {\n                                        e.printStackTrace();\n                                }\n                        }\n\n                } else if (command.equals(\"-gb\")) {\n                        final List<String> theFilesToBeGenerated = Arrays.asList(\"build.lts\", \"run.lts\");\n\n                        if (args.length != 2) {\n                                System.err.println(\"invalid command -gb.\");\n                                System.err.println(\"see --help\");\n                                return;\n                        }\n                        String projectDir = args[1].trim();\n                        if (projectDir.endsWith(File.separator)) {\n                                projectDir = projectDir.substring(0, projectDir.length() - File.separator.length());\n                        }\n\n                        String core = String.valueOf(Runtime.getRuntime().availableProcessors());\n                        String separator = File.separator;\n\n                        for (String theFile : theFilesToBeGenerated) {\n                                String filePath = projectDir + File.separator + theFile;\n                                File file = new File(filePath);\n                                if (file.exists()) {\n                                        System.out.println(\"[INFO] \" + filePath + \" exists\");\n                                } else {\n                                        try {\n                                                //noinspection ResultOfMethodCallIgnored\n                                                file.createNewFile();\n                                        } catch (IOException e) {\n                                                e.printStackTrace();\n                                        }\n                                }\n\n                                try {\n                                        FileWriter fw = new FileWriter(file);\n                                        BufferedReader br = new BufferedReader(new InputStreamReader(REPL.class.getClassLoader().getResourceAsStream(theFile + \".template\")));\n\n                                        String ss;\n                                        while ((ss = br.readLine()) != null) {\n                                                ss = ss.replace(\"${core}\", core)\n                                                        .replace(\"${dir}\", projectDir.replace(\"\\\\\", \"\\\\\\\\\"))\n                                                        .replace(\"${separator}\", separator) + \"\\n\";\n                                                fw.write(ss.toCharArray());\n                                        }\n                                        fw.flush();\n                                        fw.close();\n                                } catch (IOException e) {\n                                        e.printStackTrace();\n                                }\n                        }\n\n                } else if (command.equals(\"-repl\")) {// repl\n                        main(new String[0]);\n                } else if (command.equals(\"-e\")) {// eval\n                        if (args.length == 1 || args[1] == null || args[1].trim().isEmpty()) {\n                                System.err.println(\"missing statements to eval\");\n                                return;\n                        }\n                        String statements = args[1].trim();\n                        Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n                        EvalEntry entry = e.eval(statements);\n                        System.out.println(entry.result);\n\n                } else {// run\n                        List<URL> urls = new ArrayList<URL>();\n                        try {\n                                String url = new File(\"\").toURI().toString();\n                                urls.add(new URL(url));\n                        } catch (MalformedURLException e) {\n                                System.err.println(\"[ERROR] \" + e.getMessage());\n                                return;\n                        }\n                        String[] runArgs = new String[0];\n                        for (int i = 1; i < args.length; ++i) {\n                                String cmd = args[i];\n                                if (cmd.equals(\"-cp\")) {\n                                        if (i == args.length - 1) {\n                                                System.err.println(\"invalid option -cp. the class-path should be specified\");\n                                                System.err.println(\"see --help\");\n                                                return;\n                                        }\n                                        String cps = args[++i];\n                                        for (String cp : cps.split(\":\")) {\n                                                try {\n                                                        urls.add(new URL(new File(cp).toURI().toString()));\n                                                } catch (MalformedURLException e) {\n                                                        System.err.println(\"[ERROR] \" + e.getMessage());\n                                                        return;\n                                                }\n                                        }\n\n                                } else if (cmd.equals(\"-args\")) {\n                                        runArgs = new String[args.length - 1 - i];\n                                        System.arraycopy(args, i + 1, runArgs, 0, runArgs.length);\n                                        break;\n                                } else {\n                                        System.err.println(\"unknown option \" + cmd);\n                                        System.err.println(\"see --help\");\n                                        return;\n                                }\n                        }\n\n                        try {\n                                // run the class\n                                Run run = new Run(urls, command);\n                                run.exec(runArgs);\n                        } catch (Throwable t) {\n                                t.printStackTrace();\n                        }\n                }\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/IO.java",
    "content": "package lt.repl;\n\nimport java.io.*;\n\npublic class IO {\n        public final InputStream inStream;\n        public final OutputStream outStream;\n        public final OutputStream errStream;\n        public final Reader in;\n        public final PrintStream out;\n        public final PrintStream err;\n\n        public IO(InputStream in, OutputStream out, OutputStream err) {\n                this.inStream = in;\n                this.outStream = out;\n                this.errStream = err;\n\n                this.in = new InputStreamReader(in);\n                this.out = new PrintStream(out, true);\n                this.err = new PrintStream(err, true);\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/JLineStringReader.java",
    "content": "package lt.repl;\n\nimport jline.console.ConsoleReader;\nimport jline.console.UserInterruptException;\n\nimport java.io.IOException;\n\n/**\n * read line from jLine\n */\npublic class JLineStringReader implements StringReader {\n        private ConsoleReader reader;\n        private IO io;\n        private CtrlCHandler handler = null;\n\n        public JLineStringReader() {\n        }\n\n        @Override\n        public void setIO(IO io) {\n                this.io = io;\n                io.out.println(\"using jline.console.ConsoleReader to read input\");\n        }\n\n        @Override\n        public void setCtrlCHandler(CtrlCHandler handler) {\n                this.handler = handler;\n        }\n\n        private void initReader() throws IOException {\n                if (reader != null) {\n                        reader.close();\n                }\n                reader = new ConsoleReader(io.inStream, io.outStream);\n                reader.setHandleUserInterrupt(true);\n        }\n\n        @Override\n        public String read() throws Exception {\n                if (reader == null) {\n                        initReader();\n                }\n\n                String line;\n                while (true) {\n                        try {\n                                line = reader.readLine();\n                                break;\n                        } catch (UserInterruptException ignore) {\n                                if (handler != null) {\n                                        handler.handle();\n                                }\n                        }\n                }\n                if (line == null) return null;\n                return line + '\\n';\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/REPL.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.compiler.SyntaxException;\nimport lt.repl.scripting.Config;\nimport lt.repl.scripting.EvalEntry;\n\nimport java.io.*;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\n\n/**\n * repl\n */\npublic class REPL {\n        private final String lineStarter = \"lt> \";\n        private final String multipleLine = \"  | \";\n        private StringBuilder replSourceRec = new StringBuilder();\n        private final IO io;\n        private final CtrlCHandler.ExitCallback exitCallback;\n        private StringReader reader;\n\n        public REPL(StringReader reader, IO io, CtrlCHandler.ExitCallback exitCallback) {\n                this.reader = reader;\n                this.io = io;\n                this.exitCallback = exitCallback;\n        }\n\n        public void start() throws Exception {\n                io.out.println(\"Welcome to Latte lang\");\n                io.out.println(\"Type in expressions and double Enter to have them evaluated.\");\n                io.out.println(\"Type :help for more information.\");\n                io.out.println(\"for syntax help, please visit https://github.com/wkgcass/Latte-lang/\");\n                io.out.println();\n\n                ClassPathLoader classPathLoader = new ClassPathLoader(Thread.currentThread().getContextClassLoader());\n\n                Evaluator evaluator = new Evaluator(classPathLoader);\n                reader.setIO(io);\n                io.out.println();\n                io.out.print(lineStarter);\n\n                StringBuilder strBuilder = new StringBuilder();\n                out:\n                while (true) {\n                        while (true) {\n                                String s = reader.read();\n                                if (s == null) {\n                                        // the reader reached EOF\n                                        break out;\n                                }\n                                if (s.endsWith(\"\\n\") || s.endsWith(\"\\r\")) {\n                                        if (s.endsWith(\"\\r\\n\")) {\n                                                strBuilder.append(s.subSequence(0, s.length() - 2));\n                                        } else {\n                                                strBuilder.append(s.subSequence(0, s.length() - 1));\n                                        }\n                                        break;\n                                }\n                                strBuilder.append(s);\n                        }\n                        String str = strBuilder.toString();\n                        strBuilder.delete(0, strBuilder.length());\n                        if (str.trim().startsWith(\":\")) {\n                                String cmd = str.trim();\n                                // some functions that controls the REPL\n                                if (cmd.equals(\":help\")) {\n                                        io.out.println(\":q                                         exit the REPL\");\n                                        io.out.println(\":reset                                     reset the repl to its initial state, forgetting all session entries\");\n                                        io.out.println(\":restart                                   restart the repl environment, drop all loaded jars\");\n                                        io.out.println(\":                                          set current input to empty string\");\n                                        io.out.println(\":cp <class-path>                           load classes\");\n                                        io.out.println(\":script <script-path>                      compile a script\");\n                                        io.out.println(\"----------------------------------------------------------------\");\n                                        io.out.println(\":scanner-indent                            use IndentScanner to scan input\");\n                                        io.out.println(\":scanner-brace                             use BraceScanner to scan input\");\n                                        io.out.println(\"----------------------------------------------------------------\");\n                                        io.out.println(\"Compiler()                                 construct a new Compiler\");\n                                        io.out.println(\"compiler >> '<directory>'                  set compiler output directory\");\n                                        io.out.println(\"compiler compile filesInDirectory('<directory>')\");\n                                        io.out.println(\"                                           start compiling and generate class files\");\n                                        io.out.println(\"----------------------------------------------------------------\");\n                                        io.out.println(\"ScriptCompiler()                           construct a new ScriptCompiler\");\n                                        io.out.println(\"scriptCompiler << File('')                 add source code file\");\n                                        io.out.println(\"scriptCompiler compile File('script')      compile the script\");\n                                } else if (cmd.equals(\":q\")) {\n                                        break;\n                                } else if (cmd.equals(\":reset\")) {\n                                        replSourceRec.delete(0, replSourceRec.length());\n                                        evaluator = new Evaluator(classPathLoader);\n                                } else if (cmd.equals(\":restart\")) {\n                                        replSourceRec.delete(0, replSourceRec.length());\n                                        classPathLoader = new ClassPathLoader(Thread.currentThread().getContextClassLoader());\n                                        evaluator = new Evaluator(classPathLoader);\n                                } else if (cmd.startsWith(\":cp \")) {\n                                        String cp = cmd.substring(\":cp \".length()).trim();\n                                        try {\n                                                URL url = new URL(new File(cp).toURI().toString());\n                                                classPathLoader.load(url);\n                                        } catch (Throwable t) {\n                                                t.printStackTrace(io.err);\n                                                sleep(10);\n                                        }\n                                } else if (cmd.startsWith(\":script \")) {\n                                        String run = cmd.substring(\":script \".length()).trim();\n                                        try {\n                                                ScriptCompiler scriptCompiler = new ScriptCompiler(classPathLoader);\n                                                ScriptCompiler.Script script = scriptCompiler.compile(new File(run));\n                                                evaluator.put(\"script\", script);\n                                                io.out.println(\"script : \" + script.getClass().getName() + \" = \" + script);\n                                        } catch (Throwable t) {\n                                                t.printStackTrace(io.err);\n                                                sleep(10);\n                                        }\n                                } else if (cmd.equals(\":scanner-indent\")) {\n                                        evaluator.setScannerType(Config.SCANNER_TYPE_INDENT);\n                                } else if (cmd.equals(\":scanner-brace\")) {\n                                        evaluator.setScannerType(Config.SCANNER_TYPE_BRACE);\n                                } else if (cmd.equals(\":\")) {\n                                        replSourceRec.delete(0, replSourceRec.length());\n                                } else {\n                                        io.err.println(\"unknown command \" + cmd + \", Type :help for more more information\");\n                                        sleep(10);\n                                }\n                                io.out.print(\"\\n\" + lineStarter);\n                        } else {\n                                if (str.trim().isEmpty()) {\n                                        if (replSourceRec.length() != 0) {\n                                                // do repl\n                                                String stmt = replSourceRec.toString();\n                                                try {\n                                                        EvalEntry entry = evaluator.eval(stmt);\n                                                        String name = entry.name;\n                                                        Object o = entry.result;\n                                                        if (name == null) {\n                                                                showObjectStructure(o);\n                                                        } else {\n                                                                io.out.println(name + \" : \" + entry.type.getName().replaceAll(\"\\\\.\", \"::\") + \" = \" + o);\n                                                        }\n                                                        io.out.print(\"\\n\" + lineStarter);\n                                                } catch (Throwable t) {\n                                                        if (t instanceof InvocationTargetException) {\n                                                                t.getCause().printStackTrace(io.err);\n                                                        } else if (t instanceof SyntaxException) {\n                                                                int line = ((SyntaxException) t).lineCol.line - 1;\n                                                                int col = ((SyntaxException) t).lineCol.column - 1;\n\n                                                                if (line < 0) {\n                                                                        io.err.println(t.getMessage());\n                                                                } else {\n\n                                                                        String[] strs = stmt.split(\"\\\\n|\\\\r\");\n                                                                        String s = strs[line];\n                                                                        io.err.println(s);\n                                                                        for (int i = 0; i < col; ++i) {\n                                                                                io.err.print(\" \");\n                                                                        }\n                                                                        io.err.print(\"^ \");\n                                                                        io.err.println(t.getMessage());\n                                                                }\n                                                        } else {\n                                                                t.printStackTrace(io.err);\n                                                        }\n                                                        sleep(10);\n                                                        io.out.print(lineStarter);\n                                                }\n                                                replSourceRec.delete(0, replSourceRec.length());\n                                        } else {\n                                                io.out.print(lineStarter);\n                                        }\n                                } else {\n                                        replSourceRec.append(str).append(\"\\n\");\n                                        io.out.print(multipleLine);\n                                }\n                        }\n\n                }\n                exitCallback.exit();\n        }\n\n        private void showObjectStructure(Object o) throws IllegalAccessException {\n                Class<?> cls = o.getClass();\n                String className = cls.getName();\n                io.out.println(\"class \" + className);\n                for (Field f : cls.getDeclaredFields()) {\n                        f.setAccessible(true);\n                        Object value = f.get(o);\n                        io.out.println(\"    \" + f.getName() + \" : \" + f.getType().getName().replaceAll(\"\\\\.\", \"::\") + \" = \" + value);\n                }\n                for (Method m : cls.getDeclaredMethods()) {\n                        io.out.print(\"    \" + m.getName() + \"(\");\n                        boolean isFirst = true;\n                        for (Class<?> paramT : m.getParameterTypes()) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        io.out.print(\", \");\n                                }\n                                io.out.print(paramT);\n                        }\n                        io.out.println(\") : \" + m.getReturnType().getName().replaceAll(\"\\\\.\", \"::\"));\n                }\n        }\n\n        private void sleep(long millis) {\n                try {\n                        Thread.sleep(millis);\n                } catch (InterruptedException e) {\n                        e.printStackTrace(io.err);\n                }\n        }\n\n        public void handleCtrlC() {\n                // listen ctrl-c\n                CtrlCHandler ctrlCHandler = new CtrlCHandlerImpl(io);\n                ctrlCHandler.setExitCallback(exitCallback);\n                ctrlCHandler.setAlert(new Runnable() {\n                        @Override\n                        public void run() {\n                                io.out.print(lineStarter);\n                                replSourceRec.delete(0, replSourceRec.length());\n                        }\n                });\n                reader.setCtrlCHandler(ctrlCHandler);\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/SimpleStringReader.java",
    "content": "package lt.repl;\n\nimport sun.misc.Signal;\nimport sun.misc.SignalHandler;\n\n/**\n * scanner line reader\n */\npublic class SimpleStringReader implements StringReader {\n        private IO io;\n\n        public SimpleStringReader() {\n        }\n\n        @Override\n        public void setIO(IO io) {\n                this.io = io;\n                io.out.println(\"using java.util.Scanner to read input\");\n        }\n\n        @Override\n        public void setCtrlCHandler(final CtrlCHandler ctrlCSignalHandler) {\n                SignalHandler handler = new SignalHandler() {\n                        @Override\n                        public void handle(Signal signal) {\n                                if (!signal.getName().equals(\"INT\")) {\n                                        return;\n                                }\n                                ctrlCSignalHandler.handle();\n                        }\n                };\n                Signal.handle(new Signal(\"INT\"), handler);\n        }\n\n        @Override\n        public String read() throws Exception {\n                int b = io.in.read();\n                if (b <= 0) {\n                        return null;\n                }\n                return String.valueOf((char) b);\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/StringReader.java",
    "content": "package lt.repl;\n\n/**\n * reads a line\n */\npublic interface StringReader {\n        void setIO(IO io);\n\n        void setCtrlCHandler(CtrlCHandler handler);\n\n        String read() throws Exception;\n}\n"
  },
  {
    "path": "latte-build/src/main/java/lt/repl/VersionRetriever.java",
    "content": "package lt.repl;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\n\n/**\n * retrieves the version\n */\nclass VersionRetriever {\n        static String version() throws IOException {\n                InputStream is = VersionRetriever.class.getClassLoader().getResourceAsStream(\"version\");\n                InputStreamReader reader = new InputStreamReader(is);\n                BufferedReader br = new BufferedReader(reader);\n                String ver = br.readLine();\n                if (ver == null) return \"UNKNOWN\";\n                return ver.trim();\n        }\n}\n"
  },
  {
    "path": "latte-build/src/main/resources/version",
    "content": "0.0.11-ALPHA\r\n0.0.10-ALPHA\r\n0.0.9.1-ALPHA\r\n0.0.9-ALPHA\r\n0.0.8-ALPHA\r\n0.0.7-ALPHA\r\n"
  },
  {
    "path": "latte-class-recorder/.gitignore",
    "content": ".idea/*\n.gradle/*\nbuild/*\n"
  },
  {
    "path": "latte-class-recorder/build.gradle",
    "content": "def VERSION_FILE = file('../latte-build/src/main/resources/version')\nBufferedReader br = new BufferedReader(new FileReader(VERSION_FILE))\ndef VERSION = br.readLine().trim()\nbr.close()\n\ngroup 'org.latte-lang'\nversion VERSION\n\napply plugin: 'groovy'\napply plugin: 'maven'\napply plugin: LatteBuild\n\ncompileGroovy {\n    sourceCompatibility = 1.6\n    targetCompatibility = 1.6\n    options.encoding = \"UTF-8\"\n}\n\nrepositories {\n    mavenLocal()\n}\n\ndependencies {\n    compile localGroovy()\n    compile gradleApi()\n}\n\nuploadArchives {\n    repositories {\n        mavenDeployer {\n            mavenLocal()\n        }\n    }\n}\n\nclass LatteBuild implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def latteBuild = project.task('latteBuild')\n        latteBuild.dependsOn project.tasks['install']\n\n        project.task('latteTest') // do nothing\n\n        project.task('latteDeploy') // do nothing\n    }\n}\n"
  },
  {
    "path": "latte-class-recorder/settings.gradle",
    "content": "rootProject.name = 'latte-class-recorder'\n\n"
  },
  {
    "path": "latte-class-recorder/src/main/groovy/org/lattelang/ClassRecorder.groovy",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage org.lattelang\n\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\n\nclass ClassRecorderPlugin implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def ext = project.extensions.create('recordConfig', ClassRecorderExtension)\n        def task = project.task('recordClass').doLast { t ->\n            def path = project.buildDir.absolutePath\n            ClassRecorder.apply(path + '/' + ext.directory, ext.file)\n        }\n\n        task.dependsOn project.tasks['classes']\n        project.tasks['jar'].dependsOn task\n    }\n}\n\nclass ClassRecorderExtension {\n    String directory\n    String file\n}\n\nclass ClassRecorder {\n    /**\n     * scan the directory (including its child directories) and record all class files\n     * and write into the output file\n     *\n     * @param scanPath the directory to scan\n     * @param outputFile the output file\n     * @throws Exception exception\n     */\n    private static void doScanPath(String scanPath, String outputFile) throws Exception {\n        StringBuilder sb = new StringBuilder();\n        File scanPathFile = new File(scanPath);\n        if (!scanPathFile.exists()) return;\n        scanPathRecursive(scanPathFile, sb, scanPath.length() + 1);\n        File f = new File(outputFile);\n        if (!f.exists()) {\n            if (!f.createNewFile()) throw new IOException(\"cannot create file \" + outputFile);\n        }\n        FileOutputStream fos = new FileOutputStream(f);\n        fos.write(sb.toString().getBytes());\n    }\n\n    /**\n     * scan path recursively\n     *\n     * @param dir directory\n     * @param sb string builder\n     * @param l the base length\n     */\n    private static void scanPathRecursive(File dir, final StringBuilder sb, final int l) {\n        File[] files = dir.listFiles();\n        if (files == null) return;\n        for (File f : files) {\n            if (f.isDirectory()) {\n                scanPathRecursive(f, sb, l);\n            } else if (f.getName().endsWith(\".class\")) {\n                sb.append(f.getAbsolutePath().substring(l)).append(\"\\n\");\n            }\n        }\n    }\n\n    /**\n     * the main method called by maven\n     *\n     * @param outputDir the compile output (`classes` directory)\n     * @param fileName the fileName of the text file that records the class names\n     * @throws Exception exception\n     */\n    public static void apply(String outputDir, String fileName) throws Exception {\n        String scanResult = outputDir + \"/\" + fileName;\n\n        doScanPath(outputDir, scanResult);\n    }\n}\n"
  },
  {
    "path": "latte-class-recorder/src/main/resources/META-INF/gradle-plugins/org.latte-lang.class-recorder.properties",
    "content": "implementation-class=org.lattelang.ClassRecorderPlugin"
  },
  {
    "path": "latte-compiler/.gitignore",
    "content": ".idea/*\n.gradle/*\nbuild/*\n*.ipr\n*.iws\nout/*\n"
  },
  {
    "path": "latte-compiler/build.gradle",
    "content": "def VERSION_FILE = file('../latte-build/src/main/resources/version')\nBufferedReader br = new BufferedReader(new FileReader(VERSION_FILE))\ndef VERSION = br.readLine().trim()\nbr.close()\n\ndef ACTION = System.getenv(\"BUILD_ACTION\")\n\ngroup 'org.latte-lang'\nversion VERSION\n\nbuildscript {\n    def VERSION_FILE_ = file('../latte-build/src/main/resources/version')\n    BufferedReader br_ = new BufferedReader(new FileReader(VERSION_FILE_))\n    def VERSION_ = br_.readLine().trim()\n    br_.close()\n\n    repositories {\n        mavenLocal()\n    }\n    dependencies {\n        classpath 'org.latte-lang:latte-class-recorder:' + VERSION_\n    }\n}\n\napply plugin: 'java'\napply plugin: 'idea'\napply plugin: 'org.latte-lang.class-recorder'\napply plugin: 'maven'\nif ('deploy' == ACTION) {\n    apply plugin: 'signing'\n}\napply plugin: LatteBuild\n\nrecordConfig {\n    directory = 'classes/main'\n    file = 'classes.txt'\n}\n\nsourceCompatibility = 1.6\ntargetCompatibility = 1.6\n[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\nrepositories {\n    mavenLocal()\n    mavenCentral()\n}\n\ndependencies {\n    testCompile group: 'junit', name: 'junit', version: '4.12'\n}\n\ntest {\n    useJUnit()\n    exclude 'lt/**'\n}\n\nuploadArchives {\n    repositories {\n        mavenDeployer {\n            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n            def deploy_user = System.getenv('DEPLOY_USER')\n            def deploy_pass = System.getenv('DEPLOY_PASS')\n\n            repository(url: \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\") {\n                authentication(userName: deploy_user, password: deploy_pass)\n            }\n\n            pom.project {\n                name 'latte-compiler'\n                packaging 'jar'\n                description 'The latte-lang compiler project, which contains compiler and runtime required library.'\n                url 'http://latte-lang.org'\n                scm {\n                    url 'https://github.com/wkgcass/Latte-lang'\n                    connection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                    developerConnection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                }\n                licenses {\n                    license {\n                        name 'MIT LICENSE'\n                        url 'https://github.com/wkgcass/Latte-lang/blob/master/LICENSE/'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'wkgcass'\n                        email 'wkgcass@hotmail.com'\n                    }\n                }\n            }\n        }\n    }\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    classifier = 'sources'\n    from sourceSets.main.allSource\n}\n\nartifacts {\n    archives jar\n    archives javadocJar\n    archives sourcesJar\n}\n\njavadoc {\n    options {\n        encoding 'UTF-8'\n        charSet 'UTF-8'\n        exclude 'lt/dependencies/*'\n    }\n}\n\nif ('deploy' == ACTION) {\n    signing {\n        sign configurations.archives\n    }\n}\n\nclass LatteBuild implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def latteBuild = project.task('latteBuild')\n        project.tasks['install'].dependsOn project.tasks['test']\n        latteBuild.dependsOn project.tasks['install']\n\n        def latteTest = project.task('latteTest')\n        latteTest.dependsOn project.tasks['test']\n\n        def latteDeploy = project.task('latteDeploy')\n        latteDeploy.dependsOn project.tasks['uploadArchives']\n    }\n}\n"
  },
  {
    "path": "latte-compiler/settings.gradle",
    "content": "rootProject.name = 'latte-compiler'\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/AbstractScanner.java",
    "content": "package lt.compiler;\n\nimport lt.compiler.lexical.*;\nimport lt.compiler.syntactic.UnknownTokenException;\n\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.util.*;\n\n/**\n * the base scanner.\n */\npublic abstract class AbstractScanner implements Scanner {\n        /**\n         * the scanner creates a new <b>Layer</b> when meets these strings<br>\n         * e.g.<br>\n         * <pre>\n         * lambda = ()-&gt; a+b\n         * </pre>\n         * would be considered as the following token tree<br>\n         * <pre>\n         * [lambda]-[=]-[(]-[)]-[-&gt;]-[|]-[END]\n         *                            |\n         *                            +-[a]-[+]-[b]\n         * </pre>\n         */\n        public final Set<String> LAYER = new HashSet<String>(Arrays.asList(\"->\", \"=>\"));\n        /**\n         * the input should be split when meets these tokens\n         */\n        public final Set<String> SPLIT_X = new HashSet<String>(Arrays.asList(\n                \".\", // class positioning or method access\n                \":\", // type specification or generic extends\n                \"::\", // package::package\n                \"=\", // assignment\n                \"^^\", // pow\n                \"!\", \"&&\", \"||\", // logic\n                \"!=\", \"==\", \"!==\", \"===\", // equals/reference equals\n                \"<\", \">\", \"<=\", \">=\", // comparison or generic extends/super\n                \"+\", \"-\", \"*\", \"/\", \"%\", // operators\n                \"++\", \"--\",\n                \"@\", // @Annotation\n                \"...\", // pass\n                \":::\", // concat\n                \":=\", // assign\n                \"#\", // generator\n                \"<-\" // pattern matching destructing\n        ));\n        public final Set<String> SPLIT_TWO_VAR_OP_THAT_CAN_BE_USED_WITH_ASSIGN = new HashSet<String>(Arrays.asList(\n                \"+\", \"-\", \"*\", \"/\", \"%\",\n                \"<<\", \">>\", \">>>\", // shift\n                \"&\", \"^\", \"|\", \"~\" // bit logic\n        ));\n        /**\n         * symbols that let the scanner know the following input should be scanned as a string<br>\n         * a string starts with one of these symbols and ends with the same symbol.\n         */\n        public final Set<String> STRING = new HashSet<String>(Arrays.asList(\"\\\"\", \"'\", \"`\"));\n        /**\n         * the escape character.\n         */\n        public static String ESCAPE = \"\\\\\";\n        /**\n         * these tokens split the input, but them themselves won't be recorded into the token tree. e.g.<br>\n         * <pre>\n         * list add 1\n         * </pre>\n         * the spaces split the input, but they won't be recorded.\n         */\n        public final Set<String> NO_RECORD = new HashSet<String>(Collections.singletonList(\" \"));\n        /**\n         * the str is considered as ending text. Append an EndingNode to the token tree\n         */\n        public static Set<String> ENDING = new HashSet<String>(Arrays.asList(\",\", \";\"));\n        /**\n         * comment, strings after the token are ignored\n         */\n        public static String COMMENT = \"//\";\n        /**\n         * multiple line comment start symbol\n         */\n        public static String MultipleLineCommentStart = \"/*\";\n        /**\n         * multiple line comment end symbol\n         */\n        public static String MultipleLineCommentEnd = \"*/\";\n        /**\n         * the scanner creates a new layer when meets a <tt>key</tt> and the layer finishes at corresponding <tt>value</tt><br>\n         * <pre>\n         * map = {'name':'cass'}\n         * </pre>\n         * would be considered as the following token tree<br>\n         * <pre>\n         * [map]-[=]-[{]-[|]-[}]-[END]\n         *                |\n         *                --['name']-[:]-['cass']\n         * </pre>\n         */\n        public final Map<String, String> PAIR = new HashMap<String, String>();\n        /**\n         * the input should be split when meets these tokens\n         */\n        public final List<String> SPLIT;\n\n        {\n                PAIR.put(\"(\", \")\"); // arguments/procedures/expressions\n                PAIR.put(\"{\", \"}\"); // map\n                PAIR.put(\"[\", \"]\"); // array[index]\n                PAIR.put(\"<:\", \":>\"); // generic\n\n                SPLIT_X.addAll(NO_RECORD);\n                SPLIT_X.addAll(SPLIT_TWO_VAR_OP_THAT_CAN_BE_USED_WITH_ASSIGN);\n                for (String s : SPLIT_TWO_VAR_OP_THAT_CAN_BE_USED_WITH_ASSIGN) {\n                        SPLIT_X.add(s + \"=\");\n                }\n\n                Set<String> set = new HashSet<String>();\n                set.addAll(LAYER);\n                set.addAll(SPLIT_X);\n                set.addAll(ENDING);\n                set.add(COMMENT);\n                set.add(MultipleLineCommentStart);\n                set.add(MultipleLineCommentEnd);\n                set.addAll(PAIR.keySet());\n                set.addAll(PAIR.values());\n\n                // the longest string is considered first\n                SPLIT = new ArrayList<String>(set);\n                Collections.sort(SPLIT, new Comparator<String>() {\n                        @Override\n                        public int compare(String a, String b) {\n                                return b.length() - a.length();\n                        }\n                });\n                SPLIT.addAll(0, STRING);\n        }\n\n        protected final String fileName;\n        protected final PushLineBackReader reader;\n        protected final Properties properties;\n        protected final ErrorManager err;\n\n        /**\n         * initiate the processor with a reader\n         *\n         * @param fileName   the input text file name\n         * @param reader     text reader\n         * @param properties properties for the Scanner\n         * @param err        error manager\n         */\n        public AbstractScanner(String fileName, Reader reader, Properties properties, ErrorManager err) {\n                this.fileName = fileName;\n                this.properties = properties;\n                this.err = err;\n                if (reader instanceof PushLineBackReader) {\n                        this.reader = (PushLineBackReader) reader;\n                } else {\n                        this.reader = new PushLineBackReader(reader);\n                }\n        }\n\n        /**\n         * scan the text and generate a token tree.\n         *\n         * @return start node\n         * @throws IOException     exception when reading the text\n         * @throws SyntaxException exception when meets a syntax error\n         */\n        @Override\n        public ElementStartNode scan() throws IOException, SyntaxException {\n                Args args = new Args();\n                args.fileName = fileName;\n                ElementStartNode elementStartNode = new ElementStartNode(args, new Indent(0));\n                args.startNodeStack.push(elementStartNode);\n                args.currentLine = properties._LINE_BASE_;\n                scan(args);\n                finalCheck(elementStartNode);\n                return elementStartNode;\n        }\n\n        protected abstract void scan(Args args) throws IOException, SyntaxException;\n\n        /**\n         * remove useless EndingNode and useless StartNode <br>\n         * join double literal<br>\n         * remove `` from the valid names\n         *\n         * @param root root node\n         * @throws UnknownTokenException the token is unknown\n         */\n        protected void finalCheck(ElementStartNode root) throws UnknownTokenException {\n                if (root.hasLinkedNode()) {\n                        Node n = root.getLinkedNode();\n                        while (n != null) {\n                                if (n instanceof ElementStartNode) {\n                                        finalCheck((ElementStartNode) n);\n                                }\n                                if (n instanceof EndingNode && (!n.hasNext() || !(n.next() instanceof Element))) {\n                                        if (n.hasPrevious()) {\n                                                n.previous().setNext(n.next());\n                                        }\n                                        if (n.hasNext()) {\n                                                n.next().setPrevious(n.previous());\n                                        }\n                                } else if (n instanceof Element) {\n                                        ((Element) n).checkWhetherIsValidName();\n                                        if (((Element) n).getContent().equals(\".\")\n                                                && n.hasPrevious()\n                                                && n.hasNext()\n                                                && n.previous() instanceof Element\n                                                && n.next() instanceof Element\n                                                && CompileUtil.isNumber(((Element) n.previous()).getContent())\n                                                && CompileUtil.isNumber(((Element) n.next()).getContent())\n                                                && !((Element) n.previous()).getContent().contains(\".\")\n                                                && !((Element) n.next()).getContent().contains(\".\")) {\n                                                Element pre = (Element) n.previous();\n                                                Element ne = (Element) n.next();\n                                                String s = pre.getContent() + \".\" + ne.getContent();\n                                                Element element = new Element(new Args(), s, getTokenType(s, pre.getLineCol()));\n                                                element.setLineCol(pre.getLineCol());\n\n                                                element.setPrevious(pre.previous());\n                                                element.setNext(ne.next());\n\n                                                element.getLineCol().length = s.length();\n\n                                                if (element.hasPrevious()) {\n                                                        element.previous().setNext(element);\n                                                } else {\n                                                        root.setLinkedNode(element);\n                                                }\n                                                if (element.hasNext()) {\n                                                        element.next().setPrevious(element);\n                                                }\n                                        }\n                                }\n\n                                n = n.next();\n                        }\n                        n = root.getLinkedNode();\n                        while (n != null) {\n                                if (n instanceof ElementStartNode && n.hasNext() && !(n.next() instanceof EndingNode)) {\n                                        Node next = n.next();\n\n                                        Args args = new Args();\n                                        args.previous = n;\n                                        args.currentLine = n.getLineCol().line;\n                                        args.currentCol = n.getLineCol().column;\n                                        EndingNode endingNode = new EndingNode(args, EndingNode.SYNTHETIC);\n\n                                        endingNode.setNext(next);\n                                        next.setPrevious(endingNode);\n                                }\n                                n = n.next();\n                        }\n                } else {\n                        if (root.hasPrevious()) {\n                                root.previous().setNext(root.next());\n                        }\n                        if (root.hasNext()) {\n                                root.next().setPrevious(root.previous());\n                        }\n                }\n        }\n\n        /**\n         * @param str     the token to check type\n         * @param lineCol line column file\n         * @return TokenType or null if it's an unknown token\n         * @throws UnknownTokenException exception\n         */\n        protected final TokenType getTokenType(String str, LineCol lineCol) throws UnknownTokenException {\n                if (CompileUtil.isBoolean(str)) return TokenType.BOOL;\n                if (CompileUtil.isModifier(str)) return TokenType.MODIFIER;\n                if (CompileUtil.isNumber(str)) return TokenType.NUMBER;\n                if (CompileUtil.isString(str)) return TokenType.STRING;\n                if (CompileUtil.isKey(str))\n                        return TokenType.KEY; // however in/is/not are two variable operators, they are marked as keys\n                if (CompileUtil.isSymbol(str)) return TokenType.SYMBOL;\n                if (SPLIT.contains(str)) return TokenType.SYMBOL;\n                if (CompileUtil.isValidName(str)) return TokenType.VALID_NAME;\n                err.UnknownTokenException(str, lineCol);\n                // ignore the token, and return null\n                return null;\n        }\n\n        /**\n         * create an {@link ElementStartNode}\n         *\n         * @param args        args context\n         * @param indentation indentation of the new element start node\n         */\n        protected final void createStartNode(Args args, int indentation) {\n                ElementStartNode elementStartNode = new ElementStartNode(args, new Indent(indentation));\n                args.previous = null;\n                args.startNodeStack.push(elementStartNode);\n        }\n\n        /**\n         * check whether it's the string end. count the `\\`, check whether it%2==0\n         *\n         * @param line  the line\n         * @param index index of `\\`\n         * @return true/false\n         */\n        protected final boolean checkStringEnd(String line, int index) {\n                int count = 0;\n                char[] arr = line.toCharArray();\n                for (int i = index; i > 0; --i) {\n                        char c = arr[i];\n                        if (c == '\\\\') ++count;\n                        else break;\n                }\n                return count % 2 == 0;\n        }\n\n        /**\n         * pop one or more nodes from {@link Args#startNodeStack}, the last popped node's indentation should be the same as required indent\n         *\n         * @param args   args context\n         * @param indent required indentation\n         * @throws UnexpectedTokenException compiling error\n         */\n        protected final void redirectToPairStart(Args args, Indent indent) throws SyntaxException {\n                if (args.startNodeStack.empty()) {\n                        err.SyntaxException(\"possibly incorrect indentation or mismatched brackets\", args.generateLineCol());\n                        return;\n                }\n\n                ElementStartNode startNode = args.startNodeStack.pop();\n\n                // use `==`, compare the reference\n                if (startNode.getIndent() == indent) {\n                        if (startNode.hasNext()) {\n                                throw new LtBug(\"startNode in this step should never have nodes appended\");\n                        }\n                        // do redirect\n                        args.previous = startNode;\n                } else {\n                        if ((startNode.getIndent().getIndent() != Indent.FLEX && startNode.getIndent().getIndent() < indent.getIndent())\n                                || args.startNodeStack.empty()) {\n                                err.SyntaxException(\"possibly incorrect indentation or mismatched brackets\", args.generateLineCol());\n                                return;\n                        }\n                        redirectToPairStart(args, indent);\n                }\n        }\n\n        protected final void redirectToDeeperStartNodeByIndent(Args args, int indent, boolean newLine) throws SyntaxException {\n                if (args.startNodeStack.empty()) {\n                        throw new LtBug(\"this should never happen\");\n                }\n\n                ElementStartNode requiredNode = args.startNodeStack.pop();\n                if (args.startNodeStack.empty()) {\n                        throw new LtBug(\"this should never happen\");\n                }\n                ElementStartNode startNode = args.startNodeStack.lastElement();\n\n                if (startNode.getIndent().getIndent() == indent) {\n                        if (startNode.hasNext()) {\n                                throw new LtBug(\"startNode in this step should never have nodes appended\");\n                        }\n                        // do redirect\n                        args.previous = requiredNode;\n                        if (newLine) {\n                                args.previous = new EndingNode(args, EndingNode.WEAK);\n                        }\n                } else {\n                        if ((startNode.getIndent().getIndent() != Indent.FLEX && startNode.getIndent().getIndent() < indent)\n                                || args.startNodeStack.empty()) {\n                                err.SyntaxException(\"possibly incorrect indentation or mismatched brackets\", args.generateLineCol());\n                                return;\n                        }\n                        redirectToDeeperStartNodeByIndent(args, indent, newLine);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/BraceScanner.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.*;\nimport lt.compiler.syntactic.UnknownTokenException;\n\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.util.*;\n\n/**\n * scan text which is formed up by braces.<br>\n */\npublic class BraceScanner extends AbstractScanner {\n        /**\n         * initiate the processor with a reader\n         *\n         * @param fileName   the input text file name\n         * @param reader     text reader\n         * @param properties properties for the Scanner\n         * @param err        error manager\n         */\n        public BraceScanner(String fileName, Reader reader, Properties properties, ErrorManager err) {\n                super(fileName, reader, properties, err);\n\n                init();\n        }\n\n        private void init() {\n                SPLIT_X.addAll(LAYER);\n                LAYER.clear();\n\n                Set<String> set = new HashSet<String>();\n                set.addAll(LAYER);\n                set.addAll(SPLIT_X);\n                set.addAll(ENDING);\n                set.add(COMMENT);\n                set.add(MultipleLineCommentStart);\n                set.add(MultipleLineCommentEnd);\n                set.addAll(PAIR.keySet());\n                set.addAll(PAIR.values());\n\n                SPLIT.clear();\n                // the longest string is considered first\n                List<String> tmpList = new ArrayList<String>(set);\n                Collections.sort(tmpList, new Comparator<String>() {\n                        @Override\n                        public int compare(String a, String b) {\n                                return b.length() - a.length();\n                        }\n                });\n                SPLIT.addAll(tmpList);\n                SPLIT.addAll(0, STRING);\n        }\n\n        @Override\n        public ElementStartNode scan() throws IOException, SyntaxException {\n                ElementStartNode root = super.scan();\n                finalCheck(root);\n                return root;\n        }\n\n        @Override\n        protected void scan(Args args) throws IOException, SyntaxException {\n                String line = reader.readLine();\n                while (line != null) {\n                        ++args.currentLine;\n\n                        err.putLineRecord(args.fileName, args.currentLine, line);\n\n                        args.currentCol = properties._COLUMN_BASE_;\n                        args.useDefine.clear();\n\n                        if (args.multipleLineComment) {\n                                if (!line.contains(MultipleLineCommentEnd)) {\n                                        line = reader.readLine();\n                                        continue;\n                                } else {\n                                        int subCol = line.indexOf(MultipleLineCommentEnd) + MultipleLineCommentEnd.length();\n                                        line = line.substring(subCol);\n                                        args.currentCol += (subCol + 1);\n                                        args.multipleLineComment = false;\n                                }\n                        }\n\n                        // the line is nothing but comment\n                        if (line.trim().startsWith(COMMENT)) {\n                                line = reader.readLine();\n                                continue;\n                        }\n\n                        int COMMENT_index = line.indexOf(COMMENT);\n                        if (COMMENT_index != -1) {\n                                String pre = line.substring(0, COMMENT_index);\n                                String post = line.substring(COMMENT_index);\n                                for (Map.Entry<String, String> definedEntry : args.defined.entrySet()) {\n                                        String tmp = pre;\n                                        pre = pre.replace(definedEntry.getKey(), definedEntry.getValue());\n                                        if (!tmp.equals(pre)) {\n                                                args.useDefine.put(definedEntry.getKey(), definedEntry.getValue());\n                                        }\n                                }\n                                line = pre + post;\n                        } else {\n                                for (Map.Entry<String, String> definedEntry : args.defined.entrySet()) {\n                                        String tmp = line;\n                                        line = line.replace(definedEntry.getKey(), definedEntry.getValue());\n                                        if (!tmp.equals(line)) {\n                                                args.useDefine.put(definedEntry.getKey(), definedEntry.getValue());\n                                        }\n                                }\n                        }\n\n                        // get front spaces\n                        int spaces = 0;\n                        for (int i = 0; i < line.length(); ++i) {\n                                if (line.charAt(i) != ' ') {\n                                        spaces = i;\n                                        break;\n                                }\n                        }\n\n                        if (args.currentCol == properties._COLUMN_BASE_) {\n                                args.currentCol += spaces + 1;\n                        }\n\n                        // remove front and end spaces\n                        line = line.trim();\n\n                        // check it's an empty line\n                        if (line.isEmpty()) {\n                                line = reader.readLine();\n                                continue;\n                        }\n\n                        // start parsing\n                        scan(line, args);\n\n                        if (!args.multipleLineComment) {\n\n                                if (args.previous instanceof Element) {\n                                        args.previous = new EndingNode(args, EndingNode.WEAK);\n                                }\n                        }\n\n                        line = reader.readLine();\n                }\n        }\n\n        /**\n         * when the given line is not empty, do scanning.<br>\n         * <ol>\n         * <li>check whether the line contains tokens in {@link #SPLIT}<br>\n         * get the most front token, if several tokens are at the same position, then choose the longest one</li>\n         * <li>if the token not found, consider the whole line as one element and append to previous node</li>\n         * <li>else</li>\n         * <li>record text before the token as an element and do appending</li>\n         * <li>check which category the token is in<br>\n         * <ul>\n         * <li>{@link #LAYER} means starts after recording the token, a new ElementStartNode should be started, invoke {@link #createStartNode(Args, int)}</li>\n         * <li>{@link #SPLIT_X}: the previous element and next element should be in the same layer. if it's also among {@link #NO_RECORD}, the token won't be recorded</li>\n         * <li>{@link #STRING}: the next element is a string or a character. these characters should be considered as one element</li>\n         * <li>{@link #ENDING}: append a new {@link EndingNode} to prevent generated nodes being ambiguous. NOTE that it only means the end of an expression or a statement. not the parsing process</li>\n         * <li>{@link #COMMENT}: it's the start of a comment. the following chars would be ignored</li>\n         * <li>{@link #PAIR}: for keys, it will start a new layer. for values, it will end the layer created by the key</li>\n         * </ul>\n         * </li>\n         * </ol><br>\n         * here's an example of how the method works<br>\n         * given the following input:<br>\n         * <pre>\n         * val map={'name':'cass'}\n         * </pre>\n         * <ol>\n         * <li>the most front and longest token is ' ', and ' ' is in {@link #NO_RECORD} ::: <code>val/map={'name':'cass'}</code></li>\n         * <li>the most front and longest token is '=' ::: <code>val/map/=/{'name':'cass'}</code></li>\n         * <li>the most front and longest token is '{', and '{' is a key of {@link #PAIR} ::: <code>val/map/=/{/(LAYER-START/'name':'cass'})</code></li>\n         * <li>the most front and longest token is \"'\", and \"'\" is in {@link #STRING} ::: <code>val/map/=/{/(LAYER-START/'name'/:'cass'})</code></li>\n         * <li>the most front and longest token is ':' ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass'})</code></li>\n         * <li>the most front and longest token is \"'\", and \"'\" is in {@link #STRING} ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass'/})</code></li>\n         * <li>the most front and longest token is \"}\", and '}' is a value of {@link #PAIR} ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass')}</code></li>\n         * </ol><br>\n         * the result is <code>val/map/=/{/(LAYER-START/'name'/:/'cass')}</code><br>\n         * set a breakpoint in the method and focus on variable <tt>line</tt>, you will get exactly the same intermediate results\n         *\n         * @param line line to parse\n         * @param args args context\n         * @throws SyntaxException syntax exceptions, including {@link SyntaxException}, {@link UnexpectedTokenException}\n         */\n        private void scan(String line, Args args) throws SyntaxException {\n                if (line.isEmpty()) return;\n\n                // check multiple line comment\n                if (args.multipleLineComment) {\n                        if (line.contains(MultipleLineCommentEnd)) {\n                                int subCol = line.indexOf(MultipleLineCommentEnd) + MultipleLineCommentEnd.length();\n                                args.currentCol += subCol;\n                                line = line.substring(subCol);\n                                args.multipleLineComment = false;\n                        } else {\n                                return;\n                        }\n                }\n\n                // check SPLIT\n                // find the pattern at minimum location index and with longest words\n                int minIndex = line.length();\n                String token = null; // recorded token\n                for (String s : SPLIT) {\n                        if (line.contains(s)) {\n                                int index = line.indexOf(s);\n                                if (index != -1 && index < minIndex) {\n                                        minIndex = index;\n                                        token = s;\n                                }\n                        }\n                }\n\n                if (token == null) {\n                        if (!line.isEmpty()) {\n                                // not found, simply append whole input to previous\n                                TokenType type = getTokenType(line, args.generateLineCol());\n                                if (type != null) {\n                                        // unknown token, ignore this token\n                                        args.previous = new Element(args, line, type);\n                                        args.currentCol += line.length();\n                                }\n                        }\n                } else {\n                        String copyOfLine = line;\n                        String str = line.substring(0, minIndex);\n                        if (!str.isEmpty()) {\n                                // record text before the token\n                                TokenType type = getTokenType(str, args.generateLineCol());\n                                if (type != null) {\n                                        args.previous = new Element(args, str, type);\n                                }\n                                args.currentCol += str.length();\n                        }\n\n                        if (LAYER.contains(token)) {\n                                // start new layer\n                                args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                createStartNode(args, args.startNodeStack.lastElement().getIndent().getIndent() + 4);\n                        } else if (SPLIT_X.contains(token)) {\n                                // do split check\n                                if (!NO_RECORD.contains(token)) {\n                                        // record this token\n                                        args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                }\n                        } else if (STRING.contains(token)) {\n                                // string literal\n                                int lastIndex = minIndex;\n                                while (true) {\n                                        int index = line.indexOf(token, lastIndex + token.length());\n                                        if (token.equals(\"//\")) {\n                                                while (line.length() > index + 2) {\n                                                        if (line.charAt(index + 2) == '/') {\n                                                                ++index;\n                                                        } else {\n                                                                break;\n                                                        }\n                                                }\n                                        }\n                                        if (line.length() <= 1 || index == -1) {\n                                                err.SyntaxException(\"end of string not found\", args.generateLineCol());\n                                                // assume that the end is line end\n                                                err.debug(\"assume that the \" + token + \" end is line end\");\n\n                                                String generated = line.substring(minIndex) + token;\n\n                                                args.previous = new Element(args, generated, getTokenType(generated, args.generateLineCol()));\n                                                args.currentCol += (index - minIndex) - token.length(); // the length would be added in later steps\n                                                line = line.substring(index + 1);\n\n                                                break;\n                                        } else {\n                                                String c = String.valueOf(line.charAt(index - 1));\n                                                // check\n                                                boolean isStringEnd = !ESCAPE.equals(c) || checkStringEnd(line, index - 1);\n\n                                                if (isStringEnd) {\n                                                        // the string starts at minIndex and ends at index\n                                                        String s = line.substring(minIndex, index + token.length());\n\n                                                        args.previous = new Element(args, s, getTokenType(s, args.generateLineCol()));\n                                                        args.currentCol += (index - minIndex);\n                                                        line = line.substring(index + token.length());\n                                                        break;\n                                                }\n\n                                                lastIndex = index;\n                                        }\n                                }\n                        } else if (ENDING.contains(token)) {\n                                // ending\n                                if (args.previous instanceof Element) {\n                                        args.previous = new EndingNode(args, EndingNode.STRONG);\n                                }\n                        } else if (COMMENT.equals(token)) {\n                                // comment\n                                line = \"\"; // ignore all\n                        } else if (PAIR.containsKey(token)) {\n                                // pair start\n                                args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                createStartNode(args, args.startNodeStack.lastElement().getIndent().getIndent() + 4);\n                                args.pairEntryStack.push(new PairEntry(token, args.startNodeStack.lastElement()));\n                        } else if (PAIR.containsValue(token)) {\n                                // pair end\n                                PairEntry entry = args.pairEntryStack.pop();\n                                String start = entry.key;\n                                if (!token.equals(PAIR.get(start))) {\n                                        err.UnexpectedTokenException(PAIR.get(start), token, args.generateLineCol());\n                                        // assume that the pair ends\n                                        err.debug(\"assume that the pair ends\");\n                                }\n\n                                ElementStartNode startNode = entry.startNode;\n                                if (startNode.hasNext()) {\n                                        err.SyntaxException(\n                                                \"indentation of \" + startNode.next() + \" should be \" + startNode.getIndent(),\n                                                startNode.next().getLineCol());\n                                        // fill the LinkedNode with all nodes after the startNode\n                                        Node n = startNode.next();\n                                        n.setPrevious(null);\n                                        startNode.setNext(null);\n                                        startNode.setLinkedNode(n);\n                                }\n\n                                if (args.startNodeStack.lastElement().getIndent().getIndent() >= startNode.getIndent().getIndent()) {\n                                        redirectToPairStart(args, startNode.getIndent());\n                                } else {\n                                        args.previous = startNode;\n                                }\n                                args.previous = new Element(args, PAIR.get(start), getTokenType(token, args.generateLineCol()));\n                        } else if (token.equals(MultipleLineCommentStart)) {\n                                if (!args.multipleLineComment) {\n                                        args.multipleLineComment = true;\n                                }\n                        } else {\n                                err.UnknownTokenException(token, args.generateLineCol());\n                                // unknown token\n                                // simply ignore the token\n                        }\n\n                        // column\n                        args.currentCol += token.length();\n                        if (copyOfLine.equals(line)) {\n                                // line hasn't changed, do default modification\n                                line = line.substring(minIndex + token.length());\n                        }\n                        // recursively parse\n                        scan(line, args);\n                }\n        }\n\n        @Override\n        protected void finalCheck(ElementStartNode root) throws UnknownTokenException {\n                super.finalCheck(root);\n\n                if (root.hasLinkedNode()) {\n                        Node n = root.getLinkedNode();\n                        // remove redundant start node\n                        if (!n.hasNext() && n instanceof ElementStartNode) {\n                                Node newN = ((ElementStartNode) n).getLinkedNode();\n                                root.setLinkedNode(newN);\n                                n = newN;\n                        }\n\n                        // remove braces\n                        while (n != null) {\n                                if (n instanceof Element) {\n                                        if (((Element) n).getContent().equals(\"{\")\n                                                || ((Element) n).getContent().equals(\"}\")) {\n                                                removeBraces(root, (Element) n);\n                                        }\n                                }\n                                n = n.next();\n                        }\n                }\n        }\n\n        private void removeBraces(ElementStartNode root, Element n) {\n\n                if (n.hasPrevious()) {\n                        n.previous().setNext(n.next());\n                } else if (n.getContent().equals(\"{\")) {\n                        root.setLinkedNode(n.next());\n                }\n                if (n.hasNext()) {\n                        n.next().setPrevious(n.previous());\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/CodeGenerator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.*;\nimport lt.compiler.semantic.builtin.*;\nimport lt.compiler.util.Consts;\nimport lt.compiler.util.LocalVariables;\nimport lt.dependencies.asm.*;\nimport lt.lang.Pointer;\n\nimport java.util.*;\n\n/**\n * The code generator, generate byte code from STypeDef.\n */\npublic class CodeGenerator {\n        private final Set<STypeDef> types;\n        private final Map<String, STypeDef> typeDefMap;\n        private static final int VERSION = Opcodes.V1_6;\n\n        /**\n         * create the code generator with types to generate\n         *\n         * @param types      types\n         * @param typeDefMap a map of type name to its representing object\n         */\n        public CodeGenerator(Set<STypeDef> types, Map<String, STypeDef> typeDefMap) {\n                this.types = types;\n                this.typeDefMap = typeDefMap;\n        }\n\n        /**\n         * visit line number attribute\n         *\n         * @param methodVisitor method visitor\n         * @param lineCol       the line col (can be null)\n         * @param label         the label to visit\n         */\n        private void VisitLineNumber(MethodVisitor methodVisitor, LineCol lineCol, Label label) {\n                if (lineCol == null || lineCol.line <= 0) return;\n                methodVisitor.visitLineNumber(lineCol.line, label);\n        }\n\n        /**\n         * generate modifiers\n         *\n         * @param modifiers modifiers\n         * @return an integer representing modifiers\n         */\n        private int acc(List<SModifier> modifiers) {\n                int acc = 0;\n                for (SModifier m : modifiers) {\n                        acc |= m.flag;\n                }\n                return acc;\n        }\n\n        /**\n         * get type descriptor of the given type.<br>\n         * e.g. <code>Ljava/lang/Object;</code>\n         *\n         * @param type type\n         * @return type descriptor\n         */\n        private String typeToDesc(STypeDef type) {\n                StringBuilder sb = new StringBuilder();\n                if (type instanceof PrimitiveTypeDef) {\n                        if (type.equals(IntTypeDef.get())) sb.append(\"I\");\n                        else if (type.equals(LongTypeDef.get())) sb.append(\"J\");\n                        else if (type.equals(ShortTypeDef.get())) sb.append(\"S\");\n                        else if (type.equals(ByteTypeDef.get())) sb.append(\"B\");\n                        else if (type.equals(BoolTypeDef.get())) sb.append(\"Z\");\n                        else if (type.equals(FloatTypeDef.get())) sb.append(\"F\");\n                        else if (type.equals(DoubleTypeDef.get())) sb.append(\"D\");\n                        else if (type.equals(CharTypeDef.get())) sb.append(\"C\");\n                        else throw new LtBug(\"unknown primitive: \" + type);\n                } else if (type instanceof SArrayTypeDef) {\n                        SArrayTypeDef arr = (SArrayTypeDef) type;\n                        for (int i = 0; i < arr.dimension(); ++i) sb.append(\"[\");\n                        sb.append(typeToDesc(arr.type()));\n                } else if (type.equals(VoidType.get())) {\n                        sb.append(\"V\");\n                } else {\n                        // object L...;\n                        sb.append(\"L\").append(typeToInternalName(type)).append(\";\");\n                }\n                return sb.toString();\n        }\n\n        /**\n         * get internal name of a type.<br>\n         * e.g. <code>java/lang/Object</code>\n         *\n         * @param type type\n         * @return internal name\n         */\n        private String typeToInternalName(STypeDef type) {\n                if (type.equals(NullTypeDef.get())) return \"java/lang/Object\";\n                if (type instanceof SArrayTypeDef) {\n                        return typeToDesc(type);\n                } else return type.fullName().replace(\".\", \"/\");\n        }\n\n        /**\n         * get method descriptor.<br>\n         * e.g. <code>(II)Ljava/lang/Runnable;</code>\n         *\n         * @param returnType return type\n         * @param parameters parameter types\n         * @return method descriptor\n         */\n        private String methodDesc(STypeDef returnType, List<STypeDef> parameters) {\n                StringBuilder desc = new StringBuilder();\n                desc.append(\"(\");\n                for (STypeDef t : parameters) {\n                        desc.append(typeToDesc(t));\n                }\n                desc.append(\")\").append(typeToDesc(returnType));\n                return desc.toString();\n        }\n\n        private String methodDescWithParameters(STypeDef returnType, List<SParameter> parameters) {\n                List<STypeDef> types = new ArrayList<STypeDef>();\n                for (SParameter p : parameters) {\n                        if (p.isCapture() && !p.isUsed()) {\n                                // ignore captured but not used params\n                                continue;\n                        }\n                        types.add(p.type());\n                }\n                return methodDesc(returnType, types);\n        }\n\n        /**\n         * start the generating process.\n         *\n         * @return Map&lt;FileName, byte[]&gt;\n         */\n        public Map<String, byte[]> generate() {\n                Map<String, byte[]> result = new HashMap<String, byte[]>();\n                for (STypeDef type : types) {\n                        ClassWriter classWriter = new SClassWriter(ClassWriter.COMPUTE_FRAMES, typeDefMap);\n\n                        List<SModifier> modifiers;                // modifier\n                        List<Instruction> staticIns;              // <clinit>\n                        List<ExceptionTable> exceptionTables;     // exception table for <clinit>\n                        InvokableMeta staticMeta; // meta\n                        List<SConstructorDef> constructors = null;// constructor\n                        List<SFieldDef> fields;                   // field\n                        List<SMethodDef> methods;                 // method\n                        List<SAnno> annos = type.annos();         // annotations\n                        SClassDef superClass = null;              // super class\n                        List<SInterfaceDef> superInterfaces;      // super interface\n                        String fileName = type.line_col().fileName; // file name\n\n                        classWriter.visitSource(fileName, fileName);\n\n                        if (type instanceof SClassDef) {\n                                modifiers = ((SClassDef) type).modifiers();\n                                staticIns = ((SClassDef) type).staticStatements();\n                                exceptionTables = ((SClassDef) type).staticExceptionTable();\n                                staticMeta = ((SClassDef) type).staticMeta();\n                                constructors = ((SClassDef) type).constructors();\n                                fields = ((SClassDef) type).fields();\n                                methods = ((SClassDef) type).methods();\n                                superInterfaces = ((SClassDef) type).superInterfaces();\n                                superClass = ((SClassDef) type).parent();\n                        } else if (type instanceof SInterfaceDef) {\n                                modifiers = ((SInterfaceDef) type).modifiers();\n                                staticIns = ((SInterfaceDef) type).staticStatements();\n                                exceptionTables = ((SInterfaceDef) type).staticExceptionTable();\n                                staticMeta = ((SInterfaceDef) type).staticMeta();\n                                fields = ((SInterfaceDef) type).fields();\n                                methods = ((SInterfaceDef) type).methods();\n                                superInterfaces = ((SInterfaceDef) type).superInterfaces();\n                        } else {\n                                // generate annotation\n                                generateAnnotation(classWriter, (SAnnoDef) type);\n                                classWriter.visitEnd();\n                                result.put(type.fullName(), classWriter.toByteArray());\n                                continue;\n                        }\n\n                        String[] interfaces = new String[superInterfaces.size()];\n                        for (int i = 0; i < interfaces.length; ++i) {\n                                interfaces[i] = typeToInternalName(superInterfaces.get(i));\n                        }\n\n                        classWriter.visit(VERSION, acc(modifiers) | (type instanceof SClassDef ? 0 : Opcodes.ACC_INTERFACE),\n                                typeToInternalName(type), null, superClass == null ? \"java/lang/Object\" : typeToInternalName(superClass), interfaces);\n\n                        // annotations\n                        for (SAnno anno : annos) {\n                                AnnotationVisitor annotationVisitor = classWriter.visitAnnotation(typeToDesc(anno.type()),\n                                        annotationIsVisible(anno));\n                                buildAnnotation(annotationVisitor, anno);\n                        }\n\n                        buildStatic(classWriter, staticIns, exceptionTables, staticMeta);\n                        buildField(classWriter, fields);\n                        if (constructors != null) {\n                                buildConstructor(classWriter, constructors);\n                        }\n                        buildMethod(classWriter, methods);\n                        classWriter.visitEnd();\n\n                        result.put(type.fullName(), classWriter.toByteArray());\n                }\n                return result;\n        }\n\n        private void generateAnnotation(ClassWriter classWriter, SAnnoDef sAnnoDef) {\n                classWriter.visit(VERSION,\n                        Opcodes.ACC_INTERFACE | Opcodes.ACC_ANNOTATION | Opcodes.ACC_ABSTRACT | Opcodes.ACC_PUBLIC,\n                        typeToInternalName(sAnnoDef), null, \"java/lang/Object\",\n                        new String[]{\"java/lang/annotation/Annotation\"});\n\n                // annontations\n                for (SAnno anno : sAnnoDef.annos()) {\n                        AnnotationVisitor annotationVisitor = classWriter.visitAnnotation(typeToDesc(anno.type()),\n                                annotationIsVisible(anno));\n                        buildAnnotation(annotationVisitor, anno);\n                }\n\n                // annotation fields (which are generated as methods on jvm)\n                for (SAnnoField f : sAnnoDef.annoFields()) {\n                        int acc = Opcodes.ACC_PUBLIC | Opcodes.ACC_ABSTRACT;\n                        MethodVisitor methodVisitor = classWriter.visitMethod(\n                                acc, f.name(), methodDesc(f.type(), Collections.<STypeDef>emptyList()),\n                                null, new String[0]\n                        );\n                        if (f.defaultValue() != null) {\n                                AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotationDefault();\n                                buildAnnotationValue(annotationVisitor, f.name(), f.defaultValue());\n                        }\n                        methodVisitor.visitEnd();\n                }\n        }\n\n        /**\n         * build new<.br>\n         * <br>\n         * <code>\n         * new TYPE<br>\n         * dup<br>\n         * InvokeSpecial\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param aNew          Ins.New\n         */\n        private void buildNew(MethodVisitor methodVisitor, CodeInfo info, Ins.New aNew) {\n                methodVisitor.visitTypeInsn(Opcodes.NEW, typeToInternalName(aNew.type()));\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitInsn(Opcodes.DUP);\n                info.push(CodeInfo.Size._1);\n                for (Value v : aNew.args()) {\n                        buildValueAccess(methodVisitor, info, v, true);\n                }\n\n                Label label = new Label();\n                methodVisitor.visitLabel(label);\n\n                methodVisitor.visitMethodInsn(\n                        Opcodes.INVOKESPECIAL,\n                        typeToInternalName(aNew.type()),\n                        \"<init>\",\n                        methodDescWithParameters(\n                                VoidType.get(),\n                                aNew.constructor().getParameters()),\n                        false);\n                info.pop(1 + aNew.args().size());\n\n                VisitLineNumber(methodVisitor, aNew.line_col(), label);\n        }\n\n        /**\n         * build cast.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ------- original value<br>\n         * castIns\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param cast          Ins.Cast\n         */\n        private void buildCast(MethodVisitor methodVisitor, CodeInfo info, Ins.Cast cast) {\n                buildValueAccess(methodVisitor, info, cast.value(), true);\n\n                Label label = new Label();\n                methodVisitor.visitLabel(label);\n\n                methodVisitor.visitInsn(cast.castMode());\n                if (cast.castMode() == Ins.Cast.CAST_FLOAT_TO_DOUBLE\n                        || cast.castMode() == Ins.Cast.CAST_INT_TO_DOUBLE\n                        || cast.castMode() == Ins.Cast.CAST_LONG_TO_DOUBLE) {\n                        info.pop(1);\n                        info.push(CodeInfo.Size._2);\n                } else {\n                        info.pop(1);\n                        info.push(CodeInfo.Size._1);\n                }\n\n                VisitLineNumber(methodVisitor, cast.line_col(), label);\n        }\n\n        /**\n         * build two variable operation.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ------ a<br>\n         * buildValueAccess ------ b<br>\n         * twoVarOpIns ----------- operator\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param twoVarOp      Ins.TwoVarOp\n         */\n        private void buildTwoVarOp(MethodVisitor methodVisitor, CodeInfo info, Ins.TwoVarOp twoVarOp) {\n                buildValueAccess(methodVisitor, info, twoVarOp.a(), true);\n                buildValueAccess(methodVisitor, info, twoVarOp.b(), true);\n                methodVisitor.visitInsn(twoVarOp.op());\n                info.pop(2);\n                if (twoVarOp.op() == Ins.TwoVarOp.Dadd\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Ddiv\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Dmul\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Drem\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Dsub\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Ladd\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Land\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Ldiv\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lmul\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lor\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lrem\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lshl\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lshr\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lsub\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lushr\n                        ||\n                        twoVarOp.op() == Ins.TwoVarOp.Lxor)\n\n                        info.push(CodeInfo.Size._2);\n                else info.push(CodeInfo.Size._1);\n        }\n\n        /**\n         * build logicAND.<br>\n         * <br>\n         * <code>\n         * buildValueAccess<br>\n         * IfEq flag ----------- false<br>\n         * buildValueAccess<br>\n         * IfEq flag ----------- false<br>\n         * IConst_1<br>\n         * goto nop<br>\n         * flag: IConst_0<br>\n         * nop\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param logicAnd      Ins.LogicAnd\n         */\n        private void buildLogicAnd(MethodVisitor methodVisitor, CodeInfo info, Ins.LogicAnd logicAnd) {\n                /*\n                 * if eq b1 goto flag (if b1==false goto flag)\n                 * if eq b2 goto flag (if b2==false goto flag)\n                 * true               (push true into stack)\n                 * goto nop           (goto nop, skip `else` branch)\n                 * flag: false        (flag: push false into stack)\n                 * nop                (nop)\n                 */\n                // b1\n                buildValueAccess(methodVisitor, info, logicAnd.b1(), true);\n                // if eq goto flag\n                Label flag = new Label();\n                methodVisitor.visitJumpInsn(Opcodes.IFEQ, flag);\n                info.pop(1);\n                // b2\n                buildValueAccess(methodVisitor, info, logicAnd.b2(), true);\n                // if eq goto flag\n                methodVisitor.visitJumpInsn(Opcodes.IFEQ, flag);\n                info.pop(1);\n                // true\n                methodVisitor.visitInsn(Opcodes.ICONST_1);\n                // goto nop\n                Label nop = new Label();\n                methodVisitor.visitJumpInsn(Opcodes.GOTO, nop);\n                // flag: false\n                methodVisitor.visitLabel(flag);\n                methodVisitor.visitInsn(Opcodes.ICONST_0);\n                // nop\n                methodVisitor.visitLabel(nop);\n                methodVisitor.visitInsn(Opcodes.NOP);\n\n                info.push(CodeInfo.Size._1); // push true or false into stack\n        }\n\n        /**\n         * eval `left` and cast to bool\n         * check if it's true\n         * if true then return the `left` value\n         * else ignore the `left`\n         * do eval and return `right`\n         * <p>\n         * <p>\n         * v1 (stack is [v1])\n         * dup ([v1 v1]\n         * castToBool ([v1 I])\n         * if ne goto nop ([v1]) // I is 1\n         * pop ([])\n         * v2 ([v2])\n         * nop (v1/v2)\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param logicOr       Ins.LogicOr\n         */\n        private void buildLogicOr(MethodVisitor methodVisitor, CodeInfo info, Ins.LogicOr logicOr) {\n                buildValueAccess(methodVisitor, info, logicOr.v1(), true); // [v1]\n                methodVisitor.visitInsn(Opcodes.DUP); // dup [v1 v1]\n                info.push(CodeInfo.Size._1);\n                // invoke castToBool\n                SMethodDef castToBool = logicOr.getCastToBool();\n                methodVisitor.visitMethodInsn(\n                        Opcodes.INVOKESTATIC,\n                        typeToInternalName(castToBool.declaringType()),\n                        castToBool.name(),\n                        methodDescWithParameters(\n                                castToBool.getReturnType(),\n                                castToBool.getParameters()),\n                        false);\n                info.pop(1);\n                info.push(CodeInfo.Size._1);\n                // [v1 I]\n                // if ne goto flag\n                Label flag = new Label();\n                methodVisitor.visitJumpInsn(Opcodes.IFNE, flag); // goto flag(nop)\n                info.pop(1);\n                // pop\n                methodVisitor.visitInsn(Opcodes.POP); // [(empty stack)]\n                info.pop(1);\n                // v2\n                buildValueAccess(methodVisitor, info, logicOr.v2(), true); // v2\n                // flag: nop\n                methodVisitor.visitLabel(flag);\n                methodVisitor.visitInsn(Opcodes.NOP);\n        }\n\n        /**\n         * build TALoad.<br>\n         * <br>\n         * <code>\n         * buildValueAccess<br>\n         * buildValueAccess -------- the array<br>\n         * buildValueAccess -------- the index<br>\n         * TALoad\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param TALoad        Ins.TALoad\n         */\n        private void buildTALoad(MethodVisitor methodVisitor, CodeInfo info, Ins.TALoad TALoad) {\n                buildValueAccess(methodVisitor, info, TALoad.arr(), true);\n                buildValueAccess(methodVisitor, info, TALoad.index(), true);\n\n                Label label = new Label();\n                methodVisitor.visitLabel(label);\n\n                methodVisitor.visitInsn(TALoad.mode());\n                info.pop(2);\n                info.push(CodeInfo.Size._1);\n\n                VisitLineNumber(methodVisitor, TALoad.line_col(), label);\n        }\n\n        /**\n         * build OneVarOp.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ------ the value<br>\n         * OneVarOp\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param oneVarOp      Ins.OneVarOp\n         */\n        private void buildOneVarOp(MethodVisitor methodVisitor, CodeInfo info, Ins.OneVarOp oneVarOp) {\n                buildValueAccess(methodVisitor, info, oneVarOp.value(), true);\n                methodVisitor.visitInsn(oneVarOp.op());\n\n                if (oneVarOp.op() == Ins.OneVarOp.Dneg\n                        || oneVarOp.op() == Ins.OneVarOp.Lneg) {\n                        info.pop(1);\n                        info.push(CodeInfo.Size._2);\n                } else {\n                        info.pop(1);\n                        info.push(CodeInfo.Size._1);\n                }\n        }\n\n        /**\n         * build NewArray.<br>\n         * <br>\n         * <code>\n         * buildPrimitive ------ array length<br>\n         * NewArray<br>\n         * foreach v in initValues<br>\n         * &nbsp;&nbsp;DUP<br>\n         * &nbsp;&nbsp;Ldc index<br>\n         * &nbsp;&nbsp;buildValueAccess ---- the value to assign in<br>\n         * &nbsp;&nbsp;TAStore\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param newArray      Ins.NewArray\n         */\n        private void buildNewArray(MethodVisitor methodVisitor, CodeInfo info, Ins.NewArray newArray) {\n                buildPrimitive(methodVisitor, info, newArray.count());\n                methodVisitor.visitIntInsn(Opcodes.NEWARRAY, newArray.mode());\n                // pop 1 and push 1\n                int i = 0;\n                for (Value v : newArray.initValues()) {\n                        methodVisitor.visitInsn(Opcodes.DUP); // array ref\n                        info.push(CodeInfo.Size._1);\n                        methodVisitor.visitLdcInsn(i); // index\n                        info.push(CodeInfo.Size._1);\n                        buildValueAccess(methodVisitor, info, v, true); // value\n\n                        methodVisitor.visitInsn(newArray.storeMode());\n                        info.pop(3);\n                        ++i;\n                }\n                // stack have one element (the array)\n        }\n\n        /**\n         * build ANewArray.<br>\n         * <br>\n         * <code>\n         * buildPrimitive ---- array length<br>\n         * ANewArray Type<br>\n         * foreach v in initValues<br>\n         * &nbsp;&nbsp;DUP<br>\n         * &nbsp;&nbsp;Ldc ---- index<br>\n         * &nbsp;&nbsp;buildValueAccess ---- the value to set<br>\n         * &nbsp;&nbsp;AAStore\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param aNewArray     Ins.ANewArray\n         */\n        private void buildANewArray(MethodVisitor methodVisitor, CodeInfo info, Ins.ANewArray aNewArray) {\n                buildPrimitive(methodVisitor, info, aNewArray.count());\n                methodVisitor.visitTypeInsn(Opcodes.ANEWARRAY, typeToInternalName(aNewArray.componentType()));\n                // pop 1 and push 1\n                int i = 0;\n                for (Value v : aNewArray.initValues()) {\n                        methodVisitor.visitInsn(Opcodes.DUP); // array ref\n                        info.push(CodeInfo.Size._1);\n                        methodVisitor.visitLdcInsn(i); // index\n                        info.push(CodeInfo.Size._1);\n                        buildValueAccess(methodVisitor, info, v, true); // value\n\n                        methodVisitor.visitInsn(Opcodes.AASTORE);\n                        info.pop(3);\n                        ++i;\n                }\n                // stack have one element (the array)\n        }\n\n        /**\n         * build NewList.<br>\n         * <br>\n         * <code>\n         * NEW Type<br>\n         * DUP<br>\n         * InvokeSpecial init<br>\n         * foreach v in initValues<br>\n         * &nbsp;&nbsp;DUP<br>\n         * &nbsp;&nbsp;buildValueAccess ----- value to add<br>\n         * &nbsp;&nbsp;InvokeVirtual add(Object)\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param newList       Ins.NewList\n         */\n        private void buildNewList(MethodVisitor methodVisitor, CodeInfo info, Ins.NewList newList) {\n                // newList is LinkedList\n                methodVisitor.visitTypeInsn(Opcodes.NEW, typeToInternalName(newList.type()));\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitInsn(Opcodes.DUP);\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, typeToInternalName(newList.type()), \"<init>\", \"()V\", false);\n                info.pop(1);\n\n                for (Value v : newList.initValues()) {\n                        methodVisitor.visitInsn(Opcodes.DUP); // list ref\n                        info.push(CodeInfo.Size._1);\n                        buildValueAccess(methodVisitor, info, v, true); // arg\n                        methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE, \"java/util/List\", \"add\", \"(Ljava/lang/Object;)Z\", true);\n                        info.pop(2);\n                        info.push(CodeInfo.Size._1); // the add result (boolean add(Object))\n                        methodVisitor.visitInsn(Opcodes.POP);\n                        info.pop(1);\n                }\n                // stack have one element (the list)\n        }\n\n        /**\n         * build NewMap.<br>\n         * <br>\n         * <code>\n         * New Type<br>\n         * DUP<br>\n         * InvokeSpecial init<br>\n         * foreach k,v in initValues<br>\n         * &nbsp;&nbsp;DUP<br>\n         * &nbsp;&nbsp;buildValueAccess ---- key<br>\n         * &nbsp;&nbsp;buildValueAccess ---- value<br>\n         * &nbsp;&nbsp;InvokeVirtual ---- put(Object,Object)\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param newMap        Ins.NewMap\n         */\n        private void buildNewMap(MethodVisitor methodVisitor, CodeInfo info, Ins.NewMap newMap) {\n                methodVisitor.visitTypeInsn(Opcodes.NEW, typeToInternalName(newMap.type()));\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitInsn(Opcodes.DUP);\n                info.push(CodeInfo.Size._1);\n\n                methodVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL,\n                        typeToInternalName(newMap.type()),\n                        \"<init>\",\n                        \"()V\", false);\n                info.pop(1);\n\n                for (Map.Entry<Value, Value> entry : newMap.initValues().entrySet()) {\n                        methodVisitor.visitInsn(Opcodes.DUP);\n                        info.push(CodeInfo.Size._1);\n                        buildValueAccess(methodVisitor, info, entry.getKey(), true);\n                        buildValueAccess(methodVisitor, info, entry.getValue(), true);\n\n                        methodVisitor.visitMethodInsn(Opcodes.INVOKEINTERFACE,\n                                \"java/util/Map\",\n                                \"put\",\n                                \"(Ljava/lang/Object;Ljava/lang/Object;)Ljava/lang/Object;\", true);\n                        info.pop(3);\n                        info.push(CodeInfo.Size._1); // the put result (Object put(Object,Object))\n                        methodVisitor.visitInsn(Opcodes.POP);\n                        info.pop(1);\n                }\n                // stack have one element (the map)\n        }\n\n        /**\n         * build value pack\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param value         the value pack\n         * @param requireValue  require a value\n         */\n        private void buildValuePack(MethodVisitor methodVisitor, CodeInfo info, ValuePack value, boolean requireValue) {\n                int depth = info.getCurrentStackDepth();\n                List<Instruction> instructions = value.instructions();\n                for (int i = 0; i < instructions.size() - 1; ++i) {\n                        buildOneIns(methodVisitor, info, instructions.get(i), true);\n\n                        if (value.autoPop()) {\n                                while (info.getCurrentStackDepth() != depth) {\n                                        if (info.peekSize() == CodeInfo.Size._1) {\n                                                methodVisitor.visitInsn(Opcodes.POP);\n                                        } else {\n                                                methodVisitor.visitInsn(Opcodes.POP2);\n                                        }\n                                        info.pop(1);\n                                }\n                        }\n                }\n\n                Instruction ins = instructions.get(instructions.size() - 1);\n                boolean buildLastStmt;\n                if (!value.autoPop()) {\n                        // not auto pop\n                        buildLastStmt = true;\n                } else {\n                        // auto pop\n                        if (requireValue) {\n                                // require a value\n                                buildLastStmt = true;\n                        } else {\n                                // doesn't require a value\n                                if (ins instanceof ReadOnly) {\n                                        // read only\n                                        buildLastStmt = false;\n                                } else {\n                                        // not read only\n                                        // check LtRuntime.getField and Unit.get\n                                        if (ins instanceof Ins.InvokeStatic) {\n                                                Ins.InvokeStatic is = (Ins.InvokeStatic) ins;\n                                                SMethodDef theMethod = (SMethodDef) is.invokable();\n                                                if (\n                                                        theMethod.name().equals(\"getField\")\n                                                                &&\n                                                                theMethod.declaringType().fullName().equals(\"lt.runtime.LtRuntime\")) {\n                                                        // lt.runtime.LtRuntime.getField\n                                                        buildLastStmt = false;\n                                                } else if (\n                                                        theMethod.name().equals(\"get\")\n                                                                &&\n                                                                theMethod.declaringType().fullName().equals(\"lt.lang.Unit\")) {\n                                                        // lt.lang.Unit.get\n                                                        buildLastStmt = false;\n                                                } else {\n                                                        buildLastStmt = true;\n                                                }\n                                        } else {\n                                                buildLastStmt = true;\n                                        }\n                                }\n                        }\n                }\n\n                if (buildLastStmt) {\n                        buildOneIns(methodVisitor, info, ins, requireValue);\n                }\n        }\n\n        private int calculateIndexForLocalVariable(LeftValue theVar, SemanticScope scope, CodeInfo info) {\n                return LocalVariables.calculateIndexForLocalVariable(theVar, scope, info.isStatic());\n        }\n\n        /**\n         * build Value.\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param value         the value to build\n         * @param requireValue  requires a value when generating {@link ValuePack}\n         * @see Value\n         * @see lt.compiler.semantic.Ins.This\n         * @see lt.compiler.semantic.Ins.GetStatic\n         * @see lt.compiler.semantic.Ins.TLoad\n         * @see StringConstantValue\n         * @see PrimitiveValue\n         * @see lt.compiler.semantic.Ins.Invoke\n         * @see lt.compiler.semantic.Ins.New\n         * @see lt.compiler.semantic.Ins.Cast\n         * @see lt.compiler.semantic.Ins.TwoVarOp\n         * @see ValuePack\n         * @see lt.compiler.semantic.Ins.GetField\n         * @see lt.compiler.semantic.Ins.LogicAnd\n         * @see lt.compiler.semantic.Ins.LogicOr\n         * @see lt.compiler.semantic.Ins.GetClass\n         * @see lt.compiler.semantic.Ins.TALoad\n         * @see NullValue\n         * @see lt.compiler.semantic.Ins.ArrayLength\n         * @see lt.compiler.semantic.Ins.OneVarOp\n         * @see lt.compiler.semantic.Ins.NewArray\n         * @see lt.compiler.semantic.Ins.ANewArray\n         * @see lt.compiler.semantic.Ins.NewList\n         * @see lt.compiler.semantic.Ins.NewMap\n         * @see lt.compiler.semantic.Ins.CheckCast\n         */\n        private void buildValueAccess(MethodVisitor methodVisitor, CodeInfo info, Value value, boolean requireValue) {\n                if (value instanceof Ins.This) {\n                        methodVisitor.visitVarInsn(Opcodes.ALOAD, 0);\n                        info.push(CodeInfo.Size._1);\n                } else if (value instanceof Ins.GetStatic) {\n                        // getStatic\n                        Ins.GetStatic getStatic = (Ins.GetStatic) value;\n\n                        Label label = new Label();\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitFieldInsn(\n                                Opcodes.GETSTATIC,\n                                typeToInternalName(getStatic.field().declaringType()),\n                                getStatic.field().name(), typeToDesc(getStatic.field().type()));\n\n                        if (getStatic.field().type().equals(DoubleTypeDef.get())\n                                || (getStatic.field().type().equals(LongTypeDef.get())))\n                                info.push(CodeInfo.Size._2);\n                        else info.push(CodeInfo.Size._1);\n\n                        VisitLineNumber(methodVisitor, ((Ins.GetStatic) value).line_col(), label);\n                } else if (value instanceof Ins.TLoad) {\n                        // tLoad\n                        Ins.TLoad tLoad = (Ins.TLoad) value;\n\n                        Label label = new Label();\n                        methodVisitor.visitLabel(label);\n\n                        int index = calculateIndexForLocalVariable(tLoad.value(), tLoad.getScope(), info);\n                        methodVisitor.visitVarInsn(tLoad.mode(), index);\n                        if (tLoad.mode() == Ins.TLoad.Dload || tLoad.mode() == Ins.TLoad.Lload)\n                                info.push(CodeInfo.Size._2);\n                        else info.push(CodeInfo.Size._1);\n\n                        VisitLineNumber(methodVisitor, ((Ins.TLoad) value).line_col(), label);\n                } else if (value instanceof StringConstantValue) {\n                        methodVisitor.visitLdcInsn(((StringConstantValue) value).getStr());\n                        info.push(CodeInfo.Size._1);\n                } else if (value instanceof PrimitiveValue) {\n                        buildPrimitive(methodVisitor, info, (PrimitiveValue) value);\n                } else if (value instanceof Ins.Invoke) {\n                        buildInvoke(methodVisitor, info, (Ins.Invoke) value, requireValue);\n                } else if (value instanceof Ins.New) {\n                        buildNew(methodVisitor, info, (Ins.New) value);\n                } else if (value instanceof Ins.Cast) {\n                        buildCast(methodVisitor, info, (Ins.Cast) value);\n                } else if (value instanceof Ins.TwoVarOp) {\n                        buildTwoVarOp(methodVisitor, info, (Ins.TwoVarOp) value);\n                } else if (value instanceof ValuePack) {\n                        buildValuePack(methodVisitor, info, (ValuePack) value, requireValue);\n                } else if (value instanceof Ins.GetField) {\n                        buildGetField(methodVisitor, info, (Ins.GetField) value);\n                } else if (value instanceof Ins.LogicAnd) {\n                        buildLogicAnd(methodVisitor, info, (Ins.LogicAnd) value);\n                } else if (value instanceof Ins.LogicOr) {\n                        buildLogicOr(methodVisitor, info, (Ins.LogicOr) value);\n                } else if (value instanceof Ins.GetClass) {\n                        STypeDef targetType = ((Ins.GetClass) value).targetType();\n\n                        if (targetType.equals(VoidType.get())) {\n                                methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, \"java/lang/Void\", \"TYPE\", \"Ljava/lang/Class;\");\n                        } else if (targetType instanceof PrimitiveTypeDef) {\n                                String TYPE = \"TYPE\";\n                                String CLASS = \"Ljava/lang/Class;\";\n                                String OWNER;\n\n                                if (targetType.equals(IntTypeDef.get())) {\n                                        OWNER = \"java/lang/Integer\";\n                                } else if (targetType.equals(ShortTypeDef.get())) {\n                                        OWNER = \"java/lang/Short\";\n                                } else if (targetType.equals(ByteTypeDef.get())) {\n                                        OWNER = \"java/lang/Byte\";\n                                } else if (targetType.equals(BoolTypeDef.get())) {\n                                        OWNER = \"java/lang/Boolean\";\n                                } else if (targetType.equals(CharTypeDef.get())) {\n                                        OWNER = \"java/lang/Character\";\n                                } else if (targetType.equals(LongTypeDef.get())) {\n                                        OWNER = \"java/lang/Long\";\n                                } else if (targetType.equals(FloatTypeDef.get())) {\n                                        OWNER = \"java/lang/Float\";\n                                } else if (targetType.equals(DoubleTypeDef.get())) {\n                                        OWNER = \"java/lang/Double\";\n                                } else throw new LtBug(\"unknown primitive type \" + targetType);\n\n                                methodVisitor.visitFieldInsn(Opcodes.GETSTATIC, OWNER, TYPE, CLASS);\n                        } else {\n                                methodVisitor.visitLdcInsn(Type.getObjectType(\n                                        typeToInternalName(targetType)\n                                ));\n                        }\n                        info.push(CodeInfo.Size._1);\n                } else if (value instanceof Ins.TALoad) {\n                        buildTALoad(methodVisitor, info, (Ins.TALoad) value);\n                } else if (value instanceof NullValue) {\n                        methodVisitor.visitInsn(Opcodes.ACONST_NULL);\n                        info.push(CodeInfo.Size._1);\n                } else if (value instanceof Ins.ArrayLength) {\n                        buildValueAccess(methodVisitor, info, ((Ins.ArrayLength) value).arrayValue(), true);\n                        methodVisitor.visitInsn(Opcodes.ARRAYLENGTH);\n                        // pop 1 and push 1\n                } else if (value instanceof Ins.OneVarOp) {\n                        buildOneVarOp(methodVisitor, info, (Ins.OneVarOp) value);\n                } else if (value instanceof Ins.NewArray) {\n                        buildNewArray(methodVisitor, info, (Ins.NewArray) value);\n                } else if (value instanceof Ins.ANewArray) {\n                        buildANewArray(methodVisitor, info, (Ins.ANewArray) value);\n                } else if (value instanceof Ins.NewList) {\n                        buildNewList(methodVisitor, info, (Ins.NewList) value);\n                } else if (value instanceof Ins.NewMap) {\n                        buildNewMap(methodVisitor, info, (Ins.NewMap) value);\n                } else if (value instanceof Ins.CheckCast) {\n                        buildValueAccess(methodVisitor, info, ((Ins.CheckCast) value).theValueToCheck(), true);\n\n                        Label label = new Label();\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitTypeInsn(Opcodes.CHECKCAST, typeToInternalName(value.type()));\n                        info.pop(1);\n                        info.push(CodeInfo.Size._1);\n\n                        VisitLineNumber(methodVisitor, ((Ins.CheckCast) value).line_col(), label);\n\n                } else if (value instanceof Ins.InstanceOf) {\n                        buildValueAccess(methodVisitor, info, ((Ins.InstanceOf) value).object(), true);\n                        methodVisitor.visitTypeInsn(Opcodes.INSTANCEOF,\n                                typeToInternalName(((Ins.InstanceOf) value).aClass().targetType()));\n                        info.pop(1);\n                        info.push(CodeInfo.Size._1);\n                } else if (value instanceof ValueAnotherType) {\n                        buildValueAccess(methodVisitor, info, ((ValueAnotherType) value).value(), requireValue);\n                } else if (value instanceof Ins.PointerGetCastHelper) {\n                        buildPointerCastHelper(methodVisitor, info, (Ins.PointerGetCastHelper) value, requireValue);\n                } else {\n                        throw new LtBug(\"unknown value \" + value);\n                }\n        }\n\n        private void buildPointerCastHelper(MethodVisitor methodVisitor, CodeInfo info, Ins.PointerGetCastHelper h, boolean requireValue) {\n                if (!requireValue) {\n                        // ignore the invocation if not requiring a value\n                        return;\n                }\n\n                if (canOptimizePointerRetrieving(h.before(), info)) {\n                        buildValueAccess(methodVisitor, info, h.before(), true);\n                } else {\n                        buildValueAccess(methodVisitor, info, h.after(), true);\n                }\n        }\n\n        /**\n         * build Primitive.\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param p             primitive value\n         * @see PrimitiveValue\n         * @see IntValue\n         * @see ShortValue\n         * @see ByteValue\n         * @see BoolValue\n         * @see CharValue\n         * @see LongValue\n         * @see FloatValue\n         * @see DoubleValue\n         */\n        private void buildPrimitive(MethodVisitor methodVisitor, CodeInfo info, PrimitiveValue p) {\n                if (p instanceof IntValue) {\n                        methodVisitor.visitLdcInsn(((IntValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof ShortValue) {\n                        methodVisitor.visitLdcInsn(((ShortValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof ByteValue) {\n                        methodVisitor.visitLdcInsn(((ByteValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof BoolValue) {\n                        methodVisitor.visitLdcInsn(((BoolValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof CharValue) {\n                        methodVisitor.visitLdcInsn(((CharValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof LongValue) {\n                        methodVisitor.visitLdcInsn(((LongValue) p).getValue());\n                        info.push(CodeInfo.Size._2);\n                } else if (p instanceof FloatValue) {\n                        methodVisitor.visitLdcInsn(((FloatValue) p).getValue());\n                        info.push(CodeInfo.Size._1);\n                } else if (p instanceof DoubleValue) {\n                        methodVisitor.visitLdcInsn(((DoubleValue) p).getValue());\n                        info.push(CodeInfo.Size._2);\n                } else throw new LtBug(\"unknown primitive value \" + p);\n        }\n\n        /**\n         * build unit if invokable return a void type\n         *\n         * @param invokable the invokable object\n         * @param info      code info\n         */\n        private void buildUnitWhenInvokeVoid(SInvokable invokable, CodeInfo info) {\n                if (!invokable.getReturnType().equals(VoidType.get())) {\n                        STypeDef typeDef = invokable.getReturnType();\n                        if (typeDef.equals(DoubleTypeDef.get()) || typeDef.equals(LongTypeDef.get()))\n                                info.push(CodeInfo.Size._2);\n                        else info.push(CodeInfo.Size._1);\n                }\n        }\n\n        private void _buildOptimizedPointerTLoad(MethodVisitor methodVisitor, CodeInfo info, int index, STypeDef type) {\n                if (type instanceof PrimitiveTypeDef) {\n                        if (type.equals(DoubleTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.DLOAD, index);\n                                info.push(CodeInfo.Size._2);\n                        } else if (type.equals(LongTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.LLOAD, index);\n                                info.push(CodeInfo.Size._2);\n                        } else if (type.equals(FloatTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.FLOAD, index);\n                                info.push(CodeInfo.Size._1);\n                        } else {\n                                methodVisitor.visitVarInsn(Opcodes.ILOAD, index);\n                                info.push(CodeInfo.Size._1);\n                        }\n                } else {\n                        methodVisitor.visitVarInsn(Opcodes.ALOAD, index);\n                        info.push(CodeInfo.Size._1);\n                }\n        }\n\n        private void _buildUnbox(MethodVisitor methodVisitor, CodeInfo info, Value v) {\n                if (v.type() instanceof PrimitiveTypeDef) {\n                        buildValueAccess(methodVisitor, info, v, true);\n                } else if (v instanceof Ins.InvokeStatic && ((Ins.InvokeStatic) v).invokable() instanceof SMethodDef &&\n                        ((SMethodDef) ((Ins.InvokeStatic) v).invokable()).name().equals(\"valueOf\") &&\n                        Arrays.asList(\n                                \"java.lang.Double\",\n                                \"java.lang.Long\",\n                                \"java.lang.Float\",\n                                \"java.lang.Integer\",\n                                \"java.lang.Short\",\n                                \"java.lang.Byte\",\n                                \"java.lang.Character\",\n                                \"java.lang.Boolean\"\n                        ).contains(((Ins.InvokeStatic) v).invokable().declaringType().fullName())) {\n\n                        Value primitiveValue = ((Ins.InvokeStatic) v).arguments().get(0);\n                        buildValueAccess(methodVisitor, info, primitiveValue, true);\n                } else {\n                        buildValueAccess(methodVisitor, info, v, true);\n                        if (v.type().fullName().equals(\"java.lang.Double\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Double\", \"doubleValue\", \"()D\", false);\n                                info.push(CodeInfo.Size._2);\n                        } else if (v.type().fullName().equals(\"java.lang.Long\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Long\", \"longValue\", \"()J\", false);\n                                info.push(CodeInfo.Size._2);\n                        } else if (v.type().fullName().equals(\"java.lang.Float\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Float\", \"floatValue\", \"()F\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else if (v.type().fullName().equals(\"java.lang.Integer\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Integer\", \"intValue\", \"()I\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else if (v.type().fullName().equals(\"java.lang.Short\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Short\", \"shortValue\", \"()S\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else if (v.type().fullName().equals(\"java.lang.Byte\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Byte\", \"byteValue\", \"()B\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else if (v.type().fullName().equals(\"java.lang.Character\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Character\", \"charValue\", \"()C\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else if (v.type().fullName().equals(\"java.lang.Boolean\")) {\n                                methodVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL,\n                                        \"java/lang/Boolean\", \"booleanValue\", \"()Z\", false);\n                                info.push(CodeInfo.Size._1);\n                        } else {\n                                throw new LtBug(\"unknown boxing type \" + v.type());\n                        }\n                }\n        }\n\n        private void _buildOptimizedPointerTStore(MethodVisitor methodVisitor, CodeInfo info, int index, STypeDef type, Value v) {\n                if (type instanceof PrimitiveTypeDef) {\n                        _buildUnbox(methodVisitor, info, v);\n                        if (type.equals(DoubleTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.DSTORE, index);\n                        } else if (type.equals(LongTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.LSTORE, index);\n                        } else if (type.equals(FloatTypeDef.get())) {\n                                methodVisitor.visitVarInsn(Opcodes.FSTORE, index);\n                        } else {\n                                methodVisitor.visitVarInsn(Opcodes.ISTORE, index);\n                        }\n                        info.pop(1);\n                } else {\n                        buildValueAccess(methodVisitor, info, v, true);\n                        methodVisitor.visitVarInsn(Opcodes.ASTORE, index);\n                        info.pop(1);\n                }\n        }\n\n        private boolean canOptimizePointerRetrieving(Ins.InvokeVirtual invoke, CodeInfo info) {\n                Ins.TLoad target = (Ins.TLoad) invoke.target();\n                return !info.getMeta().pointerLocalVar.contains(target.value()) && target.type().fullName().equals(Pointer.class.getName());\n        }\n\n        private boolean isParameterWrappingPointer(LeftValue v) {\n                return LocalVariables.isParameterWrappingPointer(v);\n        }\n\n        /**\n         * build invoke.\n         *\n         * @param methodVisitor method visitor\n         * @param info          info\n         * @param invoke        Ins.Invoke\n         * @param requireValue  requires a value\n         * @see lt.compiler.semantic.Ins.Invoke\n         * @see lt.compiler.semantic.Ins.InvokeSpecial\n         * @see lt.compiler.semantic.Ins.InvokeVirtual\n         * @see lt.compiler.semantic.Ins.InvokeStatic\n         * @see lt.compiler.semantic.Ins.InvokeInterface\n         */\n        private void buildInvoke(MethodVisitor methodVisitor, CodeInfo info, Ins.Invoke invoke, boolean requireValue) {\n                Label label = new Label();\n                if (invoke instanceof Ins.InvokeSpecial) {\n                        // push target object\n                        buildValueAccess(methodVisitor, info, ((Ins.InvokeSpecial) invoke).target(), true);\n\n                        // push parameters\n                        for (Value v : invoke.arguments()) {\n                                buildValueAccess(methodVisitor, info, v, true);\n                        }\n\n                        // invoke special\n                        Ins.InvokeSpecial invokeSpecial = (Ins.InvokeSpecial) invoke;\n                        SInvokable invokable = invokeSpecial.invokable();\n\n                        String name;\n                        String desc;\n                        if (invokable instanceof SMethodDef) {\n                                name = ((SMethodDef) invokable).name();\n                                desc = methodDescWithParameters(\n                                        invokable.getReturnType(),\n                                        invokable.getParameters());\n                        } else if (invokable instanceof SConstructorDef) {\n                                name = \"<init>\";\n                                desc = methodDescWithParameters(VoidType.get(), invokable.getParameters());\n                        } else throw new LtBug(\"cannot invoke special on \" + invokable);\n\n                        String owner = typeToInternalName(invokable.declaringType());\n\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitMethodInsn(\n                                Opcodes.INVOKESPECIAL,\n                                owner,\n                                name, desc, false);\n                        info.pop(1 + invoke.arguments().size());\n                        buildUnitWhenInvokeVoid(invokable, info);\n\n                } else if (invoke instanceof Ins.InvokeVirtual) {\n                        if (Consts.flagMatch(((Ins.InvokeVirtual) invoke).flag, Consts.IS_POINTER_GET)) {\n                                // pointer get\n                                if (!requireValue) {\n                                        return;\n                                }\n                                if (canOptimizePointerRetrieving((Ins.InvokeVirtual) invoke, info)) {\n                                        Ins.TLoad target = (Ins.TLoad) ((Ins.InvokeVirtual) invoke).target();\n                                        int index;\n                                        if (isParameterWrappingPointer(target.value())) {\n                                                index = calculateIndexForLocalVariable(((LocalVariable) target.value()).getWrappingParam(), target.getScope(), info);\n                                        } else {\n                                                index = calculateIndexForLocalVariable(target.value(), target.getScope(), info);\n                                        }\n                                        // simplify to tLoad\n                                        _buildOptimizedPointerTLoad(methodVisitor, info, index, ((PointerType) target.type()).getPointingType());\n                                        return;\n                                }\n                        } else if (Consts.flagMatch(((Ins.InvokeVirtual) invoke).flag, Consts.IS_POINTER_SET)) {\n                                // pointer set\n\n                                if (((Ins.InvokeVirtual) invoke).target() instanceof Ins.TLoad) {\n                                        Ins.TLoad target = (Ins.TLoad) ((Ins.InvokeVirtual) invoke).target();\n                                        if (!info.getMeta().pointerLocalVar.contains(target.value()) && target.type().fullName().equals(Pointer.class.getName())) {\n                                                // simplify to tStore\n                                                int index;\n                                                if (isParameterWrappingPointer(target.value())) {\n                                                        index = calculateIndexForLocalVariable(((LocalVariable) target.value()).getWrappingParam(), target.getScope(), info);\n                                                } else {\n                                                        index = calculateIndexForLocalVariable(target.value(), target.getScope(), info);\n                                                }\n                                                _buildOptimizedPointerTStore(methodVisitor, info, index, ((PointerType) target.type()).getPointingType(), invoke.arguments().get(0));\n                                                return;\n                                        }\n                                } else {\n                                        // else it should be New\n                                        assert ((Ins.InvokeVirtual) invoke).target() instanceof Ins.New;\n                                }\n                        }\n\n                        // push target object\n                        buildValueAccess(methodVisitor, info, ((Ins.InvokeVirtual) invoke).target(), true);\n\n                        // push parameters\n                        for (Value v : invoke.arguments()) {\n                                buildValueAccess(methodVisitor, info, v, true);\n                        }\n\n                        // invoke special\n                        Ins.InvokeVirtual invokeSpecial = (Ins.InvokeVirtual) invoke;\n                        SInvokable invokable = invokeSpecial.invokable();\n\n                        String name;\n                        String desc;\n                        if (invokable instanceof SMethodDef) {\n                                name = ((SMethodDef) invokable).name();\n                                desc = methodDescWithParameters(\n                                        invokable.getReturnType(),\n                                        invokable.getParameters());\n                        } else throw new LtBug(\"cannot invoke virtual on \" + invokable);\n\n                        String owner = typeToInternalName(invokable.declaringType());\n\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitMethodInsn(\n                                Opcodes.INVOKEVIRTUAL,\n                                owner,\n                                name, desc, false);\n                        info.pop(1 + invoke.arguments().size());\n                        buildUnitWhenInvokeVoid(invokable, info);\n\n                } else if (invoke instanceof Ins.InvokeStatic) {\n                        // push parameters\n                        for (Value v : invoke.arguments()) {\n                                buildValueAccess(methodVisitor, info, v, true);\n                        }\n\n                        // invoke special\n                        Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) invoke;\n                        SInvokable invokable = invokeStatic.invokable();\n\n                        String name;\n                        String desc;\n                        if (invokable instanceof SMethodDef) {\n                                name = ((SMethodDef) invokable).name();\n                                desc = methodDescWithParameters(\n                                        invokable.getReturnType(),\n                                        invokable.getParameters());\n                        } else throw new LtBug(\"cannot invoke static on \" + invokable);\n\n                        String owner = typeToInternalName(invokable.declaringType());\n\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitMethodInsn(\n                                Opcodes.INVOKESTATIC,\n                                owner,\n                                name, desc, false);\n                        info.pop(invoke.arguments().size());\n                        buildUnitWhenInvokeVoid(invokable, info);\n\n                } else if (invoke instanceof Ins.InvokeInterface) {\n                        // push target object\n                        buildValueAccess(methodVisitor, info, ((Ins.InvokeInterface) invoke).target(), true);\n\n                        // push parameters\n                        for (Value v : invoke.arguments()) {\n                                buildValueAccess(methodVisitor, info, v, true);\n                        }\n\n                        // invoke interface\n                        Ins.InvokeInterface invokeInterface = (Ins.InvokeInterface) invoke;\n                        SInvokable invokable = invokeInterface.invokable();\n\n                        String name;\n                        String desc;\n                        if (invokable instanceof SMethodDef) {\n                                name = ((SMethodDef) invokable).name();\n                                desc = methodDescWithParameters(\n                                        invokable.getReturnType(),\n                                        invokable.getParameters());\n                        } else throw new LtBug(\"cannot invoke interface on \" + invokable);\n\n                        String owner = typeToInternalName(invokable.declaringType());\n\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitMethodInsn(\n                                Opcodes.INVOKEINTERFACE,\n                                owner,\n                                name, desc, true);\n                        info.pop(1 + invoke.arguments().size());\n                        buildUnitWhenInvokeVoid(invokable, info);\n\n                } else if (invoke instanceof Ins.InvokeWithCapture) {\n                        Ins.InvokeWithCapture ic = (Ins.InvokeWithCapture) invoke;\n                        // push target object if not static\n                        if (!ic.isStatic()) {\n                                buildValueAccess(methodVisitor, info, ic.target(), true);\n                        }\n                        int argCount = 0;\n                        // push captured args\n                        for (int i = 0; i < ic.capturedArguments().size(); ++i) {\n                                Value v = ic.capturedArguments().get(i);\n                                SParameter param = ic.invokable().getParameters().get(i);\n                                if (param.isCapture() && !param.isUsed()) {\n                                        // ignore captured but not used values\n                                        continue;\n                                }\n                                buildValueAccess(methodVisitor, info, v, true);\n                                ++argCount;\n                        }\n                        // push args\n                        for (Value v : ic.arguments()) {\n                                buildValueAccess(methodVisitor, info, v, true);\n                                ++argCount;\n                        }\n                        // invoke\n                        SInvokable invokable = ic.invokable();\n                        if (!(invokable instanceof SMethodDef)) {\n                                throw new LtBug(\"invokable in InvokeWithCapture should not be \" + invokable);\n                        }\n                        String name;\n                        String desc;\n                        name = ((SMethodDef) invokable).name();\n                        desc = methodDescWithParameters(\n                                invokable.getReturnType(),\n                                invokable.getParameters()\n                        );\n                        String owner = typeToInternalName(invokable.declaringType());\n                        methodVisitor.visitLabel(label);\n                        if (ic.isStatic()) {\n                                // invoke static\n                                methodVisitor.visitMethodInsn(\n                                        Opcodes.INVOKESTATIC,\n                                        owner,\n                                        name, desc, false\n                                );\n                                info.pop(argCount);\n                        } else if (invokable.modifiers().isEmpty()) {\n                                // invoke virtual (package access)\n                                methodVisitor.visitMethodInsn(\n                                        Opcodes.INVOKEVIRTUAL,\n                                        owner,\n                                        name, desc, false\n                                );\n                                info.pop(argCount + 1);\n                        } else {\n                                // invoke special\n                                methodVisitor.visitMethodInsn(\n                                        Opcodes.INVOKESPECIAL,\n                                        owner,\n                                        name, desc, false\n                                );\n                                info.pop(argCount + 1);\n                        }\n                        buildUnitWhenInvokeVoid(invokable, info);\n\n                } else throw new LtBug(\"unknown invoke type \" + invoke);\n\n                // line number\n                VisitLineNumber(methodVisitor, invoke.line_col(), label);\n\n                if (invoke.invokable().getReturnType().equals(VoidType.get()) && requireValue) {\n                        // void methods\n                        // push Unit into stack\n                        methodVisitor.visitMethodInsn(\n                                Opcodes.INVOKESTATIC,\n                                \"lt/lang/Unit\",\n                                \"get\",\n                                \"()Llt/lang/Unit;\",\n                                false);\n                        info.push(CodeInfo.Size._1);\n                }\n        }\n\n        /**\n         * build Return.<br>\n         * <br>\n         * <code>\n         * RETURN<br>\n         * or<br>\n         * buildValueAccess ---- the value to return<br>\n         * TReturn\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          info\n         * @param tReturn       Ins.TReturn\n         */\n        private void buildReturn(MethodVisitor methodVisitor, CodeInfo info, Ins.TReturn tReturn) {\n                if (tReturn.returnIns() == Ins.TReturn.Return) {\n                        methodVisitor.visitInsn(Opcodes.RETURN);\n                } else {\n                        buildValueAccess(methodVisitor, info, tReturn.value(), true);\n                        methodVisitor.visitInsn(tReturn.returnIns());\n                        info.pop(1);\n                }\n        }\n\n        /**\n         * build TStore.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- the value to store<br>\n         * TStore index\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param tStore        Ins.TStore\n         */\n        private void buildTStore(MethodVisitor methodVisitor, CodeInfo info, Ins.TStore tStore) {\n                if (tStore.flag == Consts.IS_POINTER_NEW) {\n                        if (!info.getMeta().pointerLocalVar.contains(tStore.leftValue())) {\n                                STypeDef pointerType = tStore.leftValue().type();\n                                STypeDef type = ((PointerType) pointerType).getPointingType();\n                                if (isParameterWrappingPointer(tStore.leftValue())) {\n                                        // ignore the value\n                                        return;\n                                }\n                                int index = calculateIndexForLocalVariable(tStore.leftValue(), tStore.getScope(), info);\n                                Value newValue = tStore.newValue();\n                                if (newValue instanceof Ins.New && newValue.type().fullName().equals(Pointer.class.getName())) {\n                                        // constructing a new pointer object but not assigning any value\n                                        return; // do nothing\n                                } else if (newValue instanceof Ins.InvokeVirtual) {\n                                        //                                        pointer.set(           ?            )\n                                        Value valueToBuild = ((Ins.InvokeVirtual) tStore.newValue()).arguments().get(0);\n                                        if (type instanceof PrimitiveTypeDef) {\n                                                _buildUnbox(methodVisitor, info, valueToBuild);\n                                                if (type instanceof DoubleTypeDef) {\n                                                        methodVisitor.visitVarInsn(Opcodes.DSTORE, index);\n                                                } else if (type instanceof LongTypeDef) {\n                                                        methodVisitor.visitVarInsn(Opcodes.LSTORE, index);\n                                                } else if (type instanceof FloatTypeDef) {\n                                                        methodVisitor.visitVarInsn(Opcodes.FSTORE, index);\n                                                } else {\n                                                        methodVisitor.visitVarInsn(Opcodes.ISTORE, index);\n                                                }\n                                        } else {\n                                                buildValueAccess(methodVisitor, info, valueToBuild, true);\n                                                methodVisitor.visitVarInsn(Opcodes.ASTORE, index);\n                                        }\n                                        info.pop(1);\n                                        info.registerLocal(index);\n                                        return;\n                                } else throw new LtBug(\"should not each here\");\n                        }\n                }\n\n                buildValueAccess(methodVisitor, info, tStore.newValue(), true);\n                int index = calculateIndexForLocalVariable(tStore.leftValue(), tStore.getScope(), info);\n                methodVisitor.visitVarInsn(tStore.mode(), index);\n                info.pop(1);\n                info.registerLocal(index);\n        }\n\n        /**\n         * build PutField.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- the instance<br>\n         * buildValueAccess ---- the value to be put<br>\n         * PutField Field\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param putField      Ins.PutField\n         */\n        private void buildPutField(MethodVisitor methodVisitor, CodeInfo info, Ins.PutField putField) {\n                buildValueAccess(methodVisitor, info, putField.obj(), true);\n                buildValueAccess(methodVisitor, info, putField.value(), true);\n                methodVisitor.visitFieldInsn(\n                        Opcodes.PUTFIELD,\n                        typeToInternalName(putField.field().declaringType()),\n                        putField.field().name(),\n                        typeToDesc(putField.field().type()));\n                info.pop(2);\n        }\n\n        /**\n         * build GetField.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- the instance<br>\n         * GetField Field\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param getField      Ins.GetField\n         */\n        private void buildGetField(MethodVisitor methodVisitor, CodeInfo info, Ins.GetField getField) {\n                buildValueAccess(methodVisitor, info, getField.object(), true);\n\n                Label label = new Label();\n                methodVisitor.visitLabel(label);\n\n                methodVisitor.visitFieldInsn(\n                        Opcodes.GETFIELD,\n                        typeToInternalName(getField.field().declaringType()),\n                        getField.field().name(),\n                        typeToDesc(getField.type()));\n                info.pop(1);\n\n                if (getField.field().type().equals(DoubleTypeDef.get())\n                        ||\n                        getField.field().type().equals(LongTypeDef.get())) {\n                        info.push(CodeInfo.Size._2);\n                } else info.push(CodeInfo.Size._1);\n\n                VisitLineNumber(methodVisitor, getField.line_col(), label);\n        }\n\n        /**\n         * build PutStatic.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- the value to be put<br>\n         * PutStatic Field\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param putStatic     Ins.PutStatic\n         */\n        private void buildPutStatic(MethodVisitor methodVisitor, CodeInfo info, Ins.PutStatic putStatic) {\n                buildValueAccess(methodVisitor, info, putStatic.value(), true);\n                methodVisitor.visitFieldInsn(\n                        Opcodes.PUTSTATIC,\n                        typeToInternalName(putStatic.field().declaringType()),\n                        putStatic.field().name(),\n                        typeToDesc(putStatic.field().type()));\n                info.pop(1);\n        }\n\n        /**\n         * build TAStore.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- array<br>\n         * buildValueAccess ---- index to store<br>\n         * buildValueAccess ---- the value to store<br>\n         * TAStore\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param TAStore       Ins.TAStore\n         */\n        private void buildTAStore(MethodVisitor methodVisitor, CodeInfo info, Ins.TAStore TAStore) {\n                buildValueAccess(methodVisitor, info, TAStore.array(), true); // array\n                buildValueAccess(methodVisitor, info, TAStore.index(), true); // index\n                buildValueAccess(methodVisitor, info, TAStore.value(), true); // value\n\n                methodVisitor.visitInsn(TAStore.mode());\n                info.pop(3);\n        }\n\n        /**\n         * build MonitorEnter.<br>\n         * <br>\n         * <code>\n         * buildValueAccess ---- the object to be monitored<br>\n         * DUP<br>\n         * AStore index<br>\n         * MonitorEnter\n         * </code>\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param monitorEnter  Ins.MonitorEnter\n         */\n        private void buildMonitorEnter(MethodVisitor methodVisitor, CodeInfo info, Ins.MonitorEnter monitorEnter) {\n                buildValueAccess(methodVisitor, info, monitorEnter.valueToMonitor(), true);\n                methodVisitor.visitInsn(Opcodes.DUP);\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitVarInsn(Opcodes.ASTORE, calculateIndexForLocalVariable(monitorEnter.leftValue(), monitorEnter.getScope(), info));\n                info.pop(1);\n                methodVisitor.visitInsn(Opcodes.MONITORENTER);\n                info.pop(1);\n        }\n\n        /**\n         * build MonitorExit.<br>\n         * <br>\n         * ALoad ---- the object that was monitored<br>\n         * MonitorExit\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param monitorExit   Ins.MonitorExit\n         */\n        private void buildMonitorExit(MethodVisitor methodVisitor, CodeInfo info, Ins.MonitorExit monitorExit) {\n                methodVisitor.visitVarInsn(Opcodes.ALOAD, calculateIndexForLocalVariable(monitorExit.enterInstruction().leftValue(), monitorExit.enterInstruction().getScope(), info));\n                info.push(CodeInfo.Size._1);\n                methodVisitor.visitInsn(Opcodes.MONITOREXIT);\n                info.pop(1);\n        }\n\n        /**\n         * build one Instruction.\n         *\n         * @param methodVisitor method visitor\n         * @param info          method info\n         * @param ins           Instruction\n         * @param requireValue  requires a value when generating {@link ValuePack}\n         * @see Instruction\n         * @see Value\n         * @see lt.compiler.semantic.Ins.TReturn\n         * @see lt.compiler.semantic.Ins.TStore\n         * @see lt.compiler.semantic.Ins.PutField\n         * @see lt.compiler.semantic.Ins.PutStatic\n         * @see lt.compiler.semantic.Ins.IfNe\n         * @see lt.compiler.semantic.Ins.IfEq\n         * @see lt.compiler.semantic.Ins.IfNonNull\n         * @see lt.compiler.semantic.Ins.IfACmpNe\n         * @see lt.compiler.semantic.Ins.Goto\n         * @see lt.compiler.semantic.Ins.Nop\n         * @see lt.compiler.semantic.Ins.AThrow\n         * @see lt.compiler.semantic.Ins.ExStore\n         * @see lt.compiler.semantic.Ins.Pop\n         * @see lt.compiler.semantic.Ins.TAStore\n         * @see lt.compiler.semantic.Ins.MonitorEnter\n         * @see lt.compiler.semantic.Ins.MonitorExit\n         */\n        private void buildOneIns(MethodVisitor methodVisitor, CodeInfo info, Instruction ins, boolean requireValue) {\n                CodeInfo.Container container;\n                if (info.insToLabel.containsKey(ins)) {\n                        // fill label\n                        container = info.insToLabel.get(ins);\n                } else {\n                        // add label\n                        container = new CodeInfo.Container(new Label());\n                        info.insToLabel.put(ins, container);\n                }\n                if (!container.isVisited) {\n                        methodVisitor.visitLabel(container.label);\n                        container.isVisited = true;\n                }\n\n                if (ins instanceof Value) {\n                        buildValueAccess(methodVisitor, info, (Value) ins, requireValue);\n                } else if (ins instanceof Ins.TReturn) {\n                        buildReturn(methodVisitor, info, (Ins.TReturn) ins);\n                } else if (ins instanceof Ins.TStore) {\n                        buildTStore(methodVisitor, info, (Ins.TStore) ins);\n                } else if (ins instanceof Ins.PutField) {\n                        buildPutField(methodVisitor, info, (Ins.PutField) ins);\n                } else if (ins instanceof Ins.PutStatic) {\n                        buildPutStatic(methodVisitor, info, (Ins.PutStatic) ins);\n                } else if (ins instanceof Ins.IfNe) {\n                        buildValueAccess(methodVisitor, info, ((Ins.IfNe) ins).condition(), true);\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.IfNe) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.IfNe) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.IfNe) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        methodVisitor.visitJumpInsn(Opcodes.IFNE, l);\n                        info.pop(1);\n                } else if (ins instanceof Ins.IfEq) {\n                        buildValueAccess(methodVisitor, info, ((Ins.IfEq) ins).condition(), true);\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.IfEq) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.IfEq) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.IfEq) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        methodVisitor.visitJumpInsn(Opcodes.IFEQ, l);\n                        info.pop(1);\n                } else if (ins instanceof Ins.IfNonNull) {\n                        buildValueAccess(methodVisitor, info, ((Ins.IfNonNull) ins).object(), true);\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.IfNonNull) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.IfNonNull) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.IfNonNull) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        methodVisitor.visitJumpInsn(Opcodes.IFNONNULL, l);\n                        info.pop(1);\n                } else if (ins instanceof Ins.IfNull) {\n                        buildValueAccess(methodVisitor, info, ((Ins.IfNull) ins).object(), true);\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.IfNull) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.IfNull) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.IfNull) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        methodVisitor.visitJumpInsn(Opcodes.IFNULL, l);\n                        info.pop(1);\n                } else if (ins instanceof Ins.IfACmpNe) {\n                        buildValueAccess(methodVisitor, info, ((Ins.IfACmpNe) ins).value1(), true);\n                        buildValueAccess(methodVisitor, info, ((Ins.IfACmpNe) ins).value2(), true);\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.IfACmpNe) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.IfACmpNe) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.IfACmpNe) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        methodVisitor.visitJumpInsn(Opcodes.IF_ACMPNE, l);\n                        info.pop(2);\n                } else if (ins instanceof Ins.Goto) {\n                        Label l;\n                        if (info.insToLabel.containsKey(((Ins.Goto) ins).gotoIns())) {\n                                l = info.insToLabel.get(((Ins.Goto) ins).gotoIns()).label;\n                        } else {\n                                l = new Label();\n                                info.insToLabel.put(((Ins.Goto) ins).gotoIns(), new CodeInfo.Container(l));\n                        }\n                        // methodVisitor.visitLdcInsn(0);\n                        // info.push(1);\n                        methodVisitor.visitJumpInsn(Opcodes.GOTO, l);\n                        // info.pop(1);\n                } else if (ins instanceof Ins.Nop) {\n                        methodVisitor.visitInsn(Opcodes.NOP);\n                } else if (ins instanceof Ins.AThrow) {\n                        buildValueAccess(methodVisitor, info, ((Ins.AThrow) ins).exception(), true);\n\n                        Label label = new Label();\n                        methodVisitor.visitLabel(label);\n\n                        methodVisitor.visitInsn(Opcodes.ATHROW);\n                        info.pop(1);\n\n                        VisitLineNumber(methodVisitor, ins.line_col(), label);\n\n                } else if (ins instanceof Ins.ExStore) {\n                        info.push(CodeInfo.Size._1);\n                        int index = calculateIndexForLocalVariable(((Ins.ExStore) ins).leftValue(), ((Ins.ExStore) ins).getScope(), info);\n                        methodVisitor.visitVarInsn(Opcodes.ASTORE, index);\n                        info.registerLocal(index);\n                        info.pop(1);\n                } else if (ins instanceof Ins.Pop) {\n                        methodVisitor.visitInsn(Opcodes.POP);\n                        info.pop(1);\n                } else if (ins instanceof Ins.TAStore) {\n                        buildTAStore(methodVisitor, info, (Ins.TAStore) ins);\n                } else if (ins instanceof Ins.MonitorEnter) {\n                        buildMonitorEnter(methodVisitor, info, (Ins.MonitorEnter) ins);\n                } else if (ins instanceof Ins.MonitorExit) {\n                        buildMonitorExit(methodVisitor, info, (Ins.MonitorExit) ins);\n                } else {\n                        throw new LtBug(\"unknown ins \" + ins);\n                }\n        }\n\n        /**\n         * build instructions for method/constructor/staticScope.<br>\n         * <ol>\n         * <li>build instructions</li>\n         * <li>\n         * add Return to the method ensures that the method would return normally<br>\n         * for short/byte/bool/char => IConst_0 and IReturn<br>\n         * for long => L_Const_0 and LReturn<br>\n         * for float => FConst_0 and FReturn<br>\n         * for double =>DConst_0 and DReturn<br>\n         * for void => Return<br>\n         * other => AConst_Null and AReturn\n         * </li>\n         * <li>build exception table</li>\n         * </ol>\n         *\n         * @param methodVisitor  method visitor\n         * @param info           method info\n         * @param instructions   instructions to be parsed into jvm byte codes\n         * @param exceptionTable exception tables that records exception info (start,end,handle,type)\n         * @param returnType     method return type\n         */\n        private void buildInstructions(\n                MethodVisitor methodVisitor,\n                CodeInfo info,\n                List<Instruction> instructions,\n                List<ExceptionTable> exceptionTable,\n                STypeDef returnType) {\n\n                methodVisitor.visitCode();\n                for (Instruction ins : instructions) {\n                        buildOneIns(methodVisitor, info, ins, false);\n                        while (info.getCurrentStackDepth() != 0) {\n                                CodeInfo.Size peek = info.peekSize();\n                                if (peek == CodeInfo.Size._1) methodVisitor.visitInsn(Opcodes.POP);\n                                else methodVisitor.visitInsn(Opcodes.POP2);\n                                info.pop(1);\n                        }\n                }\n                // guarantee the method can return\n                if (returnType.equals(VoidType.get())) {\n                        methodVisitor.visitInsn(Opcodes.RETURN);\n                } else if (returnType instanceof PrimitiveTypeDef) {\n                        if (returnType.equals(IntTypeDef.get())\n                                || returnType.equals(ShortTypeDef.get())\n                                || returnType.equals(ByteTypeDef.get())\n                                || returnType.equals(BoolTypeDef.get())\n                                || returnType.equals(CharTypeDef.get())) {\n                                methodVisitor.visitInsn(Opcodes.ICONST_0);\n                                info.push(CodeInfo.Size._1);\n                                methodVisitor.visitInsn(Opcodes.IRETURN);\n                        } else if (returnType.equals(LongTypeDef.get())) {\n                                methodVisitor.visitInsn(Opcodes.LCONST_0);\n                                info.push(CodeInfo.Size._2);\n                                methodVisitor.visitInsn(Opcodes.LRETURN);\n                        } else if (returnType.equals(FloatTypeDef.get())) {\n                                methodVisitor.visitInsn(Opcodes.FCONST_0);\n                                info.push(CodeInfo.Size._1);\n                                methodVisitor.visitInsn(Opcodes.FRETURN);\n                        } else if (returnType.equals(DoubleTypeDef.get())) {\n                                methodVisitor.visitInsn(Opcodes.DCONST_0);\n                                info.push(CodeInfo.Size._2);\n                                methodVisitor.visitInsn(Opcodes.DRETURN);\n                        } else throw new LtBug(\"unknown primitive:\" + returnType);\n                } else {\n                        methodVisitor.visitInsn(Opcodes.ACONST_NULL);\n                        info.push(CodeInfo.Size._1);\n                        methodVisitor.visitInsn(Opcodes.ARETURN);\n                }\n\n                for (CodeInfo.Container c : info.insToLabel.values()) {\n                        if (!c.isVisited) throw new LtBug(\"not all labels are visited\");\n                }\n\n                // exception\n                for (ExceptionTable tbl : exceptionTable) {\n                        methodVisitor.visitTryCatchBlock(\n                                info.insToLabel.get(tbl.getFrom()).label,\n                                info.insToLabel.get(tbl.getTo()).label,\n                                info.insToLabel.get(tbl.getTarget()).label,\n                                tbl.getType() == null ? null : typeToInternalName(tbl.getType()));\n                }\n\n                methodVisitor.visitMaxs(info.getMaxStack(), info.getMaxLocal());\n        }\n\n        /**\n         * build static block (clinit).\n         *\n         * @param classWriter    class writer\n         * @param staticIns      static instructions\n         * @param exceptionTable exception table\n         */\n        private void buildStatic(ClassWriter classWriter, List<Instruction> staticIns, List<ExceptionTable> exceptionTable, InvokableMeta meta) {\n                MethodVisitor methodVisitor = classWriter.visitMethod(Opcodes.ACC_STATIC, \"<clinit>\", \"()V\", null, null);\n                buildInstructions(methodVisitor, new CodeInfo(0, null, meta), staticIns, exceptionTable, VoidType.get());\n                methodVisitor.visitEnd();\n        }\n\n        /**\n         * build constructor and its annotations.\n         *\n         * @param classWriter  class writer\n         * @param constructors the constructors to build\n         */\n        private void buildConstructor(ClassWriter classWriter, List<SConstructorDef> constructors) {\n                for (SConstructorDef cons : constructors) {\n                        MethodVisitor methodVisitor = classWriter.visitMethod(\n                                acc(cons.modifiers()),\n                                \"<init>\",\n                                methodDescWithParameters(\n                                        VoidType.get(),\n                                        cons.getParameters()),\n                                null, null);\n\n                        // annotations\n                        for (SAnno anno : cons.annos()) {\n                                AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotation(typeToDesc(anno.type()),\n                                        annotationIsVisible(anno));\n                                buildAnnotation(annotationVisitor, anno);\n                        }\n                        buildParameter(methodVisitor, cons.getParameters());\n\n                        buildInstructions(\n                                methodVisitor,\n                                new CodeInfo(1 + cons.getParameters().size(), cons, cons.meta()),\n                                cons.statements(), cons.exceptionTables(), VoidType.get());\n\n                        methodVisitor.visitEnd();\n                }\n        }\n\n        /**\n         * build field and its annotations.\n         *\n         * @param classWriter class writer\n         * @param fields      the fields to build\n         */\n        private void buildField(ClassWriter classWriter, List<SFieldDef> fields) {\n                for (SFieldDef field : fields) {\n                        FieldVisitor fieldVisitor = classWriter.visitField(acc(field.modifiers()), field.name(), typeToDesc(field.type()), null, null);\n\n                        // annotations\n                        for (SAnno anno : field.annos()) {\n                                AnnotationVisitor annotationVisitor = fieldVisitor.visitAnnotation(typeToDesc(anno.type()),\n                                        annotationIsVisible(anno));\n                                buildAnnotation(annotationVisitor, anno);\n                        }\n\n                        fieldVisitor.visitEnd();\n                }\n        }\n\n        /**\n         * build method and its annotations.\n         *\n         * @param classWriter class writer\n         * @param methods     methods to build\n         */\n        private void buildMethod(ClassWriter classWriter, List<SMethodDef> methods) {\n                for (SMethodDef method : methods) {\n                        MethodVisitor methodVisitor = classWriter.visitMethod(\n                                acc(method.modifiers()),\n                                method.name(),\n                                methodDescWithParameters(\n                                        method.getReturnType(),\n                                        method.getParameters()),\n                                null, null);\n\n                        // annotations\n                        for (SAnno anno : method.annos()) {\n                                AnnotationVisitor annotationVisitor = methodVisitor.visitAnnotation(\n                                        typeToDesc(anno.type()),\n                                        annotationIsVisible(anno)\n                                );\n                                buildAnnotation(annotationVisitor, anno);\n                        }\n                        buildParameter(methodVisitor, method.getParameters());\n\n                        if (method.modifiers().contains(SModifier.ABSTRACT)) {\n                                if (!method.statements().isEmpty())\n                                        throw new LtBug(\"statements for abstract method should be empty\");\n                        } else {\n\n                                buildInstructions(\n                                        methodVisitor,\n                                        new CodeInfo(\n                                                (method.modifiers().contains(SModifier.STATIC) ? 0 : 1) + method.getParameters().size(),\n                                                method,\n                                                method.meta()),\n                                        method.statements(), method.exceptionTables(), method.getReturnType());\n\n\n                        }\n                        methodVisitor.visitEnd();\n                }\n        }\n\n        /**\n         * build parameter annotations\n         *\n         * @param methodVisitor method visitor\n         * @param params        parameters\n         */\n        private void buildParameter(MethodVisitor methodVisitor, List<SParameter> params) {\n                for (int i = 0; i < params.size(); i++) {\n                        SParameter param = params.get(i);\n\n                        if (param.isCapture() && !param.isUsed()) {\n                                // ignore those captured but not used params\n                                continue;\n                        }\n\n                        methodVisitor.visitParameter(param.name(), param.canChange() ? 0 : Opcodes.ACC_FINAL);\n                        for (SAnno anno : param.annos()) {\n                                AnnotationVisitor annotationVisitor = methodVisitor.visitParameterAnnotation(\n                                        i, typeToDesc(anno.type()), annotationIsVisible(anno)\n                                );\n                                buildAnnotation(annotationVisitor, anno);\n                        }\n                }\n        }\n\n        /**\n         * check whether the annotation should be visible at runtime.\n         *\n         * @param anno annotation to check\n         * @return true if visible at runtime, false otherwise\n         */\n        private boolean annotationIsVisible(SAnno anno) {\n                SAnnoDef annoType = anno.type();\n                for (SAnno a : annoType.annos()) {\n                        if (a.type().fullName().equals(\"java.lang.annotation.Retention\")) {\n                                for (Map.Entry<SAnnoField, Value> entry : a.values().entrySet()) {\n                                        if (entry.getKey().name().equals(\"value\")) {\n                                                Value v = entry.getValue();\n                                                if (v instanceof EnumValue) {\n                                                        if (v.type().fullName().equals(\"java.lang.annotation.RetentionPolicy\")) {\n                                                                return ((EnumValue) v).enumStr().equals(\"RUNTIME\");\n                                                        }\n                                                }\n                                                throw new LtBug(\n                                                        \"value of java.lang.annotation.Retention.value() \" +\n                                                                \"should be instance of \" +\n                                                                \"java.lang.annotation.RetentionPolicy, \" +\n                                                                \"but got \" + v\n                                                );\n                                        }\n                                }\n                                break;\n                        }\n                }\n                return false;\n        }\n\n        private void buildAnnotationValue(AnnotationVisitor annotationVisitor, String name, Value v) {\n                if (v instanceof EnumValue) {\n                        annotationVisitor.visitEnum(\n                                name,\n                                \"L\" + (v.type().fullName().replace(\".\", \"/\")) + \";\",\n                                ((EnumValue) v).enumStr());\n                } else if (v instanceof SArrayValue && !(((SArrayValue) v).type().type() instanceof PrimitiveTypeDef)) {\n                        AnnotationVisitor visitor = annotationVisitor.visitArray(name);\n                        for (Value arrValue : ((SArrayValue) v).values()) {\n                                if (arrValue instanceof EnumValue) {\n                                        visitor.visitEnum(null,\n                                                \"L\" + (arrValue.type().fullName().replace(\".\", \"/\")) + \";\",\n                                                ((EnumValue) arrValue).enumStr());\n                                } else if (arrValue instanceof SAnno) {\n                                        AnnotationVisitor annoVisitor = visitor.visitAnnotation(null, typeToDesc(arrValue.type()));\n                                        buildAnnotation(annoVisitor, (SAnno) arrValue);\n                                } else {\n                                        visitor.visit(null, parseValueIntoASMObject(arrValue));\n                                }\n                        }\n                        visitor.visitEnd();\n                } else if (v instanceof SAnno) {\n                        AnnotationVisitor visitor = annotationVisitor.visitAnnotation(name, typeToDesc(v.type()));\n                        buildAnnotation(visitor, (SAnno) v);\n                } else {\n                        // primitives\n                        annotationVisitor.visit(name, parseValueIntoASMObject(v));\n                }\n        }\n\n        /**\n         * build annotation.\n         *\n         * @param annotationVisitor annotation visitor\n         * @param anno              the annotation to build\n         */\n        private void buildAnnotation(AnnotationVisitor annotationVisitor, SAnno anno) {\n                for (Map.Entry<SAnnoField, Value> entry : anno.values().entrySet()) {\n                        String name = entry.getKey().name();\n                        Value v = entry.getValue();\n\n                        buildAnnotationValue(annotationVisitor, name, v);\n                }\n                annotationVisitor.visitEnd();\n        }\n\n        /**\n         * transform {@link Value} into asm Object.<br>\n         * the Value can only be {@link PrimitiveValue}, {@link StringConstantValue}, {link ClassValue}, {@link SArrayValue}\n         *\n         * @param value the value\n         * @return parsed object\n         */\n        private Object parseValueIntoASMObject(Value value) {\n                if (value instanceof IntValue) return ((IntValue) value).getValue();\n                else if (value instanceof LongValue) return ((LongValue) value).getValue();\n                else if (value instanceof CharValue) return (char) ((CharValue) value).getValue();\n                else if (value instanceof ShortValue) return (short) ((ShortValue) value).getValue();\n                else if (value instanceof ByteValue) return (byte) ((ByteValue) value).getValue();\n                else if (value instanceof BoolValue) return ((BoolValue) value).getValue() != 0;\n                else if (value instanceof FloatValue) return ((FloatValue) value).getValue();\n                else if (value instanceof DoubleValue) return ((DoubleValue) value).getValue();\n                else if (value instanceof StringConstantValue) return ((StringConstantValue) value).getStr();\n                else if (value instanceof Ins.GetClass) return Type.getObjectType(((Ins.GetClass) value).targetType()\n                        .fullName().replace(\".\", \"/\"));\n                else if (value instanceof SArrayValue && ((SArrayValue) value).type().type() instanceof PrimitiveTypeDef) {\n                        PrimitiveTypeDef primitiveType = (PrimitiveTypeDef) ((SArrayValue) value).type().type();\n                        int length = ((SArrayValue) value).length();\n                        if (primitiveType.equals(IntTypeDef.get())) {\n                                int[] arr = new int[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Integer) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(LongTypeDef.get())) {\n                                long[] arr = new long[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Long) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(CharTypeDef.get())) {\n                                char[] arr = new char[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Character) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(ShortTypeDef.get())) {\n                                short[] arr = new short[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Short) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(ByteTypeDef.get())) {\n                                byte[] arr = new byte[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Byte) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(BoolTypeDef.get())) {\n                                boolean[] arr = new boolean[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Boolean) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(FloatTypeDef.get())) {\n                                float[] arr = new float[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Float) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else if (primitiveType.equals(DoubleTypeDef.get())) {\n                                double[] arr = new double[length];\n                                for (int i = 0; i < length; ++i) {\n                                        arr[i] = (Double) parseValueIntoASMObject(((SArrayValue) value).values()[i]);\n                                }\n                                return arr;\n                        } else throw new LtBug(\"unknown primitive type \" + primitiveType);\n                }\n                throw new LtBug(value + \" is not supported\");\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/CodeInfo.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.*;\nimport lt.dependencies.asm.Label;\n\nimport java.util.HashMap;\nimport java.util.Map;\nimport java.util.Stack;\n\n/**\n * stack depth and local variable count\n */\npublic class CodeInfo {\n        public enum Size {\n                _1, _2\n        }\n\n        private int currentStackDepth;\n        private Stack<Size> currentStack = new Stack<Size>();\n        private int maxStack;\n        private int maxLocal;\n        private final SInvokable invokable;\n        private final boolean isStatic;\n        private final InvokableMeta meta;\n\n        public static class Container {\n                public final Label label;\n                public boolean isVisited;\n\n                public Container(Label label) {\n                        this.label = label;\n                }\n        }\n\n        public final Map<Instruction, Container> insToLabel = new HashMap<Instruction, Container>();\n\n        public CodeInfo(int localInit, SInvokable invokable, InvokableMeta meta) {\n                this.maxLocal = localInit;\n                this.invokable = invokable;\n                this.isStatic = invokable == null || this.invokable.modifiers().contains(SModifier.STATIC);\n                this.meta = meta;\n        }\n\n        public void push(Size size) {\n                currentStack.push(size);\n                if (Size._1 == size) currentStackDepth += 1;\n                else currentStackDepth += 2;\n                if (currentStackDepth > maxStack) {\n                        maxStack = currentStackDepth;\n                }\n        }\n\n        public void pop(int count) {\n                for (int i = 0; i < count; ++i) {\n                        Size size = currentStack.pop();\n                        if (size == Size._1) currentStackDepth -= 1;\n                        else currentStackDepth -= 2;\n                }\n        }\n\n        public int getMaxLocal() {\n                return maxLocal;\n        }\n\n        public void registerLocal(int theLocal) {\n                if (theLocal + 1 > this.maxLocal) {\n                        this.maxLocal = theLocal + 1;\n                }\n        }\n\n        public int getMaxStack() {\n                return maxStack;\n        }\n\n        public int getCurrentStackDepth() {\n                return currentStackDepth;\n        }\n\n        public Size peekSize() {\n                return currentStack.peek();\n        }\n\n        public SInvokable getInvokable() {\n                return invokable;\n        }\n\n        public boolean isStatic() {\n                return isStatic;\n        }\n\n        public InvokableMeta getMeta() {\n                return meta;\n        }\n\n        @Override\n        public String toString() {\n                return \"CodeInfo{\" +\n                        \"maxStack=\" + maxStack +\n                        \", maxLocal=\" + maxLocal +\n                        '}';\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/CompileException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * exceptions during compile\n */\npublic class CompileException extends Exception {\n        public CompileException() {\n        }\n\n        public CompileException(Throwable cause) {\n                super(cause);\n        }\n\n        public CompileException(String message) {\n                super(message);\n        }\n\n        public CompileException(String message, Throwable cause) {\n                super(message, cause);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/CompileUtil.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.*;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.util.*;\n\n/**\n * compile util<br>\n * checks the element type<br>\n * and defines keywords and operator priority\n */\npublic class CompileUtil {\n        /**\n         * check the given string is a number\n         *\n         * @param str string\n         * @return true if the string represents a number\n         */\n        public static boolean isNumber(String str) {\n                try {\n                        //noinspection ResultOfMethodCallIgnored\n                        Double.parseDouble(str);\n                        return true;\n                } catch (NumberFormatException ignore) {\n                        return false;\n                }\n        }\n\n        /**\n         * check the given string is a boolean literal\n         *\n         * @param str string\n         * @return true if it's a boolean.(true,false,yes,no)\n         */\n        public static boolean isBoolean(String str) {\n                return str.equals(\"true\") || str.equals(\"false\") || str.equals(\"yes\") || str.equals(\"no\");\n        }\n\n        /**\n         * check the given string is a string literal\n         *\n         * @param str string\n         * @return true/false\n         */\n        public static boolean isString(String str) {\n                return (\n                        (str.startsWith(\"\\\"\") && str.endsWith(\"\\\"\")) || (str.startsWith(\"'\") && str.endsWith(\"'\"))\n                ) && str.length() > 1;\n        }\n\n        private static Set<String> keys = new HashSet<String>(Arrays.asList(\n                \"is\", \"not\", \"bool\", \"yes\", \"no\", \"type\", \"as\",\n                \"in\", \"elseif\", \"package\", \"import\",\n                \"break\", \"continue\", \"return\", \"fun\", \"require\",\n                \"new\", \"object\", \"implicit\", \"match\", \"case\",\n                \"annotation\"\n        ));\n\n        private static Set<String> javaKeys = new HashSet<String>(Arrays.asList(\n                \"abstract\", \"assert\", \"boolean\", \"break\", \"byte\", \"case\",\n                \"catch\", \"char\", \"class\", \"const\", \"continue\", \"default\",\n                \"do\", \"double\", \"else\", \"enum\", \"extends\", \"final\", \"finally\",\n                \"float\", \"for\", \"if\", \"implements\", \"import\", \"instanceof\",\n                \"int\", \"interface\", \"long\", \"native\", \"new\", \"null\", \"package\",\n                \"private\", \"protected\", \"public\", \"return\", \"short\", \"static\",\n                \"strictfp\", \"throw\", \"try\", \"while\", \"void\"\n        ));\n\n        public static boolean isKey(String str) {\n                return keys.contains(str);\n        }\n\n        public static String SingletonFieldName = \"singletonInstance\";\n\n        /**\n         * check whether the given string can be a valid java name\n         *\n         * @param str string\n         * @return true/false\n         */\n        public static boolean isJavaValidName(String str) {\n                if (str.isEmpty()) return false;\n                if (javaKeys.contains(str)) return false;\n                char first = str.charAt(0);\n                if (isValidNameStartChar(first)) {\n                        for (int i = 1; i < str.length(); ++i) {\n                                char c = str.charAt(i);\n                                if (!isValidNameChar(c)) return false;\n                        }\n                        return true;\n                } else {\n                        return false;\n                }\n        }\n\n        /**\n         * check whether the given string can be a name\n         *\n         * @param str string\n         * @return true/false\n         */\n        public static boolean isValidName(String str) {\n                if (str.startsWith(\"`\") && str.endsWith(\"`\")) {\n                        return isJavaValidName(str.substring(1, str.length() - 1));\n                }\n                return isJavaValidName(str) && !keys.contains(str);\n        }\n\n        /**\n         * check whether is defined as a package access\n         *\n         * @param element element\n         * @return true/false (packageName::name)\n         */\n        public static boolean isPackage(Element element) {\n                if (element.getTokenType() == TokenType.VALID_NAME && element.hasNext()) {\n                        Node next = element.next();\n                        if (next instanceof Element) {\n                                String nextContent = ((Element) next).getContent();\n                                if (nextContent.equals(\"::\") && next.hasNext()) {\n                                        Node nextNext = next.next();\n                                        if (nextNext instanceof Element) {\n                                                return nextNext.getTokenType() == TokenType.VALID_NAME;\n                                        }\n                                }\n                        }\n                }\n                return false;\n        }\n\n        /**\n         * check whether the given char can be one of a name\n         *\n         * @param c char\n         * @return true/false (a-z|A-Z|$|_|0-9|&gt;=128)\n         */\n        public static boolean isValidNameChar(char c) {\n                return isValidNameStartChar(c) || (c >= '0' && c <= '9') || c >= 128;\n        }\n\n        /**\n         * check whether the given char can be start of a name\n         *\n         * @param c char\n         * @return true/false (a-z|A-Z|$|_|&gt;=128)\n         */\n        public static boolean isValidNameStartChar(char c) {\n                return (c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || c == '$' || c == '_' || c >= 128;\n        }\n\n        private static Set<String> modifiers = new HashSet<String>(Arrays.asList(\n                \"public\", \"protected\", \"private\", \"internal\",\n                \"abstract\", \"val\", \"native\", \"synchronized\", \"transient\", \"volatile\", \"strictfp\",\n                \"data\", \"var\", \"def\", \"nonnull\", \"nonempty\", \"implicit\"\n        ));\n\n        private static Set<String> accessModifiers = new HashSet<String>(Arrays.asList(\n                \"public\", \"protected\", \"private\", \"internal\"\n        ));\n\n        public static boolean isModifier(String str) {\n                return modifiers.contains(str);\n        }\n\n        /**\n         * check whether the str represented modifier is compatible with existing modifiers\n         *\n         * @param str       str\n         * @param modifiers modifiers\n         * @return true/false\n         */\n        public static boolean modifierIsCompatible(String str, Set<Modifier> modifiers) {\n                boolean isAccessMod = accessModifiers.contains(str);\n                Modifier.Available mod = getModifierFromString(str);\n                for (Modifier m : modifiers) {\n                        if (m.modifier.equals(mod)\n                                ||\n                                (isAccessMod &&\n                                        (m.modifier.equals(Modifier.Available.PUBLIC)\n                                                || m.modifier.equals(Modifier.Available.PRIVATE)\n                                                || m.modifier.equals(Modifier.Available.PROTECTED)\n                                                || m.modifier.equals(Modifier.Available.PKG))\n                                )\n                                || (mod.equals(Modifier.Available.VAL) && m.modifier.equals(Modifier.Available.ABSTRACT))\n                                || (mod.equals(Modifier.Available.ABSTRACT) && m.modifier.equals(Modifier.Available.VAL))\n                                || (mod.equals(Modifier.Available.VAL) && m.modifier.equals(Modifier.Available.VAR))\n                                || (mod.equals(Modifier.Available.VAR) && m.modifier.equals(Modifier.Available.VAL))\n                                )\n                                return false;\n                }\n                return true;\n        }\n\n        public static Modifier.Available getModifierFromString(String str) {\n                if (str.equals(\"public\")) {\n                        return Modifier.Available.PUBLIC;\n                } else if (str.equals(\"private\")) {\n                        return Modifier.Available.PRIVATE;\n                } else if (str.equals(\"protected\")) {\n                        return Modifier.Available.PROTECTED;\n                } else if (str.equals(\"internal\")) {\n                        return Modifier.Available.PKG;\n                } else if (str.equals(\"abstract\")) {\n                        return Modifier.Available.ABSTRACT;\n                } else if (str.equals(\"val\")) {\n                        return Modifier.Available.VAL;\n                } else if (str.equals(\"native\")) {\n                        return Modifier.Available.NATIVE;\n                } else if (str.equals(\"synchronized\")) {\n                        return Modifier.Available.SYNCHRONIZED;\n                } else if (str.equals(\"transient\")) {\n                        return Modifier.Available.TRANSIENT;\n                } else if (str.equals(\"volatile\")) {\n                        return Modifier.Available.VOLATILE;\n                } else if (str.equals(\"strictfp\")) {\n                        return Modifier.Available.STRICTFP;\n                } else if (str.equals(\"data\")) {\n                        return Modifier.Available.DATA;\n                } else if (str.equals(\"var\")) {\n                        return Modifier.Available.VAR;\n                } else if (str.equals(\"def\")) {\n                        return Modifier.Available.DEF;\n                } else if (str.equals(\"nonnull\")) {\n                        return Modifier.Available.NONNULL;\n                } else if (str.equals(\"nonempty\")) {\n                        return Modifier.Available.NONEMPTY;\n                } else if (str.equals(\"implicit\")) {\n                        return Modifier.Available.IMPLICIT;\n                } else {\n                        throw new LtBug(\"invalid modifier \" + str);\n                }\n        }\n\n        public static final int NOT_METHOD_DEF = 0;\n        public static final int METHOD_DEF_NORMAL = 1;\n        public static final int METHOD_DEF_TYPE = 2;\n        public static final int METHOD_DEF_EMPTY = 3;\n        public static final int METHOD_DEF_ONE_STMT = 4;\n\n        public static Node get_next_node(Node n) {\n                if (n == null) return null;\n\n                if (n.next() instanceof EndingNode) {\n                        return get_next_node(n.next());\n                } else {\n                        return n.next();\n                }\n        }\n\n        /**\n         * check whether the element starts a lambda.\n         * The element may be (...)-&gt; or xxx-&gt;\n         *\n         * @param elem elem\n         * @return true / false\n         * @throws UnexpectedEndException syntax error\n         */\n        public static boolean isLambda(Element elem) throws UnexpectedEndException {\n                if (elem.getContent().equals(\"(\")) {\n                        Node n = get_next_node(elem);\n                        if (n instanceof ElementStartNode) {\n                                n = get_next_node(n);\n                        }\n                        if (n instanceof Element) {\n                                if (((Element) n).getContent().equals(\")\")) {\n                                        n = get_next_node(n);\n                                        if (n instanceof Element && ((Element) n).getContent().equals(\"->\")) {\n                                                return true;\n                                        }\n                                }\n                        }\n                } else if (elem.getTokenType() == TokenType.VALID_NAME) {\n                        Node n = get_next_node(elem);\n                        if (n instanceof Element) {\n                                if (((Element) n).getContent().equals(\"->\")) {\n                                        return true;\n                                }\n                        }\n                }\n                return false;\n        }\n\n        public static int checkMethodDef(Element elem, boolean annosOrModifiersNotEmpty) throws UnexpectedEndException {\n                if (elem.getTokenType() == TokenType.VALID_NAME) {\n                        Node nodeAfterRightPar = null;\n                        Node rightPar = null;\n\n                        // method\n                        Node n1 = get_next_node(elem);\n                        if (n1 instanceof Element) {\n                                String p = ((Element) n1).getContent();\n                                if (p.equals(\"(\")) {\n                                        Node n2 = get_next_node(n1);\n                                        if (n2 instanceof ElementStartNode) {\n                                                // method(口\n                                                Node n3 = get_next_node(n2);\n                                                if (n3 instanceof Element) {\n                                                        // method(口)\n                                                        if (((Element) n3).getContent().equals(\")\")) {\n                                                                rightPar = n3;\n                                                                nodeAfterRightPar = get_next_node(n3);\n                                                        }\n                                                }\n                                        } else if (n2 instanceof Element) {\n                                                // method()\n                                                if (((Element) n2).getContent().equals(\")\")) {\n                                                        rightPar = n2;\n                                                        nodeAfterRightPar = get_next_node(n2);\n                                                }\n                                        }\n                                }\n                        }\n\n                        if (nodeAfterRightPar == null) {\n                                if (rightPar != null && annosOrModifiersNotEmpty) {\n                                        return METHOD_DEF_EMPTY;\n                                }\n                        } else {\n                                if (nodeAfterRightPar instanceof ElementStartNode) {\n                                        if (annosOrModifiersNotEmpty) {\n                                                return METHOD_DEF_NORMAL;\n                                        }\n                                } else if (nodeAfterRightPar instanceof Element) {\n                                        String s = ((Element) nodeAfterRightPar).getContent();\n                                        if (s.equals(\":\")) {\n                                                return METHOD_DEF_TYPE;\n                                        } else if (s.equals(\"=\")) {\n                                                Node nn = get_next_node(nodeAfterRightPar);\n                                                if (nn instanceof Element) {\n                                                        if (((Element) nn).getContent().equals(\"...\"))\n                                                                return METHOD_DEF_EMPTY;\n                                                        else\n                                                                return METHOD_DEF_ONE_STMT;\n                                                }\n                                        }\n                                } else if (nodeAfterRightPar instanceof EndingNode && annosOrModifiersNotEmpty) {\n                                        return METHOD_DEF_EMPTY;\n                                }\n                        }\n                }\n                return NOT_METHOD_DEF;\n        }\n\n        private static Set<String> twoVarOperators;\n\n        public static boolean isTwoVariableOperator(String str) {\n                return twoVarOperators.contains(str);\n        }\n\n        private static Set<String> oneVarOperatorsPost = new HashSet<String>(Arrays.asList(\n                \"++\", \"--\"\n        ));\n\n        public static boolean isOneVariableOperatorPost(String str) {\n                return oneVarOperatorsPost.contains(str);\n        }\n\n        private static Set<String> oneVarOperatorsPreWithoutCheckingExps = new HashSet<String>(Arrays.asList(\n                \"!\", \"~\"\n        ));\n\n        private static Set<String> oneVarOperatorsPreMustCheckExps = new HashSet<String>(Arrays.asList(\n                \"++\", \"--\", \"!\", \"~\", \"+\", \"-\"\n        ));\n\n        public static boolean isOneVariableOperatorPreWithoutCheckingExps(String str) {\n                return oneVarOperatorsPreWithoutCheckingExps.contains(str);\n        }\n\n        public static boolean isOneVariableOperatorPreMustCheckExps(String str) {\n                return oneVarOperatorsPreMustCheckExps.contains(str);\n        }\n\n        private static String[][] twoVar_priority = {\n                // invokes concat(?)\n                {\":::\"},\n                {\"^^\"}, // pow\n                {\"*\", \"/\", \"%\"},\n                {\"+\", \"-\"},\n                {\"<<\", \">>\", \">>>\"},\n                {\">\", \"<\", \">=\", \"<=\"},\n                {\"==\", \"!=\", \"===\", \"!==\", \"is\", \"not\", \"in\"},\n                {\"&\"},\n                {\"^\"},\n                {\"|\"},\n                {\"&&\", \"and\"},\n                {\"||\", \"or\"},\n                {\":=\"}\n        };\n\n        /**\n         * a higher or equal to b\n         *\n         * @param a a\n         * @param b b\n         * @return true if a higher or equal to b\n         */\n        public static boolean twoVar_higherOrEqual(String a, String b) {\n                int indexA = find_twoVar_priority(a);\n                if (indexA == -1) {\n                        indexA = twoVar_priority.length;\n                }\n                int indexB = find_twoVar_priority(b);\n                if (indexB == -1) {\n                        indexB = twoVar_priority.length;\n                }\n                return indexA <= indexB;\n        }\n\n        private static int find_twoVar_priority(String s) {\n                for (int i = 0; i < twoVar_priority.length; ++i) {\n                        String[] arr = twoVar_priority[i];\n                        for (String anArr : arr) {\n                                if (anArr.equals(s)) {\n                                        return i;\n                                }\n                        }\n                }\n                return -1;\n        }\n\n        public static void expecting(String token, Node previous, Node got, ErrorManager err) throws UnexpectedTokenException, UnexpectedEndException {\n                if (got == null) {\n                        err.UnexpectedEndException(previous.getLineCol());\n                } else if (!(got instanceof Element)) {\n                        throw new UnexpectedTokenException(\"\", token, got.getClass().getSimpleName(), got.getLineCol());\n                } else if (!((Element) got).getContent().endsWith(token)) {\n                        throw new UnexpectedTokenException(\"\", token, ((Element) got).getContent(), got.getLineCol());\n                }\n        }\n\n        public static boolean isAssign(String s) {\n                if (s.equals(\"=\")) return true;\n                if (s.endsWith(\"=\")) {\n                        String before = s.substring(0, s.length() - 1);\n                        if (isTwoVariableOperator(before)) return true;\n                }\n                return false;\n        }\n\n        public static boolean isDestructing(String str) {\n                return str.equals(\"<-\");\n        }\n\n        public static boolean isPatternMatchingSymbol(String str) {\n                return str.equals(\"=>\");\n        }\n\n        public static boolean isDestructing(Element e) {\n                if (e.getTokenType() != TokenType.VALID_NAME) return false;\n                while (true) {\n                        if (!(e.next() instanceof Element)) return false;\n                        e = (Element) e.next();\n                        if (e.getContent().equals(\"(\")) break;\n                        if (e.getTokenType() != TokenType.VALID_NAME\n                                && !e.getContent().equals(\"::\")\n                                && !e.getContent().equals(\".\")) {\n                                return false;\n                        }\n                }\n\n                Node rightPar;\n                // (\n                if (e.next() instanceof ElementStartNode) {\n                        if (e.next().next() instanceof EndingNode\n                                && e.next().next().next() instanceof Element\n                                && ((Element) e.next().next().next()).getContent().equals(\")\")) {\n                                rightPar = e.next().next().next();\n                        } else {\n                                return false;\n                        }\n                } else if (e.next() instanceof Element) {\n                        if (((Element) e.next()).getContent().equals(\")\")) {\n                                // )\n                                rightPar = e.next();\n                        } else {\n                                return false;\n                        }\n                } else return false;\n\n                return rightPar.next() instanceof Element && ((Element) rightPar.next()).getContent().equals(\"<-\");\n        }\n\n        public static boolean isDestructingWithoutType(Element e) {\n                // previous node is not TypeName\n                if (e.previous() != null && e.previous().getTokenType() == TokenType.VALID_NAME) return false;\n                // (......)\n                if (!e.getContent().equals(\"(\")) return false;\n                if (e.next() instanceof Element) {\n                        e = (Element) e.next();\n                } else if (e.next() instanceof ElementStartNode) {\n                        Node n = e.next();\n                        if (n.next() instanceof EndingNode) n = n.next();\n                        if (!(n.next() instanceof Element)) return false;\n                        e = (Element) n.next();\n                } else return false;\n                if (!e.getContent().equals(\")\")) return false;\n\n                // <- | =\n                if (!(e.next() instanceof Element)) return false;\n                if (!((Element) e.next()).getContent().equals(\"<-\")\n                        &&\n                        !((Element) e.next()).getContent().equals(\"=\")) return false;\n                //\n                return true;\n        }\n\n        public static boolean isSync(Element elem) {\n                String content = elem.getContent();\n                if (content.equals(\"synchronized\")) {\n                        Node n = get_next_node(elem);\n                        if (n instanceof Element) {\n                                String s = ((Element) n).getContent();\n                                if (s.equals(\"(\")) {\n                                        return true;\n                                }\n                        }\n                }\n                return false;\n        }\n\n        private static Set<String> primitives = new HashSet<String>(Arrays.asList(\n                \"int\", \"double\", \"float\", \"short\", \"long\", \"byte\", \"char\", \"bool\"\n        ));\n\n        public static boolean isPrimitive(String s) {\n                return primitives.contains(s);\n        }\n\n        static {\n                // 2 var op\n                twoVarOperators = new HashSet<String>();\n                for (String[] sArr : twoVar_priority) {\n                        Collections.addAll(twoVarOperators, sArr);\n                }\n\n                keys.addAll(modifiers);\n                keys.addAll(javaKeys);\n        }\n\n        public static String validateValidName(String validName) {\n                if (validName.startsWith(\"`\")) return validName.substring(1, validName.length() - 1);\n                return validName;\n        }\n\n        public static boolean isSymbol(String str) {\n                return isTwoVariableOperator(str)\n                        || isOneVariableOperatorPost(str)\n                        || isOneVariableOperatorPreMustCheckExps(str)\n                        || isOneVariableOperatorPreWithoutCheckingExps(str)\n                        || isAssign(str)\n                        || isDestructing(str)\n                        || isPatternMatchingSymbol(str);\n        }\n\n        public static <T> void visitStmt(Statement s, Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                if (s == null) {\n                        return;\n                }\n                if (f.apply(s, t)) {\n                        s.foreachInnerStatements(f, t);\n                }\n        }\n\n        public static <T> void visitStmt(Collection<? extends Statement> stmts, Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                if (stmts == null) {\n                        return;\n                }\n                for (Statement s : stmts) {\n                        visitStmt(s, f, t);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/ErrorManager.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.IllegalIndentationException;\nimport lt.compiler.syntactic.DuplicateVariableNameException;\nimport lt.compiler.syntactic.UnexpectedNewLayerException;\nimport lt.compiler.syntactic.UnknownTokenException;\n\nimport java.io.PrintStream;\nimport java.text.DateFormat;\nimport java.util.*;\nimport java.util.concurrent.ConcurrentHashMap;\n\n/**\n * controls compiling errors/info/warnings display and exception throwing.\n */\npublic class ErrorManager {\n        public static class Out {\n                public PrintStream debug = null;\n                public PrintStream info = System.out;\n                public PrintStream warn = System.err;\n                public PrintStream err = System.err;\n\n                public static Out allNull() {\n                        Out out = new Out();\n                        out.debug = null;\n                        out.info = null;\n                        out.warn = null;\n                        out.err = null;\n                        return out;\n                }\n        }\n\n        private boolean fastFail;\n        public Out out = new Out();\n        public final List<CompilingError> errorList = new ArrayList<CompilingError>();\n\n        public final StringBuilder sb = new StringBuilder();\n\n        /**\n         * records {fileName =&gt;{LineNumber=&gt;LineContent}}\n         */\n        public final Map<String, Map<Integer, String>> lineRecord = new ConcurrentHashMap<String, Map<Integer, String>>();\n\n        public static class CompilingError {\n                public final String msg;\n                public final LineCol lineCol;\n                public final int type;\n\n                public static final int Syntax = 1;\n                public static final int UnknownToken = 2;\n                public static final int UnexpectedToken = 3;\n                public static final int Indentation = 4;\n                public static final int UnexpectedEnd = 5;\n                public static final int UnexpectedNewLayer = 6;\n                public static final int DuplicateVariableName = 7;\n\n                private CompilingError(String msg, LineCol lineCol, int type) {\n                        this.msg = msg;\n                        this.lineCol = lineCol;\n                        this.type = type;\n                }\n        }\n\n        private static final DateFormat df = DateFormat.getDateTimeInstance();\n\n        /**\n         * construct an ErrorManager\n         *\n         * @param fastFail throw exception when meets an exception\n         */\n        public ErrorManager(boolean fastFail) {\n                this.fastFail = fastFail;\n        }\n\n        /**\n         * set fast fail. It's called in {@link SemanticProcessor}\n         *\n         * @param fastFail fast fail\n         */\n        public void setFastFail(boolean fastFail) {\n                this.fastFail = fastFail;\n        }\n\n        /**\n         * put the line record\n         *\n         * @param file    file name\n         * @param line    the line number\n         * @param content the content of the line\n         */\n        public void putLineRecord(String file, int line, String content) {\n                Map<Integer, String> map;\n                if (lineRecord.containsKey(file)) {\n                        map = lineRecord.get(file);\n                } else {\n                        map = new HashMap<Integer, String>();\n                        lineRecord.put(file, map);\n                }\n\n                map.put(line, content);\n        }\n\n        /**\n         * build error info. The error info looks like :<br>\n         * <pre>\n         * the statement\n         *     ^\n         * </pre><br>\n         * detailed info can directly concat to this string\n         *\n         * @param file the file\n         * @param line line\n         * @param col  column\n         * @return the error info\n         */\n        public String buildErrInfo(String file, int line, int col) {\n                if (!lineRecord.containsKey(file)) return \"\";\n                String content = lineRecord.get(file).get(line);\n                if (content == null) return \"\";\n                StringBuilder sb = new StringBuilder(\"\\n\");\n                sb.append(content).append(\"\\n\");\n                for (int i = 1; i < col; ++i) {\n                        sb.append(\" \");\n                }\n                sb.append(\"^ \");\n                return sb.toString();\n        }\n\n        /**\n         * invoke {@link #buildErrInfo(String, int, int)}\n         *\n         * @param lineCol line col\n         * @return the error info\n         */\n        public String buildErrInfo(LineCol lineCol) {\n                if (lineCol == null || lineCol.fileName == null || lineCol.line <= 0 || lineCol.column <= 0) return \"\";\n                return buildErrInfo(lineCol.fileName, lineCol.line, lineCol.column);\n        }\n\n        private void print(String msg, PrintStream out) {\n                if (out != null) {\n                        msg = \"[\" + df.format(new Date()) + \"]\" + msg;\n                        out.println(msg);\n                        sb.append(msg).append(\"\\n\");\n                }\n        }\n\n        /**\n         * print an error to printStream\n         *\n         * @param msg the message to print\n         */\n        public void error(String msg) {\n                print(\"[ERROR] \" + msg, out.err);\n        }\n\n        /**\n         * print a warning to printStream\n         *\n         * @param msg the message to print\n         */\n        public void warning(String msg) {\n                print(\"[WARNING] \" + msg, out.warn);\n        }\n\n        /**\n         * print a info to printStream\n         *\n         * @param msg the message to print\n         */\n        public void info(String msg) {\n                print(\"[INFO] \" + msg, out.info);\n        }\n\n        /**\n         * print a debug info to printStream\n         *\n         * @param msg the message to print\n         */\n        public void debug(String msg) {\n                print(\"[DEBUG] \" + msg, out.debug);\n        }\n\n        /**\n         * got a syntax exception\n         *\n         * @param msg     message\n         * @param lineCol file,line,column info\n         * @throws SyntaxException compiling error\n         */\n        public void SyntaxException(String msg, LineCol lineCol) throws SyntaxException {\n                if (fastFail) throw new SyntaxException(buildErrInfo(lineCol), msg, lineCol);\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.Syntax));\n        }\n\n        /**\n         * directly throw the exception if fastFail is true. otherwise call {@link #SyntaxException(String, LineCol)}\n         *\n         * @param msg     message\n         * @param lineCol lineCol\n         * @param e       exception to throw\n         * @throws SyntaxException compiling error\n         */\n        public void SyntaxException(String msg, LineCol lineCol, SyntaxException e) throws SyntaxException {\n                if (fastFail) throw e;\n                SyntaxException(msg, lineCol);\n        }\n\n        /**\n         * got an unexpected end\n         *\n         * @param lineCol file,line,column info\n         * @throws UnexpectedEndException compiling error\n         */\n        public void UnexpectedEndException(LineCol lineCol) throws UnexpectedEndException {\n                if (fastFail) throw new UnexpectedEndException(buildErrInfo(lineCol), lineCol);\n                final String msg = \"unexpected end\";\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.UnexpectedEnd));\n        }\n\n        /**\n         * occurred an unexpected token\n         *\n         * @param expected expected token structure\n         * @param got      got token\n         * @param lineCol  file,line,column info\n         * @throws UnexpectedTokenException compiling error\n         */\n        public void UnexpectedTokenException(String expected, String got, LineCol lineCol) throws UnexpectedTokenException {\n                if (fastFail) throw new UnexpectedTokenException(buildErrInfo(lineCol), expected, got, lineCol);\n                String msg = \"expecting \" + expected + \", but got \" + got;\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.UnexpectedToken));\n\n        }\n\n        /**\n         * occurred an unexpected token\n         *\n         * @param token   unexpected token\n         * @param lineCol file,line,column info\n         * @throws UnexpectedTokenException compiling error\n         */\n        public void UnexpectedTokenException(String token, LineCol lineCol) throws UnexpectedTokenException {\n                if (fastFail) throw new UnexpectedTokenException(buildErrInfo(lineCol), token, lineCol);\n                String msg = \"unexpected token \" + token;\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.UnexpectedToken));\n        }\n\n        /**\n         * occurred illegal indentation\n         *\n         * @param expectedIndent the expected indent\n         * @param lineCol        file,line,column info\n         * @throws IllegalIndentationException compiling error\n         */\n        public void IllegalIndentationException(int expectedIndent, LineCol lineCol) throws IllegalIndentationException {\n                if (fastFail) throw new IllegalIndentationException(buildErrInfo(lineCol), expectedIndent, lineCol);\n                String msg = \"the indentation should be \" + expectedIndent + \" spaces\";\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.Indentation));\n        }\n\n        /**\n         * occurred an unexpected new Layer\n         *\n         * @param lineCol file,line,column info\n         * @throws UnexpectedNewLayerException compiling error\n         */\n        public void UnexpectedNewLayerException(LineCol lineCol) throws UnexpectedNewLayerException {\n                if (fastFail) throw new UnexpectedNewLayerException(buildErrInfo(lineCol), lineCol);\n                String msg = \"unexpected new layer\";\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.UnexpectedNewLayer));\n        }\n\n        /**\n         * occurred an unknown token\n         *\n         * @param token   the unknown token\n         * @param lineCol file,line,column info\n         * @throws UnknownTokenException compiling error\n         */\n        public void UnknownTokenException(String token, LineCol lineCol) throws UnknownTokenException {\n                if (fastFail) throw new UnknownTokenException(buildErrInfo(lineCol), token, lineCol);\n                String msg = \"unknown token \" + token;\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.UnknownToken));\n        }\n\n        public void DuplicateVariableNameException(String name, LineCol lineCol) throws DuplicateVariableNameException {\n                if (fastFail) throw new DuplicateVariableNameException(buildErrInfo(lineCol), name, lineCol);\n                String msg = \"duplicate name \" + name;\n                msg = buildErrInfo(lineCol) + msg;\n\n                error(msg + \" at \" + lineCol);\n                errorList.add(new CompilingError(msg, lineCol, CompilingError.DuplicateVariableName));\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/IndentScanner.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.*;\nimport lt.compiler.syntactic.UnknownTokenException;\n\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.util.Map;\n\n/**\n * transform plain <tt>Latte</tt> text into Tokens<br>\n * <tt>Latte</tt> uses indentation to differ program blocks<br>\n * Instead of using <tt>INDENT</tt> and <tt>DEDENT</tt>, the Scanner uses a <b>Tree of Tokens</b> to record the indentation info.\n * Consistent statements with the same indentation are in the same <b>Layer</b><br>\n * <pre>\n * class User\n *     id : int\n *     name : String\n * </pre>\n * <code>(id : int)</code> and <code>(name : String)</code> are in the same layer<br>\n * the text would be considered as the following token tree<br>\n * <pre>\n * [class]-[User]-[|]-[END]\n *                 |\n *                 --[id]-[:]-[int]-[END]-[name]-[:]-[String]\n * </pre>\n *\n * @see Node\n * @see Element\n * @see ElementStartNode\n * @see EndingNode\n */\npublic class IndentScanner extends AbstractScanner {\n        /**\n         * initiate the processor with a reader\n         *\n         * @param fileName   the input text file name\n         * @param reader     text reader\n         * @param properties properties for the Scanner\n         * @param err        error manager\n         */\n        public IndentScanner(String fileName, Reader reader, Properties properties, ErrorManager err) {\n                super(fileName, reader, properties, err);\n        }\n\n        /**\n         * <ol>\n         * <li>read a line from the {@link #reader}</li>\n         * <li>check indentation</li>\n         * <li>check layer =&gt; if indent &gt; lastLayerIndent, then start a new layer.\n         * elseif indent &lt; lastLayerIndent then it should go back to upper layers<br>\n         * </li>\n         * <li>invoke {@link #scan(String, Args)} to scan the current line</li>\n         * <li>append an {@link EndingNode}</li>\n         * </ol>\n         *\n         * @param args args context\n         * @throws IOException     exceptions during reading chars from reader\n         * @throws SyntaxException syntax exceptions, including {@link SyntaxException}, {@link UnexpectedTokenException}, {@link IllegalIndentationException}\n         * @see #scan(String, Args)\n         */\n        @Override\n        protected void scan(Args args) throws IOException, SyntaxException {\n                String line = reader.readLine();\n                int rootIndent = -1;\n                while (line != null) {\n                        ++args.currentLine;\n\n                        err.putLineRecord(args.fileName, args.currentLine, line);\n\n                        args.currentCol = properties._COLUMN_BASE_;\n                        args.useDefine.clear();\n\n                        if (args.multipleLineComment) {\n                                if (!line.contains(MultipleLineCommentEnd)) {\n                                        line = reader.readLine();\n                                        continue;\n                                } else {\n                                        int subCol = line.indexOf(MultipleLineCommentEnd) + MultipleLineCommentEnd.length();\n                                        line = line.substring(subCol);\n                                        args.currentCol += (subCol + 1);\n                                        args.multipleLineComment = false;\n                                }\n                        }\n\n                        // the line is nothing but comment\n                        if (line.trim().startsWith(COMMENT)) {\n                                line = reader.readLine();\n                                continue;\n                        }\n\n                        int COMMENT_index = line.indexOf(COMMENT);\n                        if (COMMENT_index != -1) {\n                                String pre = line.substring(0, COMMENT_index);\n                                String post = line.substring(COMMENT_index);\n                                for (Map.Entry<String, String> definedEntry : args.defined.entrySet()) {\n                                        String tmp = pre;\n                                        pre = pre.replace(definedEntry.getKey(), definedEntry.getValue());\n                                        if (!tmp.equals(pre)) {\n                                                args.useDefine.put(definedEntry.getKey(), definedEntry.getValue());\n                                        }\n                                }\n                                line = pre + post;\n                        } else {\n                                for (Map.Entry<String, String> definedEntry : args.defined.entrySet()) {\n                                        String tmp = line;\n                                        line = line.replace(definedEntry.getKey(), definedEntry.getValue());\n                                        if (!tmp.equals(line)) {\n                                                args.useDefine.put(definedEntry.getKey(), definedEntry.getValue());\n                                        }\n                                }\n                        }\n\n                        // get front spaces\n                        int spaces = 0;\n                        for (int i = 0; i < line.length(); ++i) {\n                                if (line.charAt(i) != ' ') {\n                                        spaces = i;\n                                        break;\n                                }\n                        }\n\n                        // set root indent\n                        if (rootIndent == -1) {\n                                rootIndent = spaces;\n                                spaces = 0;\n                        } else {\n                                spaces -= rootIndent;\n                        }\n\n                        if (args.currentCol == properties._COLUMN_BASE_) {\n                                args.currentCol += spaces + 1 + rootIndent;\n                        }\n\n                        int indentation = spaces;\n\n                        // remove spaces\n                        line = line.trim();\n\n                        // check it's an empty line\n                        if (line.isEmpty()) {\n                                line = reader.readLine();\n                                continue;\n                        }\n\n                        // check start node\n                        ElementStartNode lastStartNode = args.startNodeStack.lastElement();\n                        Indent lastIndentElem = lastStartNode.getIndent();\n                        int lastNonFlexIndent = args.getLastNonFlexIndent();\n                        if (indentation > lastNonFlexIndent && lastIndentElem.getIndent() == Indent.FLEX) {\n                                // flex\n                                ElementStartNode parent = args.startNodeStack.elementAt(args.startNodeStack.size() - 2);\n                                Indent parentIndent = parent.getIndent();\n                                if (indentation > parentIndent.getIndent()) {\n                                        // greater indent, assign it to the flex\n                                        lastIndentElem.setIndent(indentation);\n                                } else {\n                                        // smaller or equal\n                                        // do redirect\n                                        redirectToDeeperStartNodeByIndent(args, indentation, true);\n                                }\n                        } else {\n                                if (lastIndentElem.getIndent() != indentation) {\n                                        if (indentation <= lastNonFlexIndent) {\n                                                // smaller indent\n                                                // check PAIR_END and handle\n                                                boolean isPairEnd = false;\n                                                for (String pairEnd : PAIR.values()) {\n                                                        if (line.startsWith(pairEnd)) {\n                                                                isPairEnd = true;\n                                                                PairEntry lastPair = args.pairEntryStack.lastElement();\n\n                                                                // check indentation\n                                                                ElementStartNode theStartNode = lastPair.startNode;\n                                                                // go to it's parent\n                                                                for (int i = args.startNodeStack.size() - 1; i >= 0; --i) {\n                                                                        ElementStartNode node = args.startNodeStack.get(i);\n                                                                        if (node == theStartNode) {\n                                                                                assert i != 0;\n                                                                                theStartNode = args.startNodeStack.get(i - 1);\n                                                                                break;\n                                                                        }\n                                                                }\n                                                                Indent indent = theStartNode.getIndent();\n                                                                if (indent.getIndent() != Indent.FLEX) {\n                                                                        // current should greater or equal\n                                                                        // else, raise compile error\n                                                                        if (indentation < indent.getIndent()) {\n                                                                                err.IllegalIndentationException(indent.getIndent(), args.generateLineCol());\n                                                                                // error handling: ignore and assume it's correct\n                                                                        }\n                                                                }\n                                                                if (!PAIR.get(lastPair.key).equals(pairEnd)) {\n                                                                        // last pair mismatch\n                                                                        // set `isPairEnd` to false\n                                                                        // and throw compile error\n                                                                        // in later steps\n                                                                        isPairEnd = false;\n                                                                }\n                                                                break;\n                                                        }\n                                                }\n                                                // if is  PAIR_END, handle the redirect in later steps\n                                                // if not PAIR_END, redirect the startNode\n                                                if (!isPairEnd) {\n                                                        redirectToDeeperStartNodeByIndent(args, indentation, true);\n                                                }\n                                        } else { // if (lastIndent > indentation) {\n                                                // greater indent\n                                                createStartNode(args, indentation);\n                                        }\n                                }\n                        }\n\n                        // start parsing\n                        scan(line, args);\n\n                        if (!args.multipleLineComment) {\n\n                                if (args.previous instanceof Element) {\n                                        args.previous = new EndingNode(args, EndingNode.WEAK);\n                                }\n                        }\n\n                        line = reader.readLine();\n                }\n        }\n\n        /**\n         * when the given line is not empty, do scanning.<br>\n         * <ol>\n         * <li>check whether the line contains tokens in {@link #SPLIT}<br>\n         * get the most front token, if several tokens are at the same position, then choose the longest one</li>\n         * <li>if the token not found, consider the whole line as one element and append to previous node</li>\n         * <li>else</li>\n         * <li>record text before the token as an element and do appending</li>\n         * <li>check which category the token is in<br>\n         * <ul>\n         * <li>{@link #LAYER} means starts after recording the token, a new ElementStartNode should be started, invoke {@link #createStartNode(Args, int)}</li>\n         * <li>{@link #SPLIT_X}: the previous element and next element should be in the same layer. if it's also among {@link #NO_RECORD}, the token won't be recorded</li>\n         * <li>{@link #STRING}: the next element is a string or a character. these characters should be considered as one element</li>\n         * <li>{@link #ENDING}: append a new {@link EndingNode} to prevent generated nodes being ambiguous. NOTE that it only means the end of an expression or a statement. not the parsing process</li>\n         * <li>{@link #COMMENT}: it's the start of a comment. the following chars would be ignored</li>\n         * <li>{@link #PAIR}: for keys, it will start a new layer. for values, it will end the layer created by the key</li>\n         * </ul>\n         * </li>\n         * </ol><br>\n         * here's an example of how the method works<br>\n         * given the following input:<br>\n         * <pre>\n         * val map={'name':'cass'}\n         * </pre>\n         * <ol>\n         * <li>the most front and longest token is ' ', and ' ' is in {@link #NO_RECORD} ::: <code>val/map={'name':'cass'}</code></li>\n         * <li>the most front and longest token is '=' ::: <code>val/map/=/{'name':'cass'}</code></li>\n         * <li>the most front and longest token is '{', and '{' is a key of {@link #PAIR} ::: <code>val/map/=/{/(LAYER-START/'name':'cass'})</code></li>\n         * <li>the most front and longest token is \"'\", and \"'\" is in {@link #STRING} ::: <code>val/map/=/{/(LAYER-START/'name'/:'cass'})</code></li>\n         * <li>the most front and longest token is ':' ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass'})</code></li>\n         * <li>the most front and longest token is \"'\", and \"'\" is in {@link #STRING} ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass'/})</code></li>\n         * <li>the most front and longest token is \"}\", and '}' is a value of {@link #PAIR} ::: <code>val/map/=/{/(LAYER-START/'name'/:/'cass')}</code></li>\n         * </ol><br>\n         * the result is <code>val/map/=/{/(LAYER-START/'name'/:/'cass')}</code><br>\n         * set a breakpoint in the method and focus on variable <tt>line</tt>, you will get exactly the same intermediate results\n         *\n         * @param line line to parse\n         * @param args args context\n         * @throws SyntaxException syntax exceptions, including {@link SyntaxException}, {@link UnexpectedTokenException}\n         */\n        private void scan(String line, Args args) throws SyntaxException {\n                if (line.isEmpty()) return;\n\n                // check multiple line comment\n                if (args.multipleLineComment) {\n                        if (line.contains(MultipleLineCommentEnd)) {\n                                int subCol = line.indexOf(MultipleLineCommentEnd) + MultipleLineCommentEnd.length();\n                                args.currentCol += subCol;\n                                line = line.substring(subCol);\n                                args.multipleLineComment = false;\n                        } else {\n                                return;\n                        }\n                }\n\n                // check SPLIT\n                // find the pattern at minimum location index and with longest words\n                int minIndex = line.length();\n                String token = null; // recorded token\n                for (String s : SPLIT) {\n                        if (line.contains(s)) {\n                                int index = line.indexOf(s);\n                                if (index != -1 && index < minIndex) {\n                                        minIndex = index;\n                                        token = s;\n                                }\n                        }\n                }\n\n                if (token == null) {\n                        if (!line.isEmpty()) {\n                                // not found, simply append whole input to previous\n                                TokenType type = getTokenType(line, args.generateLineCol());\n                                if (type != null) {\n                                        // unknown token, ignore this token\n                                        args.previous = new Element(args, line, type);\n                                        args.currentCol += line.length();\n                                }\n                        }\n                } else {\n                        String copyOfLine = line;\n                        String str = line.substring(0, minIndex);\n                        if (!str.isEmpty()) {\n                                // record text before the token\n                                TokenType type = getTokenType(str, args.generateLineCol());\n                                if (type != null) {\n                                        args.previous = new Element(args, str, type);\n                                }\n                                args.currentCol += str.length();\n                        }\n\n                        if (LAYER.contains(token)) {\n                                // start new layer\n                                args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                createStartNode(args, Indent.FLEX);\n                        } else if (SPLIT_X.contains(token)) {\n                                // do split check\n                                if (!NO_RECORD.contains(token)) {\n                                        // record this token\n                                        args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                }\n                        } else if (STRING.contains(token)) {\n                                // string literal\n                                int lastIndex = minIndex;\n                                while (true) {\n                                        int index = line.indexOf(token, lastIndex + token.length());\n                                        if (token.equals(\"//\")) {\n                                                while (line.length() > index + 2) {\n                                                        if (line.charAt(index + 2) == '/') {\n                                                                ++index;\n                                                        } else {\n                                                                break;\n                                                        }\n                                                }\n                                        }\n                                        if (line.length() <= 1 || index == -1) {\n                                                err.SyntaxException(\"end of string not found\", args.generateLineCol());\n                                                // assume that the end is line end\n                                                err.debug(\"assume that the \" + token + \" end is line end\");\n\n                                                String generated = line.substring(minIndex) + token;\n\n                                                args.previous = new Element(args, generated, getTokenType(generated, args.generateLineCol()));\n                                                args.currentCol += (index - minIndex) - token.length(); // the length would be added in later steps\n                                                line = line.substring(index + 1);\n\n                                                break;\n                                        } else {\n                                                String c = String.valueOf(line.charAt(index - 1));\n                                                // check\n                                                boolean isStringEnd = !ESCAPE.equals(c) || checkStringEnd(line, index - 1);\n\n                                                if (isStringEnd) {\n                                                        // the string starts at minIndex and ends at index\n                                                        String s = line.substring(minIndex, index + token.length());\n\n                                                        args.previous = new Element(args, s, getTokenType(s, args.generateLineCol()));\n                                                        args.currentCol += (index - minIndex);\n                                                        line = line.substring(index + token.length());\n                                                        break;\n                                                }\n\n                                                lastIndex = index;\n                                        }\n                                }\n                        } else if (ENDING.contains(token)) {\n                                // ending\n                                if (args.previous instanceof Element) {\n                                        args.previous = new EndingNode(args, EndingNode.STRONG);\n                                }\n                        } else if (COMMENT.equals(token)) {\n                                // comment\n                                line = \"\"; // ignore all\n                        } else if (PAIR.containsKey(token)) {\n                                // pair start\n                                args.previous = new Element(args, token, getTokenType(token, args.generateLineCol()));\n                                createStartNode(args, Indent.FLEX);\n                                args.pairEntryStack.push(new PairEntry(token, args.startNodeStack.lastElement()));\n                        } else if (PAIR.containsValue(token)) {\n                                // pair end\n                                if (args.pairEntryStack.isEmpty()) {\n                                        err.UnexpectedTokenException(token, args.generateLineCol());\n                                        return;\n                                }\n                                PairEntry entry = args.pairEntryStack.pop();\n                                String start = entry.key;\n                                if (!token.equals(PAIR.get(start))) {\n                                        err.UnexpectedTokenException(PAIR.get(start), token, args.generateLineCol());\n                                        // assume that the pair ends\n                                        err.debug(\"assume that the pair ends\");\n                                }\n\n                                ElementStartNode pairStartNode = entry.startNode;\n                                if (pairStartNode.hasNext()) {\n                                        if (pairStartNode.next() instanceof EndingNode && !pairStartNode.next().hasNext()) {\n                                                pairStartNode.setNext(null);\n                                        } else {\n                                                err.SyntaxException(\n                                                        \"indentation of \" + pairStartNode.next() + \" should be \" + pairStartNode.getIndent(),\n                                                        pairStartNode.next().getLineCol());\n                                                // fill the LinkedNode with all nodes after the pairStartNode\n                                                Node n = pairStartNode.next();\n                                                n.setPrevious(null);\n                                                pairStartNode.setNext(null);\n                                                pairStartNode.setLinkedNode(n);\n                                        }\n                                }\n\n                                ElementStartNode lastElement = args.startNodeStack.lastElement();\n                                Indent lastIndentElem = lastElement.getIndent();\n                                int lastIndent = lastIndentElem.getIndent();\n                                int pairIndent = pairStartNode.getIndent().getIndent();\n                                if (lastIndent >= pairIndent) {\n                                        redirectToPairStart(args, pairStartNode.getIndent());\n                                } else {\n                                        args.previous = pairStartNode;\n                                }\n                                args.previous = new Element(args, PAIR.get(start), getTokenType(token, args.generateLineCol()));\n                        } else if (token.equals(MultipleLineCommentStart)) {\n                                if (!args.multipleLineComment) {\n                                        args.multipleLineComment = true;\n                                }\n                        } else {\n                                err.UnknownTokenException(token, args.generateLineCol());\n                                // unknown token\n                                // simply ignore the token\n                        }\n\n                        // column\n                        args.currentCol += token.length();\n                        if (copyOfLine.equals(line)) {\n                                // line hasn't changed, do default modification\n                                line = line.substring(minIndex + token.length());\n                        }\n                        // recursively parse\n                        scan(line, args);\n                }\n        }\n\n        @Override\n        protected void finalCheck(ElementStartNode root) throws UnknownTokenException {\n                super.finalCheck(root);\n\n                if (root.hasLinkedNode()) {\n                        Node n = root.getLinkedNode();\n                        // remove redundant start node\n                        if (!n.hasNext() && n instanceof ElementStartNode) {\n                                Node newN = ((ElementStartNode) n).getLinkedNode();\n                                root.setLinkedNode(newN);\n                                n = newN;\n                        }\n\n                        while (n != null) {\n                                if (n instanceof Element) {\n                                        // remove {...} without `:` between them and not empty\n                                        if (((Element) n).getContent().equals(\"{\")) {\n                                                Node afterBraceStart = n.next();\n                                                if (!(afterBraceStart instanceof Element)\n                                                        || !((Element) afterBraceStart).getContent().equals(\"}\")) {\n                                                        assert afterBraceStart instanceof ElementStartNode;\n                                                        removeLayerControlSymbols(root, (Element) n);\n                                                        while (true) {\n                                                                n = n.next();\n                                                                if (n instanceof Element\n                                                                        && ((Element) n).getContent().equals(\"}\")) {\n                                                                        removeLayerControlSymbols(root, (Element) n);\n                                                                        break;\n                                                                }\n                                                        }\n                                                }\n                                        }\n                                }\n                                n = n.next();\n                        }\n\n                }\n        }\n\n        private void removeLayerControlSymbols(ElementStartNode root, Element n) {\n\n                if (n.hasPrevious()) {\n                        if (n.previous().previous() != null\n                                && n.previous() instanceof EndingNode\n                                && n.next() == null) {\n                                // remove the previous ending node\n                                n.previous().previous().setNext(null);\n                        } else {\n                                n.previous().setNext(n.next());\n                        }\n                } else if (n.getContent().equals(\"{\")) {\n                        root.setLinkedNode(n.next());\n                }\n                if (n.hasNext()) {\n                        n.next().setPrevious(n.previous());\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/LineCol.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport java.io.Serializable;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * line, column and filename info\n */\npublic class LineCol implements Serializable {\n        public final String fileName;\n        public final int line;\n        public final int column;\n        public int length;\n        public final Map<String, String> useDefine = new LinkedHashMap<String, String>();\n\n        /**\n         * construct an LineCol that represents (filename, line, column and whether uses define replacement) of a Token\n         *\n         * @param fileName file name\n         * @param line     line number starts from 1\n         * @param column   column starts from 1\n         */\n        public LineCol(String fileName, int line, int column) {\n                this.fileName = fileName;\n                this.line = line;\n                this.column = column;\n        }\n\n        /**\n         * a synthetic line col object\n         */\n        public static final LineCol SYNTHETIC = new LineCol(null, 0, 0);\n\n        public static LineCol SYNTHETIC_WITH_FILE(String file) {\n                return new LineCol(file, 0, 0);\n        }\n\n        @Override\n        public String toString() {\n                return fileName + \"(\" + line + \", \" + column + \")\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/LtBug.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * detect bug in less typing\n */\npublic class LtBug extends Error {\n        public LtBug(String msg) {\n                super(msg);\n        }\n\n        public LtBug(Throwable t) {\n                super(t);\n        }\n\n        public LtBug(String message, Throwable cause) {\n                super(message, cause);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/MultipleClassLoader.java",
    "content": "package lt.compiler;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.*;\n\n/**\n * proxies multiple class loaders\n */\npublic class MultipleClassLoader extends ClassLoader {\n        private final Set<ClassLoader> classLoaders = new HashSet<ClassLoader>();\n        private final Method mLoadClass;\n\n        public MultipleClassLoader(ClassLoader... classLoaders) {\n                this.classLoaders.addAll(Arrays.asList(classLoaders));\n                try {\n                        mLoadClass = ClassLoader.class.getDeclaredMethod(\"loadClass\", String.class, boolean.class);\n                } catch (NoSuchMethodException e) {\n                        throw new LtBug(e);\n                }\n                mLoadClass.setAccessible(true);\n        }\n\n        @Override\n        public Class<?> loadClass(String s) throws ClassNotFoundException {\n                for (ClassLoader cl : classLoaders) {\n                        try {\n                                return cl.loadClass(s);\n                        } catch (ClassNotFoundException ignore) {\n                        }\n                }\n                throw new ClassNotFoundException(s);\n        }\n\n        @Override\n        protected synchronized Class<?> loadClass(String s, boolean b) throws ClassNotFoundException {\n                for (ClassLoader cl : classLoaders) {\n                        try {\n                                return (Class<?>) mLoadClass.invoke(cl, s, b);\n                        } catch (IllegalAccessException e) {\n                                throw new LtBug(e);\n                        } catch (InvocationTargetException e) {\n                                // ignore class not found exception\n                                Throwable t = e.getCause();\n                                if (!(t instanceof ClassNotFoundException)) {\n                                        if (t instanceof RuntimeException) {\n                                                throw (RuntimeException) t;\n                                        } else if (t instanceof Error) {\n                                                throw (Error) t;\n                                        } else {\n                                                // should not happen\n                                                throw new LtBug(\"uncaught exception\", e);\n                                        }\n                                }\n                        }\n                }\n                throw new ClassNotFoundException(s);\n        }\n\n        @Override\n        public URL getResource(String s) {\n                for (ClassLoader cl : classLoaders) {\n                        URL url = cl.getResource(s);\n                        if (url != null) {\n                                return url;\n                        }\n                }\n                return null;\n        }\n\n        @Override\n        public Enumeration<URL> getResources(String s) throws IOException {\n                return new ProxyEnumeration(classLoaders.iterator(), s);\n        }\n\n        class ProxyEnumeration implements Enumeration<URL> {\n                final Iterator<ClassLoader> clIt;\n                final String resourceS;\n                Enumeration<URL> current;\n\n                ProxyEnumeration(Iterator<ClassLoader> clIt, String resourceS) {\n                        this.clIt = clIt;\n                        this.resourceS = resourceS;\n                }\n\n                @Override\n                public boolean hasMoreElements() {\n                        return clIt.hasNext() || (current != null && current.hasMoreElements());\n                }\n\n                @Override\n                public URL nextElement() {\n                        if (!hasMoreElements()) {\n                                throw new NoSuchElementException();\n                        }\n                        if (current == null) {\n                                try {\n                                        current = clIt.next().getResources(resourceS);\n                                } catch (IOException e) {\n                                        throw new RuntimeException(e);\n                                }\n                        }\n                        URL res = current.nextElement();\n                        if (!current.hasMoreElements()) {\n                                current = null;\n                        }\n                        return res;\n                }\n        }\n\n        @Override\n        public InputStream getResourceAsStream(String s) {\n                for (ClassLoader cl : classLoaders) {\n                        InputStream is = cl.getResourceAsStream(s);\n                        if (is != null) {\n                                return is;\n                        }\n                }\n                return null;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/Parser.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.*;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.pre.Import;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.operation.OneVariableOperation;\nimport lt.compiler.syntactic.operation.UnaryOneVariableOperation;\n\nimport java.util.*;\n\nimport static lt.compiler.CompileUtil.*;\n\n/**\n * syntactic processor\n */\npublic class Parser {\n        /**\n         * parse fail is used to skip current statement.\n         */\n        private class ParseFail extends RuntimeException {\n        }\n\n        /**\n         * current node\n         */\n        private Node current;\n        /**\n         * parsed expression stack\n         */\n        private Stack<Expression> parsedExps = new Stack<Expression>();\n        /**\n         * 2 variable operators\n         */\n        private Stack<String> last2VarOps = new Stack<String>();\n        /**\n         * 1 variable operators (unary)\n         */\n        private Stack<String> last1VarUnaryOps = new Stack<String>();\n        /**\n         * the names that's already used\n         */\n        private Set<String> usedVarNames = new HashSet<String>();\n        /**\n         * currently parsed modifiers\n         */\n        private Set<Modifier> modifiers = new HashSet<Modifier>();\n        /**\n         * currently parsed annotations\n         */\n        private Set<AST.Anno> annos = new HashSet<AST.Anno>();\n\n        /**\n         * <b>state</b>.<br>\n         * when parsing an expression and reaching a start node, if this variable is true, return normally. else throw exception\n         */\n        private boolean expectingStartNode = false;\n        /**\n         * <b>state</b>.<br>\n         * is parsing map literal\n         */\n        private boolean isParsingMap = false;\n        /**\n         * <b>state</b>.<br>\n         * is parsing operator like invocation\n         */\n        private boolean isParsingOperatorLikeInvocation = false;\n        /**\n         * <b>state</b>.<br>\n         * consider annotations as values\n         */\n        private boolean annotationAsExpression = false;\n        /**\n         * error manager\n         */\n        private final ErrorManager err;\n\n        /**\n         * init the syntactic processor with element start node\n         *\n         * @param root root node\n         * @param err  error manager\n         */\n        public Parser(ElementStartNode root, ErrorManager err) {\n                this.current = root.getLinkedNode();\n                this.err = err;\n        }\n\n        /**\n         * add variable names that's already used(must be invoked by parent parser)\n         *\n         * @param names names\n         */\n        private void addUsedVarNames(Set<String> names) {\n                this.usedVarNames.addAll(names);\n        }\n\n        /**\n         * jump to the end of the statement\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void jumpToTheNearestEndingNode() throws SyntaxException {\n                while (current != null && (!(current instanceof EndingNode))) {\n                        nextNode(true);\n                }\n        }\n\n        private <E> Set<E> getAndClear(Set<E> set) {\n                Set<E> s = new HashSet<E>(set);\n                set.clear();\n                return s;\n        }\n\n        /**\n         * parse the nodes into a list of statements\n         *\n         * @return a list of statements\n         * @throws SyntaxException compiling errors\n         */\n        public List<Statement> parse() throws SyntaxException {\n                List<Statement> list = new ArrayList<Statement>(); // the result list\n                while (true) {\n                        if (isParsingMap) {\n                                annosIsEmpty();\n                                modifiersIsEmpty();\n\n                                // specially handled : map literal\n                                if (current == null) break;\n                                LineCol lineCol = current.getLineCol();\n\n                                parse_expression(); // get key (one before ':')\n\n                                boolean continueParsing = true;\n\n                                if (parsedExps.empty()) {\n                                        err.SyntaxException(\"key is not set\", current == null ? lineCol : current.getLineCol());\n                                        jumpToTheNearestEndingNode();\n                                        nextNode(true);\n                                        continueParsing = false;\n                                } else {\n                                        Expression key = parsedExps.pop(); // the key is later pushed into the stack\n                                        list.add(key);\n                                }\n\n                                if (!continueParsing) continue;\n\n\n                                if (null == current || current.next() instanceof EndingNode || (current.next() instanceof Element && ((Element) current.next()).getContent().equals(\",\"))) {\n                                        err.SyntaxException(\"value is not set\", current == null ? lineCol : current.getLineCol());\n                                        list.remove(list.size() - 1);\n                                        nextNode(true);\n                                        if (current instanceof EndingNode) nextNode(true);\n                                        continue;\n                                }\n                                expecting(\":\", current.previous(), current, err);\n                                nextNode(false);\n\n                                parse_expression(); // get value (one after ':')\n                                if (parsedExps.empty()) {\n                                        err.SyntaxException(\"value is not set\", current == null ? lineCol : current.getLineCol());\n                                        jumpToTheNearestEndingNode();\n                                        list.remove(list.size() - 1);\n                                } else {\n                                        Expression value = parsedExps.pop();\n                                        list.add(value);\n                                }\n\n                                // add k,v into list, and return.\n                                // parse_map would take the list[0,2,4,6,8,...] as key, and list[1,3,5,7,9,...] as value\n\n                                nextNode(true);\n\n                                assert last1VarUnaryOps.empty();\n                                last2VarOps.clear();\n                        } else {\n                                // common handling process\n                                Statement stmt;\n                                try {\n                                        stmt = parse_statement(); // invoke parse_statement to get one statement\n                                } catch (ParseFail ignore) {\n                                        jumpToTheNearestEndingNode();\n                                        continue;\n                                } catch (SyntaxException e) {\n                                        err.SyntaxException(e.msg, e.lineCol, e);\n                                        jumpToTheNearestEndingNode();\n                                        continue;\n                                }\n                                if (current == null && stmt == null)\n                                        break; // break when reaching the end of nodes\n                                if (!parsedExps.empty()) {\n                                        // check parsedExps stack\n                                        // the stack should be empty because the parse_statement() method would\n                                        // take the existing expression from the stack\n                                        // and the stack should finally be filled with only one expression after\n                                        // invoking parse_expression()\n\n                                        // generate exception cause message\n                                        LineCol theFirstLineCol = null;\n                                        StringBuilder sb = new StringBuilder();\n                                        for (Expression e : parsedExps) {\n                                                sb.append(e.toString()).append(\" at \").append(e.line_col().fileName).append(\"(\").append(e.line_col().line).append(\",\").append(e.line_col().column).append(\")\\n\");\n                                                if (theFirstLineCol == null)\n                                                        theFirstLineCol = e.line_col();\n                                        }\n                                        // it should be a bug\n                                        // this err only appears only because parse_x methods don't correctly stop the parsing process when meet an invalid input\n                                        err.SyntaxException(\"got tokens which are no where to place\\n\" + sb + \"the parsed statement is \\n\" + stmt + \"\\n\", theFirstLineCol);\n                                        // ignore these tokens\n                                        parsedExps.clear();\n                                }\n\n                                // these operators must be empty\n                                assert last1VarUnaryOps.empty();\n                                // this stack may not be empty.\n                                // the peek of stack is used to determine whether to return or proceed when meeting another 2 var operator\n                                last2VarOps.clear();\n\n                                if (stmt != null)\n                                        list.add(stmt);\n                                nextNode(true);\n                        }\n                }\n                return list;\n        }\n\n        /**\n         * go to next node.<br>\n         * {@link #current} would be set to the next node<br>\n         * if the canBeEnd is set to <i>false</i>, an EndingNode.WEAK would be ignored or an EndingNode.STRONG would throw exception\n         *\n         * @param canBeEnd whether the next node can be an end\n         * @throws SyntaxException compiling error thrown if meets an end but cannot be end\n         */\n        private void nextNode(boolean canBeEnd) throws SyntaxException {\n                if (current == null) {\n                        if (canBeEnd) {\n                                return;\n                        } else {\n                                throw new LtBug(\"if canBeEnd is false, then current shouldn't be null\");\n                        }\n                }\n                Node next = current.next();\n                if (next == null || (next instanceof EndingNode && ((EndingNode) next).getType() == EndingNode.STRONG)) {\n                        if (!canBeEnd) {\n                                LineCol lineCol = new LineCol(\n                                        current.getLineCol().fileName,\n                                        current.getLineCol().line,\n                                        current.getLineCol().column + current.getLineCol().length);\n                                err.UnexpectedEndException(lineCol);\n                                // if it's not the last node, jump this token\n                                // if it's the last node, ignore the whole statement\n                                if (next == null || next.next() == null) {\n                                        err.debug(\"the next node is null, ignore the whole statement\");\n                                        throw new ParseFail();\n                                } else {\n                                        err.debug(\"the next node is not null, skip current and go to the next node\");\n                                        current = next.next();\n                                }\n                        } else {\n                                current = next;\n                        }\n                } else {\n                        current = next;\n                }\n                if (next instanceof EndingNode &&\n                        (\n                                ((EndingNode) next).getType() == EndingNode.WEAK\n                                        ||\n                                        ((EndingNode) next).getType() == EndingNode.SYNTHETIC\n                        )) {\n                        if (!canBeEnd) {\n                                nextNode(false);\n                        }\n                }\n        }\n\n        /**\n         * parse a statement<br>\n         * <code>\n         * S->Statement<br>\n         * <br>\n         * Statement->Expression<br>\n         * Statement->Pre<br>\n         * Statement->Def<br>\n         * <br>\n         * Pre->Import<br>\n         * Pre->modifier<br>\n         * Pre->PackageDeclare<br>\n         * <br>\n         * Def->ClassDef<br>\n         * Def->InterfaceDef<br>\n         * Def->MethodDef<br>\n         * Def->VariableDef\n         * </code>\n         *\n         * @return a statement object or null if there's no statements in this shift\n         * @throws SyntaxException compiling error\n         */\n        private Statement parse_statement() throws SyntaxException {\n                if (current == null) return null; // there's no node\n                // common process\n                if (current instanceof Element) {\n                        String content = ((Element) current).getContent(); // get content\n\n                        if (isSync((Element) current)) {\n                                // sync is both key and modifier\n                                // it's parsed independently\n                                annosIsEmpty();\n                                modifiersIsEmpty();\n\n                                return parse_synchronized();\n                        } else if (current.getTokenType() == TokenType.MODIFIER) {\n\n                                parse_modifier();\n                                return null;\n\n                        } else if (current.getTokenType() == TokenType.KEY) {\n                                if (content.equals(\"if\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_if();\n                                } else if (content.equals(\"for\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_for();\n                                } else if (content.equals(\"do\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_do_while();\n                                } else if (content.equals(\"while\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_while();\n                                } else if (content.equals(\"static\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        LineCol lineCol = current.getLineCol();\n                                        if (current.next() instanceof ElementStartNode) {\n                                                // static\n                                                //     ...\n                                                nextNode(false);\n                                                return new AST.StaticScope(\n                                                        parseElemStart((ElementStartNode) current, false, Collections.<String>emptySet(), false),\n                                                        lineCol);\n\n                                        } else if (current.next() instanceof Element) {\n                                                // static ...\n                                                nextNode(false);\n                                                Element curr = (Element) current;\n                                                Statement stmt = parse_statement();\n                                                if (stmt == null) {\n                                                        err.UnexpectedTokenException(\"a valid statement\", curr.toString(), curr.getLineCol());\n                                                        err.debug(\"skip the static statements\");\n                                                        // ignore the static\n                                                        // make it (static pass)\n                                                        throw new ParseFail();\n                                                }\n                                                return new AST.StaticScope(Collections.singletonList(stmt), lineCol);\n\n                                        } else {\n                                                // static\n                                                // and no other statements/expressions\n                                                return null;\n                                        }\n                                } else if (content.equals(\"class\")) {\n                                        return parse_class();\n                                } else if (content.equals(\"interface\")) {\n                                        return parse_interface();\n                                } else if (content.equals(\"object\")) {\n                                        return parse_object();\n                                } else if (content.equals(\"fun\")) {\n                                        return parse_fun();\n                                } else if (content.equals(\"annotation\")) {\n                                        modifiersIsEmpty();\n                                        return parse_annotation();\n                                } else if (content.equals(\"try\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_try();\n                                } else if (content.equals(\"throw\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_throw();\n                                } else if (content.equals(\"package\")) {\n                                        modifiersIsEmpty();\n\n                                        // package declare\n                                        return parse_pkg_declare();\n                                } else if (content.equals(\"import\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return parse_pkg_import();\n                                } else if (content.equals(\"continue\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return new AST.Continue(current.getLineCol());\n                                } else if (content.equals(\"break\")) {\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        return new AST.Break(current.getLineCol());\n                                } else if (content.equals(\"return\")) {\n                                        LineCol lineCol;\n                                        annosIsEmpty();\n                                        modifiersIsEmpty();\n\n                                        // return\n                                        lineCol = current.getLineCol();\n\n                                        if (!(current.next() instanceof Element)) {\n                                                return new AST.Return(null, lineCol);\n                                        } else {\n                                                Expression e = next_exp(false, true);\n                                                return new AST.Return(e, lineCol);\n                                        }\n                                }\n                        } else if (current.getTokenType() == TokenType.SYMBOL) {\n                                if (content.equals(\"...\")) {\n                                        return new AST.Pass(current.getLineCol());\n                                } else if (content.equals(\"@\")) {\n                                        modifiersIsEmpty();\n\n                                        boolean tmp = annotationAsExpression;\n                                        annotationAsExpression = true;\n                                        parse_anno();\n                                        annotationAsExpression = tmp;\n\n                                        if (annotationAsExpression)\n                                                if (!annos.isEmpty()) {\n                                                        AST.Anno anno = annos.iterator().next();\n                                                        annos.clear();\n                                                        return new AST.AnnoExpression(anno);\n                                                }\n\n                                        return null;\n                                }\n                        }\n\n                        // other tokens\n\n                        if (current.getTokenType() == TokenType.VALID_NAME) {\n                                // check whether is method def\n                                int def_method_type = checkMethodDef((Element) current,\n                                        !annos.isEmpty() || !modifiers.isEmpty());\n                                if (def_method_type == METHOD_DEF_TYPE) {\n                                        // method():Type\n                                        return parse_method_def_type();\n                                } else if (def_method_type == METHOD_DEF_EMPTY) {\n                                        // method()=...\n                                        return parse_method_def_empty();\n                                } else if (def_method_type == METHOD_DEF_NORMAL) {\n                                        // method()\n                                        //     ...\n                                        return parse_method_def_normal();\n                                } else if (def_method_type == METHOD_DEF_ONE_STMT) {\n                                        // method()=....\n                                        return parse_method_def_one_stmt();\n                                } else if (modifiers.contains(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC))) {\n                                        return parse_method_def_no_par();\n                                }\n                        }\n\n                        // parse expression until EndingNode or null\n                        while (true) {\n                                parse_expression();\n                                if (current == null || !(current instanceof Element)) {\n                                        if (parsedExps.empty()) return null;\n                                        return parsedExps.pop();\n                                }\n                        }\n                } else {\n                        // not element, go on and try to parse again\n                        nextNode(true);\n                        return parse_statement();\n                }\n        }\n\n        /**\n         * parse annotation type def\n         *\n         * @return annotation type def\n         * @throws SyntaxException compiling error\n         */\n        private AnnotationDef parse_annotation() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                Set<AST.Anno> annos = getAndClear(this.annos);\n                nextNode(false);\n                if (current.getTokenType() != TokenType.VALID_NAME) {\n                        err.UnexpectedTokenException(\"annotation type name\", current.toString(), current.getLineCol());\n                        throw new ParseFail();\n                }\n                String name = ((Element) current).getContent();\n                nextNode(true);\n                List<Statement> stmts;\n                if (current == null || current instanceof EndingNode) {\n                        stmts = Collections.emptyList();\n                } else if (current instanceof ElementStartNode) {\n                        stmts = parseElemStart((ElementStartNode) current, false, Collections.<String>emptySet(), false);\n                } else {\n                        err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                        err.debug(\"assume it has empty statements\");\n                        stmts = Collections.emptyList();\n                }\n                return new AnnotationDef(name, annos, stmts, lineCol);\n        }\n\n        /**\n         * parse object<br>\n         * <p>\n         * <code>\n         * object XXX [:YYY(...),ZZZ]\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return ObjectDef\n         * @throws SyntaxException compiling error\n         */\n        private ObjectDef parse_object() throws SyntaxException {\n                ClassDef classDef = parse_class();\n                if (!classDef.params.isEmpty()) {\n                        err.SyntaxException(\"object do not have params\", classDef.params.get(0).line_col());\n                }\n                return new ObjectDef(classDef.name,\n                        classDef.generics,\n                        classDef.superWithInvocation, classDef.superWithoutInvocation,\n                        classDef.modifiers,\n                        classDef.annos, classDef.statements, classDef.line_col());\n        }\n\n        /**\n         * parse synchronized<br>\n         * <code>\n         * sync(expression,...)<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return Synchronized\n         * @throws SyntaxException compiling error\n         */\n        private AST.Synchronized parse_synchronized() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                nextNode(false);\n                expecting(\"(\", current.previous(), current, err);\n\n                List<Expression> expressions = new ArrayList<Expression>();\n                if (current.next() instanceof ElementStartNode) {\n                        nextNode(false);\n                        List<Statement> statements = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n\n                        for (Statement s : statements) {\n                                if (s instanceof Expression) {\n                                        expressions.add((AST.Access) s);\n                                } else {\n                                        err.UnexpectedTokenException(\"expression\", s.toString(), s.line_col());\n                                        // ignore this value and continue on\n                                        err.debug(\"ignore this value\");\n                                }\n                        }\n                }\n\n                nextNode(false);\n                expecting(\")\", current.previous(), current, err);\n                nextNode(true);\n                List<Statement> statements = null;\n                if (current instanceof ElementStartNode) {\n                        statements = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                }\n                return new AST.Synchronized(\n                        expressions,\n                        statements == null ? Collections.<Statement>emptyList() : statements,\n                        lineCol);\n        }\n\n        /**\n         * create a new syntactic processor and parse the given node\n         *\n         * @param startNode    ElementStartNode (root node)\n         * @param addUsedNames if true, invoke {@link #addUsedVarNames(Set)}\n         * @param parseMap     set {@link #isParsingMap} to given arg\n         * @return parsed result (list of statements)\n         * @throws SyntaxException compiling error\n         */\n        private List<Statement> parseElemStart(\n                ElementStartNode startNode,\n                boolean addUsedNames,\n                Set<String> names,\n                boolean parseMap)\n                throws SyntaxException {\n                Parser parser = new Parser(startNode, err);\n                if (addUsedNames) {\n                        parser.addUsedVarNames(usedVarNames);\n                        parser.addUsedVarNames(names);\n                }\n                parser.isParsingMap = parseMap;\n                parser.annotationAsExpression = this.annotationAsExpression;\n                return parser.parse();\n        }\n\n        /**\n         * parse while<br>\n         * <code>\n         * while boolean<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return While\n         * @throws SyntaxException compiling error\n         */\n        private AST.While parse_while() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                Expression condition = next_exp(true, true); // the boolean expression\n\n                List<Statement> body;\n                if (current instanceof ElementStartNode) {\n                        // parse while body\n                        body = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                } else {\n                        err.UnexpectedTokenException(\"while body\", current == null ? \"LineEnd\" : current.toString(), current == null ? lineCol : current.getLineCol());\n                        err.debug(\"assume that the body is empty\");\n                        // assume that the body is empty\n                        body = Collections.emptyList();\n                        jumpToTheNearestEndingNode();\n                }\n                return new AST.While(condition, body, false, lineCol);\n        }\n\n        /**\n         * parse do_while<br>\n         * <code>\n         * do<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * while boolean\n         * </code>\n         *\n         * @return While\n         * @throws SyntaxException compiling error\n         */\n        private AST.While parse_do_while() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                nextNode(false); // then current node should be ElementStartNode\n\n                List<Statement> statements;\n\n                if (current instanceof ElementStartNode) {\n                        statements = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                } else {\n                        err.UnexpectedTokenException(\"while body\", current == null ? \"LineEnd\" : current.toString(), current == null ? lineCol : current.getLineCol());\n                        err.debug(\"assume that the body is empty\");\n                        // assume that the body is empty\n                        statements = Collections.emptyList();\n                        jumpToTheNearestEndingNode();\n                }\n\n                if (current == null) {\n                        err.UnexpectedEndException(lineCol);\n                        return null;\n                } else {\n                        nextNode(false);\n                        expecting(\"while\", current.previous(), current, err);\n\n                        Expression condition = next_exp(true, true); // the boolean expression\n\n                        return new AST.While(condition, statements, true, lineCol);\n                }\n        }\n\n        /**\n         * parse import<br>\n         * <code>\n         * #&gt;<br>\n         * &nbsp;&nbsp;&nbsp; java::util::List         ;import one class<br>\n         * &nbsp;&nbsp;&nbsp; java::util::_            ;import all from a package<br>\n         * &nbsp;&nbsp;&nbsp; java::util::Arrays._     ;import static<br>\n         * &nbsp;&nbsp;&nbsp; java::util::Map.Entry    ;import inner class<br>\n         * &nbsp;&nbsp;&nbsp; java::util::Map.Entry._  ;import static from inner class<br>\n         * &nbsp;&nbsp;&nbsp; Cls._                    ;import static from class in root package\n         * </code>\n         *\n         * @return Import\n         * @throws SyntaxException compiling error\n         */\n        private Import parse_pkg_import() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                boolean isImplicit = false;\n                if (current.next() instanceof Element &&\n                        current.next().getTokenType() == TokenType.MODIFIER &&\n                        ((Element) current.next()).getContent().equals(\"implicit\")) {\n                        isImplicit = true;\n                        nextNode(false);\n                }\n\n                Expression stmt = next_exp(false, true);\n\n                if (stmt instanceof AST.Access) {\n                        // import should firstly be parsed into Access\n                        AST.Access a = (AST.Access) stmt;\n                        AST.PackageRef pkg = null;\n                        AST.Access access = null;\n                        boolean importAll;\n                        if (a.name.equals(\"_\")) { // ends with '_'\n                                if (a.exp instanceof AST.PackageRef) {\n                                        // import all from a package\n                                        pkg = (AST.PackageRef) a.exp;\n                                        importAll = true;\n                                } else {\n                                        // import static\n                                        if (!(a.exp instanceof AST.Access)) {\n                                                err.UnexpectedTokenException(\"package::class\", a.exp.toString(), a.exp.line_col());\n                                                err.debug(\"ignore this import\");\n                                                return null;\n                                        }\n\n                                        access = (AST.Access) a.exp;\n                                        importAll = true;\n                                }\n                        } else {\n                                // import class or inner class\n                                access = a;\n                                importAll = false;\n                        }\n\n                        if (importAll && isImplicit) {\n                                err.SyntaxException(\"import import should be follow by a type\", lineCol);\n                        }\n                        return new Import(pkg, access, importAll, isImplicit, lineCol);\n                } else {\n                        err.UnexpectedTokenException(\"import statement\", stmt.toString(), stmt.line_col());\n                        // ignore the statement\n                        err.debug(\"ignore this import\");\n                        return null;\n                }\n        }\n\n        /**\n         * declare a package<br>\n         * <code>\n         * package java::util<br>\n         * // or<br>\n         * package java.util\n         * </code>\n         *\n         * @return PackageDeclare\n         * @throws SyntaxException compiling error\n         */\n        private PackageDeclare parse_pkg_declare() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                nextNode(false);\n                if (current instanceof Element) {\n                        StringBuilder sb = new StringBuilder();\n                        boolean isName = true;\n\n                        while (current != null && (current instanceof Element)) {\n                                Element elem = (Element) current;\n                                String s = elem.getContent();\n                                if (!isName && !s.equals(\"::\") && !s.equals(\".\")) {\n                                        err.UnexpectedTokenException(\"::\", s, elem.getLineCol());\n                                        err.debug(\"make it '::'\");\n                                        s = \"::\";\n                                } else if (s.equals(\".\")) {\n                                        s = \"::\";\n                                }\n                                isName = !isName;\n                                sb.append(s);\n                                nextNode(true);\n                        }\n\n                        // isName should be false\n                        if (isName) {\n                                sb.delete(sb.length() - 2, sb.length());\n\n                                err.SyntaxException(\"package name should end with a valid name\", lineCol);\n                                return new PackageDeclare(new AST.PackageRef(sb.toString(), LineCol.SYNTHETIC), lineCol);\n                        }\n\n                        AST.PackageRef pkg = new AST.PackageRef(sb.toString(), lineCol);\n                        return new PackageDeclare(pkg, lineCol);\n                } else {\n                        err.UnexpectedTokenException(\"package declare\", current.toString(), current.getLineCol());\n                        err.debug(\"let it be (default package)\");\n                        return new PackageDeclare(new AST.PackageRef(\"\", LineCol.SYNTHETIC), lineCol);\n                }\n        }\n\n        /**\n         * annotation<br>\n         * <code>\n         * <p/>\n         * &nbsp;@Anno<br>\n         * &nbsp;@Anno()<br>\n         * &nbsp;@Anno(exp)<br>\n         * &nbsp;@Anno(a=exp)<br>\n         * &nbsp;@Anno(a=exp1,b=exp2,exp)<br>\n         * </code>\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_anno() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                Set<AST.Anno> storeCurrentAnnos = new HashSet<AST.Anno>(annos);\n                annos.clear();\n\n                Expression e = next_exp(false, true); // annotation\n                // might be Invocation\n                // might be Access\n\n                // restore the stored annos\n                annos.addAll(storeCurrentAnnos);\n\n                AST.Anno anno;\n                if (e instanceof AST.Invocation && ((AST.Invocation) e).exp instanceof AST.Access) {\n                        // @Anno(...)\n\n                        AST.Invocation inv = (AST.Invocation) e;\n                        List<AST.Assignment> assignments = new ArrayList<AST.Assignment>();\n                        for (Expression exp : inv.args) {\n                                // convert into assignments\n                                if (exp instanceof VariableDef) {\n                                        VariableDef v = (VariableDef) exp;\n\n                                        AST.Assignment a = new AST.Assignment(\n                                                new AST.Access(null, v.getName(), v.line_col()),\n                                                \"=\",\n                                                v.getInit(), v.line_col());\n                                        assignments.add(a);\n                                } else if (exp instanceof AST.Assignment) {\n                                        assignments.add((AST.Assignment) exp);\n                                } else {\n                                        AST.Assignment a = new AST.Assignment(\n                                                new AST.Access(null, \"value\", exp.line_col()),\n                                                \"=\",\n                                                exp,\n                                                LineCol.SYNTHETIC\n                                        );\n                                        assignments.add(a);\n                                }\n                        }\n                        anno = new AST.Anno((AST.Access) inv.exp, assignments, lineCol);\n                } else if (e instanceof AST.Access) {\n                        // @Anno\n\n                        anno = new AST.Anno((AST.Access) e, Collections.<AST.Assignment>emptyList(), e.line_col());\n                } else {\n                        err.UnexpectedTokenException(\"annotation instance\", e.toString(), e.line_col());\n                        err.debug(\"ignore this annotation\");\n                        return;\n                }\n\n                annos.add(anno);\n        }\n\n        /**\n         * parse throw<br>\n         * <code>\n         * throw exp\n         * </code>\n         *\n         * @return Throw\n         * @throws SyntaxException compiling error\n         */\n        private AST.Throw parse_throw() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                Expression exp = next_exp(false, true);\n\n                return new AST.Throw(exp, lineCol);\n        }\n\n        /**\n         * parse try<br>\n         * <code>\n         * try<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * [catch exVar]<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;Exceptions,...<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;Other Exceptions,...<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * [finally]<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return Try\n         * @throws SyntaxException compiling error\n         */\n        private AST.Try parse_try() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                if (!(current.next() instanceof ElementStartNode)) {\n                        err.SyntaxException(\"invalid try statement without statements\", lineCol);\n                        err.debug(\"ignore the try statement\");\n                        return null;\n                }\n\n                nextNode(false); // element start node\n                // try[|] catch <var> [|] / finally [|]\n\n                List<Statement> statements = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n\n                nextNode(true); // catch <var> [|] finally [|]\n\n                if (current == null) {\n                        err.SyntaxException(\"invalid try statement without catch or finally\", lineCol);\n                        err.debug(\"assume no catch and finally\");\n                        return new AST.Try(statements, null, Collections.<Statement>emptyList(), Collections.<Statement>emptyList(), lineCol);\n                }\n\n                if (current instanceof EndingNode\n                        && current.next() instanceof Element\n                        &&\n                        (\n                                ((Element) current.next()).getContent().equals(\"catch\")\n                                        || ((Element) current.next()).getContent().equals(\"finally\")\n                        )) {\n                        nextNode(false);\n                }\n\n                String eName = null;\n                List<Statement> catchStatements = new ArrayList<Statement>();\n                if (current instanceof Element) {\n                        String cat = ((Element) current).getContent();\n                        // catch\n                        if (cat.equals(\"catch\")) {\n                                nextNode(false); // <var> [|] finally [|]\n\n                                if ((current instanceof Element)) {\n                                        eName = ((Element) current).getContent(); // catch e\n                                } else {\n                                        err.UnexpectedTokenException(\"exception variable\", current.toString(), current.getLineCol());\n                                        err.debug(\"let the exception variable be 'e'\");\n                                        eName = \"e\";\n                                }\n                                if (current.getTokenType() != TokenType.VALID_NAME) {\n                                        err.UnexpectedTokenException(\"valid variable name\", eName, current.getLineCol());\n                                        err.debug(\"assume that it's a valid name\");\n                                }\n                                if (usedVarNames.contains(eName)) {\n                                        err.DuplicateVariableNameException(eName, current.getLineCol());\n                                        err.debug(\"assume that it's an unused name\");\n                                }\n                                // catch e\n                                nextNode(true); // [|] finally [|]\n                                if (null != current && !(current instanceof EndingNode)) {\n                                        if (current instanceof ElementStartNode) {\n                                                catchStatements.addAll(\n                                                        parseElemStart(\n                                                                (ElementStartNode) current,\n                                                                true,\n                                                                Collections.singleton(eName), // the exception holder name\n                                                                false));\n\n                                                nextNode(true); // finally [|]\n                                                // if it's finally then go next\n                                                if (current instanceof EndingNode\n                                                        && current.next() instanceof Element\n                                                        && ((Element) current.next()).getContent().equals(\"finally\")) {\n                                                        nextNode(false);\n                                                }\n                                        } else {\n                                                // element\n                                                err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                                                err.debug(\"ignore this token\");\n                                                jumpToTheNearestEndingNode();\n                                        }\n                                }\n                        }\n                }\n\n                List<Statement> fin = new ArrayList<Statement>();\n                if (current instanceof Element) {\n                        String f = ((Element) current).getContent();\n                        // finally\n                        if (f.equals(\"finally\")) {\n                                LineCol finallyLineCol = current.getLineCol();\n                                nextNode(true);\n                                if (current instanceof ElementStartNode) {\n                                        fin = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                                } else if (current != null && !(current instanceof EndingNode)) {\n                                        err.UnexpectedTokenException(\n                                                current == null ? \"NewLine\" : current.toString(),\n                                                current == null ? finallyLineCol : current.getLineCol());\n                                        err.debug(\"ignore this token\");\n                                        jumpToTheNearestEndingNode();\n                                }\n                        }\n                }\n\n                return new AST.Try(\n                        statements == null ? Collections.<Statement>emptyList() : statements,\n                        eName,\n                        catchStatements,\n                        fin,\n                        lineCol);\n        }\n\n        /**\n         * parse interface<br>\n         * <code>\n         * interface Name [ : SuperInterface,...]<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return InterfaceDef\n         * @throws SyntaxException compiling error\n         */\n        private InterfaceDef parse_interface() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                // record modifiers and annotation\n                Set<Modifier> set = new HashSet<Modifier>(modifiers);\n                modifiers.clear();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n\n                // interface\n                nextNode(false); // interface name\n\n                if (current instanceof Element) {\n                        String name = ((Element) current).getContent();\n\n                        List<AST.Access> generics = new ArrayList<AST.Access>();\n                        List<AST.Access> superInterfaces = new ArrayList<AST.Access>();\n\n                        if (current.getTokenType() == TokenType.VALID_NAME) {\n                                nextNode(true); // can be <: or : or ending or startNode\n\n                                // generic\n                                if (current instanceof Element) {\n                                        if (((Element) current).getContent().equals(\"<:\")) {\n                                                generics = parse_generic();\n                                        }\n                                }\n\n                                // interface name :\n\n                                if (current instanceof Element) {\n                                        expecting(\":\", current.previous(), current, err);\n\n                                        nextNode(false);\n                                        while (true) {\n                                                if (current.getTokenType() == TokenType.VALID_NAME) {\n                                                        Expression e = get_exp(true, true);\n\n                                                        if (e instanceof AST.Access) {\n                                                                superInterfaces.add((AST.Access) e);\n                                                        } else {\n                                                                err.UnexpectedTokenException(\"super interface\", e.toString(), e.line_col());\n                                                                err.debug(\"ignore this super interface\");\n                                                        }\n                                                        if (current instanceof EndingNode && ((EndingNode) current).getType() == EndingNode.STRONG) {\n                                                                nextNode(true);\n                                                        } else {\n                                                                break;\n                                                        }\n                                                } else {\n                                                        break;\n                                                }\n                                        }\n                                }\n                        } else {\n                                err.UnexpectedTokenException(\"valid interface name\", name, current.getLineCol());\n                                err.debug(\"ignore the interface\");\n\n                                throw new ParseFail();\n                        }\n\n                        List<Statement> statements = null;\n                        if (current instanceof ElementStartNode) {\n                                // interface name\n                                //     ...\n                                statements = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                                nextNode(true);\n                        }\n\n                        InterfaceDef interfaceDef = new InterfaceDef(name, generics, set,\n                                superInterfaces,\n                                annos,\n                                statements == null ? Collections.<Statement>emptyList() : statements,\n                                lineCol);\n                        annos.clear();\n                        return interfaceDef;\n                } else {\n                        err.UnexpectedTokenException(\"interface name\", current.toString(), current.getLineCol());\n                        err.debug(\"ignore this interface declaration\");\n                        return null;\n                }\n        }\n\n        /**\n         * parse generic, cursor will be after :> after the method\n         *\n         * @return list of generics\n         * @throws SyntaxException exception\n         */\n        private List<AST.Access> parse_generic() throws SyntaxException {\n                List<AST.Access> generics = new ArrayList<AST.Access>();\n\n                nextNode(false);\n                if (current instanceof ElementStartNode) {\n                        ElementStartNode startNode = (ElementStartNode) current;\n                        nextNode(false);\n                        expecting(\":>\", current.previous(), current, err);\n                        nextNode(true);\n\n                        // handle generic\n                        Parser parser = new Parser(startNode, err);\n                        if (!(parser.current instanceof Element)) {\n                                err.UnexpectedTokenException(parser.current.toString(), parser.current.getLineCol());\n                        }\n                        while (true) {\n                                AST.Access type = parser.parse_cls_for_type_spec();\n                                generics.add(type);\n                                if (parser.current == null) {\n                                        break;\n                                }\n                                if (!(parser.current instanceof EndingNode)) {\n                                        err.UnexpectedTokenException(\",\", parser.current.toString(), parser.current.getLineCol());\n                                        break;\n                                }\n                                parser.nextNode(false);\n                        }\n                } else {\n                        err.UnexpectedTokenException(\"generic type definition\", current.toString(), current.getLineCol());\n                }\n                return generics;\n        }\n\n        /**\n         * parse class<br>\n         * <code>\n         * class ClassName [(params,...)] [: [SuperClass[(arg,...)],SuperInterfaces,...]]<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return ClassDef\n         * @throws SyntaxException compiling error\n         */\n        private ClassDef parse_class() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                // record modifiers and annotations\n                Set<Modifier> set = new HashSet<Modifier>(modifiers);\n                modifiers.clear();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n                // class\n                nextNode(false); // class name\n\n                if (current instanceof Element) {\n                        String name = ((Element) current).getContent();\n                        if (current.getTokenType() != TokenType.VALID_NAME) {\n                                err.UnexpectedTokenException(\"valid class name\", name, current.getLineCol());\n                                err.debug(\"assume the token is a valid name\");\n                        }\n                        nextNode(true); // can be <: or ( or : or ending or ending or startNode\n\n                        List<AST.Access> generics = new ArrayList<AST.Access>();\n\n                        // check generic\n                        if (current instanceof Element) {\n                                String p = ((Element) current).getContent();\n                                if (p.equals(\"<:\")) { // class Cls<:T:>\n                                        generics = parse_generic();\n                                }\n                        }\n\n                        List<VariableDef> params = null;\n\n                        Set<String> newParamNames = new HashSet<String>();\n\n                        // check parameters\n                        if (current instanceof Element) {\n                                String p = ((Element) current).getContent();\n                                if (p.equals(\"(\")) {// class Cls(...)\n\n                                        nextNode(false);\n                                        if (current instanceof ElementStartNode) {\n                                                // class ClassName(口\n                                                List<Statement> list = parseElemStart(\n                                                        (ElementStartNode) current, false, Collections.<String>emptySet(), false);\n\n                                                params = new ArrayList<VariableDef>();\n                                                boolean MustHaveInit = false;\n                                                for (Statement stmt : list) {\n                                                        if (stmt instanceof AST.Access) {\n                                                                if (MustHaveInit) {\n                                                                        err.SyntaxException(\"expecting parameter with init value\", stmt.line_col());\n                                                                        err.debug(\"assume it has init value\");\n                                                                }\n                                                                AST.Access access = (AST.Access) stmt;\n                                                                if (access.exp != null) {\n                                                                        err.SyntaxException(\"parameter cannot be \" + access.toString(), access.line_col());\n                                                                        err.debug(\"ignore access.exp\");\n                                                                }\n                                                                VariableDef v = new VariableDef(access.name, Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), current.getLineCol());\n                                                                params.add(v);\n\n                                                                newParamNames.add(v.getName());\n                                                        } else if (stmt instanceof VariableDef) {\n                                                                if (((VariableDef) stmt).getInit() == null) {\n                                                                        if (MustHaveInit) {\n                                                                                err.SyntaxException(\"expecting parameter with init value\", stmt.line_col());\n                                                                                err.debug(\"assume it has init value\");\n                                                                        }\n                                                                } else {\n                                                                        MustHaveInit = true;\n                                                                }\n\n                                                                params.add((VariableDef) stmt);\n\n                                                                newParamNames.add(((VariableDef) stmt).getName());\n                                                        } else {\n                                                                err.SyntaxException(\"parameter cannot be \" + stmt.toString(), stmt.line_col());\n                                                                err.debug(\"ignore this parameter def\");\n                                                        }\n                                                }\n\n\n                                                nextNode(false); // )\n                                                expecting(\")\", current.previous(), current, err);\n                                                nextNode(true);\n                                        } else if (current instanceof Element) {\n                                                expecting(\")\", current.previous(), current, err);\n                                                // class ClassName()\n\n                                                params = Collections.emptyList();\n                                                nextNode(true);\n                                        } else {\n                                                err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                                                err.debug(\"ignore the parameters\");\n                                        }\n                                } else if (!p.equals(\":\")) {\n                                        err.UnexpectedTokenException(\"( or :\", p, current.getLineCol());\n                                        err.debug(\"ignore the token\");\n                                        nextNode(true);\n                                }\n                                // else class Cls:...\n                                // do nothing\n                        }\n\n                        AST.Invocation invocation = null; // super class with constructor arguments\n                        List<AST.Access> accesses = new ArrayList<AST.Access>(); // inherit without invocation (class or interface)\n\n                        if (current instanceof Element) {\n                                // :\n                                expecting(\":\", current.previous(), current, err);\n                                nextNode(false);\n                                while (true) {\n                                        if (current.getTokenType() == TokenType.VALID_NAME) {\n                                                Expression e = get_exp(true, true);\n\n                                                if (e instanceof AST.Access) {\n                                                        accesses.add((AST.Access) e);\n                                                } else if (e instanceof AST.Invocation && ((AST.Invocation) e).exp instanceof AST.Access) {\n                                                        if (invocation == null) {\n                                                                invocation = (AST.Invocation) e;\n                                                        } else {\n                                                                err.SyntaxException(\"Multiple Inheritance is not allowed\", e.line_col());\n                                                                err.debug(\"ignore the arguments and only record the name\");\n                                                                accesses.add((AST.Access) ((AST.Invocation) e).exp);\n                                                        }\n                                                } else {\n                                                        err.SyntaxException(\"super class or super interfaces cannot be \" + e.toString(), e.line_col());\n                                                        err.debug(\"ignore this inheritance\");\n                                                }\n                                                if (current instanceof EndingNode && ((EndingNode) current).getType() == EndingNode.STRONG) {\n                                                        nextNode(true);\n                                                } else {\n                                                        break;\n                                                }\n                                        } else {\n                                                break;\n                                        }\n                                }\n                        }\n\n                        // statements\n                        List<Statement> stmts = null;\n                        if (current instanceof ElementStartNode) {\n                                stmts = parseElemStart((ElementStartNode) current, true, newParamNames, false);\n                        }\n\n                        return new ClassDef(\n                                name,\n                                generics,\n                                set,\n                                params == null ? Collections.<VariableDef>emptyList() : params,\n                                invocation,\n                                accesses,\n                                annos, stmts == null ? Collections.<Statement>emptyList() : stmts,\n                                lineCol);\n                } else {\n                        err.UnexpectedTokenException(\"class name\", current.toString(), current.getLineCol());\n                        err.debug(\"ignore this class definition\");\n                        throw new ParseFail();\n                }\n        }\n\n        /**\n         * parse function.<br>\n         * <code>\n         * fun FunctionName [(params,...)] : SuperType<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return FunDef\n         * @throws SyntaxException compiling error\n         */\n        private FunDef parse_fun() throws SyntaxException {\n                ClassDef classDef = parse_class();\n                if (classDef.superWithoutInvocation.isEmpty()) {\n                        classDef.superWithoutInvocation.add(\n                                new AST.Access(\n                                        new AST.PackageRef(\"lt::lang::function\", LineCol.SYNTHETIC),\n                                        \"Function\" + classDef.params.size(),\n                                        LineCol.SYNTHETIC\n                                )\n                        );\n                }\n                if ((classDef.superWithInvocation != null) || classDef.superWithoutInvocation.size() != 1) {\n                        err.SyntaxException(\"function definitions should have one super type, which should be functional interface or functional abstract class\",\n                                classDef.line_col());\n                        // if no super type defined, then assert it is lt::lang::FunctionX (X is parameter size)\n                        if (classDef.superWithoutInvocation.isEmpty()) {\n                                classDef.superWithoutInvocation.add(\n                                        new AST.Access(\n                                                new AST.PackageRef(\n                                                        \"lt::lang::function\", LineCol.SYNTHETIC\n                                                ),\n                                                \"Function\" + classDef.params.size(),\n                                                LineCol.SYNTHETIC\n                                        )\n                                );\n                        }\n                }\n                if (!classDef.modifiers.isEmpty()) {\n                        err.SyntaxException(\"function definitions do not have modifiers\", classDef.line_col());\n                }\n                if (!classDef.generics.isEmpty()) {\n                        err.SyntaxException(\"function definitions do not have generic types\", classDef.line_col());\n                }\n\n                // transform into fun\n\n                return new FunDef(\n                        classDef.name,\n                        classDef.params,\n                        classDef.superWithoutInvocation.get(0),\n                        classDef.annos,\n                        classDef.statements,\n                        classDef.line_col()\n                );\n        }\n\n        /**\n         * for<br>\n         * <code>\n         * for i @ exp<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return For\n         * @throws SyntaxException compiling error\n         */\n        private AST.For parse_for() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                nextNode(false); // variable\n                if (!(current instanceof Element)) {\n                        err.SyntaxException(\"invalid for statement\", current == null ? lineCol : current.getLineCol());\n                        err.debug(\"ignore the statement\");\n                        throw new ParseFail();\n                }\n                Element varElem = (Element) current;\n                String varName = varElem.getContent();\n                if (varElem.getTokenType() != TokenType.VALID_NAME) {\n                        err.UnexpectedTokenException(\"valid variable name\", varName, current.getLineCol());\n                        err.debug(\"assume that the name is 'i'\");\n                        varName = \"i\";\n                }\n                if (usedVarNames.contains(varName)) {\n                        err.DuplicateVariableNameException(varName, current.getLineCol());\n                        err.debug(\"assume that it's an unused name\");\n                }\n\n                nextNode(false); // in\n                expecting(\"in\", current.previous(), current, err);\n\n                Expression exp = next_exp(true, true); // expression\n\n                List<Statement> statements = null;\n                if (current instanceof ElementStartNode) {\n                        statements = parseElemStart((ElementStartNode) current, true, Collections.singleton(varName), false);\n                }\n\n                return new AST.For(\n                        varName,\n                        exp,\n                        statements == null ? Collections.<Statement>emptyList() : statements,\n                        lineCol);\n        }\n\n        /**\n         * if<br>\n         * <code>\n         * if expression<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * elseif expression<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * else<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return If\n         * @throws SyntaxException compiling error\n         */\n        private AST.If parse_if() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                List<AST.If.IfPair> pairs = new ArrayList<AST.If.IfPair>();\n\n                boolean isLast = false;\n\n                while (current instanceof Element || current instanceof EndingNode) {\n                        LineCol ifPairLineCol = current.getLineCol();\n\n                        // parse expression next to if/elseif/else\n                        if (current instanceof EndingNode\n                                && current.next() instanceof Element) {\n                                String content = ((Element) current.next()).getContent();\n                                if (content.equals(\"elseif\") || content.equals(\"else\")) {\n                                        nextNode(false);\n                                } else {\n                                        break;\n                                }\n                        }\n                        Expression condition = null;\n                        String content = ((Element) current).getContent();\n\n                        // out of if scope\n                        if (!content.equals(\"if\") && !content.equals(\"elseif\") && !content.equals(\"else\")) {\n                                break;\n                        }\n\n                        // nodes next to else might be Ending or ElemStart\n                        if (((Element) current).getContent().equals(\"else\")) {\n                                if (isLast) {\n                                        err.SyntaxException(\"if-else statement had already reached 'else' but got \" + content + \" instead\", current.getLineCol());\n                                        err.debug(\"ignore this if branch\");\n                                } else {\n                                        nextNode(true);\n                                }\n                        } else {\n                                nextNode(false);\n                        }\n                        if (content.equals(\"if\") || content.equals(\"elseif\")) {\n\n                                if (isLast) {\n                                        err.SyntaxException(\"if-else statement had already reached 'else' but got \" + content + \" instead\", current.getLineCol());\n                                        err.debug(\"ignore this if branch\");\n                                } else {\n                                        condition = get_exp(true, true);\n                                }\n                        }\n\n                        List<Statement> list = null;\n                        if (current instanceof ElementStartNode) {\n                                list = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                        }\n\n                        if (condition == null) {\n                                if (!isLast) {\n                                        isLast = true;\n\n                                        AST.If.IfPair pair = new AST.If.IfPair(null, list == null ? Collections.<Statement>emptyList() : list, ifPairLineCol);\n                                        pairs.add(pair);\n                                }\n                        } else {\n                                AST.If.IfPair pair = new AST.If.IfPair(condition, list == null ? Collections.<Statement>emptyList() : list, ifPairLineCol);\n                                pairs.add(pair);\n                        }\n\n                        nextNode(true);\n                        last2VarOps.clear();\n                }\n\n                if (current != null) {\n                        // the last loop invoked nextNode(true)\n                        // but parse_statement() also invokes nextNode(true)\n                        current = current.previous();\n                }\n\n                return new AST.If(pairs, lineCol);\n        }\n\n        /**\n         * parse method param contents<br>\n         * method<b>(params,...)</b><br>\n         * the current node should be `method name`<br>\n         * after the process, current node would be the ')'\n         *\n         * @param variableList variable list to fill\n         * @param names        a set of defined names to fill\n         * @throws SyntaxException compiling error\n         */\n        private void parse_method_def_variables(List<VariableDef> variableList, Set<String> names) throws SyntaxException {\n                nextNode(false); // method(\n                expecting(\"(\", current.previous(), current, err);\n                nextNode(false);\n                if (current instanceof ElementStartNode) {\n                        // method(口\n                        List<Statement> statements = parseElemStart((ElementStartNode) current, false, Collections.<String>emptySet(), false);\n                        boolean MustHaveInit = false;\n                        for (Statement s : statements) {\n                                if (s instanceof AST.Access && ((AST.Access) s).exp == null) {\n                                        if (MustHaveInit) {\n                                                err.SyntaxException(\"expecting parameter with init value\", s.line_col());\n                                                err.debug(\"assume it has init value\");\n                                        }\n\n                                        AST.Access access = (AST.Access) s;\n                                        VariableDef d = new VariableDef(access.name, Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), access.line_col());\n                                        variableList.add(d);\n                                        names.add(access.name);\n                                } else if (s instanceof VariableDef) {\n                                        if (((VariableDef) s).getInit() == null) {\n                                                if (MustHaveInit) {\n                                                        err.SyntaxException(\"expecting parameter with init value\", s.line_col());\n                                                        err.debug(\"assume it has init value\");\n                                                }\n                                        } else {\n                                                MustHaveInit = true;\n                                        }\n                                        variableList.add((VariableDef) s);\n                                        names.add(((VariableDef) s).getName());\n                                } else {\n                                        err.SyntaxException(\"parameter cannot be \" + s.toString(), s.line_col());\n                                        err.debug(\"ignore this parameter\");\n                                }\n                        }\n                        nextNode(false);\n                }\n                expecting(\")\", current.previous(), current, err);\n        }\n\n        /**\n         * parse method definition<br>\n         * <code>\n         * method(params,...)<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return MethodDef\n         * @throws SyntaxException compiling error\n         */\n        private MethodDef parse_method_def_normal() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                String methodName = ((Element) current).getContent();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n                Set<Modifier> modifiers = new HashSet<Modifier>(this.modifiers);\n                this.modifiers.clear();\n\n                List<VariableDef> variableList = new ArrayList<VariableDef>();\n                Set<String> names = new HashSet<String>();\n                parse_method_def_variables(variableList, names);\n                // method(..)\n                nextNode(false); // 口\n\n                List<Statement> stmts = parseElemStart((ElementStartNode) current, true, names, false);\n                return new MethodDef(methodName, modifiers, null, variableList, annos, stmts, lineCol);\n        }\n\n        /**\n         * parse method definition<br>\n         * <code>\n         * method(params,...)=pass\n         * </code>\n         *\n         * @return MethodDef\n         * @throws SyntaxException compiling error\n         */\n        private MethodDef parse_method_def_empty() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                String methodName = ((Element) current).getContent();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n                Set<Modifier> modifiers = new HashSet<Modifier>(this.modifiers);\n                this.modifiers.clear();\n\n                List<VariableDef> variableList = new ArrayList<VariableDef>();\n                Set<String> names = new HashSet<String>();\n                parse_method_def_variables(variableList, names);\n                // method(..)\n\n                nextNode(true); // method(..)= or method(..)\n                if (current != null && !(current instanceof EndingNode)) {\n                        nextNode(false); // method(..)=pass\n                        nextNode(true);\n                }\n\n                MethodDef def = new MethodDef(methodName, modifiers, null, variableList, annos,\n                        Collections.<Statement>emptyList(),\n                        lineCol);\n                annos.clear();\n                return def;\n        }\n\n        /**\n         * parse method definition<br>\n         * <code>\n         * method(params,...)=exp\n         * </code>\n         *\n         * @return MethodDef\n         * @throws SyntaxException compiling error\n         */\n        private MethodDef parse_method_def_one_stmt() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                String methodName = ((Element) current).getContent();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n                Set<Modifier> modifiers = new HashSet<Modifier>(this.modifiers);\n                this.modifiers.clear();\n\n                List<VariableDef> variableList = new ArrayList<VariableDef>();\n                Set<String> names = new HashSet<String>();\n                parse_method_def_variables(variableList, names);\n                // method(..)\n                nextNode(false); // method(..)=\n                nextNode(false); // method(..)=exp\n\n                parse_expression();\n\n                Expression exp = parsedExps.pop();\n                return new MethodDef(methodName, modifiers, null, variableList, annos, Collections.<Statement>singletonList(\n                        new AST.Return(exp, exp.line_col())\n                ), lineCol);\n        }\n\n        /**\n         * parse method definition<br>\n         * <code>\n         * method(params,...):Type<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...\n         * </code>\n         *\n         * @return MethodDef\n         * @throws SyntaxException compiling error\n         */\n        private MethodDef parse_method_def_type() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                String methodName = ((Element) current).getContent();\n                Set<AST.Anno> annos = new HashSet<AST.Anno>(this.annos);\n                this.annos.clear();\n                Set<Modifier> modifiers = new HashSet<Modifier>(this.modifiers);\n                this.modifiers.clear();\n\n                List<VariableDef> variableList = new ArrayList<VariableDef>();\n                Set<String> names = new HashSet<String>();\n                parse_method_def_variables(variableList, names);\n                // method(..)\n                nextNode(false); // method(..):\n                nextNode(false); // method(..):..\n                AST.Access returnType = parse_cls_for_type_spec();\n\n                if (current instanceof Element && ((Element) current).getContent().equals(\"=\")) {\n                        // check \"=\"\n                        if (current.next() instanceof Element && ((Element) current.next()).getContent().equals(\"...\")) {\n                                return new MethodDef(methodName, modifiers, returnType, variableList, annos,\n                                        Collections.<Statement>emptyList(),\n                                        lineCol);\n                        } else {\n                                Expression exp = next_exp(false, true);\n\n                                return new MethodDef(methodName, modifiers, returnType, variableList, annos,\n                                        Collections.<Statement>singletonList(\n                                                new AST.Return(exp, exp.line_col())\n                                        ),\n                                        lineCol);\n                        }\n                } else {\n                        if (current instanceof ElementStartNode) {\n                                // parse\n                                List<Statement> list = parseElemStart((ElementStartNode) current, true, names, false);\n                                MethodDef def = new MethodDef(methodName, modifiers, returnType, variableList, annos, list, lineCol);\n                                annos.clear();\n                                modifiers.clear();\n                                return def;\n                        } else {\n                                // ending or null\n                                MethodDef def = new MethodDef(methodName, modifiers, returnType, variableList, annos, Collections.<Statement>emptyList(), lineCol);\n                                annos.clear();\n                                modifiers.clear();\n                                return def;\n                        }\n                }\n        }\n\n        /**\n         * parse an expression\n         *\n         * @throws SyntaxException compiling errors\n         */\n        private void parse_expression() throws SyntaxException {\n                if (current == null) {\n                        return;\n                }\n                if (current instanceof Element) {\n                        String content = ((Element) current).getContent();\n\n                        boolean doCheckParsedExps = true;\n                        // first go to `doCheckParsedExps` branch, if not handled, then goto normal branch\n                        while (true) {\n                                if (doCheckParsedExps) {\n                                        if (parsedExps.empty()) {\n                                                // check unary operator that require no parsed expressions\n                                                if (isOneVariableOperatorPreMustCheckExps(content)) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_oneVarPreOperation();\n\n                                                        return;\n                                                }\n                                        }\n\n                                        doCheckParsedExps = false;\n                                } else {\n\n                                        if (current.getTokenType() == TokenType.NUMBER) {\n                                                annosIsEmpty();\n                                                modifiersIsEmpty();\n\n                                                NumberLiteral numberLiteral = new NumberLiteral(content, current.getLineCol());\n\n                                                parsedExps.push(numberLiteral);\n                                                nextNode(true);\n                                                parse_expression();\n\n                                        } else if (current.getTokenType() == TokenType.BOOL) {\n                                                annosIsEmpty();\n                                                modifiersIsEmpty();\n\n                                                BoolLiteral boolLiteral = new BoolLiteral(content, current.getLineCol());\n\n                                                parsedExps.push(boolLiteral);\n                                                nextNode(true);\n                                                parse_expression();\n\n                                        } else if (current.getTokenType() == TokenType.STRING) {\n                                                annosIsEmpty();\n                                                modifiersIsEmpty();\n\n                                                StringLiteral stringLiteral = new StringLiteral(content, current.getLineCol());\n\n                                                parsedExps.push(stringLiteral);\n                                                nextNode(true);\n                                                parse_expression();\n\n                                        } else if (isTwoVariableOperator(content) &&\n                                                (\n                                                        current.getTokenType() == TokenType.KEY || (current.getTokenType() == TokenType.SYMBOL)\n                                                )) {\n                                                // is/not/in are both two var op and keys\n                                                // it's handled independently\n                                                annosIsEmpty();\n                                                modifiersIsEmpty();\n\n                                                parse_twoVarOperation();\n\n                                        } else if (current.getTokenType() == TokenType.KEY) {\n                                                if (content.equals(\"type\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        LineCol lineCol = current.getLineCol();\n                                                        nextNode(false);\n                                                        AST.Access access = parse_cls_for_type_spec();\n                                                        parsedExps.push(new AST.TypeOf(access, lineCol));\n\n                                                        parse_expression();\n\n\n                                                } else if (content.equals(\"null\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n                                                        parsedExps.push(new AST.Null(current.getLineCol()));\n                                                        nextNode(true);\n                                                        parse_expression();\n\n                                                } else if (content.equals(\"as\")) {\n                                                        LineCol lineCol;\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (parsedExps.isEmpty()) {\n                                                                err.UnexpectedTokenException(\"expression\", \"as\", current.getLineCol());\n                                                                err.debug(\"ignore the statement\");\n                                                                throw new ParseFail();\n                                                        } else {\n                                                                lineCol = current.getLineCol();\n                                                                Expression exp = parsedExps.pop();\n                                                                nextNode(false);\n                                                                AST.Access type = parse_cls_for_type_spec();\n                                                                AST.AsType asType = new AST.AsType(exp, type, lineCol);\n                                                                parsedExps.push(asType);\n                                                        }\n\n                                                } else if (content.equals(\"require\")) {\n                                                        LineCol lineCol;\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n                                                        nextNode(false);\n                                                        lineCol = current.getLineCol();\n                                                        Expression exp = get_exp(false, true);\n                                                        parsedExps.push(new AST.Require(exp, lineCol));\n                                                        parse_expression();\n\n                                                } else if (content.equals(\"new\")) {\n                                                        LineCol lineCol;\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        // new\n                                                        lineCol = current.getLineCol();\n\n                                                        Expression next = next_exp(false, true);\n                                                        AST.New aNew;\n                                                        if (next instanceof AST.Invocation) {\n                                                                if (((AST.Invocation) next).invokeWithNames) {\n                                                                        err.SyntaxException(\"constructing an object does not support invokeWithNames\", next.line_col());\n                                                                        // assume it's not invokeWithNames\n                                                                }\n                                                                aNew = new AST.New((AST.Invocation) next, lineCol);\n                                                        } else if (next instanceof AST.Access) {\n                                                                aNew = new AST.New(\n                                                                        new AST.Invocation(\n                                                                                next,\n                                                                                Collections.<Expression>emptyList(),\n                                                                                false,\n                                                                                next.line_col()\n                                                                        ),\n                                                                        lineCol\n                                                                );\n                                                        } else {\n                                                                err.UnexpectedTokenException(\n                                                                        \"invoking a constructor\",\n                                                                        next.toString(), next.line_col());\n                                                                // ignore the exp\n                                                                throw new ParseFail();\n                                                        }\n                                                        parsedExps.push(aNew);\n                                                        parse_expression();\n\n                                                } else if (content.equals(\"match\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_pattern_matching();\n\n\n                                                } else {\n                                                        err.UnexpectedTokenException(content, current.getLineCol());\n                                                        // ignore\n                                                        err.debug(\"ignore the token\");\n                                                        nextNode(true);\n                                                }\n\n                                        } else if (current.getTokenType() == TokenType.SYMBOL) {\n\n                                                if (content.equals(\".\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (parsedExps.isEmpty()) {\n                                                                parse_dot_start_invocation();\n                                                        } else {\n                                                                nextNode(false);\n                                                                parse_access(true);\n                                                        }\n\n                                                } else if (isOneVariableOperatorPreWithoutCheckingExps(content)) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_oneVarPreOperation();\n\n                                                } else if (isOneVariableOperatorPost(content)) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_oneVarPostOperation();\n\n                                                } else if (isAssign(content)) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_assign();\n\n                                                } else if (content.equals(\":\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (isParsingMap) {\n                                                                // directly return\n                                                                // the key would be retrieved from the parsedExp stack\n                                                                return;\n                                                        } else {\n                                                                parse_type_spec();\n                                                        }\n\n                                                } else if (content.equals(\"[\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (parsedExps.empty()) {\n                                                                parse_array_exp();\n                                                        } else {\n                                                                parse_index_access();\n                                                        }\n                                                } else if (content.equals(\"{\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (current.next() instanceof Element && ((Element) current.next()).getContent().equals(\"}\")) {\n                                                                parse_map();\n                                                        } else {\n                                                                err.UnexpectedEndException(current.getLineCol());\n                                                                throw new ParseFail();\n                                                        }\n\n                                                } else if (content.equals(\"@\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        boolean tmp = annotationAsExpression;\n                                                        annotationAsExpression = true;\n                                                        parse_anno();\n                                                        annotationAsExpression = tmp;\n                                                        if (!annos.isEmpty()) {\n                                                                AST.Anno anno = annos.iterator().next();\n                                                                parsedExps.push(new AST.AnnoExpression(anno));\n                                                                annos.clear();\n                                                        }\n\n                                                } else if (content.equals(\"#\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        LineCol lineCol = current.getLineCol();\n                                                        if (parsedExps.isEmpty()) {\n                                                                // #generator\n                                                                //     ...\n                                                                Expression theType = next_exp(true, true);\n                                                                if (theType instanceof AST.Access) {\n                                                                        List<Statement> ast;\n                                                                        if (current instanceof ElementStartNode) {\n                                                                                ast = parseElemStart((ElementStartNode) current, false, Collections.<String>emptySet(), false);\n                                                                                nextNode(true);\n                                                                        } else {\n                                                                                ast = Collections.emptyList();\n                                                                        }\n                                                                        parsedExps.push(new AST.GeneratorSpec((AST.Access) theType, ast, lineCol));\n                                                                } else if (theType instanceof AST.GeneratorSpec) {\n                                                                        parsedExps.push(theType);\n                                                                } else {\n                                                                        err.UnexpectedTokenException(\"a type\", theType.toString(), theType.line_col());\n                                                                }\n                                                        } else {\n                                                                // #geneartor#...\n                                                                Expression exp = parsedExps.pop();\n                                                                if (!(exp instanceof AST.Access)) {\n                                                                        err.UnexpectedTokenException(exp.toString(), lineCol);\n                                                                        exp = new AST.Access(null, \"x\", lineCol);\n                                                                }\n                                                                AST.Access generator = (AST.Access) exp;\n                                                                parsedExps.push(\n                                                                        new AST.GeneratorSpec(generator,\n                                                                                Collections.<Statement>singletonList(next_exp(false, true)), lineCol));\n                                                        }\n\n                                                } else if (isDestructingWithoutType((Element) current)) {\n\n                                                        parse_destructing_withoutType();\n\n                                                } else if (content.equals(\"(\")) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        if (isLambda((Element) current)) {\n                                                                parse_lambda();\n                                                        } else {\n\n                                                                nextNode(false);\n\n                                                                if (current instanceof Element) {\n                                                                        // element should be ')'\n                                                                        expecting(\")\", current.previous(), current, err);\n                                                                        if (!parsedExps.empty()) {\n                                                                                // method() invocation\n                                                                                Expression invocationExp = parsedExps.pop();\n                                                                                AST.Invocation invocation = new AST.Invocation(invocationExp, Collections.<Expression>emptyList(),\n                                                                                        false, invocationExp.line_col());\n                                                                                parsedExps.push(invocation);\n                                                                        } else {\n                                                                                parsedExps.push(new AST.Procedure(Collections.<Statement>emptyList(), current.getLineCol()));\n                                                                        }\n\n                                                                        nextNode(true);\n                                                                        parse_expression();\n                                                                } else if (current instanceof ElementStartNode) {\n                                                                        // element start node : ...(口)...\n                                                                        ElementStartNode startNode = (ElementStartNode) current;\n                                                                        List<Statement> statements = parseElemStart(startNode, true, Collections.<String>emptySet(), false);\n\n                                                                        if (!parsedExps.empty()) {\n                                                                                // method(...) or xx[i]() or xx()()()...()\n                                                                                Expression invocationExp = parsedExps.pop();\n                                                                                List<Expression> args = new LinkedList<Expression>();\n\n                                                                                Statement lastStmt = null;\n                                                                                if (!statements.isEmpty()) {\n                                                                                        lastStmt = statements.get(statements.size() - 1);\n                                                                                }\n                                                                                boolean endWithVarDef = !statements.isEmpty()\n                                                                                        && lastStmt instanceof VariableDef\n                                                                                        && ((VariableDef) lastStmt).getInit() != null\n                                                                                        && ((VariableDef) lastStmt).getModifiers().isEmpty()\n                                                                                        && ((VariableDef) lastStmt).getAnnos().isEmpty();\n                                                                                boolean hasNonVarDef = false;\n                                                                                for (int i = statements.size() - 1; i >= 0; --i) {\n                                                                                        Statement stmt = statements.get(i);\n                                                                                        if ((stmt instanceof Expression)) {\n                                                                                                args.add(0, (Expression) stmt);\n\n                                                                                                if (stmt instanceof VariableDef) {\n                                                                                                        if (((VariableDef) stmt).getType() != null) {\n                                                                                                                err.UnexpectedTokenException(\"argument\", \"variable definition\", stmt.line_col());\n                                                                                                        }\n                                                                                                        if (((VariableDef) stmt).getInit() == null\n                                                                                                                ||\n                                                                                                                !((VariableDef) stmt).getAnnos().isEmpty()\n                                                                                                                ||\n                                                                                                                !((VariableDef) stmt).getModifiers().isEmpty()) {\n                                                                                                                hasNonVarDef = true;\n                                                                                                        } else {\n                                                                                                                if (hasNonVarDef) {\n                                                                                                                        err.SyntaxException(\"params with assignment should be at the end\", stmt.line_col());\n                                                                                                                }\n                                                                                                        }\n                                                                                                } else {\n                                                                                                        hasNonVarDef = true;\n                                                                                                }\n                                                                                        } else {\n                                                                                                err.UnexpectedTokenException(\"expression\", stmt.toString(), stmt.line_col());\n                                                                                                err.debug(\"ignore the argument\");\n                                                                                        }\n                                                                                }\n\n                                                                                AST.Invocation invocation = new AST.Invocation(invocationExp,\n                                                                                        args, endWithVarDef, current.getLineCol());\n                                                                                parsedExps.push(invocation);\n                                                                        } else {\n                                                                                if (statements.size() == 1) {\n                                                                                        Statement stmt = statements.get(0);\n                                                                                        if (stmt instanceof Expression) {\n                                                                                                // something like 3*(1+2)\n                                                                                                parsedExps.push((Expression) stmt);\n                                                                                        } else {\n                                                                                                // statement\n                                                                                                AST.Procedure procedure = new AST.Procedure(statements, startNode.getLineCol());\n                                                                                                parsedExps.push(procedure);\n                                                                                        }\n                                                                                } else {\n                                                                                        AST.Procedure procedure = new AST.Procedure(statements, startNode.getLineCol());\n                                                                                        parsedExps.push(procedure);\n                                                                                }\n                                                                        }\n\n                                                                        nextNode(false); // should be ')'\n                                                                        expecting(\")\", startNode, current, err);\n                                                                        nextNode(true);\n                                                                        parse_expression();\n                                                                }\n                                                        }\n                                                } else if (isPatternMatchingSymbol(content)) {\n                                                        // do nothing\n                                                        return;\n                                                } else {\n                                                        err.UnexpectedTokenException(content, current.getLineCol());\n                                                        err.debug(\"ignore the token\");\n                                                        nextNode(true);\n                                                }\n                                        } else if (current.getTokenType() == TokenType.VALID_NAME) {\n                                                if (isLambda((Element) current)) {\n                                                        parse_lambda();\n                                                } else if (isDestructing((Element) current)) {\n\n                                                        parse_destructing();\n\n                                                } else if (isPackage((Element) current)) {\n                                                        annosIsEmpty();\n                                                        modifiersIsEmpty();\n\n                                                        parse_package(true);\n\n                                                } else {\n                                                        // could be a var if it's the first expression in the exp stack\n                                                        // or it could be method invocation\n\n                                                        if (parsedExps.empty()) {\n                                                                parse_var();\n                                                        } else {\n                                                                parse_operator_like_invocation();\n                                                        }\n\n                                                }\n                                        } else {\n                                                err.UnexpectedTokenException(content, current.getLineCol());\n                                                err.debug(\"ignore the token\");\n                                                nextNode(true);\n                                        }\n\n                                        break;\n                                }\n                        }\n\n                } else if (current instanceof ElementStartNode) {\n                        if (!expectingStartNode) {\n                                /*\n                                expression\n                                    ...\n\n                                will be parsed into\n\n                                expression(it->\n                                        ...\n                                )\n\n                                the behavior of the expression may change because the AST changed\n                                 */\n                                if (parsedExps.isEmpty()) {\n                                        err.UnexpectedEndException(current.getLineCol());\n                                        throw new ParseFail();\n                                }\n                                Expression exp = parsedExps.pop();\n                                List<Statement> lambdaStmts = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                                AST.Lambda lambda = new AST.Lambda(Collections.singletonList(\n                                        new VariableDef(\"it\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                ), lambdaStmts, LineCol.SYNTHETIC_WITH_FILE(current.getLineCol().fileName));\n                                AST.Invocation invocation = new AST.Invocation(exp, Collections.<Expression>singletonList(lambda), false, LineCol.SYNTHETIC_WITH_FILE(current.getLineCol().fileName));\n                                parsedExps.push(invocation);\n                                nextNode(true);\n                                if (current instanceof EndingNode && ((EndingNode) current).getType() == EndingNode.SYNTHETIC) {\n                                        nextNode(true);\n                                }\n                                parse_expression();\n                        }\n                }\n                // else\n        }\n\n        /**\n         * parse invocation which starts with a dot\n         *\n         * @throws SyntaxException compile error\n         */\n        private void parse_dot_start_invocation() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                nextNode(false);\n                if (current.getTokenType() != TokenType.VALID_NAME) {\n                        err.UnexpectedTokenException(\"valid name\", current.toString(), current.getLineCol());\n                        throw new ParseFail();\n                }\n                String name = ((Element) current).getContent();\n                nextNode(true);\n                if (current == null || current instanceof EndingNode || (isParsingMap && ((Element) current).getContent().equals(\":\"))) {\n                        // .op\n                        parsedExps.push(new AST.Invocation(new AST.Access(null, name, lineCol),\n                                Collections.<Expression>emptyList(), false, lineCol));\n                        return;\n                }\n\n                List<Expression> args = new ArrayList<Expression>();\n                // .op exp\n                args.add(get_exp(false, true));\n\n                while (current instanceof EndingNode && ((EndingNode) current).getType() == EndingNode.STRONG) {\n                        nextNode(true);\n                        if (current != null && !(current instanceof EndingNode)) {\n                                args.add(get_exp(false, true));\n                        }\n                }\n                parsedExps.push(new AST.Invocation(new AST.Access(null, name, lineCol), args, false, lineCol));\n        }\n\n        /**\n         * parse destructing without type\n         */\n        private void parse_destructing_withoutType() throws SyntaxException {\n                nextNode(false);\n                Set<Modifier> theModifiers = getAndClear(modifiers);\n                Set<AST.Anno> theAnnos = getAndClear(annos);\n                if (current instanceof Element) {\n                        // )\n                        nextNode(false);\n                        // <-\n                        LineCol lineCol = current.getLineCol();\n\n                        Expression exp = next_exp(false, true);\n                        parsedExps.push(new AST.Destruct(\n                                theModifiers,\n                                theAnnos,\n                                new AST.Pattern_Destruct(null, Collections.<AST.Pattern>emptyList()), exp, lineCol\n                        ));\n                } else {\n                        // element start node\n                        ElementStartNode esn = (ElementStartNode) current;\n                        nextNode(false);\n                        // )\n                        nextNode(false);\n                        // <-\n                        LineCol lineCol = current.getLineCol();\n\n                        Expression exp = next_exp(false, true);\n\n                        List<AST.Pattern> patterns = parse_destructing_withoutType$patterns(esn);\n                        parsedExps.push(new AST.Destruct(\n                                theModifiers,\n                                theAnnos,\n                                new AST.Pattern_Destruct(null, patterns), exp, lineCol\n                        ));\n                }\n        }\n\n        private List<AST.Pattern> parse_destructing_withoutType$patterns(ElementStartNode esn) throws SyntaxException {\n                List<AST.Pattern> patternList = new ArrayList<AST.Pattern>();\n                Node n = esn.getLinkedNode();\n                while (n != null) {\n                        if (n instanceof Element) {\n                                Element e = (Element) n;\n                                if (e.getTokenType() != TokenType.VALID_NAME) {\n                                        err.UnexpectedTokenException(\"valid name\", n.toString(), n.getLineCol());\n                                        n = n.next();\n                                        continue;\n                                }\n                                if (e.getContent().equals(\"_\")) {\n                                        patternList.add(AST.Pattern_Default.get());\n                                        n = n.next();\n                                        continue;\n                                }\n                                if (usedVarNames.contains(e.getContent())) {\n                                        err.DuplicateVariableNameException(e.getContent(), n.getLineCol());\n                                        n = n.next();\n                                        continue;\n                                }\n                                patternList.add(new AST.Pattern_Define(e.getContent(), null));\n                                usedVarNames.add(e.getContent());\n                        } else if (!(n instanceof EndingNode)) {\n                                err.UnexpectedTokenException(\"valid name\", n.toString(), n.getLineCol());\n                        }\n                        n = n.next();\n                }\n                return patternList;\n        }\n\n        /**\n         * parse destructing\n         */\n        private void parse_destructing() throws SyntaxException {\n                AST.Access type = parse_cls_for_type_spec();\n                parse_destructing_withoutType();\n                AST.Destruct de = (AST.Destruct) parsedExps.pop();\n                parsedExps.push(\n                        new AST.Destruct(de.modifiers, de.annos,\n                                new AST.Pattern_Destruct(type, de.pattern.subPatterns),\n                                de.exp, de.line_col())\n                );\n        }\n\n        /**\n         * parse pattern matching\n         */\n        private void parse_pattern_matching() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                parsedExpsNotEmpty(current);\n                Expression expToMatch = parsedExps.pop();\n                nextNode(false);\n                LinkedHashMap<AST.PatternCondition, List<Statement>> resultMap = new LinkedHashMap<AST.PatternCondition, List<Statement>>();\n                if (current instanceof ElementStartNode) {\n                        ElementStartNode startNode = (ElementStartNode) current;\n                        Node switchLayerStart = current;\n                        current = startNode.getLinkedNode();\n                        while (true) {\n                                if (null == current) {\n                                        break;\n                                }\n                                if (current instanceof Element && ((Element) current).getContent().equals(\"case\")) {\n                                        nextNode(false);\n                                        AST.Pattern pattern = parse_pattern_matching_$_parse_pattern(false);\n                                        // check whether is `if`\n                                        Expression matchCondition = null;\n                                        if (current instanceof Element && ((Element) current).getContent().equals(\"if\")) {\n                                                nextNode(false);\n                                                matchCondition = get_exp(false, true);\n                                        }\n                                        expecting(\"=>\", current.previous(), current, err);\n                                        nextNode(false);\n                                        List<Statement> stmts;\n                                        if (current instanceof ElementStartNode) {\n                                                Set<String> newVarNames = parse_pattern_matching_$_extract_var_names(pattern);\n                                                stmts = parseElemStart((ElementStartNode) current, true, newVarNames, false);\n                                        } else if (current instanceof Element) {\n                                                // one line statement\n                                                stmts = Collections.singletonList(parse_statement());\n                                        } else {\n                                                err.UnexpectedTokenException(\"statements when the pattern matches\", current.toString(), current.getLineCol());\n                                                throw new ParseFail();\n                                        }\n                                        resultMap.put(new AST.PatternCondition(pattern, matchCondition), stmts);\n                                        nextNode(true);\n                                        if (current instanceof EndingNode) {\n                                                nextNode(true);\n                                        } else if (null == current) {\n                                                break;\n                                        } else {\n                                                err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                                                jumpToTheNearestEndingNode();\n                                                nextNode(true);\n                                        }\n                                } else {\n                                        err.UnexpectedTokenException(\"case\", current.toString(), current.getLineCol());\n                                        jumpToTheNearestEndingNode();\n                                        nextNode(true);\n                                }\n                        }\n                        current = switchLayerStart;\n                        nextNode(true);\n                }\n                parsedExps.push(new AST.PatternMatching(expToMatch, resultMap, lineCol));\n                parse_expression();\n        }\n\n        private Set<String> parse_pattern_matching_$_extract_var_names(AST.Pattern pattern) {\n                switch (pattern.patternType) {\n                        case TYPE:\n                        case VALUE:\n                        case DEFAULT:\n                                return Collections.emptySet();\n                        case DEFINE:\n                                return Collections.singleton(((AST.Pattern_Define) pattern).name);\n                        case DESTRUCT:\n                                AST.Pattern_Destruct pd = (AST.Pattern_Destruct) pattern;\n                                Set<String> result = new HashSet<String>();\n                                for (AST.Pattern p : pd.subPatterns) {\n                                        result.addAll(parse_pattern_matching_$_extract_var_names(p));\n                                }\n                                return result;\n                        default:\n                                throw new LtBug(\"unknown pattern type \" + pattern.patternType);\n                }\n        }\n\n        private AST.Pattern parse_pattern_matching_$_parse_pattern$_parse(boolean parsingSubPattern) throws SyntaxException {\n                /*\n                _:XX::YY::ZZ\n                _\n                xx::yy::zz::Bean(a, _)\n                1\n                */\n                boolean condition1;\n                if (parsingSubPattern) {\n                        condition1 = (current.next() == null || current.next() instanceof EndingNode\n                                || ((current.next() instanceof Element) && ((Element) current.next()).getContent().equals(\",\")));\n                } else {\n                        condition1 = ((Element) current.next()).getContent().equals(\"=>\")\n                                || ((Element) current.next()).getContent().equals(\"if\");\n                }\n                if (condition1) {\n                        AST.Pattern subPattern;\n                        // check _/123/\"xxx\"/true/a\n                        if (current.getTokenType() == TokenType.VALID_NAME) {\n                                if (((Element) current).getContent().equals(\"_\")) {\n                                        subPattern = AST.Pattern_Default.get();\n                                } else if (usedVarNames.contains(((Element) current).getContent())) {\n                                        // use the var\n                                        subPattern = new AST.Pattern_Value(\n                                                new AST.Access(null, ((Element) current).getContent(), current.getLineCol())\n                                        );\n                                } else {\n                                        // use as defined\n                                        String name = ((Element) current).getContent();\n                                        if (parsingSubPattern) {\n                                                usedVarNames.add(name);\n                                        }\n                                        subPattern = new AST.Pattern_Define(name, null);\n                                }\n                        } else if (current.getTokenType() == TokenType.BOOL) {\n                                subPattern = new AST.Pattern_Value(new BoolLiteral(((Element) current).getContent(), current.getLineCol()));\n                        } else if (current.getTokenType() == TokenType.NUMBER) {\n                                subPattern = new AST.Pattern_Value(new NumberLiteral(((Element) current).getContent(), current.getLineCol()));\n                        } else if (current.getTokenType() == TokenType.STRING) {\n                                String content = ((Element) current).getContent();\n                                subPattern = new AST.Pattern_Value(new StringLiteral(content, current.getLineCol()));\n                        } else {\n                                err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                                throw new ParseFail();\n                        }\n                        nextNode(true);\n                        return subPattern;\n                } else if (current.getTokenType() == TokenType.VALID_NAME && current.next() instanceof Element && ((Element) current.next()).getContent().equals(\":\")) {\n                        String name = ((Element) current).getContent();\n                        if (usedVarNames.contains(name)) {\n                                err.DuplicateVariableNameException(name, current.getLineCol());\n                                throw new ParseFail();\n                        } else {\n                                nextNode(false); // :\n                                nextNode(false);\n                                AST.Access type = parse_cls_for_type_spec();\n                                if (name.equals(\"_\")) {\n                                        return new AST.Pattern_Type(type);\n                                } else {\n                                        if (parsingSubPattern) {\n                                                usedVarNames.add(name);\n                                        }\n                                        return new AST.Pattern_Define(name, type);\n                                }\n                        }\n                } else {\n                        AST.Access type = null;\n                        try {\n                                type = parse_cls_for_type_spec();\n                        } catch (SyntaxException ignore) {\n                        }\n                        if (type == null) {\n                                // not type\n                                // try exp\n                                Expression exp = next_exp(true, true);\n                                return new AST.Pattern_Value(exp);\n                        } else {\n                                // type specified\n                                if (current instanceof Element) {\n                                        if (((Element) current).getContent().equals(\"(\")) {\n                                                nextNode(false);\n                                                if (current instanceof Element) {\n                                                        expecting(\")\", current.previous(), current, err);\n                                                        nextNode(true);\n                                                        return new AST.Pattern_Destruct(type, Collections.<AST.Pattern>emptyList());\n                                                }\n                                                ElementStartNode startNode = (ElementStartNode) current;\n                                                nextNode(false); // )\n                                                expecting(\")\", current.previous(), current, err);\n                                                nextNode(true);\n                                                Parser subParser = new Parser(startNode, err);\n                                                subParser.addUsedVarNames(usedVarNames);\n                                                List<AST.Pattern> patterns = new ArrayList<AST.Pattern>();\n                                                while (subParser.current instanceof Element) {\n                                                        AST.Pattern p = subParser.parse_pattern_matching_$_parse_pattern$_parse(true);\n                                                        patterns.add(p);\n                                                        subParser.nextNode(true);\n                                                }\n                                                return new AST.Pattern_Destruct(type, patterns);\n                                        } else {\n                                                err.UnexpectedTokenException(\"destructing expression\", ((Element) current).getContent(), current.getLineCol());\n                                                throw new ParseFail();\n                                        }\n                                } else {\n                                        return new AST.Pattern_Destruct(type, Collections.<AST.Pattern>emptyList());\n                                }\n                        }\n                }\n        }\n\n        private AST.Pattern parse_pattern_matching_$_parse_pattern(boolean parsingSubPattern) throws SyntaxException {\n                if (current instanceof Element && current.next() instanceof Element) {\n                        return parse_pattern_matching_$_parse_pattern$_parse(parsingSubPattern);\n                } else {\n                        err.UnexpectedTokenException(current.toString(), current.getLineCol());\n                        throw new ParseFail();\n                }\n        }\n\n        /**\n         * parse method def and there's no `(` after the name\n         */\n        private MethodDef parse_method_def_no_par() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                String name = ((Element) current).getContent();\n                Set<AST.Anno> annoSet = new HashSet<AST.Anno>(annos);\n                annos.clear();\n                Set<Modifier> modSet = new HashSet<Modifier>(modifiers);\n                modifiers.clear();\n                nextNode(true);\n                if (current == null || current instanceof EndingNode) {\n                        return new MethodDef(name, modSet, null, Collections.<VariableDef>emptyList(), annoSet, Collections.<Statement>emptyList(), lineCol);\n                } else if (current instanceof ElementStartNode) {\n                        return new MethodDef(name, modSet, null, Collections.<VariableDef>emptyList(), annoSet,\n                                parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false), lineCol);\n                } else if (current instanceof Element) {\n                        try {\n                                expecting(\":\", current.previous(), current, err);\n                        } catch (SyntaxException ignore) {\n                                // =\n                                expecting(\"=\", current.previous(), current, err);\n                                return new MethodDef(name, modSet, null, Collections.<VariableDef>emptyList(), annoSet,\n                                        Collections.<Statement>singletonList(next_exp(false, true)), lineCol);\n                        }\n                        // :\n                        nextNode(false);\n                        AST.Access type = parse_cls_for_type_spec();\n                        if (current == null || current instanceof EndingNode) {\n                                return new MethodDef(name, modSet, type, Collections.<VariableDef>emptyList(), annoSet,\n                                        Collections.<Statement>emptyList(), lineCol);\n                        } else if (current instanceof ElementStartNode) {\n                                return new MethodDef(name, modSet, type, Collections.<VariableDef>emptyList(), annoSet,\n                                        parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false), lineCol);\n                        } else if (current instanceof Element && ((Element) current).getContent().equals(\"=\")) {\n                                return new MethodDef(name, modSet, type, Collections.<VariableDef>emptyList(), annoSet,\n                                        Collections.<Statement>singletonList(next_exp(false, true)), lineCol);\n                        } else {\n                                err.UnexpectedTokenException(\"end of definition or method body\", current.toString(), current.getLineCol());\n                                err.debug(\"assume it's empty body\");\n                                return new MethodDef(name, modSet, type, Collections.<VariableDef>emptyList(), annoSet,\n                                        Collections.<Statement>emptyList(), lineCol);\n                        }\n                } else throw new LtBug(\"unknown node type\");\n        }\n\n        /**\n         * parse expression like these<br>\n         * <code>a op b</code><br>\n         * which would be parsed into <code>a.op(b)</code><br>\n         * <code>a op</code><br>\n         * which would be parsed into <code>a.op()</code>\n         * </code>\n         */\n        private void parse_operator_like_invocation() throws SyntaxException {\n                // is parsing operator like invocation then disable this feature\n                if (isParsingOperatorLikeInvocation) return;\n\n                parsedExpsNotEmpty(current);\n                Expression a = parsedExps.pop();\n                String op = ((Element) current).getContent();\n                LineCol opLineCol = current.getLineCol();\n\n                if (current.next() instanceof Element && (!isParsingMap || !((Element) current.next()).getContent().equals(\":\"))) {\n                        // is two var op\n                        if (!last2VarOps.empty()) {\n                                String lastOp = last2VarOps.pop();\n                                if (twoVar_higherOrEqual(lastOp, op)) {\n                                        parsedExps.push(a);\n                                        return;\n                                }\n                                last2VarOps.push(lastOp);\n                        }\n                        nextNode(true);\n                        // another expression exists\n                        // e.g. a op b\n                        last2VarOps.push(op);\n                        List<Expression> opArgs = new ArrayList<Expression>();\n                        opArgs.add(get_exp(false, false));\n\n                        while (current instanceof EndingNode && ((EndingNode) current).getType() == EndingNode.STRONG) {\n                                // take out all var op from stack\n                                Stack<String> tmp = new Stack<String>();\n                                while (!last2VarOps.empty()) tmp.push(last2VarOps.pop());\n                                nextNode(false);\n\n                                isParsingOperatorLikeInvocation = true;\n\n                                opArgs.add(get_exp(false, false));\n\n                                isParsingOperatorLikeInvocation = false;\n\n                                while (!tmp.empty()) last2VarOps.push(tmp.pop());\n                        }\n                        AST.Invocation invocation = new AST.Invocation(\n                                new AST.Access(a, op, opLineCol),\n                                opArgs,\n                                false, opLineCol);\n                        parsedExps.push(invocation);\n                } else {\n                        // a.op()\n                        if (!last2VarOps.empty()) {\n                                last2VarOps.pop();\n                                parsedExps.push(a);\n                                return;\n                        }\n                        nextNode(true);\n                        AST.Access access = new AST.Access(a, op, opLineCol);\n                        parsedExps.push(access);\n                }\n\n                parse_expression();\n        }\n\n        /**\n         * parse map<br>\n         * <code>\n         * {<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;a:b<br>\n         * }\n         * </code>\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_map() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                nextNode(false);\n\n                if (current instanceof Element) {\n                        // {}\n                        expecting(\"}\", current.previous(), current, err);\n                        parsedExps.push(new AST.MapExp(new LinkedHashMap<Expression, Expression>(), lineCol));\n\n                        nextNode(true);\n                } else {\n                        // current instance of ElementStartNode\n                        expecting(\"}\", current, current.next() == null ? null : current.next().next(), err);\n\n                        parsedExps.push(parseExpMap((ElementStartNode) current));\n\n                        nextNode(false); // }\n                        nextNode(true);\n                }\n\n                parse_expression();\n        }\n\n        /**\n         * parse map contents\n         *\n         * @param startNode root\n         * @return MapExp\n         * @throws SyntaxException compiling error\n         */\n        private AST.MapExp parseExpMap(ElementStartNode startNode) throws SyntaxException {\n                List<Statement> stmts = parseElemStart(startNode, true, Collections.<String>emptySet(), true);\n                if (stmts.size() % 2 != 0) {\n                        throw new LtBug(\"the list should contain key-value entries\");\n                }\n\n                boolean isKey = true;\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                Expression exp = null;\n\n                boolean jumpValue = false;\n\n                for (Statement s : stmts) {\n                        if (jumpValue) {\n                                jumpValue = false;\n                                continue;\n                        }\n                        if (s instanceof Expression) {\n                                if (isKey) {\n                                        exp = (Expression) s;\n                                } else {\n                                        map.put(exp, (Expression) s);\n                                }\n                                isKey = !isKey;\n                        } else {\n                                err.UnexpectedTokenException(\"expression\", s.toString(), s.line_col());\n                                err.debug(\"ignore this entry\");\n                                if (isKey) {\n                                        jumpValue = true;\n                                } else {\n                                        isKey = true;\n                                }\n                        }\n                }\n                return new AST.MapExp(map, startNode.getLineCol());\n        }\n\n        /**\n         * parse index<br>\n         * <code>\n         * v[i]<br>\n         * v[]<br>\n         * v[i,j]\n         * </code>\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_index_access() throws SyntaxException {\n                Expression e = parsedExps.pop();\n                nextNode(false);\n                if (current instanceof Element) {\n                        // e[]\n                        expecting(\"]\", current.previous(), current, err);\n                        parsedExps.push(new AST.Index(e, Collections.<Expression>emptyList(), e.line_col()));\n\n                        nextNode(true);\n                } else {\n                        // current instance of ElementStartNode\n                        expecting(\"]\", current, current.next() == null ? null : current.next().next(), err);\n                        List<Statement> stmts = parseElemStart((ElementStartNode) current, true, Collections.<String>emptySet(), false);\n                        List<Expression> exps = new ArrayList<Expression>();\n\n                        for (Statement stmt : stmts) {\n                                if (stmt instanceof Expression) {\n                                        exps.add((Expression) stmt);\n                                } else {\n                                        err.UnexpectedTokenException(\"index access expression\", stmt.toString(), stmt.line_col());\n                                        err.debug(\"ignore the statement\");\n                                }\n                        }\n                        parsedExps.push(new AST.Index(e, exps, e.line_col()));\n\n                        nextNode(false); // [...]\n                        nextNode(true); // [...] ..\n                }\n\n                parse_expression();\n        }\n\n        /**\n         * parse array expression<br>\n         * <code>\n         * [expression,...]\n         * </code>\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_array_exp() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n                nextNode(false);\n                if (current instanceof Element) {\n                        // [] empty array\n                        expecting(\"]\", current.previous(), current, err);\n                        parsedExps.push(new AST.ArrayExp(Collections.<Expression>emptyList(), lineCol));\n\n                        nextNode(true);\n                } else {\n                        // current instanceof ElementStartNode\n                        // [...]\n                        expecting(\"]\", current, current.next() == null ? null : current.next().next(), err);\n\n                        // check whether it's a map or a list\n                        ElementStartNode startNode = (ElementStartNode) current;\n                        Node linked = startNode.getLinkedNode();\n                        boolean isMap = false;\n                        while (linked != null) {\n                                if (linked instanceof Element && ((Element) linked).getContent().equals(\":\")) {\n                                        isMap = true;\n                                        break;\n                                }\n                                linked = linked.next();\n                        }\n\n                        List<Statement> stmts = parseElemStart(startNode, true, Collections.<String>emptySet(), isMap);\n\n                        if (isMap) {\n                                parsedExps.push(parseExpMap(startNode));\n                        } else {\n                                List<Expression> exps = new ArrayList<Expression>();\n\n                                for (Statement stmt : stmts) {\n                                        if (stmt instanceof Expression) {\n                                                exps.add((Expression) stmt);\n                                        } else {\n                                                err.UnexpectedTokenException(\"array contents\", stmt.toString(), stmt.line_col());\n                                                err.debug(\"ignore the statement\");\n                                        }\n                                }\n                                parsedExps.push(new AST.ArrayExp(exps, lineCol));\n                        }\n\n                        nextNode(false); // [...]\n                        nextNode(true); // [...] ..\n                }\n\n                parse_expression();\n        }\n\n        /**\n         * parse lambda<br>\n         * <code>\n         * ()=&gt;<br>\n         * (args,...)-&gt;\n         * </code>\n         *\n         * @throws SyntaxException compiling errors\n         */\n        private void parse_lambda() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                List<VariableDef> variableDefList = new ArrayList<VariableDef>();\n                Set<String> set = new HashSet<String>();\n                if (((Element) current).getContent().equals(\"(\")) {\n                        nextNode(false);\n                        if (current instanceof ElementStartNode) {\n                                List<Statement> list = parseElemStart((ElementStartNode) current, false, Collections.<String>emptySet(), false);\n                                for (Statement statement : list) {\n                                        if (statement instanceof AST.Access) {\n                                                AST.Access access = (AST.Access) statement;\n                                                if (access.exp == null) {\n                                                        VariableDef v = new VariableDef(access.name, Collections.<Modifier>emptySet(), annos, access.line_col());\n                                                        annos.clear();\n                                                        variableDefList.add(v);\n\n                                                        set.add(access.name);\n                                                } else {\n                                                        err.UnexpectedTokenException(\"variable\", access.exp.toString(), access.exp.line_col());\n                                                        err.debug(\"ignore the variable\");\n                                                }\n                                        } else if (statement instanceof VariableDef) {\n                                                VariableDef v = (VariableDef) statement;\n                                                variableDefList.add(v);\n\n                                                set.add(v.getName());\n                                        } else {\n                                                err.UnexpectedTokenException(\"variable\", statement.toString(), statement.line_col());\n                                                err.debug(\"ignore the variable\");\n                                        }\n                                }\n\n                                nextNode(false);\n                        }\n                } else {\n                        // it's a valid name\n                        assert isValidName(((Element) current).getContent());\n                        String name = ((Element) current).getContent();\n                        set.add(name);\n                        variableDefList.add(new VariableDef(name, Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), current.getLineCol()));\n                }\n\n                nextNode(false); // ->\n                expecting(\"->\", current.previous(), current, err);\n                nextNode(false);\n                // (...)->口\n\n                List<Statement> stmts;\n                if (current instanceof ElementStartNode) {\n                        stmts = parseElemStart((ElementStartNode) current, true, set, false);\n                        nextNode(true);\n                } else {\n                        stmts = new ArrayList<Statement>();\n                        stmts.add(get_exp(false, true));\n                }\n\n                AST.Lambda l = new AST.Lambda(variableDefList, stmts, lineCol);\n\n                parsedExps.push(l);\n\n                parse_expression();\n        }\n\n        /**\n         * check whether the parsedExps stack is empty\n         *\n         * @param tokenNode current token\n         * @throws UnexpectedTokenException compiling error\n         */\n        private void parsedExpsNotEmpty(Node tokenNode) throws UnexpectedTokenException {\n                if (parsedExps.empty()) {\n                        err.UnexpectedTokenException(tokenNode.toString(), tokenNode.getLineCol());\n                        throw new ParseFail();\n                }\n        }\n\n        /**\n         * parse 2 variable operations<br>\n         * <code>\n         * + - * / % = == != &gt; &lt; and other operations\n         * </code>\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_twoVarOperation() throws SyntaxException {\n                Element opNode = (Element) current;\n                String op = opNode.getContent();\n\n                LineCol lineCol = current.getLineCol();\n\n                parsedExpsNotEmpty(opNode);\n                Expression e1 = parsedExps.pop();\n\n                // check operator priority\n                if (!last1VarUnaryOps.empty()) {\n                        parsedExps.push(e1);\n                        return;\n                }\n                if (!last2VarOps.empty() && twoVar_higherOrEqual(last2VarOps.peek(), op)) {\n                        // e.g. 1+2*3-4\n                        // stack:(empty)\n                        // 1+ stack:\n                        // 2* stack:+ ( + < * )\n                        // 3- stack: + * ( * > - )\n                        // then return 3 directly\n                        // then return 2*3\n                        // then return 1+(2*3)\n                        // then\n                        // 1+(2*3)- stack:\n                        // 4 return 4\n                        // (1+(2*3))-4\n                        parsedExps.push(e1);\n                        last2VarOps.pop();\n                        return;\n                }\n                last2VarOps.push(op);\n                Expression e2 = next_exp(false, false);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(op, e1, e2, lineCol);\n                parsedExps.push(tvo);\n\n                parse_expression();\n        }\n\n        /**\n         * parse one variable post operations\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_oneVarPostOperation() throws SyntaxException {\n                Element opNode = (Element) current;\n                String op = opNode.getContent();\n\n                // get exp\n                parsedExpsNotEmpty(opNode);\n                Expression e = parsedExps.pop();\n\n                OneVariableOperation ovo = new OneVariableOperation(op, e, opNode.getLineCol());\n                parsedExps.push(ovo);\n\n                // continue\n                nextNode(true);\n\n                parse_expression();\n        }\n\n        /**\n         * parse one variable pre operations\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_oneVarPreOperation() throws SyntaxException {\n                Element opNode = (Element) current;\n                String op = opNode.getContent();\n                last1VarUnaryOps.push(op);\n\n                // get exp\n                Expression e = next_exp(false, false);\n\n                UnaryOneVariableOperation uovo = new UnaryOneVariableOperation(op, e, opNode.getLineCol());\n                parsedExps.push(uovo);\n\n                last1VarUnaryOps.pop();\n\n                parse_expression();\n        }\n\n        /**\n         * parse a package, which will may fill the stack with {@link AST.PackageRef} or {@link AST.Access}\n         *\n         * @param parse_exp call {@link #parse_expression()} after finished\n         * @throws SyntaxException compiling error\n         */\n        private void parse_package(boolean parse_exp) throws SyntaxException {\n                StringBuilder sb = new StringBuilder();\n                boolean isName = true;\n\n                LineCol lineCol = current.getLineCol();\n\n                while (current != null && (current instanceof Element) && (((Element) current).getContent().equals(\"::\")\n                        ||\n                        current.getTokenType() == TokenType.VALID_NAME\n                )) {\n                        Element elem = (Element) current;\n                        String s = elem.getContent();\n                        if (!isName && !s.equals(\"::\")) {\n                                err.UnexpectedTokenException(\"::\", s, elem.getLineCol());\n                                err.debug(\"let the string be '::'\");\n                                s = \"::\";\n                        }\n                        isName = !isName;\n                        sb.append(s);\n                        nextNode(true);\n                }\n\n                String str = sb.toString();\n                AST.PackageRef pkg = new AST.PackageRef(str.substring(0, str.lastIndexOf(\"::\")), lineCol);\n                String cls = str.substring(str.lastIndexOf(\"::\") + 2);\n                AST.Access access = new AST.Access(pkg, cls, lineCol);\n                parsedExps.push(access);\n\n                if (parse_exp) {\n                        parse_expression();\n                }\n        }\n\n        /**\n         * parse XXX.xx\n         *\n         * @param parse_exp invoke {@link #parse_expression()} after finished\n         * @throws SyntaxException compiling error\n         */\n        private void parse_access(boolean parse_exp) throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                Expression exp = null;\n                if (!parsedExps.isEmpty()) {\n                        exp = parsedExps.pop();\n                }\n                if (current instanceof Element) {\n                        String name = ((Element) current).getContent();\n                        if (current.getTokenType() != TokenType.VALID_NAME) {\n                                err.UnexpectedTokenException(\"valid name\", name, current.getLineCol());\n                                err.debug(\"assume that the token is a valid name\");\n                        }\n\n                        AST.Access access = new AST.Access(exp, name, lineCol);\n                        parsedExps.push(access);\n\n                        nextNode(true);\n\n                        if (current != null && current.getTokenType() == TokenType.SYMBOL && ((Element) current).getContent().equals(\"<:\")) {\n                                // generic\n                                access.generics.addAll(parse_generic());\n                        }\n\n                        if (parse_exp) {\n                                parse_expression();\n                        }\n                } else {\n                        err.UnexpectedTokenException(\"valid name\", current.toString(), current.getLineCol());\n                        err.debug(\"ignore the statement\");\n                        throw new ParseFail();\n                }\n        }\n\n        /**\n         * parse next expression<br>\n         * nextNode(false) would be invoked\n         *\n         * @param expectingStartNode true if expecting start node\n         * @return expression\n         * @throws SyntaxException compiling error\n         */\n        private Expression next_exp(boolean expectingStartNode, boolean clearVarOpStack) throws SyntaxException {\n                nextNode(false);\n                return get_exp(expectingStartNode, clearVarOpStack);\n        }\n\n        /**\n         * parse current expression\n         *\n         * @param expectingStartNode true if expecting start node\n         * @return expression\n         * @throws SyntaxException compiling error\n         */\n        private Expression get_exp(boolean expectingStartNode, boolean clearVarOpStack) throws SyntaxException {\n                // set expecting start node\n                if (expectingStartNode) {\n                        this.expectingStartNode = true;\n                }\n                parse_expression();\n                if (clearVarOpStack) {\n                        last2VarOps.clear();\n                }\n                // reset expecting start node\n                if (expectingStartNode) {\n                        this.expectingStartNode = false;\n                }\n                return parsedExps.pop();\n        }\n\n        /**\n         * annotation set {@link #annos} should be empty\n         */\n        private void annosIsEmpty() throws SyntaxException {\n                if (!annos.isEmpty()) {\n                        LineCol lineCol = null;\n                        for (AST.Anno a : annos) {\n                                if (lineCol == null || a.line_col().line < lineCol.line) {\n                                        lineCol = a.line_col();\n                                } else if (a.line_col().line == lineCol.line) {\n                                        if (a.line_col().column < lineCol.column) {\n                                                lineCol = a.line_col();\n                                        }\n                                }\n                        }\n                        err.SyntaxException(\"annotations are not presented at correct position\", lineCol);\n                        err.debug(\"clear the annotation set\");\n                        annos.clear();\n                }\n        }\n\n        /**\n         * modifier set {@link #modifiers} shoud be empty\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void modifiersIsEmpty() throws SyntaxException {\n                if (!modifiers.isEmpty()) {\n                        LineCol lineCol = null;\n                        for (Modifier m : modifiers) {\n                                if (lineCol == null || m.line_col().line < lineCol.line) {\n                                        lineCol = m.line_col();\n                                } else if (m.line_col().line == lineCol.line) {\n                                        if (m.line_col().column < lineCol.column) {\n                                                lineCol = m.line_col();\n                                        }\n                                }\n                        }\n                        err.SyntaxException(\"modifiers are not in the right position\", lineCol);\n                        err.debug(\"clear the modifier set\");\n                        modifiers.clear();\n                }\n        }\n\n        /**\n         * parse assign\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_assign() throws SyntaxException {\n                String op = ((Element) current).getContent();\n\n                parsedExpsNotEmpty(current);\n                Expression exp = parsedExps.pop();\n\n                LineCol lineCol = current.getLineCol();\n                if (exp instanceof AST.Access) {\n                        AST.Access access = (AST.Access) exp;\n                        if (access.exp == null && !usedVarNames.contains(access.name) && op.equals(\"=\")) {\n                                // define a new variable\n                                VariableDef def = new VariableDef(access.name, modifiers, annos, access.line_col());\n                                annos.clear();\n                                modifiers.clear();\n                                usedVarNames.add(access.name);\n\n                                Expression e = next_exp(false, true);\n\n                                def.setInit(e);\n                                parsedExps.push(def);\n\n                        } else {\n                                Expression e = next_exp(false, true);\n                                AST.Assignment a = new AST.Assignment((AST.Access) exp, op, e, lineCol);\n\n                                parsedExps.push(a);\n                        }\n                } else if (exp instanceof AST.Index) {\n                        AST.Index index = (AST.Index) exp;\n                        Expression e = next_exp(false, true);\n                        AST.Assignment a = new AST.Assignment(new AST.Access(index, null, index.line_col()), op, e, lineCol);\n\n                        parsedExps.push(a);\n                } else if (exp instanceof VariableDef) {\n                        VariableDef def = (VariableDef) exp;\n\n                        Expression e = next_exp(false, true);\n                        def.setInit(e);\n\n                        parsedExps.push(def);\n                } else {\n                        err.UnexpectedTokenException(\"assignable variable\", exp.toString(), exp.line_col());\n                        err.debug(\"ignore the assign statement\");\n                        throw new ParseFail();\n                }\n\n                parse_expression();\n        }\n\n        /**\n         * parse modifiers\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_modifier() throws SyntaxException {\n                Element elem = (Element) current;\n                String modifier = elem.getContent();\n                if (modifierIsCompatible(modifier, modifiers)) {\n                        modifiers.add(new Modifier(getModifierFromString(modifier), current.getLineCol()));\n                } else {\n                        err.UnexpectedTokenException(\"valid modifier\", modifier, elem.getLineCol());\n                        err.debug(\"ignore this modifier\");\n                }\n        }\n\n        /**\n         * parse variable\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_var() throws SyntaxException {\n                String content = ((Element) current).getContent();\n                if (!modifiers.isEmpty() || !annos.isEmpty()) {\n                        // define\n                        if (usedVarNames.contains(content)) {\n                                err.DuplicateVariableNameException(content, current.getLineCol());\n                                err.debug(\"assume that it's an unused name\");\n                        }\n\n                        VariableDef def = new VariableDef(content, modifiers, annos, current.getLineCol());\n                        annos.clear();\n                        modifiers.clear();\n                        usedVarNames.add(content);\n                        parsedExps.push(def);\n\n                        nextNode(true);\n                } else {\n                        parse_access(false);\n                }\n                parse_expression();\n        }\n\n        /**\n         * parse class for type specification\n         *\n         * @return Access\n         * @throws SyntaxException compiling error\n         */\n        private AST.Access parse_cls_for_type_spec() throws SyntaxException {\n                AST.Access a;\n\n                // parse array\n                // []Type or [][]Type ...\n                int arrayDepth = 0;\n                while (((Element) current).getContent().equals(\"[\")) {\n                        nextNode(false);\n                        expecting(\"]\", current.previous(), current, err);\n                        nextNode(false);\n                        ++arrayDepth;\n                }\n                if (isPackage((Element) current)) {\n                        parse_package(false);\n\n                        while (current instanceof Element && ((Element) current).getContent().equals(\".\")) {\n                                // package::name::Class.Inner\n                                nextNode(false);\n                                parse_access(false);\n                        }\n                        // i:pkg::Cls.[Inner]\n                        a = (AST.Access) parsedExps.pop();\n\n                } else if (current.getTokenType() == TokenType.VALID_NAME\n                        ||\n                        isPrimitive(((Element) current).getContent())) {\n                        // Cls.Inner\n                        AST.Access access = new AST.Access(null, ((Element) current).getContent(), current.getLineCol());\n                        parsedExps.push(access);\n                        nextNode(true);\n\n                        while (current instanceof Element && ((Element) current).getContent().equals(\".\")) {\n                                // package::name::Class.[Inner]\n                                nextNode(false);\n                                parse_access(false);\n                        }\n\n                        a = (AST.Access) parsedExps.pop();\n                } else {\n\n                        err.UnexpectedTokenException(\"type\", ((Element) current).getContent(), current.getLineCol());\n                        err.debug(\"assume that the token is Object\");\n                        a = new AST.Access(null, \"Object\", LineCol.SYNTHETIC);\n\n                }\n\n                if (current instanceof Element && ((Element) current).getContent().equals(\"<:\")) {\n                        a.generics.addAll(parse_generic());\n                }\n\n                for (int i = 0; i < arrayDepth; ++i) {\n                        a = new AST.Access(a, \"[]\", a.line_col());\n                }\n\n                return a;\n        }\n\n        /**\n         * parse type specification (:)<br>\n         * the result would be VariableDef\n         *\n         * @throws SyntaxException compiling error\n         */\n        private void parse_type_spec() throws SyntaxException {\n                LineCol lineCol = current.getLineCol();\n\n                parsedExpsNotEmpty(current);\n                Expression v = parsedExps.pop();\n\n                if (v instanceof AST.Access) {\n                        if (((AST.Access) v).exp != null) {\n                                err.UnexpectedTokenException(\"variable definition\", v.toString(), v.line_col());\n                                err.debug(\"ignore current statement\");\n                                throw new ParseFail();\n                        }\n\n                        String name = ((AST.Access) v).name;\n                        if (usedVarNames.contains(name)) {\n                                err.DuplicateVariableNameException(name, v.line_col());\n                                err.debug(\"assume that it's an unused name\");\n                        }\n                        v = new VariableDef(name, modifiers, annos, v.line_col());\n                        annos.clear();\n                        usedVarNames.add(name);\n                        modifiers.clear();\n                }\n\n                if (!(v instanceof VariableDef)) {\n                        err.UnexpectedTokenException(\"variable\", v.toString(), v.line_col());\n                        err.debug(\"ignore current statement\");\n                        throw new ParseFail();\n                }\n\n                nextNode(false);\n                if (current instanceof Element) {\n                        AST.Access a = parse_cls_for_type_spec();\n                        ((VariableDef) v).setType(a);\n                } else {\n                        err.UnexpectedTokenException(\"type\", current.toString(), current == null ? lineCol : current.getLineCol());\n                        err.debug(\"ignore current statement\");\n                        throw new ParseFail();\n                }\n\n                parsedExps.push(v);\n                parse_expression();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/Properties.java",
    "content": "package lt.compiler;\n\n/**\n * properties for the scanner\n */\npublic class Properties {\n        /**\n         * base of line numbers. all lines += _LINE_BASE_\n         */\n        public int _LINE_BASE_ = 0;\n        /**\n         * base of column numbers. all columns += _COLUMN_BASE_\n         */\n        public int _COLUMN_BASE_ = 0;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/PushLineBackReader.java",
    "content": "package lt.compiler;\n\nimport java.io.BufferedReader;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.util.LinkedList;\n\n/**\n * a line reader that can push lines back from the outside.\n */\npublic class PushLineBackReader extends Reader {\n        private final BufferedReader reader;\n        private final LinkedList<String> lines = new LinkedList<String>();\n\n        public PushLineBackReader(Reader reader) {\n                if (reader instanceof BufferedReader) {\n                        this.reader = (BufferedReader) reader;\n                } else {\n                        this.reader = new BufferedReader(reader);\n                }\n        }\n\n        public String readLine() throws IOException {\n                if (lines.isEmpty()) {\n                        return reader.readLine();\n                } else {\n                        return lines.pop();\n                }\n        }\n\n        public void push(String line) {\n                lines.push(line);\n        }\n\n        @Override\n        public int read(char[] cbuf, int off, int len) throws IOException {\n                return reader.read(cbuf, off, len);\n        }\n\n        @Override\n        public void close() throws IOException {\n                reader.close();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/SClassWriter.java",
    "content": "package lt.compiler;\n\nimport lt.compiler.semantic.SClassDef;\nimport lt.compiler.semantic.SInterfaceDef;\nimport lt.compiler.semantic.STypeDef;\nimport lt.dependencies.asm.ClassWriter;\n\nimport java.util.Map;\n\n/**\n * the ClassWriter used when generating class files.\n * Overrides the {@link lt.dependencies.asm.ClassWriter#getCommonSuperClass(String, String)} for the classes to be compiled.\n */\npublic class SClassWriter extends ClassWriter {\n        private final Map<String, STypeDef> typeDefMap;\n\n        public SClassWriter(int flags, Map<String, STypeDef> typeDefMap) {\n                super(flags);\n                this.typeDefMap = typeDefMap;\n        }\n\n        @Override\n        protected String getCommonSuperClass(String type1, String type2) {\n                // try to get class info from typeMap\n                STypeDef sc = typeDefMap.get(type1.replace('/', '.'));\n                STypeDef sd = typeDefMap.get(type2.replace('/', '.'));\n                if (sc == null || sd == null)\n                        throw new LtBug(\"class \" + (sc == null ? type1 : type2) + \" not found\");\n\n                if (sc.isAssignableFrom(sd)) {\n                        return type1;\n                } else if (sd.isAssignableFrom(sc)) {\n                        return type2;\n                } else if (sc instanceof SInterfaceDef || sd instanceof SInterfaceDef) {\n                        return \"java/lang/Object\";\n                } else {\n                        do {\n                                sc = ((SClassDef) sc).parent();\n                        } while (!sc.isAssignableFrom(sd));\n                        return sc.fullName().replace(\".\", \"/\");\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/Scanner.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.ElementStartNode;\n\nimport java.io.IOException;\n\n/**\n * the scanner interface.\n */\npublic interface Scanner {\n        ElementStartNode scan() throws IOException, SyntaxException;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/ScannerSwitcher.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.lexical.ElementStartNode;\n\nimport java.io.IOException;\nimport java.io.Reader;\n\n/**\n * the entrance of scanners. it will read the first line of the file to determine which scanner to use.\n */\npublic class ScannerSwitcher implements Scanner {\n        private final Scanner scanner;\n\n        public ScannerSwitcher(String fileName, Reader reader, Properties properties, ErrorManager err) throws IOException, SyntaxException {\n                PushLineBackReader plbr;\n                if (reader instanceof PushLineBackReader) {\n                        plbr = (PushLineBackReader) reader;\n                } else {\n                        plbr = new PushLineBackReader(reader);\n                }\n\n                String firstLine = plbr.readLine();\n                plbr.push(firstLine);\n                String text = firstLine.trim();\n                if (text.startsWith(\"///\")) {\n                        text = text.substring(3).trim();\n                } else {\n                        text = \"\";\n                }\n\n                if (text.equals(\":scanner-brace\")) {\n                        scanner = new BraceScanner(fileName, plbr, properties, err);\n\n                } else if (text.equals(\"\") || text.equals(\":scanner-indent\")) {\n                        scanner = new IndentScanner(fileName, plbr, properties, err);\n\n                } else {\n                        err.SyntaxException(\"got \" + text + \" which is not a valid scanner select command\", LineCol.SYNTHETIC_WITH_FILE(fileName));\n                        err.info(\"assume it's :scanner-indent\");\n                        scanner = new IndentScanner(fileName, plbr, properties, err);\n                }\n        }\n\n        @Override\n        public ElementStartNode scan() throws IOException, SyntaxException {\n                return scanner.scan();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/SemanticProcessor.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.*;\nimport lt.compiler.semantic.builtin.*;\nimport lt.compiler.semantic.helper.ASTGHolder;\nimport lt.compiler.semantic.helper.HalfAppliedTypes;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.OneVariableOperation;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.operation.UnaryOneVariableOperation;\nimport lt.compiler.syntactic.pre.Import;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\nimport lt.compiler.util.BindList;\nimport lt.compiler.util.Consts;\nimport lt.dependencies.asm.MethodVisitor;\nimport lt.generator.SourceGenerator;\nimport lt.lang.GenericTemplate;\nimport lt.lang.Unit;\nimport lt.lang.function.Function1;\nimport lt.lang.function.Function2;\nimport lt.runtime.*;\n\nimport java.io.*;\nimport java.lang.annotation.Annotation;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.reflect.*;\nimport java.net.URL;\nimport java.util.*;\nimport java.util.jar.JarFile;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipFile;\n\n/**\n * semantic processor\n */\npublic class SemanticProcessor {\n        public static final int PARSING_CLASS = 0;\n        public static final int PARSING_INTERFACE = 1;\n\n        public static final String DYNAMIC_CLASS_NAME = Dynamic.class.getName();\n\n        public static final int INDEX_invoke_targetClass = 0;\n        public static final int INDEX_invoke_o = 1;\n        public static final int INDEX_invoke_isStatic = 2;\n        public static final int INDEX_invoke_functionalObject = 3;\n        public static final int INDEX_invoke_invoker = 4;\n        public static final int INDEX_invoke_method = 5;\n        public static final int INDEX_invoke_primitives = 6;\n        public static final int INDEX_invoke_args = 7;\n        public static final int INDEX_invoke_canInvokeImport = 8;\n\n        /**\n         * Map&lt;FileName, List of statements&gt;\n         */\n        public final Map<String, List<Statement>> mapOfStatements;\n        /**\n         * maps full name to type<br>\n         * one type should only exist once in a Processor\n         */\n        public Map<String, STypeDef> types = new HashMap<String, STypeDef>();\n        /**\n         * full name to {@link ClassDef} from {@link Parser}\n         */\n        public Map<String, ASTGHolder<ClassDef>> originalClasses = new HashMap<String, ASTGHolder<ClassDef>>();\n        /**\n         * full name to {@link InterfaceDef} from {@link Parser}\n         */\n        public Map<String, ASTGHolder<InterfaceDef>> originalInterfaces = new HashMap<String, ASTGHolder<InterfaceDef>>();\n        /**\n         * full name to {@link FunDef} from {@link Parser}\n         */\n        public Map<String, ASTGHolder<FunDef>> originalFunctions = new HashMap<String, ASTGHolder<FunDef>>();\n        /**\n         * full name to {@link ObjectDef} from {@link Parser}\n         */\n        public Map<String, ASTGHolder<ObjectDef>> originalObjects = new HashMap<String, ASTGHolder<ObjectDef>>();\n        /**\n         * full name to {@link AnnotationDef} from {@link Parser}\n         */\n        public Map<String, ASTGHolder<AnnotationDef>> originalAnnotations = new HashMap<String, ASTGHolder<AnnotationDef>>();\n        /**\n         * {@link SMethodDef} to it's containing statements\n         */\n        public Map<SMethodDef, List<Statement>> methodToStatements = new HashMap<SMethodDef, List<Statement>>();\n        /**\n         * file name to Import info\n         */\n        public Map<String, List<Import>> fileNameToImport = new HashMap<String, List<Import>>();\n        /**\n         * file name to package name\n         */\n        public Map<String, String> fileNameToPackageName = new HashMap<String, String>();\n        /**\n         * a set of types that should be return value of {@link #parse()} method.<br>\n         * these types are to be compiled into byte codes\n         */\n        public final Set<STypeDef> typeDefSet = new HashSet<STypeDef>();\n        /**\n         * invokable =&gt; (the-invokable-to-invoke =&gt; the current default parameter).\n         */\n        public Map<SInvokable, Map<SInvokable, Expression>> defaultParamInvokable = new HashMap<SInvokable, Map<SInvokable, Expression>>();\n        /**\n         * retrieve existing classes from this class loader\n         */\n        public final ClassLoader classLoader;\n        /**\n         * error manager\n         */\n        public final ErrorManager err;\n        /**\n         * access which represents a type can be converted into instantiation\n         */\n        public boolean enableTypeAccess = true;\n        /**\n         * source files\n         */\n        private static List<ZipFile> sourceClasses = new LinkedList<ZipFile>();\n        private boolean alreadyWarnJar = false;\n\n        /**\n         * initialize the Processor\n         *\n         * @param mapOfStatements a map of fileName to statements\n         * @param classLoader     retrieve loaded classes from this class loader\n         * @param err             error manager. the fast fail would be set to `true`\n         */\n        public SemanticProcessor(Map<String, List<Statement>> mapOfStatements, ClassLoader classLoader, ErrorManager err) {\n                this.mapOfStatements = mapOfStatements;\n                this.classLoader = classLoader;\n                this.err = err;\n                err.setFastFail(true);\n                // initiate types map\n                // primitive and void\n                types.put(\"int\", IntTypeDef.get());\n                types.put(\"long\", LongTypeDef.get());\n                types.put(\"double\", DoubleTypeDef.get());\n                types.put(\"float\", FloatTypeDef.get());\n                types.put(\"boolean\", BoolTypeDef.get());\n                types.put(\"bool\", BoolTypeDef.get());\n                types.put(\"char\", CharTypeDef.get());\n                types.put(\"short\", ShortTypeDef.get());\n                types.put(\"byte\", ByteTypeDef.get());\n        }\n\n        public static String byte2hex(byte[] b) {\n                StringBuilder sb = new StringBuilder();\n                String tmp;\n                for (byte aB : b) {\n                        tmp = Integer.toHexString(aB & 0XFF);\n                        if (tmp.length() == 1) {\n                                sb.append(\"0\").append(tmp);\n                        } else {\n                                sb.append(tmp);\n                        }\n\n                }\n                return sb.toString();\n        }\n\n        public static byte[] hex2byte(String str) {\n                str = str.trim();\n                int len = str.length();\n\n                if (len == 0 || len % 2 == 1) {\n                        return null;\n                }\n\n                byte[] b = new byte[len / 2];\n                for (int i = 0; i < str.length(); i += 2) {\n                        b[i / 2] = (byte) Integer.decode(\"0X\" + str.substring(i, i + 2)).intValue();\n                }\n                return b;\n        }\n\n        /**\n         * get the map of defined types.\n         *\n         * @return a map of name =&gt; type\n         */\n        public Map<String, STypeDef> getTypes() {\n                return types;\n        }\n\n        /**\n         * parse the input AST into STypeDef objects.<br>\n         * the parsing process are divided into 4 steps.<br>\n         * <ol>\n         * <li><b>recording</b> : scan all classes and record them</li>\n         * <li><b>signatures</b> : parse parents/superInterfaces, members, annotations, but don't parse statements or annotation values</li>\n         * <li><b>validate</b> :\n         * check circular inheritance and override,\n         * check overload with super classes/interfaces and check whether the class overrides all methods from super interfaces/super abstract classes,\n         * check @Override @FunctionalInterface @FunctionalAbstractClass,\n         * check whether the class is a `data class` and do some modifications</li>\n         * <li><b>parse</b> : parse annotation values and statements</li>\n         * </ol>\n         *\n         * @return parsed types, including all inside members and statements\n         * @throws SyntaxException compile error\n         */\n        public Set<STypeDef> parse() throws SyntaxException {\n                Map<String, List<ClassDef>> fileNameToClassDef = new HashMap<String, List<ClassDef>>();\n                Map<String, List<InterfaceDef>> fileNameToInterfaceDef = new HashMap<String, List<InterfaceDef>>();\n                Map<String, List<FunDef>> fileNameToFunctions = new HashMap<String, List<FunDef>>();\n                Map<String, List<ObjectDef>> fileNameToObjectDef = new HashMap<String, List<ObjectDef>>();\n                Map<String, List<AnnotationDef>> fileNameToAnnotationDef = new HashMap<String, List<AnnotationDef>>();\n                // record types and packages\n                for (String fileName : mapOfStatements.keySet()) {\n                        List<Statement> statements = mapOfStatements.get(fileName);\n                        Iterator<Statement> statementIterator = statements.iterator();\n\n                        // import\n                        List<Import> imports = new ArrayList<Import>();\n                        // class definition\n                        List<ClassDef> classDefs = new ArrayList<ClassDef>();\n                        // interface definition\n                        List<InterfaceDef> interfaceDefs = new ArrayList<InterfaceDef>();\n                        // fun definition\n                        List<FunDef> funDefs = new ArrayList<FunDef>();\n                        // object definition\n                        List<ObjectDef> objectDefs = new ArrayList<ObjectDef>();\n                        // annotation definition\n                        List<AnnotationDef> annotationDefs = new ArrayList<AnnotationDef>();\n\n                        // put into map\n                        fileNameToImport.put(fileName, imports);\n                        fileNameToClassDef.put(fileName, classDefs);\n                        fileNameToInterfaceDef.put(fileName, interfaceDefs);\n                        fileNameToFunctions.put(fileName, funDefs);\n                        fileNameToObjectDef.put(fileName, objectDefs);\n                        fileNameToAnnotationDef.put(fileName, annotationDefs);\n\n                        // package\n                        String pkg; // if no package, then it's an empty string, otherwise, it's 'packageName.' with dot at the end\n                        if (statementIterator.hasNext()) {\n                                Statement statement = statementIterator.next();\n                                if (statement instanceof PackageDeclare) {\n                                        PackageDeclare p = (PackageDeclare) statement;\n                                        pkg = p.pkg.pkg.replace(\"::\", \".\") + \".\";\n                                } else {\n                                        pkg = \"\";\n                                        select_import_class_interface_fun_object(\n                                                statement, imports, classDefs, interfaceDefs, funDefs, objectDefs, annotationDefs);\n                                }\n                                while (statementIterator.hasNext()) {\n                                        Statement stmt = statementIterator.next();\n                                        select_import_class_interface_fun_object(\n                                                stmt, imports, classDefs, interfaceDefs, funDefs, objectDefs, annotationDefs);\n                                }\n                        } else continue;\n\n                        // add package into import list at index 0\n                        imports.add(0, new Import(new AST.PackageRef(\n                                pkg.endsWith(\".\")\n                                        ? pkg.substring(0, pkg.length() - 1).replace(\".\", \"::\")\n                                        : pkg\n                                , LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        // add java.lang into import list\n                        // java::lang::_\n                        // lt::lang::_\n                        // lt::util::Utils._\n                        imports.add(new Import(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        imports.add(new Import(new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        imports.add(new Import(null, new AST.Access(new AST.PackageRef(\"lt::util\", LineCol.SYNTHETIC), \"Utils\", LineCol.SYNTHETIC), true, false, LineCol.SYNTHETIC));\n                        // import implicit built in casts\n                        imports.add(new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang::implicit\", LineCol.SYNTHETIC), \"PrimitivesImplicit\", LineCol.SYNTHETIC), false, true, LineCol.SYNTHETIC));\n                        imports.add(new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang::implicit\", LineCol.SYNTHETIC), \"StringImplicit\", LineCol.SYNTHETIC), false, true, LineCol.SYNTHETIC));\n                        imports.add(new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang::implicit\", LineCol.SYNTHETIC), \"CollectionImplicit\", LineCol.SYNTHETIC), false, true, LineCol.SYNTHETIC));\n                        imports.add(new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang::implicit\", LineCol.SYNTHETIC), \"ObjectImplicit\", LineCol.SYNTHETIC), false, true, LineCol.SYNTHETIC));\n\n                        fileNameToPackageName.put(fileName, pkg);\n                }\n                for (String fileName : mapOfStatements.keySet()) {\n                        // import\n                        List<Import> imports = fileNameToImport.get(fileName);\n                        // class definition\n                        List<ClassDef> classDefs = fileNameToClassDef.get(fileName);\n                        // interface definition\n                        List<InterfaceDef> interfaceDefs = fileNameToInterfaceDef.get(fileName);\n                        // fun definition\n                        List<FunDef> funDefs = fileNameToFunctions.get(fileName);\n                        // package name\n                        String pkg = fileNameToPackageName.get(fileName);\n                        // object definition\n                        List<ObjectDef> objectDefs = fileNameToObjectDef.get(fileName);\n                        // annotation definition\n                        List<AnnotationDef> annotationDefs = fileNameToAnnotationDef.get(fileName);\n\n                        // check importing same simple name\n                        Set<String> importSimpleNames = new HashSet<String>();\n                        for (Import i : imports) {\n                                if (i.pkg == null && !i.importAll) {\n                                        // class name are the same\n                                        if (importSimpleNames.contains(i.access.name)) {\n                                                err.SyntaxException(\"duplicate imports\", i.line_col());\n                                                return null;\n                                        }\n                                        importSimpleNames.add(i.access.name);\n                                }\n                        }\n                        importSimpleNames.clear(); // release\n\n                        // ======= step 1 =======\n                        // record all classes and interfaces to compile\n                        // classes and interfaces should be filled with\n                        // package|fullName|modifiers\n                        // in this step\n                        for (ClassDef c : classDefs) {\n                                recordClass(c, pkg, Collections.<STypeDef>emptyList());\n                        }\n                        for (InterfaceDef i : interfaceDefs) {\n                                recordInterface(i, pkg, Collections.<STypeDef>emptyList());\n                        }\n                        for (FunDef f : funDefs) {\n                                recordFun(f, pkg, Collections.<STypeDef>emptyList());\n                        }\n                        for (ObjectDef o : objectDefs) {\n                                recordObject(o, pkg, Collections.<STypeDef>emptyList());\n                        }\n                        for (AnnotationDef a : annotationDefs) {\n                                recordAnnotation(a, pkg, Collections.<STypeDef>emptyList());\n                        }\n                }\n\n                // templateName to halfAppliedTypes\n                // templateName means the type without generic parameters\n                // halfAppliedType means the type is not fully applied, e.g. class A<:T,U:> and A<:int, U:>\n                final Map<String, HalfAppliedTypes> templateNameToHalfAppliedTypes = new HashMap<String, HalfAppliedTypes>();\n                for (String file : mapOfStatements.keySet()) {\n                        List<Statement> stmts = mapOfStatements.get(file);\n                        final List<Import> imports = fileNameToImport.get(file);\n                        final String pkg = fileNameToPackageName.get(file);\n\n                        // traverse func\n                        Function2<Boolean, Statement, HalfAppliedTypes> traverseFunc = new Function2<Boolean, Statement, HalfAppliedTypes>() {\n                                @Override\n                                public Boolean apply(Statement statement, HalfAppliedTypes halfAppliedTypes) throws Exception {\n                                        if (statement instanceof AST.Access) {\n                                                AST.Access access = (AST.Access) statement;\n                                                handleGenericAST(access, imports, halfAppliedTypes, templateNameToHalfAppliedTypes);\n                                                return true;\n                                        }\n                                        if (statement instanceof ClassDef || statement instanceof InterfaceDef || statement instanceof ObjectDef) {\n                                                assert halfAppliedTypes == null;\n                                                List<AST.Access> generics;\n                                                String simpleName;\n                                                if (statement instanceof ClassDef) {\n                                                        ClassDef c = (ClassDef) statement;\n                                                        generics = c.generics;\n                                                        simpleName = c.name;\n                                                } else if (statement instanceof InterfaceDef) {\n                                                        InterfaceDef i = (InterfaceDef) statement;\n                                                        generics = i.generics;\n                                                        simpleName = i.name;\n                                                } else /*if (statement instanceof ObjectDef)*/ {\n                                                        ObjectDef o = (ObjectDef) statement;\n                                                        generics = o.generics;\n                                                        simpleName = o.name;\n                                                }\n                                                if (!generics.isEmpty()) {\n                                                        // record the generics\n                                                        if (templateNameToHalfAppliedTypes.containsKey(pkg + simpleName)) {\n                                                                halfAppliedTypes = templateNameToHalfAppliedTypes.get(pkg + simpleName);\n                                                        } else {\n                                                                halfAppliedTypes = new HalfAppliedTypes();\n                                                                templateNameToHalfAppliedTypes.put(pkg + simpleName, halfAppliedTypes);\n                                                        }\n                                                        statement.foreachInnerStatements(this, halfAppliedTypes);\n                                                        return false;\n                                                }\n                                        }\n                                        return true;\n                                }\n                        };\n\n                        for (Statement stmt : stmts) {\n                                try {\n                                        if (traverseFunc.apply(stmt, null)) {\n                                                stmt.foreachInnerStatements(traverseFunc, null);\n                                        }\n                                } catch (SyntaxException e) {\n                                        throw e;\n                                } catch (Exception e) {\n                                        throw new LtBug(\"should not have any exception other than SyntaxException\", e);\n                                }\n                        }\n                }\n                // all classes occurred in the parsing process will be inside `types` map or is already defined\n\n                // check package and type exists\n                for (String fileName : mapOfStatements.keySet()) {\n                        // import\n                        List<Import> imports = fileNameToImport.get(fileName);\n                        ListIterator<Import> ite = imports.listIterator();\n                        while (ite.hasNext()) {\n                                Import i = ite.next();\n                                if (i.pkg == null) {\n                                        // try class\n                                        STypeDef type = getTypeWithAccess(i.access, Collections.<String, STypeDef>emptyMap(), Collections.<Import>emptyList(), true);\n                                        if (null == type) {\n                                                boolean pass = false;\n                                                if (i.importAll) {\n                                                        // test whether it's a package\n                                                        AST.Access access = i.access;\n                                                        AST.PackageRef pkgRef = checkAndGetPackage(fileNameToPackageName, access);\n                                                        if (pkgRef != null) {\n                                                                pass = true;\n                                                                ite.set(new Import(pkgRef, null, true, i.implicit, i.line_col()));\n                                                        }\n                                                        // else {\n                                                        // do nothing\n                                                        // should error }\n                                                } else {\n                                                        AST.Access newAccessWithPkg = transformAccess(i.access);\n                                                        if (i.access != newAccessWithPkg) {\n                                                                pass = true;\n                                                                // replace the original object with new one\n                                                                ite.set(new Import(null, newAccessWithPkg, false, i.implicit, i.line_col()));\n                                                        }\n                                                }\n                                                if (!pass) {\n                                                        err.SyntaxException(\"Type \" + i.access + \" not found\", i.access.line_col());\n                                                }\n                                        } // else: pass, for that a type is retrieved\n                                } else {\n                                        // check package exists\n                                        String pkg = i.pkg.pkg.replace(\"::\", \".\");\n                                        if (!isPackage(fileNameToPackageName, pkg)) {\n                                                err.SyntaxException(\"Package \" + i.pkg.pkg + \" not found\", i.pkg.line_col());\n                                        }\n                                }\n                        }\n                }\n\n                step2(fileNameToPackageName);\n                step3();\n                // ensures some annotations are loaded\n                getTypeWithName(ImplicitImports.class.getName(), LineCol.SYNTHETIC);\n                getTypeWithName(StaticImports.class.getName(), LineCol.SYNTHETIC);\n                getTypeWithName(GenericTemplate.class.getName(), LineCol.SYNTHETIC);\n                getTypeWithName(Retention.class.getName(), LineCol.SYNTHETIC);\n                step4();\n                addImportImplicit();\n                addImportStatic();\n                addRetention();\n\n                return typeDefSet;\n        }\n\n        private void recordClass(ClassDef c, String pkg, List<STypeDef> generics) throws SyntaxException {\n                recordClass(c, pkg, generics, false);\n        }\n\n        private void recordClass(ClassDef c, String pkg, List<STypeDef> generics, boolean isTemplateType) throws SyntaxException {\n                String className = buildTemplateAppliedName(pkg + c.name, generics);\n                // check occurrence\n                if (typeExists(className)) {\n                        if (!isTemplateType) {\n                                err.SyntaxException(\"duplicate type names \" + className, c.line_col());\n                                return;\n                        }\n                }\n\n                SClassDef sClassDef = new SClassDef(SClassDef.NORMAL, c.line_col());\n                sClassDef.setFullName(className);\n                sClassDef.setPkg(pkg.endsWith(\".\") ? pkg.substring(0, pkg.length() - 1) : pkg);\n                sClassDef.modifiers().add(SModifier.PUBLIC);\n\n                for (Modifier m : c.modifiers) {\n                        switch (m.modifier) {\n                                case ABSTRACT:\n                                        sClassDef.modifiers().add(SModifier.ABSTRACT);\n                                        break;\n                                case VAL:\n                                        sClassDef.modifiers().add(SModifier.FINAL);\n                                        break;\n                                case PUBLIC:\n                                case PRIVATE:\n                                case PROTECTED:\n                                case PKG:\n                                        // pub|pri|pro|pkg are for constructors\n                                        break;\n                                case DATA:\n                                        sClassDef.setIsDataClass(true);\n                                        break;\n                                default:\n                                        err.UnexpectedTokenException(\"valid modifier for class (val|abstract|public|private|protected|internal)\", m.toString(), m.line_col());\n                                        return;\n                        }\n                }\n\n                if (!isTemplateType) {\n                        types.put(className, sClassDef); // record the class\n                        typeDefSet.add(sClassDef);\n                }\n                originalClasses.put(className, new ASTGHolder<ClassDef>(c, generics));\n        }\n\n        private void recordInterface(InterfaceDef i, String pkg, List<STypeDef> generics) throws SyntaxException {\n                recordInterface(i, pkg, generics, false);\n        }\n\n        private void recordInterface(InterfaceDef i, String pkg, List<STypeDef> generics, boolean isTemplateType) throws SyntaxException {\n                String interfaceName = buildTemplateAppliedName(pkg + i.name, generics);\n                // check occurrence\n                if (typeExists(interfaceName)) {\n                        if (!isTemplateType) {\n                                err.SyntaxException(\"duplicate type names \" + interfaceName, i.line_col());\n                                return;\n                        }\n                }\n\n                SInterfaceDef sInterfaceDef = new SInterfaceDef(i.line_col());\n                sInterfaceDef.setFullName(interfaceName);\n                sInterfaceDef.setPkg(pkg.endsWith(\".\") ? pkg.substring(0, pkg.length() - 1) : pkg);\n                sInterfaceDef.modifiers().add(SModifier.PUBLIC);\n                sInterfaceDef.modifiers().add(SModifier.ABSTRACT);\n\n                for (Modifier m : i.modifiers) {\n                        switch (m.modifier) {\n                                case PUBLIC:\n                                case ABSTRACT:\n                                        // can only be abstract or public\n                                        break;\n                                default:\n                                        err.UnexpectedTokenException(\"valid modifier for interface (abs)\", m.toString(), m.line_col());\n                                        return;\n                        }\n                }\n\n                if (!isTemplateType) {\n                        types.put(interfaceName, sInterfaceDef); // record the interface\n                        typeDefSet.add(sInterfaceDef);\n                }\n                originalInterfaces.put(interfaceName, new ASTGHolder<InterfaceDef>(i, generics));\n        }\n\n        private void recordFun(FunDef f, String pkg, List<STypeDef> generics) throws SyntaxException {\n                recordFun(f, pkg, generics, false);\n        }\n\n        private void recordFun(FunDef f, String pkg, List<STypeDef> generics, boolean isTemplateType) throws SyntaxException {\n                String className = buildTemplateAppliedName(pkg + f.name, generics);\n                // check occurrence\n                if (typeExists(className)) {\n                        if (!isTemplateType) {\n                                err.SyntaxException(\"duplicate type names \" + className, f.line_col());\n                                return;\n                        }\n                }\n\n                SClassDef sClassDef = new SClassDef(SClassDef.FUN, f.line_col());\n                sClassDef.setFullName(className);\n                sClassDef.setPkg(pkg.endsWith(\".\") ? pkg.substring(0, pkg.length() - 1) : pkg);\n                sClassDef.modifiers().add(SModifier.PUBLIC);\n                sClassDef.modifiers().add(SModifier.FINAL);\n\n                if (!isTemplateType) {\n                        types.put(className, sClassDef); // record the class\n                        typeDefSet.add(sClassDef);\n                }\n                originalFunctions.put(className, new ASTGHolder<FunDef>(f, generics));\n        }\n\n        private void recordObject(ObjectDef o, String pkg, List<STypeDef> generics) throws SyntaxException {\n                recordObject(o, pkg, generics, false);\n        }\n\n        private void recordObject(ObjectDef o, String pkg, List<STypeDef> generics, boolean isTemplateType) throws SyntaxException {\n                String className = buildTemplateAppliedName(pkg + o.name, generics);\n                // check occurrence\n                if (typeExists(className)) {\n                        if (!isTemplateType) {\n                                err.SyntaxException(\"duplicate type names \" + className, o.line_col());\n                                return;\n                        }\n                }\n\n                SClassDef sClassDef = new SClassDef(SClassDef.OBJECT, o.line_col());\n                sClassDef.setFullName(className);\n                sClassDef.setPkg(pkg.endsWith(\".\") ? pkg.substring(0, pkg.length() - 1) : pkg);\n                sClassDef.modifiers().add(SModifier.PUBLIC);\n                sClassDef.modifiers().add(SModifier.FINAL);\n\n                if (!isTemplateType) {\n                        types.put(className, sClassDef); // record the object\n                        typeDefSet.add(sClassDef);\n                }\n                originalObjects.put(className, new ASTGHolder<ObjectDef>(o, generics));\n        }\n\n        private void recordAnnotation(AnnotationDef a, String pkg, List<STypeDef> generics) throws SyntaxException {\n                recordAnnotation(a, pkg, generics, false);\n        }\n\n        private void recordAnnotation(AnnotationDef a, String pkg, List<STypeDef> generics, boolean isTemplateType) throws SyntaxException {\n                String annoName = buildTemplateAppliedName(pkg + a.name, generics);\n                // check occurrence\n                if (typeExists(annoName)) {\n                        if (!isTemplateType) {\n                                err.SyntaxException(\"duplicate type names \" + annoName, a.line_col());\n                                return;\n                        }\n                }\n\n                SAnnoDef sAnnoDef = new SAnnoDef(a.line_col());\n                sAnnoDef.setPkg(pkg);\n                sAnnoDef.setFullName(annoName);\n\n                if (!isTemplateType) {\n                        types.put(annoName, sAnnoDef); // record the annotation\n                        typeDefSet.add(sAnnoDef);\n                }\n                originalAnnotations.put(annoName, new ASTGHolder<AnnotationDef>(a, generics));\n        }\n\n        /**\n         * handle the {@link lt.compiler.syntactic.AST.Access} found in ast.\n         * <br>\n         * for those generics are fully applied, check the map and apply all\n         * corresponding half applied types.<br>\n         * for those half applied types, record in list\n         *\n         * @param accessType                     the access instance\n         * @param imports                        current file imports\n         * @param currentHalfAppliedTypes        list (as the variable name says)\n         * @param templateNameToHalfAppliedTypes map (as the variable name says)\n         * @return true if fully applied, false otherwise\n         * @throws SyntaxException compile exception\n         */\n        private boolean handleGenericAST(AST.Access accessType,\n                                         List<Import> imports,\n                                         /*@Nullable*/ HalfAppliedTypes currentHalfAppliedTypes,\n                                         Map<String, HalfAppliedTypes> templateNameToHalfAppliedTypes) throws SyntaxException {\n                if (accessType.generics.isEmpty()) {\n                        return true;\n                }\n                boolean isFullyApplied = true; // any one sub generic type not fully applied then it's not applied\n                for (AST.Access g : accessType.generics) {\n                        boolean b = handleGenericAST(g, imports, currentHalfAppliedTypes, templateNameToHalfAppliedTypes);\n                        if (!b) {\n                                isFullyApplied = false;\n                        }\n                }\n\n                if (!isFullyApplied) {\n                        // record in the list\n                        assert null != currentHalfAppliedTypes;\n                        currentHalfAppliedTypes.add(accessType);\n                        return false;\n                }\n\n                AST.Access accessWithoutGeneric = new AST.Access(accessType.exp, accessType.name, accessType.line_col());\n                // templateName means\n                // the generic type name without type parameters\n                // e.g. class A<:T:>, the templateName would be A\n                //\n                // the templateName might not be able to find when\n                // higher kind is supportted\n                String templateName = accessToClassName(accessWithoutGeneric, Collections.<String, STypeDef>emptyMap(), imports, true);\n                if (templateName == null) {\n                        currentHalfAppliedTypes.add(accessType);\n                        return false;\n                }\n                if (tryToApplyGenericType(accessType, imports, templateName, Collections.<String, STypeDef>emptyMap(), true)) {\n                        List<STypeDef> genericTypes = new ArrayList<STypeDef>();\n                        for (AST.Access a : accessType.generics) {\n                                STypeDef t = getTypeWithAccess(a, Collections.<String, STypeDef>emptyMap(), imports);\n                                genericTypes.add(t);\n                        }\n                        applyToHalfAppliedTypes(templateNameToHalfAppliedTypes, templateName, genericTypes);\n                        return true;\n                } else {\n                        assert null != currentHalfAppliedTypes;\n                        currentHalfAppliedTypes.add(accessType);\n                        return false;\n                }\n        }\n\n        private boolean tryToApplyGenericType(AST.Access access,\n                                              List<Import> imports,\n                                              String templateName,\n                                              Map<String, STypeDef> genericMap,\n                                              boolean allowException) throws SyntaxException {\n                // load the template type first\n                AST.Access tmpAccess = new AST.Access(access.exp, access.name, access.line_col());\n                getTypeWithAccess(tmpAccess, Collections.<String, STypeDef>emptyMap(), imports, /* exception allowed */true);\n\n                // clsName means\n                // the generic type full name\n                // Latte generates a long name for the applied generic type\n                // e.g. class A<:T:> and A<:int:> would be something looks like 'A_xxx_int'\n                String clsName = accessToClassName(access, genericMap, imports, allowException);\n                if (null == clsName) {\n                        return false;\n                }\n                if (types.containsKey(clsName)) {\n                        // already defined\n                        // ignore and return\n                        return true;\n                }\n                List<STypeDef> genericTypes = new ArrayList<STypeDef>();\n                for (AST.Access a : access.generics) {\n                        STypeDef t = getTypeWithAccess(a, genericMap, imports);\n                        genericTypes.add(t);\n                }\n                int genericParamSize;\n                if (originalClasses.containsKey(templateName)) {\n                        ClassDef ast = originalClasses.get(templateName).s;\n                        String file = ast.line_col().fileName;\n                        recordClass(ast, fileNameToPackageName.get(file), genericTypes);\n\n                        genericParamSize = ast.generics.size();\n\n                } else if (originalInterfaces.containsKey(templateName)) {\n                        InterfaceDef ast = originalInterfaces.get(templateName).s;\n                        String file = ast.line_col().fileName;\n                        recordInterface(ast, fileNameToPackageName.get(file), genericTypes);\n\n                        genericParamSize = ast.generics.size();\n\n                } else if (originalObjects.containsKey(templateName)) {\n                        ObjectDef ast = originalObjects.get(templateName).s;\n                        String file = ast.line_col().fileName;\n                        recordObject(ast, fileNameToPackageName.get(file), genericTypes);\n\n                        genericParamSize = ast.generics.size();\n\n                } else if (originalFunctions.containsKey(templateName)) {\n                        err.SyntaxException(\"function definitions are never generic types\", access.line_col());\n                        return true; // would not reach here\n\n                } else if (originalAnnotations.containsKey(templateName)) {\n                        err.SyntaxException(\"annotations are never generic types\", access.line_col());\n                        return true; // would not reach here\n\n                } else {\n                        err.SyntaxException(\"type \" + templateName + \" not found\", access.line_col());\n                        return true; // would not reach here\n                }\n\n                if (genericParamSize != access.generics.size()) {\n                        err.SyntaxException(\"generic params size is \" + genericParamSize\n                                        + \", but generic args size is \" + access.generics.size(),\n                                access.line_col());\n                }\n\n                return true;\n        }\n\n        private void applyToHalfAppliedTypes(Map<String, HalfAppliedTypes> templateNameToHalfAppliedTypes,\n                                             String templateName,\n                                             List<STypeDef> genericTypes) throws SyntaxException {\n                HalfAppliedTypes types;\n                if (templateNameToHalfAppliedTypes.containsKey(templateName)) {\n                        types = templateNameToHalfAppliedTypes.get(templateName);\n                } else {\n                        types = new HalfAppliedTypes();\n                        templateNameToHalfAppliedTypes.put(templateName, types);\n                }\n                final Map<String, STypeDef> genericMap = new HashMap<String, STypeDef>();\n                List<AST.Access> typeGenerics;\n                if (originalClasses.containsKey(templateName)) {\n                        typeGenerics = originalClasses.get(templateName).s.generics;\n                } else if (originalObjects.containsKey(templateName)) {\n                        typeGenerics = originalObjects.get(templateName).s.generics;\n                } else if (originalInterfaces.containsKey(templateName)) {\n                        typeGenerics = originalInterfaces.get(templateName).s.generics;\n                } else {\n                        throw new LtBug(\"trying to get generic parameters from \" + templateName);\n                }\n                for (int i = 0; i < typeGenerics.size(); ++i) {\n                        AST.Access g = typeGenerics.get(i);\n                        STypeDef t = genericTypes.get(i);\n                        genericMap.put(g.name, t);\n                }\n                types.setApply(new Function1<Void, AST.Access>() {\n                        @Override\n                        public Void apply(AST.Access type) throws Exception {\n                                String filename = type.line_col().fileName;\n                                List<Import> imports = fileNameToImport.get(filename);\n                                // build non generic access\n                                AST.Access nonGenericType = new AST.Access(type.exp, type.name, type.line_col());\n                                String clsName = accessToClassName(nonGenericType, genericMap, imports, false);\n                                tryToApplyGenericType(type, imports, clsName, genericMap, false);\n                                return null;\n                        }\n                });\n        }\n\n        private AST.PackageRef checkAndGetPackage(Map<String, String> fileNameToPackageName, AST.Access access) {\n                if (access.exp == null) {\n                        if (isPackage(fileNameToPackageName, access.name)) {\n                                return new AST.PackageRef(access.name, access.line_col());\n                        } else {\n                                return null;\n                        }\n                }\n                if (!(access.exp instanceof AST.Access)) {\n                        return null;\n                }\n                List<String> pkgSplitList = new ArrayList<String>();\n                pkgSplitList.add(access.name);\n                AST.Access tmp = (AST.Access) access.exp;\n                while (true) {\n                        pkgSplitList.add(tmp.name);\n                        Expression exp = tmp.exp;\n                        if (null == exp) break;\n                        if (!(exp instanceof AST.Access)) return null;\n                        tmp = (AST.Access) exp;\n                }\n                Collections.reverse(pkgSplitList);\n                StringBuilder pkgBuilder = new StringBuilder();\n                boolean isFirst = true;\n                for (String pkgSplitName : pkgSplitList) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                pkgBuilder.append(\".\");\n                        }\n                        pkgBuilder.append(pkgSplitName);\n                }\n                String pkg = pkgBuilder.toString();\n                if (isPackage(fileNameToPackageName, pkg)) {\n                        return new AST.PackageRef(pkg.replace(\".\", \"::\"), access.line_col());\n                } else {\n                        return null;\n                }\n        }\n\n        private boolean isPackage(Map<String, String> fileNameToPackageName, String javaPkg) {\n                return fileNameToPackageName.containsValue(javaPkg + \".\")\n                        || packageExistsInClassPath(javaPkg, classLoader)\n                        || packageExistInJRE(javaPkg);\n        }\n\n        private void addImportImplicit() throws SyntaxException {\n                // validate imports\n                for (List<Import> imports : fileNameToImport.values()) {\n                        for (Import im : imports) {\n                                if (im.implicit) {\n                                        STypeDef type = getTypeWithAccess(im.access, Collections.<String, STypeDef>emptyMap(), Collections.<Import>emptyList());\n                                        if (!(type instanceof SClassDef)) {\n                                                err.SyntaxException(\"import implicit should be an implicit class\", im.line_col());\n                                                return;\n                                        }\n                                        SClassDef cType = (SClassDef) type;\n                                        int count = 0;\n                                        for (SAnno a : cType.annos()) {\n                                                if (a.type().fullName().equals(\"lt.runtime.Implicit\")) {\n                                                        ++count;\n                                                }\n                                        }\n                                        if (count != 1) {\n                                                err.SyntaxException(\"import implicit should be an implicit class\", im.line_col());\n                                                return;\n                                        }\n                                }\n                        }\n                }\n\n                SAnnoDef ImplicitImports = (SAnnoDef) getTypeWithName(\"lt.runtime.ImplicitImports\", LineCol.SYNTHETIC);\n                SArrayTypeDef classArrayTypeDef = (SArrayTypeDef) getTypeWithName(\"[Ljava.lang.Class;\", LineCol.SYNTHETIC);\n                SClassDef classTypeDef = (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC);\n                SAnnoField annoField = null;\n                for (SAnnoField f : ImplicitImports.annoFields()) {\n                        if (f.name().equals(\"implicitImports\")) {\n                                annoField = f;\n                                break;\n                        }\n                }\n                if (annoField == null) throw new LtBug(\"lt.runtime.ImplicitImports#implicitImports should exist\");\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (sTypeDef instanceof SAnnoDef) continue;\n                        // filter\n                        if (sTypeDef.line_col().fileName == null || !fileNameToImport.containsKey(sTypeDef.line_col().fileName)) {\n                                continue;\n                        }\n                        int count = 0;\n                        for (SAnno anno : sTypeDef.annos()) {\n                                if (anno.type().fullName().equals(\"lt.runtime.ImplicitImports\")) {\n                                        ++count;\n                                }\n                        }\n                        boolean alreadyExists = count > 0;\n                        if (alreadyExists) continue;\n                        List<Import> imports = fileNameToImport.get(sTypeDef.line_col().fileName);\n                        List<Ins.GetClass> valueList = new ArrayList<Ins.GetClass>();\n                        Set<Ins.GetClass> tmpSet = new HashSet<Ins.GetClass>(); // distinct\n                        for (Import i : imports) {\n                                if (i.implicit) {\n                                        Ins.GetClass getC = new Ins.GetClass(getTypeWithAccess(i.access, Collections.<String, STypeDef>emptyMap(), Collections.<Import>emptyList()), classTypeDef);\n                                        if (!getC.targetType().equals(sTypeDef)) {\n                                                if (tmpSet.add(getC)) {\n                                                        valueList.add(getC);\n                                                }\n                                        }\n                                }\n                        }\n                        if (valueList.isEmpty()) continue;\n\n                        // build the annotation instance\n                        SAnno importImplicit = new SAnno();\n                        importImplicit.setAnnoDef(ImplicitImports);\n                        importImplicit.setPresent(sTypeDef);\n                        sTypeDef.annos().add(importImplicit);\n\n                        // build the array instance\n                        SArrayValue arrayValue = new SArrayValue();\n                        arrayValue.setDimension(1);\n                        arrayValue.setType(classArrayTypeDef);\n\n                        Value[] valueArray = new Value[valueList.size()];\n                        arrayValue.setValues(valueList.toArray(valueArray));\n\n                        // add value into anno\n                        importImplicit.values().put(annoField, arrayValue);\n                }\n        }\n\n        private void addImportStatic() throws SyntaxException {\n                SAnnoDef StaticImports = (SAnnoDef) getTypeWithName(\"lt.runtime.StaticImports\", LineCol.SYNTHETIC);\n                SArrayTypeDef classArrayTypeDef = (SArrayTypeDef) getTypeWithName(\"[Ljava.lang.Class;\", LineCol.SYNTHETIC);\n                SClassDef classTypeDef = (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC);\n                SAnnoField annoField = null;\n                for (SAnnoField f : StaticImports.annoFields()) {\n                        if (f.name().equals(\"staticImports\")) {\n                                annoField = f;\n                                break;\n                        }\n                }\n                if (annoField == null) throw new LtBug(\"lt.runtime.StaticImports#staticImports should exist\");\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (sTypeDef instanceof SAnnoDef) continue;\n                        // filter\n                        if (sTypeDef.line_col().fileName == null || !fileNameToImport.containsKey(sTypeDef.line_col().fileName)) {\n                                continue;\n                        }\n                        int count = 0;\n                        for (SAnno anno : sTypeDef.annos()) {\n                                if (anno.type().fullName().equals(\"lt.runtime.StaticImports\")) {\n                                        ++count;\n                                }\n                        }\n                        boolean alreadyExists = count > 0;\n                        if (alreadyExists) continue;\n                        List<Import> imports = fileNameToImport.get(sTypeDef.line_col().fileName);\n                        List<Ins.GetClass> valueList = new ArrayList<Ins.GetClass>();\n                        Set<Ins.GetClass> tmpSet = new HashSet<Ins.GetClass>(); // distinct\n                        for (Import i : imports) {\n                                if (i.importAll && i.pkg == null) {\n                                        Ins.GetClass getC = new Ins.GetClass(getTypeWithAccess(i.access, Collections.<String, STypeDef>emptyMap(), Collections.<Import>emptyList()), classTypeDef);\n                                        if (!getC.targetType().equals(sTypeDef)) {\n                                                if (tmpSet.add(getC)) {\n                                                        valueList.add(getC);\n                                                }\n                                        }\n                                }\n                        }\n                        if (valueList.isEmpty()) continue;\n\n                        // build the annotation instance\n                        SAnno importStatic = new SAnno();\n                        importStatic.setAnnoDef(StaticImports);\n                        importStatic.setPresent(sTypeDef);\n                        sTypeDef.annos().add(importStatic);\n\n                        // build the array instance\n                        SArrayValue arrayValue = new SArrayValue();\n                        arrayValue.setDimension(1);\n                        arrayValue.setType(classArrayTypeDef);\n\n                        Value[] valueArray = new Value[valueList.size()];\n                        arrayValue.setValues(valueList.toArray(valueArray));\n\n                        // add value into anno\n                        importStatic.values().put(annoField, arrayValue);\n                }\n        }\n\n        private void addRetention() throws SyntaxException {\n                SAnnoDef RetentionType = (SAnnoDef) getTypeWithName(\"java.lang.annotation.Retention\", LineCol.SYNTHETIC);\n                SAnnoField value = null;\n                EnumValue enumValue = new EnumValue();\n                enumValue.setType(getTypeWithName(\"java.lang.annotation.RetentionPolicy\", LineCol.SYNTHETIC));\n                enumValue.setEnumStr(\"RUNTIME\");\n\n                for (SAnnoField af : RetentionType.annoFields()) {\n                        if (af.name().equals(\"value\")) {\n                                value = af;\n                                break;\n                        }\n                }\n                assert value != null;\n                out:\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (!(sTypeDef instanceof SAnnoDef)) continue;\n                        SAnnoDef sAnnoDef = (SAnnoDef) sTypeDef;\n                        for (SAnno anno : sAnnoDef.annos()) {\n                                if (anno.type().equals(RetentionType)) {\n                                        continue out;\n                                }\n                        }\n                        SAnno anno = new SAnno();\n                        anno.setAnnoDef(RetentionType);\n                        anno.setPresent(sAnnoDef);\n                        anno.values().put(value, enumValue);\n                        sAnnoDef.annos().add(anno);\n                }\n        }\n\n        public static boolean packageExistsInClassPath(String pkg, ClassLoader classLoader) {\n                if (classLoader == null) return false;\n                String path = pkg.replace(\".\", \"/\");\n                URL url = classLoader.getResource(path);\n                return url != null || packageExistsInClassPath(pkg, classLoader.getParent());\n        }\n\n        public boolean packageExistInJRE(String pkg) {\n                if (alreadyWarnJar) return true;\n                if (sourceClasses.isEmpty()) {\n                        String homePath = System.getProperty(\"java.home\");\n                        if (homePath == null) {\n                                err.warning(\"Cannot find java home via System.getProperty('java.home')\");\n                                alreadyWarnJar = true;\n                                return true; // assume it's a valid import\n                        }\n                        File homePathFile = new File(homePath);\n                        File[] rtFileA = null;\n\n                        boolean found = false;\n\n                        // the file may be in $JAVA_HOME/../Contents/Classes/classes.jar\n                        // instead of $JAVA_HOME/lib/rt.jar\n\n                        // check for classes.jar\n                        File[] classesFileA = homePathFile.getParentFile().listFiles(new FileFilter() {\n                                @Override\n                                public boolean accept(File f) {\n                                        return f.getName().equals(\"Classes\");\n                                }\n                        });\n                        if (classesFileA != null && classesFileA.length != 0) {\n                                File classesFile = classesFileA[0];\n                                rtFileA = classesFile.listFiles(\n                                        new FileFilter() {\n                                                @Override\n                                                public boolean accept(File f) {\n                                                        return f.getName().equals(\"classes.jar\");\n                                                }\n                                        });\n                                found = true;\n                        }\n\n                        // not found\n                        // check rt.jar\n                        if (!found) {\n                                File[] libFileA = homePathFile.listFiles(\n                                        new FileFilter() {\n                                                @Override\n                                                public boolean accept(File f) {\n                                                        return f.getName().equals(\"lib\");\n                                                }\n                                        });\n                                if (libFileA == null || libFileA.length == 0) {\n                                        err.warning(homePath + \"/lib not exist\");\n                                        alreadyWarnJar = true;\n                                        return true;\n                                }\n                                File libFile = libFileA[0];\n                                rtFileA = libFile.listFiles(\n                                        new FileFilter() {\n                                                @Override\n                                                public boolean accept(File f) {\n                                                        return f.getName().equals(\"rt.jar\");\n                                                }\n                                        });\n                                if (rtFileA != null && rtFileA.length > 0 && rtFileA[0].exists()) {\n                                        found = true;\n                                }\n                        }\n\n                        if (found) {\n                                assert rtFileA != null;\n                                File rtFile = rtFileA[0];\n                                if (!rtFile.exists()) {\n                                        err.warning(homePath + \"/lib/rt.jar not exist\");\n                                        alreadyWarnJar = true;\n                                        return true;\n                                }\n                                try {\n                                        sourceClasses.add(new JarFile(rtFile));\n                                } catch (IOException e) {\n                                        err.warning(\"Occurred exception \" + e + \" when opening rt.jar\");\n                                        alreadyWarnJar = true;\n                                        return true;\n                                }\n                        } else {\n                                // check java 9 mods\n                                if (!findJava9(homePathFile)) {\n                                        err.warning(homePath + \"/lib/rt.jar not exist\");\n                                        alreadyWarnJar = true;\n                                        return true;\n                                }\n                        }\n                }\n                return findPackage(pkg, sourceClasses);\n        }\n\n        private boolean findJava9(File home) {\n                return findJava9JMods(home);\n        }\n\n        private boolean findJava9JMods(File home) {\n                File[] jmodsDirA = home.listFiles(new FileFilter() {\n                        @Override\n                        public boolean accept(File file) {\n                                return file.getName().equals(\"jmods\") && file.isDirectory();\n                        }\n                });\n                if (jmodsDirA == null || jmodsDirA.length == 0) {\n                        return false;\n                }\n                File jmodsDir = jmodsDirA[0];\n                File[] mods = jmodsDir.listFiles(new FileFilter() {\n                        @Override\n                        public boolean accept(File file) {\n                                return file.getName().endsWith(\".jmod\") && file.isFile();\n                        }\n                });\n                if (mods == null || mods.length == 0) {\n                        return false;\n                }\n                for (File f : mods) {\n                        try {\n                                sourceClasses.add(new ZipFile(f));\n                        } catch (IOException e) {\n                                return false;\n                        }\n                }\n                return true;\n        }\n\n        private static boolean findPackage(String pkg, List<ZipFile> files) {\n                for (ZipFile f : files) {\n                        if (findPackage(pkg, f.entries())) {\n                                return true;\n                        }\n                }\n                return false;\n        }\n\n        private static boolean findPackage(String pkg, Enumeration<? extends ZipEntry> entries) {\n                while (entries.hasMoreElements()) {\n                        ZipEntry entry = entries.nextElement();\n                        if (entry.getName().startsWith(pkg.replace(\".\", \"/\"))) {\n                                return true;\n                        }\n                        if (entry.getName().startsWith(\"classes/\" + pkg.replace(\".\", \"/\"))) {\n                                return true;\n                        }\n                }\n                return false;\n        }\n\n        /**\n         * ======= step 2 =======\n         * build fields,methods,constructors,parameters,parent-classes,super-interfaces,annotations.\n         * but no details (annotation's values|method statements|constructor statements won't be parsed)\n         *\n         * @param fileNameToPackageName file name to package name\n         * @throws SyntaxException exception\n         */\n        public void step2(Map<String, String> fileNameToPackageName) throws SyntaxException {\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (isGenericTemplateType(sTypeDef)) {\n                                continue; // ignore the template types\n                        }\n                        String fileName = sTypeDef.line_col().fileName;\n                        List<Import> imports = fileNameToImport.get(fileName);\n                        String pkg = fileNameToPackageName.get(fileName);\n\n                        if (sTypeDef instanceof SClassDef) {\n                                SClassDef sClassDef = (SClassDef) sTypeDef;\n                                if (sClassDef.classType() == SClassDef.FUN) {\n                                        SAnno latteFun = new SAnno();\n                                        latteFun.setAnnoDef((SAnnoDef) getTypeWithName(\"lt.runtime.LatteFun\", LineCol.SYNTHETIC));\n                                        latteFun.setPresent(sClassDef);\n                                        sClassDef.annos().add(latteFun);\n                                } else if (sClassDef.classType() == SClassDef.OBJECT) {\n                                        ASTGHolder<ObjectDef> objectHolder = originalObjects.get(sClassDef.fullName());\n                                        ObjectDef objectDef = objectHolder.s;\n\n                                        // present annotation\n                                        SAnno objectAnno = new SAnno();\n                                        objectAnno.setAnnoDef((SAnnoDef) getTypeWithName(\"lt.runtime.LatteObject\", LineCol.SYNTHETIC));\n                                        objectAnno.setPresent(sClassDef);\n                                        sClassDef.annos().add(objectAnno);\n\n                                        parseClassDefInfo(sClassDef, objectDef.superWithInvocation,\n                                                objectDef.superWithoutInvocation, imports, objectDef.line_col());\n\n                                        // modifiers\n                                        boolean isImplicit = false;\n                                        for (Modifier m : objectDef.modifiers) {\n                                                switch (m.modifier) {\n                                                        case IMPLICIT:\n                                                                isImplicit = true;\n                                                                break;\n                                                        default:\n                                                                err.UnexpectedTokenException(\"valid modifier (implicit)\", m.toString(), m.line_col());\n                                                                return;\n                                                }\n                                        }\n\n                                        // annos\n                                        parseAnnos(objectDef.annos, sClassDef, imports, ElementType.TYPE,\n                                                Collections.singletonList(ElementType.CONSTRUCTOR));\n\n                                        if (isImplicit) {\n                                                checkAndAddImplicitAnno(sClassDef);\n                                        }\n\n                                        // build constructor\n                                        SConstructorDef constructor = new SConstructorDef(LineCol.SYNTHETIC);\n                                        constructor.setDeclaringType(sClassDef);\n\n                                        // annotation\n                                        parseAnnos(objectDef.annos, constructor, imports, ElementType.CONSTRUCTOR,\n                                                Collections.singletonList(ElementType.TYPE));\n\n                                        // modifier\n                                        constructor.modifiers().add(SModifier.PRIVATE);\n\n                                        // declaring\n                                        constructor.setDeclaringType(sClassDef);\n                                        sClassDef.constructors().add(constructor);\n\n                                        // only add once, for that all types under one template share the same ast structure\n                                        if (objectDef.statements.isEmpty() || !(objectDef.statements.get(0) instanceof AST.StaticScope)) {\n                                                // static public val singletonInstance = XXX\n                                                VariableDef v = new VariableDef(CompileUtil.SingletonFieldName,\n                                                        new HashSet<Modifier>(Arrays.asList(\n                                                                new Modifier(Modifier.Available.VAL, LineCol.SYNTHETIC),\n                                                                new Modifier(Modifier.Available.PUBLIC, LineCol.SYNTHETIC)\n                                                        )), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                                                AST.Access vType = new AST.Access(pkg.isEmpty() ? null : new AST.PackageRef(pkg, LineCol.SYNTHETIC),\n                                                        objectDef.name, LineCol.SYNTHETIC);\n                                                vType.generics.addAll(objectDef.generics);\n                                                v.setType(vType);\n                                                objectDef.statements.add(0, new AST.StaticScope(Collections.<Statement>singletonList(v),\n                                                        LineCol.SYNTHETIC));\n\n                                        }\n                                        // fields methods\n                                        parseFieldsAndMethodsForClass(sClassDef, objectDef.statements, imports);\n                                } else if (sClassDef.classType() == SClassDef.NORMAL) {\n                                        ASTGHolder<ClassDef> classHolder = originalClasses.get(sClassDef.fullName());\n                                        ClassDef classDef = classHolder.s;\n\n                                        parseClassDefInfo(sClassDef, classDef.superWithInvocation,\n                                                classDef.superWithoutInvocation, imports, classDef.line_col());\n\n                                        // annos\n                                        parseAnnos(classDef.annos, sClassDef, imports, ElementType.TYPE,\n                                                Collections.singletonList(ElementType.CONSTRUCTOR));\n\n                                        // parse constructor\n                                        int generateIndex = -1;\n                                        for (VariableDef v : classDef.params) {\n                                                if (v.getInit() == null) {\n                                                        ++generateIndex;\n                                                } else break;\n                                        }\n\n                                        SConstructorDef lastConstructor = null;\n                                        for (int i = classDef.params.size(); i > generateIndex; --i) {\n                                                // generate constructors\n                                                // these constructors will call the constructor that has length+1 parameter length constructor\n                                                // e.g.\n                                                // class Cls(a,b=1)\n                                                // will be parsed into\n                                                // public class Cls{\n                                                //      public Cls(a){\n                                                //              this(a,1);\n                                                //      }\n                                                //      public Cls(a,b){\n                                                //              ...\n                                                //      }\n                                                // }\n                                                // however the statements won't be filled in this step\n                                                SConstructorDef constructor = new SConstructorDef(classDef.line_col());\n\n                                                constructor.setDeclaringType(sClassDef);\n                                                sClassDef.constructors().add(constructor);\n\n                                                // constructor should be filled with\n                                                // parameters|declaringType(class)|modifiers\n                                                // in this step\n\n                                                // annotation\n                                                parseAnnos(classDef.annos, constructor, imports, ElementType.CONSTRUCTOR,\n                                                        Collections.singletonList(ElementType.TYPE));\n\n                                                // modifier\n                                                boolean hasAccessModifier = false;\n                                                for (Modifier m : classDef.modifiers) {\n                                                        if (m.modifier.equals(Modifier.Available.PUBLIC)\n                                                                || m.modifier.equals(Modifier.Available.PRIVATE)\n                                                                || m.modifier.equals(Modifier.Available.PROTECTED)\n                                                                || m.modifier.equals(Modifier.Available.PKG)) {\n                                                                hasAccessModifier = true;\n                                                        }\n                                                }\n                                                if (!hasAccessModifier) {\n                                                        constructor.modifiers().add(SModifier.PUBLIC);\n                                                }\n                                                for (Modifier m : classDef.modifiers) {\n                                                        switch (m.modifier) {\n                                                                case PUBLIC:\n                                                                        constructor.modifiers().add(SModifier.PUBLIC);\n                                                                        break;\n                                                                case PRIVATE:\n                                                                        constructor.modifiers().add(SModifier.PRIVATE);\n                                                                        break;\n                                                                case PROTECTED:\n                                                                        constructor.modifiers().add(SModifier.PROTECTED);\n                                                                        break;\n                                                                case VAL:\n                                                                case PKG:\n                                                                case DATA:\n                                                                case ABSTRACT:\n                                                                        // data, val and abs are presented on class\n                                                                        break; // pkg don't need to sign modifier\n                                                                default:\n                                                                        err.UnexpectedTokenException(\"valid constructor modifier (public|private|protected|internal)\", m.toString(), m.line_col());\n                                                                        return;\n                                                        }\n                                                }\n\n                                                // parameters\n                                                parseParameters(classDef.params, i, constructor, imports, true);\n\n                                                if (lastConstructor != null) {\n                                                        // record the constructor and expressions\n                                                        Map<SInvokable, Expression> invoke = new HashMap<SInvokable, Expression>();\n                                                        invoke.put(lastConstructor, classDef.params.get(i).getInit());\n                                                        defaultParamInvokable.put(constructor, invoke);\n                                                }\n                                                lastConstructor = constructor;\n                                        }\n                                        // constructor finished\n\n                                        // fields and methods\n                                        // parse field from constructor parameters\n                                        for (VariableDef v : classDef.params) {\n                                                parseField(v, sClassDef, imports, PARSING_CLASS, false, true);\n                                        }\n                                        parseFieldsAndMethodsForClass(sClassDef, classDef.statements, imports);\n                                } else {\n                                        throw new LtBug(\"unknown sClassDef.classType(): \" + sClassDef.classType());\n                                }\n                        } else if (sTypeDef instanceof SInterfaceDef) {\n                                SInterfaceDef sInterfaceDef = (SInterfaceDef) sTypeDef;\n                                ASTGHolder<InterfaceDef> interfaceHolder = originalInterfaces.get(sInterfaceDef.fullName());\n                                InterfaceDef interfaceDef = interfaceHolder.s;\n\n                                // parse super interfaces\n                                for (AST.Access access : interfaceDef.superInterfaces) {\n                                        SInterfaceDef superInterface = (SInterfaceDef) getTypeWithAccess(access, getGenericMap(sInterfaceDef), imports);\n                                        sInterfaceDef.superInterfaces().add(superInterface);\n                                }\n\n                                // parse annos\n                                parseAnnos(interfaceDef.annos, sInterfaceDef, imports, ElementType.TYPE, Collections.<ElementType>emptyList());\n\n                                // parse fields and methods\n                                List<AST.StaticScope> staticScopes = new ArrayList<AST.StaticScope>();\n                                for (Statement stmt : interfaceDef.statements) {\n                                        if (stmt instanceof VariableDef) {\n                                                parseField((VariableDef) stmt, sInterfaceDef, imports, PARSING_INTERFACE, false, false);\n                                        } else if (stmt instanceof MethodDef) {\n                                                MethodDef m = (MethodDef) stmt;\n                                                int generateIndex = -1;\n                                                for (VariableDef param : m.params) {\n                                                        if (param.getInit() == null) {\n                                                                ++generateIndex;\n                                                        } else break;\n                                                }\n\n                                                SMethodDef lastMethod = null;\n                                                for (int i = m.params.size(); i > generateIndex; --i) {\n                                                        parseMethod(m, i, sInterfaceDef, lastMethod, imports, PARSING_INTERFACE, false);\n                                                        lastMethod = sInterfaceDef.methods().get(sInterfaceDef.methods().size() - 1);\n\n                                                        // record the method\n                                                        methodToStatements.put(lastMethod, m.body);\n                                                }\n\n                                        } else if (stmt instanceof AST.StaticScope) {\n                                                staticScopes.add((AST.StaticScope) stmt);\n                                        } else if (stmt instanceof AST.Destruct) {\n                                                parseFieldsFromDestruct((AST.Destruct) stmt, sInterfaceDef, true);\n                                        } else {\n                                                err.SyntaxException(\"interfaces don't have initiators\", stmt.line_col());\n                                                return;\n                                        }\n                                }\n                                for (AST.StaticScope staticScope : staticScopes) {\n                                        for (Statement stmt : staticScope.statements) {\n                                                if (stmt instanceof VariableDef) {\n                                                        parseField((VariableDef) stmt, sInterfaceDef, imports, PARSING_INTERFACE, true, false);\n                                                } else if (stmt instanceof MethodDef) {\n                                                        MethodDef m = (MethodDef) stmt;\n                                                        int generateIndex = -1;\n                                                        for (VariableDef param : m.params) {\n                                                                if (param.getInit() == null) {\n                                                                        ++generateIndex;\n                                                                } else break;\n                                                        }\n\n                                                        SMethodDef lastMethod = null;\n                                                        for (int i = m.params.size(); i > generateIndex; --i) {\n                                                                parseMethod(m, i, sInterfaceDef, lastMethod, imports, PARSING_INTERFACE, true);\n                                                                lastMethod = sInterfaceDef.methods().get(sInterfaceDef.methods().size() - 1);\n\n                                                                // record the method\n                                                                methodToStatements.put(lastMethod, m.body);\n                                                        }\n                                                } else if (stmt instanceof AST.Destruct) {\n                                                        parseFieldsFromDestruct((AST.Destruct) stmt, sInterfaceDef, true);\n                                                } else {\n                                                        err.SyntaxException(\"interfaces don't have initiators\", stmt.line_col());\n                                                        return;\n                                                }\n                                        }\n                                }\n                        } else if (sTypeDef instanceof SAnnoDef) {\n                                SAnnoDef sAnnoDef = (SAnnoDef) sTypeDef;\n                                ASTGHolder<AnnotationDef> annoHolder = originalAnnotations.get(sAnnoDef.fullName());\n                                AnnotationDef annotationDef = annoHolder.s;\n\n                                // annos\n                                parseAnnos(annotationDef.annos, sAnnoDef, imports, ElementType.ANNOTATION_TYPE,\n                                        Collections.<ElementType>emptyList());\n\n                                // annotation fields\n                                parseAnnotationFields(sAnnoDef, annotationDef.stmts, imports);\n                        } else {\n                                throw new LtBug(\"unknown STypeDef \" + sTypeDef);\n                        }\n                }\n        }\n\n        private void assertToBeAnnotationField(STypeDef type) throws SyntaxException {\n                if (type instanceof PrimitiveTypeDef) return;\n                if (type.fullName().equals(\"java.lang.String\")) return;\n                if (type.fullName().equals(\"java.lang.Class\")) return;\n                if (getTypeWithName(Enum.class.getName(), LineCol.SYNTHETIC).isAssignableFrom(type)) return;\n                if (type instanceof SArrayTypeDef && ((SArrayTypeDef) type).dimension() == 1) {\n                        assertToBeAnnotationField(((SArrayTypeDef) type).type());\n                        return;\n                }\n                if (type instanceof SAnnoDef) return;\n                err.SyntaxException(type + \" cannot be type of annotation fields\", type.line_col());\n        }\n\n        /**\n         * fill annotation fields into the annotation, but values are not parsed\n         *\n         * @param sAnnoDef the annotation def\n         * @param stmts    statements in annotation\n         * @param imports  imports\n         * @throws SyntaxException compiling error\n         */\n        public void parseAnnotationFields(SAnnoDef sAnnoDef, List<Statement> stmts, List<Import> imports) throws SyntaxException {\n                for (Statement stmt : stmts) {\n                        if (stmt instanceof VariableDef) {\n                                VariableDef v = (VariableDef) stmt;\n                                if (!v.getModifiers().isEmpty()) {\n                                        err.SyntaxException(\"modifiers cannot present on annotation fields\", v.line_col());\n                                }\n                                if (!v.getAnnos().isEmpty()) {\n                                        err.SyntaxException(\"annotations cannot present on annotation fields\", v.line_col());\n                                }\n                                if (v.getType() == null) {\n                                        err.SyntaxException(\"annotation fields should have a type\", v.line_col());\n                                }\n                                STypeDef type = getTypeWithAccess(v.getType(), getGenericMap(sAnnoDef), imports);\n                                assertToBeAnnotationField(type);\n                                SAnnoField f = new SAnnoField();\n                                f.setName(v.getName());\n                                f.setType(type);\n                                f.setDeclaringType(sAnnoDef);\n                                sAnnoDef.annoFields().add(f);\n                        } else {\n                                err.SyntaxException(\"only variable definition can exist in annotation\", stmt.line_col());\n                        }\n                }\n        }\n\n        private void checkAndAddImplicitAnno(SAnnotationPresentable annoPresentable) throws SyntaxException {\n                // check implicit annotation\n                boolean hasImplicitAnno = false;\n                for (SAnno sAnno : annoPresentable.annos()) {\n                        if (sAnno.type().fullName().equals(\"lt.runtime.Implicit\")) {\n                                hasImplicitAnno = true;\n                                break;\n                        }\n                }\n                if (!hasImplicitAnno) {\n                        SAnno ImplicitAnno = new SAnno();\n                        ImplicitAnno.setAnnoDef((SAnnoDef) getTypeWithName(\"lt.runtime.Implicit\", LineCol.SYNTHETIC));\n                        ImplicitAnno.setPresent(annoPresentable);\n                        annoPresentable.annos().add(ImplicitAnno);\n                }\n        }\n\n        /**\n         * parse class info\n         *\n         * @param sClassDef              SClassDef object\n         * @param superWithInvocation    :???(...)\n         * @param superWithoutInvocation :???\n         * @param imports                imports\n         * @param lineCol                lineCol\n         * @throws SyntaxException compiling error\n         */\n        private void parseClassDefInfo(SClassDef sClassDef,\n                                       AST.Invocation superWithInvocation,\n                                       List<AST.Access> superWithoutInvocation,\n                                       List<Import> imports,\n                                       LineCol lineCol) throws SyntaxException {\n                // generic type map\n                Map<String, STypeDef> genericTypeMap = getGenericMap(sClassDef);\n                // parse parent\n                Iterator<AST.Access> superWithoutInvocationAccess;\n                if (superWithInvocation == null) {\n                        if (superWithoutInvocation.isEmpty()) {\n                                // no interfaces, no parent class\n                                sClassDef.setParent((SClassDef) getTypeWithName(\"java.lang.Object\", lineCol));\n                                superWithoutInvocationAccess = null;\n                        } else {\n                                superWithoutInvocationAccess = superWithoutInvocation.iterator();\n                                AST.Access mightBeClassAccess = superWithoutInvocationAccess.next();\n                                STypeDef tmp = getTypeWithAccess(mightBeClassAccess, genericTypeMap, imports);\n                                if (tmp instanceof SClassDef) {\n                                        // constructor without constructor invocation\n                                        sClassDef.setParent((SClassDef) tmp);\n                                } else if (tmp instanceof SInterfaceDef) {\n                                        // interface\n                                        sClassDef.superInterfaces().add((SInterfaceDef) tmp);\n                                        // set java.lang.Object as super class\n                                        sClassDef.setParent((SClassDef) getTypeWithName(\"java.lang.Object\", lineCol));\n                                } else {\n                                        err.SyntaxException(mightBeClassAccess.toString() + \" is not class or interface\",\n                                                mightBeClassAccess.line_col());\n                                        return;\n                                }\n                        }\n                } else {\n                        // super class\n                        if (!(superWithInvocation.exp instanceof AST.Access)) {\n                                throw new LtBug(\"classDef.superWithInvocation.exp should always be AST.Access\");\n                        }\n\n                        AST.Access access = (AST.Access) superWithInvocation.exp;\n                        STypeDef tmp = getTypeWithAccess(access, genericTypeMap, imports);\n                        if (tmp instanceof SClassDef) {\n                                sClassDef.setParent((SClassDef) tmp);\n                        } else {\n                                err.SyntaxException(access.toString() + \" is not class or interface\",\n                                        access.line_col());\n                                return;\n                        }\n                        superWithoutInvocationAccess = superWithoutInvocation.iterator();\n                }\n                // interfaces to be parsed\n                while (superWithoutInvocationAccess != null && superWithoutInvocationAccess.hasNext()) {\n                        AST.Access interfaceAccess = superWithoutInvocationAccess.next();\n                        STypeDef tmp = getTypeWithAccess(interfaceAccess, getGenericMap(sClassDef), imports);\n                        if (tmp instanceof SInterfaceDef) {\n                                sClassDef.superInterfaces().add((SInterfaceDef) tmp);\n                        } else {\n                                err.SyntaxException(interfaceAccess.toString() + \" is not interface\",\n                                        interfaceAccess.line_col());\n                                return;\n                        }\n                }\n        }\n\n        /**\n         * parse fields and methods for class\n         *\n         * @param sClassDef  SClassDef object\n         * @param statements statements\n         * @param imports    imports\n         * @throws SyntaxException compiling error\n         */\n        private void parseFieldsAndMethodsForClass(SClassDef sClassDef,\n                                                   List<Statement> statements,\n                                                   List<Import> imports) throws SyntaxException {\n                // get static scope and parse non-static fields/methods\n                List<AST.StaticScope> staticScopes = new ArrayList<AST.StaticScope>();\n                for (Statement stmt : statements) {\n                        if (stmt instanceof AST.StaticScope) {\n                                staticScopes.add((AST.StaticScope) stmt);\n                        } else if (stmt instanceof VariableDef) {\n                                // define a non-static field\n                                parseField((VariableDef) stmt, sClassDef, imports, PARSING_CLASS, false, false);\n                        } else if (stmt instanceof MethodDef) {\n                                // define a non-static method\n                                MethodDef methodDef = (MethodDef) stmt;\n                                int generateIndex = -1;\n                                for (VariableDef v : methodDef.params) {\n                                        if (v.getInit() == null) {\n                                                ++generateIndex;\n                                        } else break;\n                                }\n\n                                SMethodDef lastMethod = null;\n                                for (int i = methodDef.params.size(); i > generateIndex; --i) {\n                                        parseMethod((MethodDef) stmt, i, sClassDef, lastMethod, imports, PARSING_CLASS, false);\n                                        lastMethod = sClassDef.methods().get(sClassDef.methods().size() - 1);\n\n                                        // record the method\n                                        methodToStatements.put(lastMethod, methodDef.body);\n                                }\n                        } else if (stmt instanceof AST.Destruct) {\n                                parseFieldsFromDestruct((AST.Destruct) stmt, sClassDef, false);\n                        }\n                }\n                // get static field and methods\n                for (AST.StaticScope scope : staticScopes) {\n                        for (Statement stmt : scope.statements) {\n                                if (stmt instanceof VariableDef) {\n                                        // define a static field\n                                        parseField((VariableDef) stmt, sClassDef, imports, PARSING_CLASS, true, false);\n                                } else if (stmt instanceof MethodDef) {\n                                        // define a static method\n                                        MethodDef methodDef = (MethodDef) stmt;\n                                        int generateIndex = -1;\n                                        for (VariableDef v : methodDef.params) {\n                                                if (v.getInit() == null) {\n                                                        ++generateIndex;\n                                                } else break;\n                                        }\n\n                                        SMethodDef lastMethod = null;\n                                        for (int i = methodDef.params.size(); i > generateIndex; --i) {\n                                                parseMethod((MethodDef) stmt, i, sClassDef, lastMethod, imports, PARSING_CLASS, true);\n                                                lastMethod = sClassDef.methods().get(sClassDef.methods().size() - 1);\n\n                                                // record the method\n                                                methodToStatements.put(lastMethod, methodDef.body);\n                                        }\n                                } else if (stmt instanceof AST.Destruct) {\n                                        parseFieldsFromDestruct((AST.Destruct) stmt, sClassDef, true);\n                                }\n                        }\n                }\n        }\n\n        /**\n         * ========step 3========\n         * validation\n         * <p>\n         * check circular inheritance\n         * check method override\n         * check method signature\n         * check annotations\n         *\n         * @throws SyntaxException exception\n         */\n        public void step3() throws SyntaxException {\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (isGenericTemplateType(sTypeDef)) continue;\n                        if (sTypeDef instanceof SClassDef) {\n                                List<STypeDef> circularRecorder = new ArrayList<STypeDef>();\n                                SClassDef parent = ((SClassDef) sTypeDef).parent();\n                                while (parent != null) {\n                                        circularRecorder.add(parent);\n                                        if (parent.equals(sTypeDef)) {\n                                                err.SyntaxException(\"circular inheritance \" + circularRecorder, LineCol.SYNTHETIC);\n                                                return;\n                                        }\n                                        parent = parent.parent();\n                                }\n                                circularRecorder.clear();\n                        } else if (sTypeDef instanceof SInterfaceDef) {\n                                SInterfaceDef i = (SInterfaceDef) sTypeDef;\n                                checkInterfaceCircularInheritance(i, i.superInterfaces(), new ArrayList<SInterfaceDef>());\n                        } else if (!(sTypeDef instanceof SAnnoDef)) {\n                                throw new LtBug(\"wrong STypeDefType \" + sTypeDef.getClass());\n                        }\n                }\n                // check override and overload with super methods\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (isGenericTemplateType(sTypeDef)) continue;\n                        if (sTypeDef instanceof SAnnoDef) continue;\n                        checkOverrideAllMethods(sTypeDef);\n                }\n\n                // after the override check are done, try to get signatures of functions.\n                for (STypeDef sTypeDef : typeDefSet) {\n                        if (isGenericTemplateType(sTypeDef)) continue;\n                        if (sTypeDef instanceof SClassDef) {\n                                SClassDef sClassDef = (SClassDef) sTypeDef;\n                                if (sClassDef.classType() != SClassDef.FUN) {\n                                        continue;\n                                }\n\n                                ASTGHolder<FunDef> funHolder = originalFunctions.get(sClassDef.fullName());\n                                FunDef fun = funHolder.s;\n                                List<Import> imports = fileNameToImport.get(fun.line_col().fileName);\n\n                                // get super class/interface\n                                STypeDef type = getTypeWithAccess(fun.superType, getGenericMap(sTypeDef), imports);\n                                if (!(type instanceof SClassDef || type instanceof SInterfaceDef)) {\n                                        err.SyntaxException(\"function super type should be functional interfaces or functional abstract classes\", fun.superType.line_col());\n                                        return;\n                                }\n                                SConstructorDef[] zeroParamConstructor = new SConstructorDef[1];\n                                SMethodDef[] methodToOverride = new SMethodDef[1];\n                                if (!getMethodForLambda(type, zeroParamConstructor, methodToOverride)) {\n                                        err.SyntaxException(\"function super type should be functional interfaces or functional abstract classes\", fun.superType.line_col());\n                                        return;\n                                }\n\n                                // class and the annos, super class\n                                parseAnnos(fun.annos, sClassDef, imports, ElementType.TYPE, Arrays.asList(ElementType.METHOD, ElementType.CONSTRUCTOR));\n                                if (zeroParamConstructor[0] == null) {\n                                        sClassDef.setParent(getObject_Class());\n                                        assert type instanceof SInterfaceDef;\n                                        sClassDef.superInterfaces().add((SInterfaceDef) type);\n                                } else {\n                                        sClassDef.setParent((SClassDef) zeroParamConstructor[0].declaringType());\n                                }\n\n                                // constructors (fill statements directly)\n                                SConstructorDef cons = new SConstructorDef(LineCol.SYNTHETIC);\n                                parseAnnos(fun.annos, cons, imports, ElementType.CONSTRUCTOR, Arrays.asList(ElementType.TYPE, ElementType.METHOD));\n                                cons.setDeclaringType(sClassDef);\n                                sClassDef.constructors().add(cons);\n                                if (zeroParamConstructor[0] == null) {\n                                        zeroParamConstructor[0] = getObject_Class().constructors().get(0);\n                                }\n                                cons.statements().add(new Ins.InvokeSpecial(new Ins.This(sClassDef), zeroParamConstructor[0], LineCol.SYNTHETIC));\n                                cons.modifiers().add(SModifier.PUBLIC);\n\n                                // method name, declaringType, return type, params\n                                SMethodDef method = new SMethodDef(LineCol.SYNTHETIC);\n                                method.setDeclaringType(sClassDef);\n                                method.setReturnType(\n                                        getRealReturnType(\n                                                methodToOverride[0].getReturnType(), true));\n                                method.setName(methodToOverride[0].name());\n                                sClassDef.methods().add(method);\n                                parseAnnos(fun.annos, method, imports, ElementType.METHOD, Arrays.asList(ElementType.TYPE, ElementType.CONSTRUCTOR));\n                                method.modifiers().add(SModifier.PUBLIC);\n\n                                // fill parameters\n                                parseParameters(fun.params, fun.params.size(), method, imports, false);\n\n                                methodToStatements.put(method, fun.statements);\n\n                                // check signature\n                                checkOverrideAllMethods(sClassDef);\n                        }\n                }\n\n                // check annotation (@FunctionalInterface @FunctionalAbstractClass @Override @Implicit)\n                for (STypeDef typeDef : typeDefSet) {\n                        // annotation would never be generic\n                        // no need to check\n                        // if (isGenericTemplateType(typeDef)) continue;\n                        if (typeDef instanceof SAnnoDef) continue;\n                        for (SAnno anno : typeDef.annos()) {\n                                if (anno.type().fullName().equals(\"java.lang.FunctionalInterface\")\n                                        || anno.type().fullName().equals(\"lt.lang.FunctionalInterface\")) {\n                                        final String msg = typeDef + \" is not a functional interface\";\n                                        if (typeDef instanceof SInterfaceDef) {\n                                                if (!getMethodForLambda(typeDef, new SConstructorDef[1], new SMethodDef[1])) {\n                                                        err.SyntaxException(msg, typeDef.line_col());\n                                                        return;\n                                                }\n                                        } else {\n                                                err.SyntaxException(msg, typeDef.line_col());\n                                                return;\n                                        }\n                                } else if (anno.type().fullName().equals(\"lt.lang.FunctionalAbstractClass\")) {\n                                        final String msg = typeDef + \" is not a functional abstract class\";\n                                        if (typeDef instanceof SClassDef) {\n                                                if (!getMethodForLambda(typeDef, new SConstructorDef[1], new SMethodDef[1])) {\n                                                        err.SyntaxException(msg, typeDef.line_col());\n                                                        return;\n                                                }\n                                        } else {\n                                                err.SyntaxException(msg, typeDef.line_col());\n                                                return;\n                                        }\n                                } else if (anno.type().fullName().equals(\"lt.runtime.Implicit\")) {\n                                        if (typeDef instanceof SClassDef) {\n                                                boolean isObject = false;\n                                                for (SAnno a : typeDef.annos()) {\n                                                        if (a.type().fullName().equals(\"lt.runtime.LatteObject\")) {\n                                                                isObject = true;\n                                                                break;\n                                                        }\n                                                }\n                                                if (isObject) {\n                                                        // check methods\n                                                        for (SMethodDef m : ((SClassDef) typeDef).methods()) {\n                                                                for (SAnno a : m.annos()) {\n                                                                        if (a.type().fullName().equals(\"lt.runtime.Implicit\")) {\n                                                                                if (m.getParameters().size() != 1) {\n                                                                                        err.SyntaxException(\"implicit methods should contain only one param\", m.line_col());\n                                                                                }\n                                                                                if (m.getReturnType().equals(VoidType.get())) {\n                                                                                        err.SyntaxException(\"implicit method's return type should not be Unit\", m.line_col());\n                                                                                }\n                                                                        }\n                                                                }\n                                                        }\n                                                } else {\n                                                        err.SyntaxException(\"implicit should only exist on object classes\", typeDef.line_col());\n                                                }\n                                        } else {\n                                                err.SyntaxException(\"implicit should only exist on object classes\", typeDef.line_col());\n                                        }\n                                }\n                        }\n                        List<SMethodDef> methods;\n                        if (typeDef instanceof SClassDef) methods = ((SClassDef) typeDef).methods();\n                        else methods = ((SInterfaceDef) typeDef).methods();\n\n                        for (SMethodDef method : methods) {\n                                for (SAnno anno : method.annos()) {\n                                        if (anno.type().fullName().equals(\"java.lang.Override\")) {\n                                                if (method.overRide().isEmpty()) {\n                                                        err.SyntaxException(method + \" doesn't override any method\", method.line_col());\n                                                        return;\n                                                }\n                                        }\n                                }\n                        }\n                }\n\n                // data class\n                for (STypeDef typeDef : typeDefSet) {\n                        if (isGenericTemplateType(typeDef)) continue;\n                        if (typeDef instanceof SClassDef) {\n                                SClassDef cls = (SClassDef) typeDef;\n                                if (cls.isDataClass()) {\n                                        fillMethodsIntoDataClass(cls);\n                                }\n                        }\n                }\n        }\n\n        private void checkAndFillAnnotations() throws SyntaxException {\n                // not compiled annotations\n                for (STypeDef typeDef : typeDefSet) {\n                        if (typeDef instanceof SAnnoDef) {\n                                SAnnoDef annoDef = (SAnnoDef) typeDef;\n                                ASTGHolder<AnnotationDef> holder = originalAnnotations.get(annoDef.fullName());\n                                AnnotationDef astAnnoDef = holder.s;\n                                for (SAnnoField f : annoDef.annoFields()) {\n                                        for (Statement stmt : astAnnoDef.stmts) {\n                                                if (stmt instanceof VariableDef\n                                                        &&\n                                                        ((VariableDef) stmt).getName().equals(f.name())) {\n\n                                                        Expression exp = ((VariableDef) stmt).getInit();\n                                                        if (exp != null) {\n                                                                // do fill\n                                                                f.doesHaveDefaultValue();\n                                                        }\n                                                }\n                                        }\n                                }\n                        }\n                }\n                // compiled annotations\n                // fill the values directly\n                for (STypeDef typeDef : types.values()) {\n                        if (typeDef instanceof SAnnoDef) {\n                                boolean isCompiledAnnotation = true;\n                                SAnnoDef annoDef = (SAnnoDef) typeDef;\n                                Class<?> cls = null;\n                                try {\n                                        cls = loadClass(annoDef.fullName());\n                                } catch (ClassNotFoundException e) {\n                                        isCompiledAnnotation = false;\n                                }\n                                // parse field default values\n                                if (isCompiledAnnotation) {\n                                        for (SAnnoField f : annoDef.annoFields()) {\n                                                try {\n                                                        Method annoM = cls.getDeclaredMethod(f.name());\n                                                        try {\n                                                                Object o = annoM.getDefaultValue();\n                                                                if (null != o) {\n                                                                        Value value = parseValueFromObject(o);\n                                                                        f.setDefaultValue(value);\n                                                                }\n                                                        } catch (TypeNotPresentException ignore) {\n                                                        }\n                                                } catch (NoSuchMethodException e) {\n                                                        throw new LtBug(e);\n                                                }\n                                        }\n                                }\n                        }\n                }\n                // fill true value to not compiled annotations\n                for (STypeDef typeDef : typeDefSet) {\n                        if (typeDef instanceof SAnnoDef) {\n                                SAnnoDef annoDef = (SAnnoDef) typeDef;\n                                ASTGHolder<AnnotationDef> holder = originalAnnotations.get(annoDef.fullName());\n                                AnnotationDef astAnnoDef = holder.s;\n                                for (SAnnoField f : annoDef.annoFields()) {\n                                        for (Statement stmt : astAnnoDef.stmts) {\n                                                if (stmt instanceof VariableDef\n                                                        &&\n                                                        ((VariableDef) stmt).getName().equals(f.name())) {\n\n                                                        Expression exp = ((VariableDef) stmt).getInit();\n                                                        if (exp != null) {\n                                                                Value value = transformIntoAnnoValidValue(\n                                                                        parseValueFromExpression(exp, f.type(), null),\n                                                                        exp.line_col());\n                                                                f.setDefaultValue(value);\n                                                        }\n                                                }\n                                        }\n                                }\n                        }\n                }\n                // parse annotations presented on this type\n                for (STypeDef typeDef : types.values()) {\n                        if (typeDef instanceof SAnnoDef) {\n                                SAnnoDef annoDef = (SAnnoDef) typeDef;\n                                parseAnnoValues(annoDef.annos());\n                        }\n                }\n        }\n\n        private Value transformIntoAnnoValidValue(Value value, LineCol lineCol) throws SyntaxException {\n                if (value.type() instanceof PrimitiveTypeDef) return value;\n                if (value instanceof StringConstantValue) return value;\n                if (value instanceof Ins.GetClass) return value;\n                if (value instanceof SAnno) return value;\n                if (value instanceof Ins.GetStatic) {\n                        // enum\n                        EnumValue enumValue = new EnumValue();\n                        enumValue.setType(((Ins.GetStatic) value).field().declaringType());\n                        enumValue.setEnumStr(((Ins.GetStatic) value).field().name());\n                        return enumValue;\n                }\n                if (value instanceof Ins.NewArray) {\n                        // array\n                        SArrayValue sArrayValue = new SArrayValue();\n                        sArrayValue.setDimension(1);\n                        List<Value> values = ((Ins.NewArray) value).initValues();\n                        sArrayValue.setValues(values.toArray(new Value[values.size()]));\n                        sArrayValue.setType((SArrayTypeDef) value.type());\n                        return sArrayValue;\n                }\n                if (value instanceof Ins.ANewArray) {\n                        // ref array\n                        SArrayValue sArrayValue = new SArrayValue();\n                        sArrayValue.setDimension(1);\n                        List<Value> values = ((Ins.ANewArray) value).initValues();\n                        sArrayValue.setValues(values.toArray(new Value[values.size()]));\n                        sArrayValue.setType((SArrayTypeDef) value.type());\n                        return sArrayValue;\n                }\n                err.SyntaxException(\"cannot resolve valid value for annotation field\", lineCol);\n                return null;\n        }\n\n        /**\n         * ========step 4========\n         * first parse anno types\n         * the annotations presented on these anno types will also be parsed\n         *\n         * @throws SyntaxException exception\n         */\n        public void step4() throws SyntaxException {\n                checkAndFillAnnotations();\n                // then\n                // foreach typeDefSet, parse their statements\n                List<STypeDef> typeDefList = new ArrayList<STypeDef>(typeDefSet);\n                for (STypeDef sTypeDef : typeDefList) {\n                        if (isGenericTemplateType(sTypeDef)) {\n                                typeDefSet.remove(sTypeDef);\n                                generateGenericTemplateClass(sTypeDef);\n                                continue;\n                        }\n                        if (sTypeDef instanceof SClassDef) {\n                                SClassDef sClassDef = (SClassDef) sTypeDef;\n                                ASTGHolder<ClassDef> classHolder = originalClasses.get(sClassDef.fullName());\n                                ASTGHolder<ObjectDef> objectHolder = originalObjects.get(sClassDef.fullName());\n                                ClassDef astClass = (null == classHolder) ? null : classHolder.s;\n                                ObjectDef astObject = (null == objectHolder) ? null : objectHolder.s;\n\n                                parseAnnoValues(sClassDef.annos());\n\n                                // initiate the type scope\n                                SemanticScope scope = new SemanticScope(sTypeDef, null);\n\n                                // parse constructors\n                                for (SConstructorDef constructorToFillStatements : sClassDef.constructors()) {\n                                        // if is not empty then continue\n                                        if (!constructorToFillStatements.statements().isEmpty())\n                                                continue;\n                                        // initiate constructor scope\n                                        SemanticScope constructorScope = new SemanticScope(scope, constructorToFillStatements.meta());\n                                        constructorScope.setThis(new Ins.This(sTypeDef)); // set `this`\n                                        for (SParameter param : constructorToFillStatements.getParameters()) {\n                                                constructorScope.putLeftValue(param.name(), param);\n                                        }\n\n                                        if (defaultParamInvokable.containsKey(constructorToFillStatements)) {\n                                                fillDefaultParamMethod(constructorToFillStatements, constructorScope);\n                                        } else {\n                                                // parse invoke super constructor statement\n                                                SClassDef parent = sClassDef.parent();\n                                                Ins.InvokeSpecial invokeConstructor = null;\n\n                                                assert (astClass == null && astObject != null) || (astClass != null && astObject == null);\n\n                                                AST.Invocation superWithInvocation = (\n                                                        astClass == null) ? astObject.superWithInvocation\n                                                        : astClass.superWithInvocation;\n\n                                                if (null == superWithInvocation) {\n                                                        // invoke super();\n                                                        for (SConstructorDef cons : parent.constructors()) {\n                                                                if (cons.getParameters().size() == 0) {\n                                                                        invokeConstructor = new Ins.InvokeSpecial(new Ins.This(sClassDef), cons,\n                                                                                sClassDef.line_col());\n                                                                        break;\n                                                                }\n                                                        }\n                                                } else {\n                                                        // invoke super with args\n                                                        for (SConstructorDef cons : parent.constructors()) {\n                                                                if (cons.getParameters().size() == superWithInvocation.args.size()) {\n                                                                        invokeConstructor = new Ins.InvokeSpecial(new Ins.This(sClassDef), cons,\n                                                                                superWithInvocation.line_col());\n\n                                                                        List<SParameter> parameters = cons.getParameters();\n                                                                        List<Expression> args = superWithInvocation.args;\n                                                                        for (int i = 0; i < parameters.size(); ++i) {\n                                                                                Value v = parseValueFromExpression(args.get(i), parameters.get(i).type(), constructorScope);\n                                                                                invokeConstructor.arguments().add(v);\n                                                                        }\n                                                                        break;\n                                                                }\n                                                        }\n                                                }\n                                                if (null == invokeConstructor) {\n                                                        err.SyntaxException(\"no suitable super constructor to invoke in \" + sClassDef, sClassDef.line_col());\n                                                        return;\n                                                }\n                                                constructorToFillStatements.statements().add(invokeConstructor);\n\n                                                // put field\n                                                for (SParameter param : constructorToFillStatements.getParameters()) {\n                                                        SFieldDef f = null;\n                                                        for (SFieldDef field : sClassDef.fields()) {\n                                                                if (field.name().equals(param.name())) {\n                                                                        f = field;\n                                                                        break;\n                                                                }\n                                                        }\n                                                        if (f == null) throw new LtBug(\"f should not be null\");\n\n                                                        Ins.PutField putField = new Ins.PutField(f, constructorScope.getThis(),\n                                                                new Ins.TLoad(param, constructorScope, LineCol.SYNTHETIC), LineCol.SYNTHETIC, err);\n                                                        constructorToFillStatements.statements().add(putField);\n                                                }\n\n                                                // a new constructor scope\n                                                // the parameters are ignored and all variables are fields\n                                                constructorScope = new SemanticScope(scope, constructorToFillStatements.meta());\n                                                constructorScope.setThis(new Ins.This(sTypeDef)); // set `this`\n                                                for (SParameter param : constructorToFillStatements.getParameters()) {\n                                                        constructorScope.putLeftValue(constructorScope.generateTempName(), param);\n                                                }\n\n                                                paramValueAvaliable(constructorToFillStatements.getParameters(),\n                                                        constructorToFillStatements.statements(), constructorScope,\n                                                        constructorToFillStatements.line_col());\n\n                                                // parse this constructor\n                                                List<Statement> statements = (\n                                                        astClass == null) ? astObject.statements\n                                                        : astClass.statements;\n                                                for (Statement stmt : statements) {\n                                                        parseStatement(\n                                                                stmt,\n                                                                VoidType.get(),\n                                                                constructorScope,\n                                                                constructorToFillStatements.statements(),\n                                                                constructorToFillStatements.exceptionTables(),\n                                                                null, null,\n                                                                true);\n                                                }\n                                        }\n                                }\n\n                                // parse method\n                                // use traditional for loop because the method list might be modified\n                                int methodSize = sClassDef.methods().size();\n                                List<SMethodDef> methods = sClassDef.methods();\n                                for (int i = 0; i < methodSize; i++) {\n                                        SMethodDef method = methods.get(i);\n                                        parseAnnoValues(method.annos());\n                                        parseMethod(method, methodToStatements.get(method), scope);\n                                }\n\n                                // if not function\n                                if (sClassDef.classType() != SClassDef.FUN) {\n                                        assert (astClass == null && astObject != null) || (astClass != null && astObject == null);\n\n                                        List<Statement> statements = (\n                                                astClass == null) ? astObject.statements\n                                                : astClass.statements;\n                                        // parse static\n                                        SemanticScope staticScope = new SemanticScope(scope, sClassDef.staticMeta());\n\n                                        if (sClassDef.classType() == SClassDef.OBJECT) {\n                                                SFieldDef singletonInstanceField = null;\n                                                for (SFieldDef f : sClassDef.fields()) {\n                                                        if (f.name().equals(CompileUtil.SingletonFieldName)) {\n                                                                singletonInstanceField = f;\n                                                                break;\n                                                        }\n                                                }\n                                                if (singletonInstanceField == null)\n                                                        throw new LtBug(\"object class should have field \" + CompileUtil.SingletonFieldName);\n                                                Ins.New aNew = new Ins.New(\n                                                        sClassDef.constructors().get(0), LineCol.SYNTHETIC\n                                                );\n                                                Ins.PutStatic ps = new Ins.PutStatic(singletonInstanceField,\n                                                        aNew, LineCol.SYNTHETIC, err);\n                                                sClassDef.staticStatements().add(ps);\n                                        }\n\n                                        for (Statement statement : statements) {\n                                                if (statement instanceof AST.StaticScope) {\n                                                        AST.StaticScope sta = (AST.StaticScope) statement;\n                                                        for (Statement stmt : sta.statements) {\n                                                                parseStatement(\n                                                                        stmt,\n                                                                        VoidType.get(),\n                                                                        staticScope,\n                                                                        sClassDef.staticStatements(),\n                                                                        sClassDef.staticExceptionTable(),\n                                                                        null, null,\n                                                                        true);\n                                                        }\n                                                }\n                                        }\n                                }\n                        } else if (sTypeDef instanceof SInterfaceDef) {\n                                SInterfaceDef sInterfaceDef = (SInterfaceDef) sTypeDef;\n                                ASTGHolder<InterfaceDef> holder = originalInterfaces.get(sInterfaceDef.fullName());\n                                InterfaceDef astInterface = holder.s;\n\n                                parseAnnoValues(sInterfaceDef.annos());\n\n                                SemanticScope scope = new SemanticScope(sInterfaceDef, null);\n\n                                // parse method\n                                // use traditional for loop because the method list might be modified\n                                int methodSize = sInterfaceDef.methods().size();\n                                List<SMethodDef> methods = sInterfaceDef.methods();\n                                for (int i = 0; i < methodSize; ++i) {\n                                        SMethodDef method = methods.get(i);\n                                        parseMethod(method, methodToStatements.get(method), scope);\n                                }\n\n                                // parse static\n                                SemanticScope staticScope = new SemanticScope(scope, sInterfaceDef.staticMeta());\n                                for (Statement statement : astInterface.statements) {\n                                        if (statement instanceof AST.StaticScope) {\n                                                for (Statement statementInStatic : ((AST.StaticScope) statement).statements) {\n                                                        parseStatement(\n                                                                statementInStatic,\n                                                                VoidType.get(),\n                                                                staticScope,\n                                                                sInterfaceDef.staticStatements(),\n                                                                sInterfaceDef.staticExceptionTable(),\n                                                                null, null,\n                                                                true);\n                                                }\n                                        } else {\n                                                parseStatement(\n                                                        statement,\n                                                        VoidType.get(),\n                                                        staticScope,\n                                                        sInterfaceDef.staticStatements(),\n                                                        sInterfaceDef.staticExceptionTable(),\n                                                        null, null,\n                                                        true);\n                                        }\n                                }\n                        } else if (!(sTypeDef instanceof SAnnoDef)) {\n                                throw new LtBug(\"wrong STypeDefType \" + sTypeDef.getClass());\n                        }\n                }\n        }\n\n        private void generateGenericTemplateClass(STypeDef sTypeDef) throws SyntaxException {\n                Definition defi;\n                if (sTypeDef instanceof SClassDef) {\n                        switch (((SClassDef) sTypeDef).classType()) {\n                                case SClassDef.NORMAL:\n                                        defi = originalClasses.get(sTypeDef.fullName()).s;\n                                        break;\n                                case SClassDef.OBJECT:\n                                        defi = originalObjects.get(sTypeDef.fullName()).s;\n                                        break;\n                                case SClassDef.FUN:\n                                        defi = originalFunctions.get(sTypeDef.fullName()).s;\n                                        break;\n                                default:\n                                        throw new LtBug(\"unknown class type: \" + ((SClassDef) sTypeDef).classType());\n                        }\n                } else if (sTypeDef instanceof SInterfaceDef) {\n                        defi = originalInterfaces.get(sTypeDef.fullName()).s;\n                } else if (sTypeDef instanceof SAnnoDef) {\n                        defi = originalInterfaces.get(sTypeDef.fullName()).s;\n                } else {\n                        throw new LtBug(\"unknown sTypeDef \" + sTypeDef);\n                }\n                String str = serializeObjectToString(defi);\n\n                // class\n                SClassDef c = new SClassDef(SClassDef.NORMAL, LineCol.SYNTHETIC);\n                c.setFullName(sTypeDef.fullName());\n                c.modifiers().add(SModifier.PUBLIC);\n                // field\n                SFieldDef f = new SFieldDef(LineCol.SYNTHETIC);\n                f.setName(Consts.AST_FIELD);\n                f.setType(getTypeWithName(\"java.lang.String\", LineCol.SYNTHETIC));\n                f.modifiers().add(SModifier.PUBLIC);\n                f.modifiers().add(SModifier.STATIC);\n                c.fields().add(f);\n                f.setDeclaringType(c);\n                c.staticStatements().add(new Ins.PutStatic(f, new StringConstantValue(str), LineCol.SYNTHETIC, err));\n                f.alreadyAssigned();\n                // anno\n                SAnnoDef aDef = (SAnnoDef) getTypeWithName(GenericTemplate.class.getName(), LineCol.SYNTHETIC);\n                SAnno a = new SAnno();\n                a.setAnnoDef(aDef);\n                c.annos().add(a);\n                a.setPresent(c);\n\n                typeDefSet.add(c);\n        }\n\n        /**\n         * check whether overrides all methods from super\n         *\n         * @param sTypeDef sTypeDef\n         * @throws SyntaxException exception\n         */\n        public void checkOverrideAllMethods(STypeDef sTypeDef) throws SyntaxException {\n                checkOverride(sTypeDef);\n\n                // check whether overrides all methods from super\n                if (sTypeDef instanceof SClassDef) {\n                        SClassDef c = (SClassDef) sTypeDef;\n                        if (c.modifiers().contains(SModifier.ABSTRACT)) return;\n\n                        // check all abstract methods\n                        // record them\n                        List<SMethodDef> abstractMethods = new ArrayList<SMethodDef>();\n                        recordAbstractMethodsForOverrideCheck(c, abstractMethods);\n\n                        // do check\n                        for (SMethodDef m : abstractMethods) {\n                                boolean found = false;\n                                for (SMethodDef overridden : m.overridden()) {\n                                        if (overridden.declaringType().equals(c)) {\n                                                found = true;\n                                                break;\n                                        }\n                                }\n                                if (!found) {\n                                        err.SyntaxException(m + \" is not overridden in \" + c, c.line_col());\n                                        return;\n                                }\n                        }\n                }\n        }\n\n        /**\n         * fill statements into default param invokable.\n         *\n         * @param invokable the invokable to fill\n         * @param scope     the invokable scope\n         * @throws SyntaxException exception\n         */\n        public void fillDefaultParamMethod(SInvokable invokable, SemanticScope scope) throws SyntaxException {\n                Map<SInvokable, Expression> invokePair = defaultParamInvokable.get(invokable);\n                SInvokable methodToInvoke = invokePair.keySet().iterator().next();\n                Expression arg = invokePair.get(methodToInvoke);\n                if (invokable instanceof SConstructorDef) {\n                        // invoke another constructor\n                        Ins.InvokeSpecial invoke = new Ins.InvokeSpecial(scope.getThis(), methodToInvoke, LineCol.SYNTHETIC);\n                        for (SParameter p : invokable.getParameters()) {\n                                invoke.arguments().add(new Ins.TLoad(p, scope, LineCol.SYNTHETIC));\n                        }\n                        List<SParameter> paramsOfLast = methodToInvoke.getParameters();\n                        invoke.arguments().add(parseValueFromExpression(arg, paramsOfLast.get(paramsOfLast.size() - 1).type(),\n                                scope));\n\n                        invokable.statements().add(invoke);\n                } else {\n                        assert invokable instanceof SMethodDef;\n                        SMethodDef methodDef = (SMethodDef) invokable;\n                        SMethodDef lastMethod = (SMethodDef) methodToInvoke;\n                        boolean isStatic = lastMethod.modifiers().contains(SModifier.STATIC);\n\n                        Ins.Invoke invoke;\n                        if (lastMethod.modifiers().contains(SModifier.PRIVATE)) {\n                                invoke = new Ins.InvokeSpecial(new Ins.This(methodDef.declaringType()), lastMethod, LineCol.SYNTHETIC);\n                        } else if (isStatic) {\n                                invoke = new Ins.InvokeStatic(lastMethod, LineCol.SYNTHETIC);\n                        } else {\n                                invoke = new Ins.InvokeVirtual(new Ins.This(methodDef.declaringType()), lastMethod, LineCol.SYNTHETIC);\n                        }\n                        for (int ii = 0; ii < methodDef.getParameters().size(); ++ii) {\n                                // load arguments\n                                invoke.arguments().add(new Ins.TLoad(methodDef.getParameters().get(ii), scope, LineCol.SYNTHETIC));\n                        }\n                        List<SParameter> lastParams = lastMethod.getParameters();\n                        invoke.arguments().add(parseValueFromExpression(arg, lastParams.get(lastParams.size() - 1).type(), null));\n                        if (methodDef.getReturnType().equals(VoidType.get())) {\n                                methodDef.statements().add(invoke);\n                        } else {\n                                methodDef.statements().add(new Ins.TReturn(invoke, LineCol.SYNTHETIC));\n                        }\n                }\n        }\n\n        /**\n         * override {@link Object#toString()} {@link Object#hashCode()} {@link Object#equals(Object)}\n         * and generate g/setters for the data class\n         * and generate unapply\n         *\n         * @param cls the class should be data class\n         * @throws SyntaxException compiling error\n         */\n        public void fillMethodsIntoDataClass(SClassDef cls) throws SyntaxException {\n                // check parameter modifiers\n                // cannot be `val`\n                for (SParameter p : cls.constructors().get(0).getParameters()) {\n                        if (!p.canChange()) {\n                                err.SyntaxException(\"data class cannot have `val` parameters\", cls.line_col());\n                                return;\n                        }\n                }\n\n                // implement Cloneable and Serializable\n                cls.superInterfaces().add((SInterfaceDef) getTypeWithName(Cloneable.class.getName(), LineCol.SYNTHETIC));\n                cls.superInterfaces().add((SInterfaceDef) getTypeWithName(Serializable.class.getName(), LineCol.SYNTHETIC));\n                // add clone()=super.clone()\n                SMethodDef methodClone = new SMethodDef(LineCol.SYNTHETIC);\n                methodClone.setName(\"clone\");\n                methodClone.setDeclaringType(cls);\n                cls.methods().add(methodClone);\n                methodClone.setReturnType(getObject_Class());\n                methodClone.modifiers().add(SModifier.PUBLIC);\n                SMethodDef Object_clone = null;\n                for (SMethodDef m : getObject_Class().methods()) {\n                        if (m.name().equals(\"clone\")) {\n                                Object_clone = m;\n                                break;\n                        }\n                }\n                assert Object_clone != null;\n                Ins.InvokeSpecial invokeObjectClone = new Ins.InvokeSpecial(new Ins.This(cls), Object_clone, LineCol.SYNTHETIC);\n                methodClone.statements().add(new Ins.TReturn(invokeObjectClone, LineCol.SYNTHETIC));\n\n                Map<SFieldDef, SMethodDef> setters = new HashMap<SFieldDef, SMethodDef>();\n                Map<SFieldDef, SMethodDef> getters = new HashMap<SFieldDef, SMethodDef>();\n                SMethodDef toStringOverride = null;\n                SMethodDef equalsOverride = null;\n                SMethodDef hashCodeOverride = null;\n                SMethodDef unapply = null;\n                SConstructorDef zeroParamCons = null;\n\n                // get existing setters\n                for (SFieldDef f : cls.fields()) {\n                        if (f.modifiers().contains(SModifier.STATIC)) continue;\n                        String name = f.name();\n                        String setterName = \"set\" + name.substring(0, 1).toUpperCase() + name.substring(1);\n                        String getterName = \"get\" + name.substring(0, 1).toUpperCase() + name.substring(1);\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(setterName)\n                                        &&\n                                        m.getParameters().size() == 1\n                                        &&\n                                        m.getParameters().get(0).type().equals(f.type())) {\n                                        setters.put(f, m);\n                                }\n                                if (m.name().equals(getterName)\n                                        &&\n                                        m.getParameters().size() == 0) {\n                                        getters.put(f, m);\n                                }\n                        }\n                }\n\n                // get existing equals(o)/toString()/hashCode()/unapply(?)\n                for (SMethodDef m : cls.methods()) {\n                        if (m.name().equals(\"toString\") && m.getParameters().size() == 0) toStringOverride = m;\n                        if (m.name().equals(\"equals\")\n                                && m.getParameters().size() == 1\n                                && m.getParameters().get(0).type().fullName().equals(\"java.lang.Object\"))\n                                equalsOverride = m;\n                        if (m.name().equals(\"hashCode\") && m.getParameters().size() == 0) hashCodeOverride = m;\n                        if (m.name().equals(\"unapply\") && m.getParameters().size() == 1\n                                && m.getParameters().get(0).type().isAssignableFrom(cls)) unapply = m;\n                }\n\n                // get existing zero param constructor\n                for (SConstructorDef con : cls.constructors()) {\n                        if (con.getParameters().isEmpty()) {\n                                zeroParamCons = con;\n                                break;\n                        }\n                }\n\n                SemanticScope scope = new SemanticScope(cls, null);\n                scope.setThis(new Ins.This(cls));\n\n                String className = cls.fullName();\n                String simpleName = className.contains(\".\") ? className.substring(className.lastIndexOf(\".\") + 1) : className;\n\n                LineCol lineCol = new LineCol(cls.line_col().fileName, 0, 0);\n\n                if (toStringOverride == null) {\n                        // toString():String\n                        //     return \"SimpleName(\"+\n                        //     \"field=\"+field+\n                        //     \", field2=\"+field2+\n                        //     ...+\n                        //     \")\"\n                        toStringOverride = new SMethodDef(lineCol);\n                        toStringOverride.setName(\"toString\");\n                        toStringOverride.setDeclaringType(cls);\n                        cls.methods().add(toStringOverride);\n                        toStringOverride.setReturnType(getTypeWithName(\"java.lang.String\", lineCol));\n                        toStringOverride.modifiers().add(SModifier.PUBLIC);\n\n                        // SimpleName(\n                        Expression lastExp = new StringLiteral(\"\\\"\" + simpleName + \"(\\\"\", lineCol);\n                        // fields\n                        boolean isFirst = true;\n                        for (SFieldDef f : cls.fields()) {\n                                if (f.modifiers().contains(SModifier.STATIC)) continue;\n                                String literal = \"\";\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        literal = \", \";\n                                }\n                                literal += (f.name() + \"=\");\n\n                                StringLiteral s = new StringLiteral(\"\\\"\" + literal + \"\\\"\", lineCol);\n                                lastExp = new TwoVariableOperation(\n                                        \"+\", lastExp, s, lineCol\n                                );\n                                lastExp = new TwoVariableOperation(\n                                        \"+\", lastExp, new AST.Access(\n                                        new AST.Access(null, \"this\", lineCol),\n                                        f.name(), lineCol),\n                                        lineCol\n                                );\n                        }\n                        // )\n                        StringLiteral s2 = new StringLiteral(\"\\\")\\\"\", lineCol);\n                        lastExp = new TwoVariableOperation(\n                                \"+\", lastExp, s2, lineCol\n                        );\n\n\n                        Statement stmt = new AST.Return(lastExp, lineCol);\n\n                        parseStatement(stmt, toStringOverride.getReturnType(),\n                                new SemanticScope(scope, toStringOverride.meta()),\n                                toStringOverride.statements(), toStringOverride.exceptionTables(),\n                                null, null, false);\n                }\n\n                if (hashCodeOverride == null) {\n                        // hashCode():int\n                        //     return field1 as int +\n                        //     field2 as int +\n                        //     ...\n                        hashCodeOverride = new SMethodDef(lineCol);\n                        hashCodeOverride.setName(\"hashCode\");\n                        hashCodeOverride.setDeclaringType(cls);\n                        cls.methods().add(hashCodeOverride);\n                        hashCodeOverride.setReturnType(IntTypeDef.get());\n                        hashCodeOverride.modifiers().add(SModifier.PUBLIC);\n\n                        Expression lastExp;\n                        if (cls.fields().isEmpty()) {\n                                lastExp = new NumberLiteral(\"0\", lineCol);\n                        } else {\n                                Iterator<SFieldDef> it = cls.fields().iterator();\n                                // LtRuntime.getHashCode(this.field)\n                                lastExp = null;\n                                while (it.hasNext()) {\n                                        SFieldDef f = it.next();\n                                        if (f.modifiers().contains(SModifier.STATIC)) continue;\n\n                                        Expression exp = new AST.Invocation(\n                                                new AST.Access(\n                                                        new AST.Access(\n                                                                new AST.PackageRef(\"lt::runtime\", lineCol),\n                                                                \"LtRuntime\",\n                                                                lineCol\n                                                        ),\n                                                        \"getHashCode\",\n                                                        lineCol\n                                                ),\n                                                Collections.<Expression>singletonList(\n                                                        new AST.Access(\n                                                                new AST.Access(\n                                                                        null, \"this\", lineCol\n                                                                ),\n                                                                f.name(),\n                                                                lineCol\n                                                        )\n                                                ),\n                                                false,\n                                                lineCol\n                                        );\n\n                                        if (lastExp == null) {\n                                                lastExp = exp;\n                                        } else {\n                                                lastExp =\n                                                        new TwoVariableOperation(\n                                                                \"+\",\n                                                                lastExp,\n                                                                exp, lineCol\n                                                        );\n                                        }\n                                }\n                        }\n\n                        if (lastExp == null) {\n                                lastExp = new NumberLiteral(\"0\", lineCol);\n                        }\n\n                        Statement stmt = new AST.Return(lastExp, lineCol);\n\n                        parseStatement(stmt, hashCodeOverride.getReturnType(),\n                                new SemanticScope(scope, hashCodeOverride.meta()),\n                                hashCodeOverride.statements(), hashCodeOverride.exceptionTables(),\n                                null, null, false);\n                }\n\n                if (equalsOverride == null) {\n                        // equals(o):bool\n                        //     return o is type CurrentType and\n                        //     o.field1 is this.field1 and\n                        //     o.field2 is this.field2\n                        //     ...\n                        equalsOverride = new SMethodDef(lineCol);\n                        equalsOverride.setName(\"equals\");\n                        equalsOverride.setDeclaringType(cls);\n                        cls.methods().add(equalsOverride);\n                        equalsOverride.setReturnType(BoolTypeDef.get());\n                        SParameter o = new SParameter();\n                        o.setTarget(equalsOverride);\n                        equalsOverride.getParameters().add(o);\n                        o.setName(\"o\");\n                        o.setType(getTypeWithName(\"java.lang.Object\", lineCol));\n                        equalsOverride.modifiers().add(SModifier.PUBLIC);\n\n                        // o is type CurrentType\n                        Expression lastExp = new TwoVariableOperation(\n                                \"is\",\n                                new AST.Access(null, \"o\", lineCol),\n                                new AST.TypeOf(\n                                        new AST.Access(null, simpleName, lineCol),\n                                        lineCol\n                                ),\n                                lineCol\n                        );\n                        for (SFieldDef f : cls.fields()) {\n                                if (f.modifiers().contains(SModifier.STATIC)) continue;\n                                lastExp = new TwoVariableOperation(\n                                        \"and\",\n                                        lastExp,\n                                        // o.field is this.field\n                                        new TwoVariableOperation(\n                                                \"is\",\n                                                new AST.Access(\n                                                        new AST.Access(\n                                                                null, \"o\", lineCol\n                                                        ),\n                                                        f.name(),\n                                                        lineCol\n                                                ),\n                                                new AST.Access(\n                                                        new AST.Access(\n                                                                null, \"this\", lineCol\n                                                        ),\n                                                        f.name(),\n                                                        lineCol\n                                                ),\n                                                lineCol\n                                        ),\n                                        lineCol\n                                );\n                        }\n\n                        Statement stmt = new AST.Return(lastExp, lineCol);\n                        SemanticScope equalsScope = new SemanticScope(scope, equalsOverride.meta());\n                        equalsScope.putLeftValue(\"o\", o);\n                        parseStatement(stmt, equalsOverride.getReturnType(),\n                                equalsScope,\n                                equalsOverride.statements(), equalsOverride.exceptionTables(),\n                                null, null, false);\n                }\n                if (zeroParamCons == null) {\n                        zeroParamCons = new SConstructorDef(lineCol);\n                        zeroParamCons.setDeclaringType(cls);\n                        cls.constructors().add(zeroParamCons);\n                        zeroParamCons.modifiers().add(SModifier.PUBLIC);\n\n                        SConstructorDef con = cls.constructors().get(cls.constructors().size() - 2);\n                        List<Value> initValues = new ArrayList<Value>();\n                        for (SParameter p : con.getParameters()) {\n                                if (p.type().equals(IntTypeDef.get())) {\n                                        initValues.add(new IntValue(0));\n                                } else if (p.type().equals(ShortTypeDef.get())) {\n                                        initValues.add(new ShortValue((short) 0));\n                                } else if (p.type().equals(ByteTypeDef.get())) {\n                                        initValues.add(new ByteValue((byte) 0));\n                                } else if (p.type().equals(BoolTypeDef.get())) {\n                                        initValues.add(new BoolValue(false));\n                                } else if (p.type().equals(CharTypeDef.get())) {\n                                        initValues.add(new CharValue((char) 0));\n                                } else if (p.type().equals(LongTypeDef.get())) {\n                                        initValues.add(new LongValue(0));\n                                } else if (p.type().equals(FloatTypeDef.get())) {\n                                        initValues.add(new FloatValue(0));\n                                } else if (p.type().equals(DoubleTypeDef.get())) {\n                                        initValues.add(new DoubleValue(0));\n                                } else {\n                                        initValues.add(NullValue.get());\n                                }\n                        }\n\n                        Ins.InvokeSpecial is = new Ins.InvokeSpecial(\n                                new Ins.This(cls),\n                                con,\n                                LineCol.SYNTHETIC\n                        );\n                        is.arguments().addAll(initValues);\n                        zeroParamCons.statements().add(is);\n\n                        // annotations\n                        for (SAnno anno : con.annos()) {\n                                SAnno newAnno = new SAnno();\n                                newAnno.setAnnoDef(anno.type());\n                                newAnno.setPresent(zeroParamCons);\n                                newAnno.values().putAll(anno.values());\n                                zeroParamCons.annos().add(newAnno);\n                        }\n                }\n                for (SFieldDef f : cls.fields()) {\n                        if (f.modifiers().contains(SModifier.STATIC)) continue;\n                        SMethodDef getter = getters.get(f);\n                        SMethodDef setter = setters.get(f);\n\n                        String name = f.name();\n                        name = name.substring(0, 1).toUpperCase() + name.substring(1);\n\n                        if (getter == null) {\n                                // getField():Type\n                                //     return this.field\n                                getter = new SMethodDef(lineCol);\n                                getter.setName(\"get\" + name);\n                                getter.setDeclaringType(cls);\n                                cls.methods().add(getter);\n                                getter.setReturnType(f.type());\n                                getter.modifiers().add(SModifier.PUBLIC);\n\n                                Statement stmt = new AST.Return(\n                                        new AST.Access(\n                                                new AST.Access(null, \"this\", lineCol),\n                                                f.name(),\n                                                lineCol\n                                        ),\n                                        lineCol\n                                );\n                                parseStatement(stmt, getter.getReturnType(), new SemanticScope(scope, getter.meta()), getter.statements(),\n                                        getter.exceptionTables(), null, null, false);\n                        }\n                        if (setter == null) {\n                                // setField(field:Type)\n                                //     this.field=field\n                                setter = new SMethodDef(lineCol);\n                                setter.setName(\"set\" + name);\n                                setter.setDeclaringType(cls);\n                                cls.methods().add(setter);\n                                setter.setReturnType(VoidType.get());\n                                SParameter p = new SParameter();\n                                p.setName(f.name());\n                                setter.getParameters().add(p);\n                                p.setTarget(setter);\n                                p.setType(f.type());\n                                setter.modifiers().add(SModifier.PUBLIC);\n\n                                SemanticScope setterScope = new SemanticScope(scope, setter.meta());\n                                setterScope.putLeftValue(f.name(), p);\n\n                                Statement stmt = new AST.Assignment(\n                                        new AST.Access(\n                                                new AST.Access(null, \"this\", lineCol),\n                                                f.name(),\n                                                lineCol\n                                        ),\n                                        \"=\",\n                                        new AST.Access(null, f.name(), lineCol),\n                                        lineCol\n                                );\n                                parseStatement(stmt, setter.getReturnType(), setterScope, setter.statements(),\n                                        setter.exceptionTables(), null, null, false);\n                        }\n                }\n                if (unapply == null) {\n                        unapply = new SMethodDef(LineCol.SYNTHETIC);\n                        unapply.setName(\"unapply\");\n                        unapply.setDeclaringType(cls);\n                        unapply.setReturnType(getTypeWithName(\"java.util.List\", LineCol.SYNTHETIC));\n                        unapply.modifiers().add(SModifier.PUBLIC);\n                        unapply.modifiers().add(SModifier.STATIC);\n                        cls.methods().add(unapply);\n\n                        SParameter p = new SParameter();\n                        p.setTarget(unapply);\n                        p.setName(\"o\");\n                        p.setType(cls);\n                        unapply.getParameters().add(p);\n\n                        // static { unapply }\n                        SemanticScope unapplyScope = new SemanticScope(new SemanticScope(cls, null), unapply.meta());\n                        unapplyScope.putLeftValue(\"o\", p);\n\n                        List<Expression> tmpList = new ArrayList<Expression>();\n                        for (SFieldDef f : cls.fields()) {\n                                tmpList.add(new AST.Access(\n                                        // o.f\n                                        new AST.Access(null, \"o\", LineCol.SYNTHETIC),\n                                        f.name(), LineCol.SYNTHETIC\n                                ));\n                        }\n                        AST.Return ret = new AST.Return(\n                                new AST.ArrayExp(tmpList, LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        );\n                        parseStatement(ret, unapply.getReturnType(), unapplyScope, unapply.statements(),\n                                unapply.exceptionTables(), null, null, false);\n                }\n        }\n\n        /**\n         * in step 4<br>\n         * fills the method with instructions\n         *\n         * @param methodDef  the method to be filled with instructions\n         * @param statements statements to be parsed into instructions\n         * @param superScope the class scope\n         * @throws SyntaxException compile error\n         */\n        public void parseMethod(SMethodDef methodDef, List<Statement> statements, SemanticScope superScope) throws SyntaxException {\n                if (!methodDef.statements().isEmpty()) return;\n                if (methodDef.modifiers().contains(SModifier.ABSTRACT)) {\n                        if (!statements.isEmpty()) {\n                                err.SyntaxException(\"abstract method cannot contain statements\", statements.get(0).line_col());\n                                return;\n                        }\n                        return;\n                }\n                if (methodDef.declaringType() instanceof SInterfaceDef) {\n                        if (!statements.isEmpty()) {\n                                err.SyntaxException(\"default methods are not supported in interfaces\", statements.get(0).line_col());\n                                return;\n                        }\n                }\n                if (methodDef.modifiers().contains(SModifier.STATIC) && methodDef.declaringType() instanceof SInterfaceDef) {\n                        err.SyntaxException(\"static methods are not allowed in interfaces\", methodDef.line_col());\n                        return;\n                }\n\n                // fill in return\n                if (!methodDef.getReturnType().equals(VoidType.get())) {\n                        transformLastExpToReturn(statements);\n                }\n\n                SemanticScope scope = new SemanticScope(superScope, methodDef.meta());\n                if (!methodDef.modifiers().contains(SModifier.STATIC)) {\n                        scope.setThis(new Ins.This(scope.type()));\n                }\n                for (SParameter p : methodDef.getParameters()) {\n                        if (p.canChange() && !isPointerType(p.type()) && CompileUtil.isValidName(p.name())) {\n                                scope.putLeftValue(scope.generateTempName(), p);\n                        } else {\n                                scope.putLeftValue(p.name(), p);\n                        }\n                }\n\n                if (defaultParamInvokable.containsKey(methodDef)) {\n                        fillDefaultParamMethod(methodDef, scope);\n                } else {\n                        paramValueAvaliable(methodDef.getParameters(), methodDef.statements(), scope, methodDef.line_col());\n                        for (SParameter p : methodDef.getParameters()) {\n                                if (p.canChange() && !isPointerType(p.type()) && CompileUtil.isValidName(p.name())) {\n                                        // get the value and put into container\n                                        PointerType t = new PointerType(p.type());\n                                        if (types.containsKey(t.toString())) {\n                                                t = (PointerType) types.get(t.toString());\n                                        } else {\n                                                types.put(t.toString(), t);\n                                        }\n\n                                        LocalVariable local = new LocalVariable(t, p.canChange());\n                                        scope.putLeftValue(p.name(), local);\n                                        local.setWrappingParam(p);\n\n                                        // local = new Pointer(p)\n                                        Ins.TStore tStore = new Ins.TStore(\n                                                local, invokePointerSet(\n                                                constructPointer(p.isNotNull(), p.isNotEmpty()),\n                                                new Ins.TLoad(p, scope, LineCol.SYNTHETIC),\n                                                LineCol.SYNTHETIC),\n                                                scope, LineCol.SYNTHETIC, err);\n                                        tStore.flag |= Consts.IS_POINTER_NEW;\n                                        methodDef.statements().add(tStore);\n                                }\n                        }\n                        // fill statements\n                        if (statements.isEmpty()) {\n                                methodDef.statements().add(new Ins.Nop());\n                        } else {\n                                for (Statement stmt : statements) {\n                                        parseStatement(\n                                                stmt,\n                                                methodDef.getReturnType(),\n                                                scope,\n                                                methodDef.statements(),\n                                                methodDef.exceptionTables(),\n                                                null, null,\n                                                false);\n                                }\n                        }\n                }\n        }\n\n        private SConstructorDef java_lang_NullPointerException_cons;\n\n        private SConstructorDef getJava_lang_NullPointerException_cons() throws SyntaxException {\n                if (java_lang_NullPointerException_cons == null) {\n                        SClassDef NPE = (SClassDef) getTypeWithName(\"java.lang.NullPointerException\", LineCol.SYNTHETIC);\n                        for (SConstructorDef cons : NPE.constructors()) {\n                                if (cons.getParameters().isEmpty()) {\n                                        java_lang_NullPointerException_cons = cons;\n                                        break;\n                                }\n                        }\n                }\n                return java_lang_NullPointerException_cons;\n        }\n\n        private SConstructorDef java_lang_IllegalArgumentException_cons;\n\n        private SConstructorDef getJava_lang_IllegalArgumentException_cons() throws SyntaxException {\n                if (java_lang_IllegalArgumentException_cons == null) {\n                        SClassDef IAE = (SClassDef) getTypeWithName(\"java.lang.IllegalArgumentException\", LineCol.SYNTHETIC);\n                        for (SConstructorDef cons : IAE.constructors()) {\n                                if (cons.getParameters().isEmpty()) {\n                                        java_lang_IllegalArgumentException_cons = cons;\n                                        break;\n                                }\n                        }\n                }\n                return java_lang_IllegalArgumentException_cons;\n        }\n\n        /**\n         * handle nonnull/nonempty modifiers on parameters\n         *\n         * @param params       parameters\n         * @param instructions instructions\n         * @param scope        current scope\n         * @param lineCol      line and column\n         * @throws SyntaxException compiling error\n         */\n        public void paramValueAvaliable(List<SParameter> params, List<Instruction> instructions, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                for (SParameter param : params) {\n                        if (param.isNotEmpty()) {\n                                Ins.Nop nop = new Ins.Nop();\n                                Ins.IfNe ifNe = new Ins.IfNe(\n                                        cast(BoolTypeDef.get(), new Ins.TLoad(param, scope, lineCol), scope.type(), lineCol),\n                                        nop, lineCol);\n                                instructions.add(ifNe);\n                                instructions.add(new Ins.AThrow(\n                                        new Ins.New(\n                                                getJava_lang_IllegalArgumentException_cons(), lineCol\n                                        ), lineCol));\n                                instructions.add(nop);\n                        } else if (param.isNotNull()) {\n                                if (param.type() instanceof PrimitiveTypeDef) {\n                                        continue;\n                                }\n                                // null\n                                Ins.Nop nop = new Ins.Nop();\n                                Ins.IfNonNull ifNonNull = new Ins.IfNonNull(\n                                        new Ins.TLoad(param, scope, lineCol),\n                                        nop, lineCol);\n                                instructions.add(ifNonNull);\n                                instructions.add(new Ins.AThrow(\n                                        new Ins.New(\n                                                getJava_lang_NullPointerException_cons(), lineCol\n                                        ), lineCol));\n                                instructions.add(nop);\n                                // unit\n                                Ins.Nop nop2 = new Ins.Nop();\n                                Ins.IfACmpNe ifACmpNe = new Ins.IfACmpNe(\n                                        new Ins.TLoad(param, scope, lineCol),\n                                        invoke_Unit_get(lineCol),\n                                        nop2, lineCol\n                                );\n                                instructions.add(ifACmpNe);\n                                instructions.add(new Ins.AThrow(\n                                        new Ins.New(\n                                                getJava_lang_IllegalArgumentException_cons(), lineCol\n                                        ), lineCol));\n                                instructions.add(nop2);\n                        }\n                }\n        }\n\n        private void transformLastExpToReturn(List<Statement> statements) {\n                if (statements.isEmpty()) return;\n                int lastIndex = statements.size() - 1;\n                Statement lastStmt = statements.get(lastIndex);\n                if (lastStmt instanceof Expression) {\n                        AST.Return ret = new AST.Return((Expression) lastStmt, lastStmt.line_col());\n                        statements.set(lastIndex, ret);\n                } else if (lastStmt instanceof AST.If) {\n                        for (AST.If.IfPair pair : ((AST.If) lastStmt).ifs) {\n                                transformLastExpToReturn(pair.body);\n                        }\n                } else if (lastStmt instanceof AST.Synchronized) {\n                        transformLastExpToReturn(((AST.Synchronized) lastStmt).statements);\n                } else if (lastStmt instanceof AST.Try) {\n                        AST.Try aTry = (AST.Try) lastStmt;\n                        transformLastExpToReturn(aTry.statements);\n                        transformLastExpToReturn(aTry.catchStatements);\n                }\n        }\n\n        /**\n         * in step 4<br>\n         * fill the given annotation with parsed values\n         *\n         * @param annos annotations to fill values\n         * @throws SyntaxException exception\n         */\n        public void parseAnnoValues(Collection<SAnno> annos) throws SyntaxException {\n                // check annotation\n                for (SAnno sAnno : annos) {\n                        AST.Anno anno = annotationRecorder.get(sAnno); // get original anno object\n                        Map<SAnnoField, Value> map = new HashMap<SAnnoField, Value>();\n                        out:\n                        for (SAnnoField f : sAnno.type().annoFields()) {\n                                if (anno == null) {\n                                        for (Map.Entry<String, Object> entry : sAnno.alreadyCompiledAnnotationValueMap().entrySet()) {\n                                                if (entry.getKey().equals(f.name())) {\n                                                        // find annotation field\n                                                        Value v = parseValueFromObject(entry.getValue());\n                                                        map.put(f, v);\n                                                        continue out;\n                                                }\n                                        }\n                                } else {\n                                        for (AST.Assignment a : anno.args) {\n                                                if (a.assignTo.name.equals(f.name())) {\n                                                        // find annotation field\n                                                        Value v = parseValueFromExpression(a.assignFrom, f.type(), null);\n                                                        v = checkAndCastAnnotationValues(v, a.assignTo.line_col());\n                                                        map.put(f, v);\n                                                        continue out;\n                                                }\n                                        }\n                                }\n                                // not found, check defaultValue\n                                if (!f.hasDefaultValue()) {\n                                        err.SyntaxException(f.name() + \" is missing\",\n                                                anno == null ? LineCol.SYNTHETIC : anno.line_col());\n                                        return;\n                                }\n                        }\n                        sAnno.values().putAll(map);\n                }\n        }\n\n        /**\n         * check and cast annotation values\n         *\n         * @param value   value\n         * @param lineCol line column\n         * @return the cast value\n         * @throws SyntaxException compiling error\n         */\n        public Value checkAndCastAnnotationValues(Value value, LineCol lineCol) throws SyntaxException {\n                if (value instanceof IntValue\n                        || value instanceof ShortValue\n                        || value instanceof ByteValue\n                        || value instanceof CharValue\n                        || value instanceof BoolValue\n                        || value instanceof LongValue\n                        || value instanceof DoubleValue\n                        || value instanceof FloatValue\n                        || value instanceof SArrayValue\n                        || value instanceof StringConstantValue\n                        || value instanceof SAnno\n                        || value instanceof Ins.GetClass\n                        || value instanceof EnumValue) {\n                        return value;\n                } else if (value instanceof Ins.GetStatic) {\n                        Ins.GetStatic gs = (Ins.GetStatic) value;\n                        EnumValue enumValue = new EnumValue();\n                        enumValue.setType(gs.field().declaringType());\n                        enumValue.setEnumStr(gs.field().name());\n                        return enumValue;\n                } else if (value instanceof Ins.NewArray || value instanceof Ins.ANewArray) {\n                        List<Value> theValues =\n                                value instanceof Ins.NewArray\n                                        ? ((Ins.NewArray) value).initValues()\n                                        : ((Ins.ANewArray) value).initValues();\n\n                        SArrayValue arr = new SArrayValue();\n                        arr.setDimension(1);\n                        arr.setType((SArrayTypeDef) value.type());\n\n                        List<Value> values = new ArrayList<Value>();\n                        for (Value v : theValues) {\n                                values.add(checkAndCastAnnotationValues(v, lineCol));\n                        }\n\n                        arr.setValues(values.toArray(new Value[values.size()]));\n                        return arr;\n                } else if (value instanceof DummyValue) {\n                        return value;\n                } else {\n                        err.SyntaxException(\"invalid annotation field \" + value, lineCol);\n                        return null;\n                }\n        }\n\n        /**\n         * check whether the literal is int type<br>\n         * also, the requiredType should be int or superclass or Integer or null\n         *\n         * @param requiredType required type(should be int or superclass of Integer)\n         *                     or null\n         * @param literal      int literal\n         * @param lineCol      file_line_col\n         * @return true if it's int(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isInt(STypeDef requiredType, NumberLiteral literal, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof IntTypeDef ||\n                        (requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Integer\", lineCol))\n                        )) &&\n                        // &&\n                        !literal.literal().contains(\".\");\n        }\n\n        /**\n         * check whether the literal is long type\n         *\n         * @param requiredType required type(should be long or superclass of Long)\n         *                     or null\n         * @param literal      long literal\n         * @param lineCol      file_line_col\n         * @return true if it's long(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isLong(STypeDef requiredType, NumberLiteral literal, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof LongTypeDef ||\n                        (requiredType instanceof SClassDef) && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Long\", lineCol)\n                        )) &&\n                        // &&\n                        !literal.literal().contains(\".\");\n        }\n\n        /**\n         * check whether the literal is short type\n         *\n         * @param requiredType required type(should be short or superclass of Short)\n         *                     or null\n         * @param literal      short literal\n         * @param lineCol      file_line_col\n         * @return true if it's short(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isShort(STypeDef requiredType, NumberLiteral literal, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof ShortTypeDef ||\n                        requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Short\", lineCol)\n                        )) &&\n                        // &&\n                        !literal.literal().contains(\".\");\n        }\n\n        /**\n         * check whether the literal is byte type\n         *\n         * @param requiredType required type(should be byte or superclass of Byte)\n         *                     or null\n         * @param literal      byte literal\n         * @param lineCol      file_line_col\n         * @return true if it's byte(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isByte(STypeDef requiredType, NumberLiteral literal, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof ByteTypeDef ||\n                        requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Byte\", lineCol)\n                        )) &&\n                        // &&\n                        !literal.literal().contains(\".\");\n        }\n\n        /**\n         * check whether the required type is float type<br>\n         * number literal always will match float value\n         *\n         * @param requiredType required type(should be float or superclass of Float)\n         *                     or null\n         * @param lineCol      file_line_col\n         * @return true if it's float(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isFloat(STypeDef requiredType, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof FloatTypeDef ||\n                        requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Float\", lineCol)\n                        ));\n        }\n\n        /**\n         * check whether the required type is double type<br>\n         * number literal always will match double value\n         *\n         * @param requiredType required type(should be double or superclass of Double)\n         *                     or null\n         * @param lineCol      file_line_col\n         * @return true if it's double(boxed or primitive)\n         * @throws SyntaxException exception\n         */\n        public boolean isDouble(STypeDef requiredType, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof DoubleTypeDef ||\n                        requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Double\", lineCol)\n                        ));\n        }\n\n        /**\n         * check whetehr the required type is bool type\n         *\n         * @param requiredType required type(should be boolean or superclass of Boolean)\n         *                     or null\n         * @param lineCol      file_line_col\n         * @return true if it's boolean(boxed or primitve)\n         * @throws SyntaxException exception\n         */\n        public boolean isBool(STypeDef requiredType, LineCol lineCol) throws SyntaxException {\n                return (requiredType == null ||\n                        requiredType instanceof BoolTypeDef ||\n                        requiredType instanceof SClassDef && requiredType.isAssignableFrom(\n                                getTypeWithName(\"java.lang.Boolean\", lineCol)\n                        ));\n        }\n\n        /**\n         * check whether the literal is char type<br>\n         * the literal should be string literal with only one character and required type should match char or Character<br>\n         * if the requiredType is Character or char, the literal can be surrounded with either \\\" or \\'.<br>\n         * if the requiredType is not Character but assignable from Character and not assignable from String, the literal can be surrounded with either \\\" or \\'<br>\n         * if the requiredType is assignable from both Character and String, the literal should be surrounded with \\' and length should == 1\n         *\n         * @param requiredType required type\n         * @param literal      literal\n         * @param lineCol      file_line_col\n         * @return true if it's char\n         * @throws SyntaxException exception\n         */\n        public boolean isChar(STypeDef requiredType, StringLiteral literal, LineCol lineCol) throws SyntaxException {\n                if (requiredType == null)\n                        return isChar(literal, lineCol, true);\n                if (requiredType instanceof CharTypeDef)\n                        return isChar(literal, lineCol, false);\n                if (requiredType instanceof SClassDef) {\n                        SClassDef characterClass = (SClassDef) getTypeWithName(\"java.lang.Character\", lineCol);\n                        if (requiredType.equals(characterClass)) return true; // Character\n                        if (requiredType.isAssignableFrom(characterClass)) {\n                                SClassDef stringClass = (SClassDef) getTypeWithName(\"java.lang.String\", lineCol);\n                                if (requiredType.isAssignableFrom(stringClass)) {\n                                        // assignable from Character and String\n                                        // check start with \\' and length == 1\n                                        return isChar(literal, lineCol, true);\n                                } else // assignable from only Character\n                                        return isChar(literal, lineCol, false);\n                        }\n                }\n                return false;\n        }\n\n        /**\n         * check whether the literal is char<br>\n         * the method only checks literal start symbol and it's length\n         *\n         * @param literal    literal\n         * @param lineCol    file_line_col\n         * @param testSymbol true if the symbol is taken into consideration\n         * @return true if the literal is char\n         * @throws SyntaxException exception\n         */\n        public boolean isChar(StringLiteral literal, LineCol lineCol, boolean testSymbol) throws SyntaxException {\n                String str = literal.literal();\n                str = str.substring(1);\n                str = str.substring(0, str.length() - 1);\n                // testSymbol==true and not start with \\' then return false\n                if (testSymbol && !literal.literal().startsWith(\"\\'\")) return false;\n                // check whether the string length is 1\n                String s = unescape(str, lineCol);\n                assert s != null;\n                return s.length() == 1;\n        }\n\n        private SClassDef Throwable_Class;\n\n        public SClassDef getThrowable_Class() throws SyntaxException {\n                if (Throwable_Class == null) {\n                        Throwable_Class = (SClassDef) getTypeWithName(\"java.lang.Throwable\", LineCol.SYNTHETIC);\n                }\n                return Throwable_Class;\n        }\n\n        /**\n         * in step 4<br>\n         * parse instructions<br>\n         * <ul>\n         * <li>{@link Statement} =&gt; {@link Instruction}</li>\n         * <li>{@link Expression} =&gt; {@link Value}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Return} =&gt; {@link lt.compiler.semantic.Ins.TReturn}</li>\n         * <li>{@link lt.compiler.syntactic.AST.If} =&gt; a list of Instructions containing {@link lt.compiler.semantic.Ins.IfEq} {@link lt.compiler.semantic.Ins.IfNe} {@link lt.compiler.semantic.Ins.Goto}</li>\n         * <li>{@link lt.compiler.syntactic.AST.While} =&gt; a list of Instructions (same as above)</li>\n         * <li>{@link lt.compiler.syntactic.AST.For} =&gt; a list of Instructions (same as above)</li>\n         * <li>{@link lt.compiler.syntactic.AST.Throw} =&gt; {@link lt.compiler.semantic.Ins.AThrow}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Try} =&gt; a list of Instructions and some ExceptionTable</li>\n         * <li>{@link lt.compiler.syntactic.AST.Synchronized} =&gt; {@link lt.compiler.semantic.Ins.MonitorEnter} and {@link lt.compiler.semantic.Ins.MonitorExit}</li>\n         * <li>{@link MethodDef} =&gt; {@link #parseInnerMethod(MethodDef, SemanticScope, boolean)}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Break =&gt; goto instruction}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Continue =&gt; goto instruction}</li>\n         * </ul>\n         *\n         * @param statement           instructions\n         * @param methodReturnType    the method's return type\n         * @param scope               scope that contains local variables and local methods\n         * @param instructions        currently parsing {@link SInvokable} object instructions\n         * @param exceptionTable      the exception table (start,end,handle,type)\n         * @param breakIns            jump to this position when meets a break    (or null if it's not inside any loop)\n         * @param continueIns         jump to this position when meets a continue (or null if it's not inside any loop)\n         * @param doNotParseMethodDef the methodDef should not be parsed( in this case, they should be outer methods instead of inner methods)\n         * @throws SyntaxException compile error\n         */\n        public void parseStatement(Statement statement,\n                                   STypeDef methodReturnType,\n                                   SemanticScope scope,\n                                   List<Instruction> instructions,\n                                   List<ExceptionTable> exceptionTable,\n                                   Ins.Nop breakIns,\n                                   Ins.Nop continueIns,\n                                   boolean doNotParseMethodDef) throws SyntaxException {\n                if (statement instanceof Expression) {\n                        // expression\n                        // required type is null , which means no required type\n                        Value v = parseValueFromExpression((Expression) statement, null, scope);\n                        if (v instanceof Instruction) {\n                                instructions.add((Instruction) v);\n                        } // else ignore the result\n                } else if (statement instanceof AST.Return) {\n                        parseInstructionFromReturn((AST.Return) statement, methodReturnType, scope, instructions);\n\n                } else if (statement instanceof AST.If) {\n                        parseInstructionFromIf((AST.If) statement, methodReturnType, scope,\n                                instructions, exceptionTable, breakIns, continueIns);\n                } else if (statement instanceof AST.While) {\n                        // while or do while\n                        parseInstructionFromWhile((AST.While) statement, methodReturnType, scope, instructions, exceptionTable);\n                } else if (statement instanceof AST.For) {\n                        // for i in xxx\n                        parseInstructionFromFor((AST.For) statement, methodReturnType, scope, instructions, exceptionTable);\n                } else if (statement instanceof AST.Throw) {\n                        // throw xxx\n                        Value throwable = parseValueFromExpression(\n                                ((AST.Throw) statement).exp,\n                                null,\n                                scope);\n                        assert throwable != null;\n                        if (!getThrowable_Class().isAssignableFrom(throwable.type())) {\n                                // cast to throwable\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(getLang_castToThrowable(), LineCol.SYNTHETIC);\n                                invokeStatic.arguments().add(throwable);\n                                throwable = invokeStatic;\n                        }\n                        Ins.AThrow aThrow = new Ins.AThrow(throwable, statement.line_col());\n                        instructions.add(aThrow);\n                } else if (statement instanceof AST.Try) {\n                        parseInstructionFromTry((AST.Try) statement, methodReturnType, scope, instructions, exceptionTable, breakIns, continueIns);\n                } else if (statement instanceof AST.Synchronized) {\n                        parseInstructionFromSynchronized((AST.Synchronized) statement,\n                                methodReturnType,\n                                scope,\n                                instructions,\n                                exceptionTable,\n                                breakIns, continueIns);\n                } else if (statement instanceof MethodDef) {\n                        if (!doNotParseMethodDef)\n                                parseInnerMethod((MethodDef) statement, scope, false);\n                } else if (statement instanceof AST.Break) {\n                        if (breakIns == null) {\n                                err.SyntaxException(\"break should be inside a loop\", statement.line_col());\n                                return;\n                        }\n                        instructions.add(new Ins.Goto(breakIns));\n                } else if (statement instanceof AST.Continue) {\n                        if (continueIns == null) {\n                                err.SyntaxException(\"continue should be inside a loop\", statement.line_col());\n                                return;\n                        }\n                        instructions.add(new Ins.Goto(continueIns));\n                } else if (!(statement instanceof AST.StaticScope || statement instanceof AST.Pass)) {\n                        throw new LtBug(\"unknown statement \" + statement);\n                }\n        }\n\n        /**\n         * {@link LtRuntime#castToBool(Object)}\n         */\n        private SMethodDef Lang_castToBool;\n\n        /**\n         * @return {@link LtRuntime#castToThrowable(Object)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_castToBool() throws SyntaxException {\n                if (Lang_castToBool == null) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToBool\")) {\n                                        Lang_castToBool = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_castToBool;\n        }\n\n        /**\n         * {@link LtRuntime#castToThrowable(Object)}\n         */\n        private SMethodDef Lang_castToThrowable;\n\n        /**\n         * @return {@link LtRuntime#castToThrowable(Object)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_castToThrowable() throws SyntaxException {\n                if (Lang_castToThrowable == null) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToThrowable\")) {\n                                        Lang_castToThrowable = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_castToThrowable;\n        }\n\n        /**\n         * parse inner method<br>\n         * the inner method name is automatically generated<br>\n         * method parameters would capture all existing local variables. they are positioned ahead of params that the inner method requires<br>\n         * e.g.<br>\n         * <code>\n         * outer()<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;i=1<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;j=2<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;inner(x)=1+i+j+x\n         * </code><br>\n         * the inner method would be parsed into <code>inner$SomeGeneratedName$(i,j,x)</code><br>\n         * when invoking, the captured local variables would be passed in as parameters<br>\n         * both final and not-final variables can be captured, <br>\n         * but the variable inside the inner method would NOT have effect on the outer one\n         *\n         * @param methodDef   method def object, defines the inner method\n         * @param scope       current scope\n         * @param lambdaParam add one param for lambda\n         * @return the new method (the inner method)\n         * @throws SyntaxException compile error\n         */\n        public SMethodDef parseInnerMethod(MethodDef methodDef, SemanticScope scope, boolean lambdaParam) throws SyntaxException {\n                if (scope.parent == null) throw new LtBug(\"scope.parent should not be null\");\n\n                SemanticScope theTopScope = scope.parent;\n                while (theTopScope.parent != null) theTopScope = theTopScope.parent;\n\n                // check method name\n                if (scope.containsInnerMethod(methodDef.name)) {\n                        err.SyntaxException(\"duplicate inner method name\", methodDef.line_col());\n                        return null;\n                }\n\n                // inner method cannot have modifiers or annotations\n                if (!methodDef.modifiers.isEmpty() &&\n                        (methodDef.modifiers.size() != 1 || !methodDef.modifiers.iterator().next().modifier.equals(Modifier.Available.DEF))\n                        ) {\n                        err.SyntaxException(\"inner method cannot have modifiers\", methodDef.line_col());\n                        return null;\n                }\n                if (!methodDef.annos.isEmpty()) {\n                        err.SyntaxException(\"inner method cannot have annotations\", methodDef.line_col());\n                        return null;\n                }\n\n                // check param names, see if it's already used\n                // also, init values are not allowed\n                for (VariableDef v : methodDef.params) {\n                        if (null != scope.getLeftValue(v.getName())) {\n                                err.SyntaxException(v.getName() + \" is already used\", v.line_col());\n                                return null;\n                        }\n                        if (v.getInit() != null) {\n                                err.SyntaxException(\"parameters of inner methods cannot have default value\", v.line_col());\n                                return null;\n                        }\n                }\n\n                // get current type methods\n                List<SMethodDef> methods;\n                if (scope.type() instanceof SClassDef) {\n                        methods = ((SClassDef) scope.type()).methods();\n                } else {\n                        methods = ((SInterfaceDef) scope.type()).methods();\n                }\n\n                // generate method name\n                String generatedMethodName = methodDef.name + \"$Latte$InnerMethod$\";\n                int i = 0;\n                out:\n                while (true) {\n                        String tmpName = generatedMethodName + i;\n                        for (SMethodDef m : methods) {\n                                if (m.name().equals(tmpName)) {\n                                        ++i;\n                                        continue out;\n                                }\n                        }\n                        break;\n                }\n                generatedMethodName += i;\n\n                String name = methodDef.name;\n                int paramCount = methodDef.params.size();\n\n                // fill in local variable as parameters\n                // the params are added to front positions\n                LinkedHashMap<String, STypeDef> localVariables = scope.getLocalVariables();\n                List<VariableDef> param4Locals = new ArrayList<VariableDef>();\n                List<PointerType> realPointerTypes = new ArrayList<PointerType>();\n                for (Map.Entry<String, STypeDef> entry : localVariables.entrySet()) {\n                        String k = entry.getKey();\n                        STypeDef v = entry.getValue();\n                        if (!CompileUtil.isValidName(k)) continue;\n                        if (k.equals(\"$\")) continue;\n\n                        // construct a synthetic VariableDef as param\n                        VariableDef variable = new VariableDef(k, Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                        if (v instanceof SArrayTypeDef) {\n                                STypeDef x = ((SArrayTypeDef) v).type();\n                                AST.Access theType = new AST.Access(\n                                        x.pkg() == null\n                                                ? null\n                                                : new AST.PackageRef(x.pkg(), LineCol.SYNTHETIC),\n                                        x.fullName().contains(\".\")\n                                                ? x.fullName().substring(x.fullName().lastIndexOf('.') + 1)\n                                                : x.fullName(),\n                                        LineCol.SYNTHETIC\n                                );\n                                for (int ii = 0; ii < ((SArrayTypeDef) v).dimension(); ++ii) {\n                                        theType = new AST.Access(theType, \"[]\", LineCol.SYNTHETIC);\n                                }\n                                variable.setType(theType);\n                        } else {\n                                variable.setType(\n                                        new AST.Access(\n                                                v.pkg() == null\n                                                        ? null\n                                                        : new AST.PackageRef(v.pkg(), LineCol.SYNTHETIC),\n                                                v.fullName().contains(\".\")\n                                                        ? v.fullName().substring(v.fullName().lastIndexOf('.') + 1)\n                                                        : v.fullName(),\n                                                LineCol.SYNTHETIC\n                                        )\n                                );\n                                if (v instanceof PointerType) {\n                                        realPointerTypes.add((PointerType) v);\n                                }\n                        }\n                        param4Locals.add(variable);\n                }\n                MethodDef newMethodDef = new MethodDef(\n                        generatedMethodName,\n                        Collections.<Modifier>emptySet(),\n                        methodDef.returnType,\n                        new ArrayList<VariableDef>(methodDef.params),\n                        Collections.<AST.Anno>emptySet(),\n                        methodDef.body,\n                        methodDef.line_col()\n                );\n                newMethodDef.params.addAll(0, param4Locals);\n                if (lambdaParam) {\n                        newMethodDef.params.add(\n                                new VariableDef(\"$\",\n                                        Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC));\n                }\n\n                // parse the method\n                parseMethod(newMethodDef, newMethodDef.params.size(), scope.type(), null, fileNameToImport.get(newMethodDef.line_col().fileName),\n                        (scope.type() instanceof SClassDef) ? PARSING_CLASS : PARSING_INTERFACE, scope.getThis() == null);\n                SMethodDef m = methods.get(methods.size() - 1);\n                // set captured values\n                for (int x = 0; x < param4Locals.size(); ++x) {\n                        m.meta().pointerLocalVar.add(m.getParameters().get(x));\n                }\n\n                // change the modifier\n                m.modifiers().remove(SModifier.PUBLIC);\n                m.modifiers().remove(SModifier.PROTECTED);\n                m.modifiers().add(0, SModifier.PRIVATE);\n\n                // change to real pointer type\n                // and mark capture parameters\n                int cursor = 0;\n                int currentIndex = 0;\n                int capturedParamSize = param4Locals.size();\n                for (SParameter p : m.getParameters()) {\n                        if (isPointerType(p.type())) {\n                                p.setType(realPointerTypes.get(cursor++));\n                        }\n                        if (currentIndex < capturedParamSize) {\n                                p.setCapture(true);\n                        }\n                        ++currentIndex;\n                }\n                assert cursor == realPointerTypes.size();\n\n                // add into scope\n                SemanticScope.MethodRecorder rec = new SemanticScope.MethodRecorder(m, paramCount);\n                scope.addMethodDef(name, rec);\n\n                // generate a scope for the inner method\n                // the scope contains the inner method itself\n                SemanticScope innerMethodScope = new SemanticScope(theTopScope, m.meta());\n                for (Map.Entry<String, SemanticScope.MethodRecorder> srec : scope.getInnerMethods().entrySet()) {\n                        innerMethodScope.addMethodDef(srec.getKey(), srec.getValue());\n                }\n\n                parseMethod(m, newMethodDef.body, innerMethodScope);\n\n                return m;\n        }\n\n        /**\n         * parse synchronized<br>\n         * every monitor must have an exit<br>\n         * <code>\n         * sync(a,b,c)<br>\n         * &nbsp;&nbsp;&nbsp;&nbsp;...<br>\n         * ==&gt;<br>\n         * a<br>\n         * astoreX<br>\n         * monitor enter<br>\n         * b<br>\n         * astoreY<br>\n         * monitor enter<br>\n         * c<br>\n         * astoreZ<br>\n         * monitor enter<br>\n         * ...<br>\n         * astore<br>\n         * Z<br>\n         * monitor exit<br>\n         * Y<br>\n         * monitor exit<br>\n         * X<br>\n         * monitor exit<br>\n         * goto `nop`<br>\n         * [end normally]<br>\n         * --------------------<br>\n         * [end with exception]<br>\n         * Z<br>\n         * monitor exit<br>\n         * Y<br>\n         * monitor exit<br>\n         * X<br>\n         * monitor exit<br>\n         * athrow<br>\n         * nop\n         * </code><br>\n         * and every position of return should insert after monitor exit instructions\n         *\n         * @param aSynchronized    synchronized object\n         * @param methodReturnType method return type\n         * @param scope            current scope\n         * @param instructions     instructions\n         * @param exceptionTable   exception table\n         * @param breakIns         jump to this position when meets a break\n         * @param continueIns      jump to this position when meets a continue\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromSynchronized(AST.Synchronized aSynchronized,\n                                                     STypeDef methodReturnType,\n                                                     SemanticScope scope,\n                                                     List<Instruction> instructions,\n                                                     List<ExceptionTable> exceptionTable,\n                                                     Ins.Nop breakIns,\n                                                     Ins.Nop continueIns) throws SyntaxException {\n\n                SemanticScope subScope = new SemanticScope(scope, scope.getMeta());\n                Stack<Ins.MonitorEnter> stack = new Stack<Ins.MonitorEnter>();\n                for (Expression exp : aSynchronized.toSync) {\n                        Value v = parseValueFromExpression(exp, null, subScope);\n                        Ins.MonitorEnter enter = new Ins.MonitorEnter(v, subScope, exp.line_col());\n                        stack.push(enter);\n\n                        instructions.add(enter); // monitor enter\n                }\n\n                // parse statements\n                List<Instruction> instructionList = new ArrayList<Instruction>();\n                for (Statement stmt : aSynchronized.statements) {\n                        parseStatement(stmt, methodReturnType, subScope, instructionList, exceptionTable, breakIns, continueIns, false);\n                }\n                if (instructionList.size() == 0) instructionList.add(new Ins.Nop());\n\n                // build exit for return, continue and break\n\n                int returnCount = 0;\n                int continueCount = 0;\n                int breakCount = 0;\n                for (Instruction ins : instructionList) {\n                        if (ins instanceof Ins.TReturn) ++returnCount;\n                        else if (breakIns != null) {\n                                assert continueIns != null;\n                                if (ins instanceof Ins.Goto) {\n                                        if (((Ins.Goto) ins).gotoIns() == breakIns) ++breakCount;\n                                        else if (((Ins.Goto) ins).gotoIns() == continueIns) ++continueCount;\n                                }\n                        }\n                }\n\n                List<Ins.MonitorExit> exitNormal = new ArrayList<Ins.MonitorExit>(stack.size());\n                List<Ins.MonitorExit> exitForExceptions = new ArrayList<Ins.MonitorExit>(stack.size());\n                List<List<Ins.MonitorExit>> exitForReturn = new ArrayList<List<Ins.MonitorExit>>();\n                List<List<Ins.MonitorExit>> exitForBreak = new ArrayList<List<Ins.MonitorExit>>();\n                List<List<Ins.MonitorExit>> exitForContinue = new ArrayList<List<Ins.MonitorExit>>();\n                for (int i = 0; i < returnCount; ++i) exitForReturn.add(new ArrayList<Ins.MonitorExit>());\n                for (int i = 0; i < continueCount; ++i) exitForContinue.add(new ArrayList<Ins.MonitorExit>());\n                for (int i = 0; i < breakCount; ++i) exitForBreak.add(new ArrayList<Ins.MonitorExit>());\n\n                while (!stack.empty()) {\n                        Ins.MonitorEnter monitorEnter = stack.pop();\n                        exitNormal.add(new Ins.MonitorExit(monitorEnter));\n                        exitForExceptions.add(new Ins.MonitorExit(monitorEnter));\n                        for (List<Ins.MonitorExit> list : exitForReturn) list.add(new Ins.MonitorExit(monitorEnter));\n                        for (List<Ins.MonitorExit> list : exitForContinue) list.add(new Ins.MonitorExit(monitorEnter));\n                        for (List<Ins.MonitorExit> list : exitForBreak) list.add(new Ins.MonitorExit(monitorEnter));\n                }\n\n                // insert exit before return\n                returnCount = 0;\n                continueCount = 0;\n                breakCount = 0;\n                for (int i = 0; i < instructionList.size(); ++i) {\n                        Instruction ins = instructionList.get(i);\n\n                        if (ins instanceof Ins.TReturn) {\n                                i += insertInstructionsBeforeReturn(instructionList, i, exitForReturn.get(returnCount++), subScope);\n                        } else if (breakIns != null) {\n                                if (ins instanceof Ins.Goto) {\n                                        List<Ins.MonitorExit> exitList = null;\n                                        if (((Ins.Goto) ins).gotoIns() == breakIns) {\n                                                exitList = exitForBreak.get(breakCount++);\n                                        } else if (((Ins.Goto) ins).gotoIns() == continueIns) {\n                                                exitList = exitForContinue.get(continueCount++);\n                                        }\n\n                                        if (exitList != null) {\n                                                instructionList.addAll(i, exitList);\n                                                i += exitList.size();\n                                        }\n                                }\n                        }\n                }\n\n                instructions.addAll(instructionList);\n                instructions.addAll(exitNormal);\n\n                // might occur an exception\n                LocalVariable localVariable = new LocalVariable(\n                        getTypeWithName(\"java.lang.Throwable\", aSynchronized.line_col()),\n                        false);\n                subScope.putLeftValue(subScope.generateTempName(), localVariable);\n\n                Ins.AThrow aThrow = new Ins.AThrow(\n                        new Ins.TLoad(localVariable, subScope, aSynchronized.line_col()),\n                        aSynchronized.line_col());\n\n                Ins.ExStore exStore = new Ins.ExStore(localVariable, subScope);\n                Ins.Nop nop = new Ins.Nop();\n\n                Ins.Goto aGoto = new Ins.Goto(nop);\n                instructions.add(aGoto); // goto athrow\n                instructions.add(exStore); // astore\n                instructions.addAll(exitForExceptions);\n                instructions.add(aThrow); // athrow\n                instructions.add(nop); // nop\n\n                ExceptionTable table = new ExceptionTable(instructionList.get(0), exitNormal.get(0), exStore, null);\n                exceptionTable.add(table);\n        }\n\n        /**\n         * separate TReturn with it's return value, and insert instructions<br>\n         * <code>TheValueToReturn, TStore, instructionToInsert, TLoad, TReturn</code>\n         *\n         * @param instructions the original instruction list\n         * @param returnIndex  TReturn position\n         * @param toInsert     the instructions to insert\n         * @param scope        scope\n         * @return the cursor should += this return value\n         * @throws SyntaxException compiling error\n         */\n        public int insertInstructionsBeforeReturn(List<Instruction> instructions,\n                                                  int returnIndex,\n                                                  List<? extends Instruction> toInsert,\n                                                  SemanticScope scope) throws SyntaxException {\n                Ins.TReturn tReturn = (Ins.TReturn) instructions.remove(returnIndex); // get return\n                Value returnValue = tReturn.value();\n                if (returnValue != null) {\n                        LocalVariable tmp = new LocalVariable(returnValue.type(), false);\n                        scope.putLeftValue(scope.generateTempName(), tmp);\n\n                        Ins.TStore TStore = new Ins.TStore(tmp, returnValue, scope, LineCol.SYNTHETIC, err); // store the value\n                        Ins.TLoad tLoad = new Ins.TLoad(tmp, scope, LineCol.SYNTHETIC); // retrieve the value\n                        tReturn.setReturnValue(tLoad); // return the value\n\n                        instructions.add(returnIndex++, TStore);\n                }\n\n                instructions.addAll(returnIndex, toInsert);\n                returnIndex += toInsert.size();\n                instructions.add(returnIndex, tReturn);\n\n                return toInsert.size() + 2;\n        }\n\n        /**\n         * {@link LtRuntime#throwableWrapperObject(Throwable)}\n         */\n        private SMethodDef Lang_throwableWrapperObject;\n\n        /**\n         * @return {@link LtRuntime#throwableWrapperObject(Throwable)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_throwableWrapperObject() throws SyntaxException {\n                if (Lang_throwableWrapperObject == null) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"throwableWrapperObject\")) {\n                                        Lang_throwableWrapperObject = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_throwableWrapperObject;\n        }\n\n        /**\n         * parse try<br>\n         * <pre>\n         * try\n         *     A\n         * catch Ex\n         *     B\n         * finally\n         *     D\n         * E\n         *\n         * ==&gt;\n         *\n         * A------------------┐\n         * (                  │\n         *     DoSomething    │\n         *     D              │\n         *     return        goto D2\n         * or                 │\n         *     DoSomething    │\n         * )                  │\n         * goto D1------------┘\n         * B-----------------goto D2\n         * goto D1------------┘\n         * D2 (exception)\n         * D1 (normal)\n         * E\n         * </pre>\n         * <br>\n         * when meets a return value, separate <code>value to return</code> and the return instruction itself using {@link #insertInstructionsBeforeReturn(List, int, List, SemanticScope)} <br>\n         * the <tt>finally</tt> part would be inserted and they shouldn't be caught<br>\n         * <pre>\n         * something\n         * TReturn(Value)\n         *\n         * ==&gt;\n         *\n         * something-------------┐\n         * Value               caught\n         * TStore----------------┘\n         * [the finally part]----shoudn't be caught\n         * TLoad\n         * TReturn\n         * </pre>\n         *\n         * @param aTry             try\n         * @param methodReturnType method return type\n         * @param scope            scope\n         * @param instructions     instruction list\n         * @param exceptionTable   exception table\n         * @param breakIns         jump to this position when meets a break\n         * @param continueIns      jump to this position when meets a continue\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromTry(AST.Try aTry,\n                                            STypeDef methodReturnType,\n                                            SemanticScope scope,\n                                            List<Instruction> instructions,\n                                            List<ExceptionTable> exceptionTable,\n                                            Ins.Nop breakIns,\n                                            Ins.Nop continueIns) throws SyntaxException {\n                // try ...\n                SemanticScope scopeA = new SemanticScope(scope, scope.getMeta());\n                List<Instruction> insA = new ArrayList<Instruction>(); // instructions in scope A\n                for (Statement stmt : aTry.statements) {\n                        parseStatement(stmt, methodReturnType, scopeA, insA, exceptionTable, breakIns, continueIns, false);\n                }\n\n                // record the start and end for exception table\n                // end is inclusive in this map\n                // and should be converted to an exclusive one when added into exception table\n                LinkedHashMap<Instruction, Instruction> startToEnd = new LinkedHashMap<Instruction, Instruction>();\n                Instruction start = null;\n                for (int i1 = 0; i1 < insA.size(); i1++) {\n                        Instruction i = insA.get(i1);\n                        if (start == null) { // start is not set\n                                // if no instructions before return\n                                // then the block would not be added into exception table\n                                // else\n                                if (!(i instanceof Ins.TReturn)) {\n                                        start = i;\n                                }\n                        } else {\n                                // start is already set\n                                // if it's return\n                                // put into map and set `start` to null\n                                if (i instanceof Ins.TReturn\n                                        ||\n                                        (breakIns != null && i instanceof Ins.Goto && (((Ins.Goto) i).gotoIns() == breakIns\n                                                || ((Ins.Goto) i).gotoIns() == continueIns))\n                                        ) {\n                                        startToEnd.put(start, insA.get(i1 - 1));\n                                        start = null;\n                                }\n                        }\n                }\n                // put last pair\n                if (start != null) startToEnd.put(start, insA.get(insA.size() - 1));\n                if (startToEnd.isEmpty() && insA.size() == 1) {\n                        // insA[0] is return / break / continue\n                        insA.add(0, new Ins.Nop());\n                        startToEnd.put(insA.get(0), insA.get(0));\n                }\n\n                // the map preparation is done\n\n                // build normal finally (D1)\n                List<Instruction> normalFinally = new ArrayList<Instruction>();\n                for (Statement stmt : aTry.fin) {\n                        parseStatement(stmt, methodReturnType, new SemanticScope(scope, scope.getMeta()), normalFinally, exceptionTable, breakIns, continueIns, false);\n                }\n                if (normalFinally.isEmpty()) {\n                        normalFinally.add(new Ins.Nop());\n                }\n                Instruction D1start = normalFinally.get(0);\n\n                // build exception finally (D2)\n                SemanticScope exceptionFinallyScope = new SemanticScope(scope, scope.getMeta());\n                // add D2start to exception finally at 0\n                // add throw to exception finally at end\n                LocalVariable tmpForExStore = new LocalVariable(\n                        getTypeWithName(\"java.lang.Throwable\", aTry.line_col()), false);\n                exceptionFinallyScope.putLeftValue(exceptionFinallyScope.generateTempName(), tmpForExStore);\n                // store\n                Ins.ExStore D2start = new Ins.ExStore(tmpForExStore, exceptionFinallyScope);\n                // throw\n                Ins.AThrow aThrow = new Ins.AThrow(\n                        new Ins.TLoad(tmpForExStore, exceptionFinallyScope,\n                                aTry.line_col()),\n                        aTry.line_col());\n                List<Instruction> exceptionFinally = new ArrayList<Instruction>();\n                // fill the list\n                exceptionFinally.add(D2start);\n                for (Statement stmt : aTry.fin) {\n                        parseStatement(stmt, methodReturnType, exceptionFinallyScope,\n                                exceptionFinally, exceptionTable, breakIns, continueIns, false);\n                }\n                exceptionFinally.add(aThrow);\n\n                // add D into every position before\n                // return, break, continue in insA\n                for (int i = 0; i < insA.size(); ++i) {\n                        Instruction ins = insA.get(i);\n                        if (ins instanceof Ins.TReturn) {\n                                List<Instruction> list = new ArrayList<Instruction>();\n                                for (Statement stmt : aTry.fin) {\n                                        parseStatement(stmt, methodReturnType,\n                                                new SemanticScope(scopeA, scope.getMeta()),\n                                                list, exceptionTable, breakIns, continueIns, false);\n                                }\n                                i += insertInstructionsBeforeReturn(insA, i, list, scopeA);\n                        } else if (breakIns != null) {\n                                if (ins instanceof Ins.Goto) {\n                                        if (((Ins.Goto) ins).gotoIns() == breakIns\n                                                || ((Ins.Goto) ins).gotoIns() == continueIns) {\n\n                                                List<Instruction> list = new ArrayList<Instruction>();\n                                                for (Statement stmt : aTry.fin) {\n                                                        parseStatement(stmt, methodReturnType,\n                                                                new SemanticScope(scopeA, scope.getMeta()),\n                                                                list, exceptionTable, breakIns, continueIns, false);\n                                                }\n                                                insA.addAll(i, list);\n                                                i += list.size();\n                                        }\n                                }\n                        }\n                }\n\n                insA.add(new Ins.Goto(D1start)); // goto D1\n                // add A into instruction list\n                instructions.addAll(insA); // A\n\n                // create a map that end is exclusive\n                LinkedHashMap<Instruction, Instruction> startToEndEx = new LinkedHashMap<Instruction, Instruction>();\n                int cursor = 0;\n                for (Map.Entry<Instruction, Instruction> entry : startToEnd.entrySet()) {\n                        Instruction key = entry.getKey();\n                        Instruction inclusive = entry.getValue();\n                        Instruction exclusive = null;\n                        for (; cursor < insA.size(); ++cursor) {\n                                Instruction i = insA.get(cursor);\n                                if (inclusive.equals(i)) {\n                                        Instruction tmp = insA.get(++cursor);\n                                        if (tmp instanceof Ins.TStore) {\n                                                exclusive = insA.get(++cursor);\n                                        } else {\n                                                exclusive = tmp;\n                                        }\n                                        break;\n                                }\n                        }\n                        if (exclusive == null) throw new LtBug(\"exclusive should not be null\");\n                        startToEndEx.put(key, exclusive);\n                }\n\n                SemanticScope catchScope = new SemanticScope(scope, scope.getMeta()); // catch scope\n\n                STypeDef THROWABLE = getTypeWithName(\"java.lang.Throwable\", LineCol.SYNTHETIC);\n\n                LocalVariable ex = new LocalVariable(THROWABLE, true);\n                catchScope.putLeftValue(catchScope.generateTempName(), ex); // the exception value\n\n                LocalVariable unwrapped = new LocalVariable(getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC), false);\n                catchScope.putLeftValue(aTry.varName, unwrapped);\n\n                // build instructions\n                List<Instruction> insCatch = new ArrayList<Instruction>();\n                insCatch.add(new Ins.ExStore(ex, catchScope)); // store the ex\n\n                Ins.InvokeStatic invokeUnwrap = new Ins.InvokeStatic(\n                        getLang_throwableWrapperObject(), LineCol.SYNTHETIC\n                );\n                invokeUnwrap.arguments().add(new Ins.TLoad(\n                        ex,\n                        catchScope,\n                        LineCol.SYNTHETIC\n                ));\n                Ins.TStore storeUnwrapped = new Ins.TStore(\n                        unwrapped,\n                        invokeUnwrap,\n                        catchScope,\n                        LineCol.SYNTHETIC, err\n                );\n                insCatch.add(storeUnwrapped);\n\n                for (Statement stmt : aTry.catchStatements) {\n                        parseStatement(stmt, methodReturnType, catchScope, insCatch,\n                                exceptionTable, breakIns, continueIns, false);\n                }\n\n                // record start to end for exception table\n                // end is inclusive\n                // and should be parsed into an exclusive one when added into exception table\n                LinkedHashMap<Instruction, Instruction> catch_startToEnd = new LinkedHashMap<Instruction, Instruction>();\n                Instruction catch_start = null;\n                for (int i1 = 0; i1 < insCatch.size(); ++i1) {\n                        Instruction i = insCatch.get(i1);\n                        if (catch_start == null) { // the start hasn't been recorded\n                                // if i is return\n                                // then ignore it and continue\n                                // else record the instruction as start\n                                if (!(i instanceof Ins.TReturn)) {\n                                        catch_start = i;\n                                }\n                        } else { // start is already recorded\n                                if (i instanceof Ins.TReturn\n                                        ||\n                                        (breakIns != null && i instanceof Ins.Goto && (((Ins.Goto) i).gotoIns() == breakIns\n                                                || ((Ins.Goto) i).gotoIns() == continueIns))\n                                        ) {\n                                        catch_startToEnd.put(catch_start, insCatch.get(i1 - 1));\n                                        catch_start = null;\n                                }\n                        }\n                }\n                // record last pair\n                if (catch_start != null) catch_startToEnd.put(catch_start, insCatch.get(insCatch.size() - 1));\n\n                // add finally before every return, break and continue\n                for (int i = 0; i < insCatch.size(); ++i) {\n                        Instruction ins = insCatch.get(i);\n                        if (ins instanceof Ins.TReturn) {\n                                List<Instruction> list = new ArrayList<Instruction>();\n                                for (Statement stmt : aTry.fin) {\n                                        parseStatement(stmt, methodReturnType, new SemanticScope(catchScope, catchScope.getMeta()),\n                                                list, exceptionTable, breakIns, continueIns, false);\n                                }\n                                i += insertInstructionsBeforeReturn(insCatch, i, list, catchScope);\n                        } else if (breakIns != null) {\n                                if (ins instanceof Ins.Goto) {\n                                        if (((Ins.Goto) ins).gotoIns() == breakIns\n                                                || ((Ins.Goto) ins).gotoIns() == continueIns) {\n\n                                                List<Instruction> list = new ArrayList<Instruction>();\n                                                for (Statement stmt : aTry.fin) {\n                                                        parseStatement(stmt, methodReturnType,\n                                                                new SemanticScope(catchScope, catchScope.getMeta()),\n                                                                list, exceptionTable, breakIns, continueIns, false);\n                                                }\n                                                insCatch.addAll(i, list);\n                                                i += list.size();\n                                        }\n                                }\n                        }\n                }\n                insCatch.add(new Ins.Goto(D1start)); // goto D1\n                instructions.addAll(insCatch); // B\n\n                // transform the startToEnd map into exclusive end map\n                LinkedHashMap<Instruction, Instruction> catch_startToEndEx = new LinkedHashMap<Instruction, Instruction>();\n                cursor = 0;\n                for (Map.Entry<Instruction, Instruction> entry : catch_startToEnd.entrySet()) {\n                        Instruction key = entry.getKey();\n                        Instruction inclusive = entry.getValue();\n                        Instruction exclusive = null;\n                        for (; cursor < insCatch.size(); ++cursor) {\n                                Instruction i = insCatch.get(cursor);\n                                if (i.equals(inclusive)) {\n                                        Instruction tmp = insCatch.get(++cursor);\n                                        if (tmp instanceof Ins.TStore) {\n                                                exclusive = insCatch.get(++cursor);\n                                        } else {\n                                                exclusive = tmp;\n                                        }\n                                        break;\n                                }\n                        }\n                        if (exclusive == null) throw new LtBug(\"exclusive should not be null\");\n                        catch_startToEndEx.put(key, exclusive);\n                }\n\n                // build exception table for A\n                for (Map.Entry<Instruction, Instruction> entry : startToEndEx.entrySet()) {\n                        ExceptionTable tbl = new ExceptionTable(entry.getKey(), entry.getValue(), insCatch.get(0), THROWABLE);\n                        exceptionTable.add(tbl);\n                }\n\n                // build exception table for B\n                for (Map.Entry<Instruction, Instruction> entry : catch_startToEndEx.entrySet()) {\n                        ExceptionTable tbl = new ExceptionTable(entry.getKey(), entry.getValue(), D2start, null);\n                        exceptionTable.add(tbl);\n                }\n\n                instructions.addAll(exceptionFinally); // D2\n                instructions.addAll(normalFinally); // D1\n        }\n\n        /**\n         * {@link LtIterator#getIterator(Object)}\n         */\n        private SMethodDef LtIterator_getIterator;\n\n        /**\n         * @return {@link LtIterator#getIterator(Object)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLtIterator_Get() throws SyntaxException {\n                if (LtIterator_getIterator == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtIterator\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"getIterator\")) {\n                                        LtIterator_getIterator = m;\n                                        break;\n                                }\n                        }\n                }\n                return LtIterator_getIterator;\n        }\n\n        /**\n         * {@link LtIterator#hasNext()}\n         */\n        private SMethodDef LtIterator_hasNext;\n\n        /**\n         * @return {@link LtIterator#hasNext()}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLtIterator_hasNext() throws SyntaxException {\n                if (LtIterator_hasNext == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtIterator\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"hasNext\")) {\n                                        LtIterator_hasNext = m;\n                                        break;\n                                }\n                        }\n                }\n                return LtIterator_hasNext;\n        }\n\n        /**\n         * {@link LtIterator#next()}\n         */\n        private SMethodDef LtIterator_next;\n\n        /**\n         * @return {@link LtIterator#next()}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLtIterator_next() throws SyntaxException {\n                if (LtIterator_next == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtIterator\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"next\")) {\n                                        LtIterator_next = m;\n                                        break;\n                                }\n                        }\n                }\n                return LtIterator_next;\n        }\n\n        /**\n         * parse for<br>\n         * <br>\n         * <pre>\n         * for i in I\n         *     A\n         * B\n         *\n         * ==&gt;\n         *\n         * LtIterator.get(aFor.exp)\n         * aStore\n         * here::\n         * aLoad\n         * hasNext\n         * if eq (==false) goto B\n         * aLoad\n         * next\n         * A\n         * noo --------- also known as continue position\n         * goto here\n         * B ----------- also known as break position\n         * </pre>\n         *\n         * @param aFor             for\n         * @param methodReturnType method return type\n         * @param scope            scope\n         * @param instructions     instruction list\n         * @param exceptionTable   exception table\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromFor(AST.For aFor,\n                                            STypeDef methodReturnType,\n                                            SemanticScope scope,\n                                            List<Instruction> instructions,\n                                            List<ExceptionTable> exceptionTable) throws SyntaxException {\n                // LtIterator.get(aFor.exp)\n                Ins.InvokeStatic getIterator = new Ins.InvokeStatic(getLtIterator_Get(), LineCol.SYNTHETIC);\n                Value looper = parseValueFromExpression(aFor.exp, null, scope);\n                assert looper != null;\n                if (looper.type() instanceof PrimitiveTypeDef)\n                        looper = boxPrimitive(looper, LineCol.SYNTHETIC);\n                getIterator.arguments().add(looper);\n\n                // aStore\n                LocalVariable localVariable = new LocalVariable(getTypeWithName(\"lt.runtime.LtIterator\", LineCol.SYNTHETIC), false);\n                scope.putLeftValue(scope.generateTempName(), localVariable);\n                Ins.TStore tStore = new Ins.TStore(localVariable, getIterator, scope, LineCol.SYNTHETIC, err);\n                instructions.add(tStore);\n                // aLoad\n                Ins.TLoad tLoad = new Ins.TLoad(localVariable, scope, LineCol.SYNTHETIC);\n                // hasNext\n                Ins.InvokeVirtual hasNext = new Ins.InvokeVirtual(tLoad, getLtIterator_hasNext(), LineCol.SYNTHETIC);\n                // if eq goto B\n                Ins.Nop nop = new Ins.Nop(); // B\n                // if eq goto\n                Ins.IfEq ifEq = new Ins.IfEq(hasNext, nop, aFor.line_col());\n                instructions.add(ifEq);\n                // aLoad\n                Ins.TLoad tLoad1 = new Ins.TLoad(localVariable, scope, LineCol.SYNTHETIC);\n                // next\n                Ins.InvokeVirtual next = new Ins.InvokeVirtual(tLoad1, getLtIterator_next(), LineCol.SYNTHETIC);\n                SemanticScope subScope = new SemanticScope(scope, scope.getMeta());\n                LocalVariable newLocal = new LocalVariable(getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC), true);\n                subScope.putLeftValue(aFor.name, newLocal);\n                Ins.TStore tStore1 = new Ins.TStore(newLocal, next, subScope, LineCol.SYNTHETIC, err);\n                instructions.add(tStore1); // name = it.next()\n\n                Ins.Nop nopForContinue = new Ins.Nop();\n\n                for (Statement stmt : aFor.body) {\n                        parseStatement(\n                                stmt,\n                                methodReturnType,\n                                subScope,\n                                instructions,\n                                exceptionTable, nop, nopForContinue, false);\n                }\n                instructions.add(nopForContinue);\n                instructions.add(new Ins.Goto(ifEq));\n                instructions.add(nop);\n        }\n\n        /**\n         * parse while<br><br>\n         * while:\n         * <pre>\n         * while B\n         *     A\n         * C\n         *\n         * ==&gt;\n         *\n         * ifEq B (B==false) goto C\n         * A\n         * goto while\n         * C\n         * </pre>\n         * do-while:\n         * <pre>\n         * do\n         *     A\n         * while B\n         * C\n         *\n         * ==&gt;\n         *\n         * A\n         * ifNe B (B==true) goto A\n         * C\n         * </pre>\n         *\n         * @param aWhile           while\n         * @param methodReturnType method return type\n         * @param scope            scope\n         * @param instructions     instruction list\n         * @param exceptionTable   exception table\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromWhile(AST.While aWhile, STypeDef methodReturnType, SemanticScope scope, List<Instruction> instructions, List<ExceptionTable> exceptionTable) throws SyntaxException {\n                Ins.Nop nopBreak = new Ins.Nop();\n                Ins.Nop nopContinue = new Ins.Nop();\n\n                SemanticScope whileScope = new SemanticScope(scope, scope.getMeta());\n\n                List<Instruction> ins = new ArrayList<Instruction>();\n                for (Statement stmt : aWhile.statements) {\n                        parseStatement(\n                                stmt,\n                                methodReturnType,\n                                whileScope,\n                                ins,\n                                exceptionTable, nopBreak, nopContinue, false);\n                }\n\n                Value condition = parseValueFromExpression(aWhile.condition, BoolTypeDef.get(), whileScope);\n\n                if (aWhile.doWhile) {\n                        /*\n                         * do\n                         *     A\n                         * while B\n                         * C\n                         *\n                         * ==>\n                         *\n                         * A\n                         * nop --------- continue nop\n                         * if B goto A\n                         * C ----------- break nop\n                         */\n                        instructions.addAll(ins); // A\n                        instructions.add(nopContinue);\n                        // loop, if B goto A\n                        if (ins.isEmpty()) {\n                                // A is empty then goto self\n                                Ins.IfNe ifNe = new Ins.IfNe(condition, null, aWhile.line_col());\n                                ifNe.setGotoIns(ifNe);\n                                instructions.add(ifNe);\n                        } else {\n                                // A not empty then goto A\n                                Ins.IfNe ifNe = new Ins.IfNe(condition, ins.get(0), aWhile.line_col());\n                                instructions.add(ifNe);\n                        }\n                        instructions.add(nopBreak);\n                } else {\n                        /*\n                         * while B\n                         *     A\n                         * C\n                         *\n                         * ==>\n                         *\n                         * if not B goto C\n                         * A\n                         * nop ------------- continue nop\n                         * goto while\n                         * C --------------- break nop\n                         */\n                        Ins.IfEq ifEq; // if B == 0 (false) goto C\n                        ifEq = new Ins.IfEq(condition, nopBreak, aWhile.line_col());\n                        instructions.add(ifEq); // if not B goto C\n\n                        instructions.addAll(ins); // A\n                        instructions.add(nopContinue);\n                        instructions.add(new Ins.Goto(ifEq)); // goto while\n                        instructions.add(nopBreak); // C\n                }\n        }\n\n        private void parseStatementPartOfIf(AST.If.IfPair ifPair, STypeDef methodReturnType,\n                                            SemanticScope ifScope, List<ExceptionTable> exceptionTable,\n                                            Ins.Nop breakIns, Ins.Nop continueIns,\n                                            List<Instruction> ins) throws SyntaxException {\n                for (Statement stmt : ifPair.body) {\n                        parseStatement(\n                                stmt,\n                                methodReturnType,\n                                ifScope,\n                                ins,\n                                exceptionTable, breakIns, continueIns, false);\n                }\n        }\n\n        /**\n         * parse if<br><br>\n         * <pre>\n         * if a\n         *     A\n         * elseif b\n         *     B\n         * elseif c\n         *     C\n         * else\n         *     D\n         *\n         * ==&gt;\n         *\n         * a ifEq (a!=true) goto nop1\n         * A\n         * goto nop\n         * nop1\n         * b ifEq (b!=true) goto nop2\n         * B\n         * goto nop\n         * nop2\n         * c ifEq (c!=true) goto nop3\n         * C\n         * goto nop\n         * nop3\n         * D\n         * nop\n         * </pre>\n         *\n         * @param anIf             if\n         * @param methodReturnType method return type\n         * @param scope            current scope\n         * @param instructions     instruction list\n         * @param exceptionTable   exception table\n         * @param breakIns         jump to this position when meets break\n         * @param continueIns      to this position when meets continue\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromIf(AST.If anIf,\n                                           STypeDef methodReturnType,\n                                           SemanticScope scope,\n                                           List<Instruction> instructions,\n                                           List<ExceptionTable> exceptionTable,\n                                           Ins.Nop breakIns,\n                                           Ins.Nop continueIns) throws SyntaxException {\n                Ins.Nop nop = new Ins.Nop();\n\n                for (AST.If.IfPair ifPair : anIf.ifs) {\n                        SemanticScope ifScope = new SemanticScope(scope, scope.getMeta());\n                        List<Instruction> instructionList = new ArrayList<Instruction>();\n\n                        if (ifPair.condition == null) {\n                                // it's else\n                                parseStatementPartOfIf(ifPair,\n                                        methodReturnType,\n                                        ifScope,\n                                        exceptionTable,\n                                        breakIns, continueIns,\n                                        instructionList\n                                );\n                        } else {\n                                // if/elseif\n\n                                Ins.Goto gotoNop = new Ins.Goto(nop); // goto nop\n                                Ins.Nop thisNop = new Ins.Nop(); // nop1/nop2/nop3/...\n\n                                Value condition = parseValueFromExpression(ifPair.condition, BoolTypeDef.get(), ifScope);\n                                Ins.IfEq ifEq = new Ins.IfEq(condition, thisNop, ifPair.condition.line_col());\n                                instructionList.add(ifEq); // a ifEq (a!=true) goto nop\n                                parseStatementPartOfIf(ifPair,\n                                        methodReturnType,\n                                        ifScope,\n                                        exceptionTable,\n                                        breakIns, continueIns,\n                                        instructionList\n                                ); // A\n                                instructionList.add(gotoNop); // goto nop\n                                instructionList.add(thisNop); // nop1\n                        }\n\n                        instructions.addAll(instructionList);\n                }\n\n                instructions.add(nop); // nop\n        }\n\n        /**\n         * parse return\n         *\n         * @param ret              return object\n         * @param methodReturnType method return type\n         * @param scope            current scope\n         * @param instructions     instruction list\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromReturn(AST.Return ret, STypeDef methodReturnType, SemanticScope scope, List<Instruction> instructions) throws SyntaxException {\n                Ins.TReturn tReturn;\n                if (ret.exp == null) {\n                        if (methodReturnType.equals(VoidType.get())) {\n                                tReturn = new Ins.TReturn(null, ret.line_col());\n                        } else {\n                                if (methodReturnType.fullName().equals(\"lt.lang.Unit\")\n                                        || methodReturnType.fullName().equals(\"java.lang.Object\")) {\n                                        tReturn = new Ins.TReturn(invoke_Unit_get(LineCol.SYNTHETIC), ret.line_col());\n                                } else {\n                                        err.SyntaxException(\"the method is not void but returns nothing\", ret.line_col());\n                                        return;\n                                }\n                        }\n                } else {\n                        Value v = parseValueFromExpression(ret.exp,\n                                methodReturnType.equals(VoidType.get()) ? null : methodReturnType, scope);\n                        if (methodReturnType.equals(VoidType.get())) {\n                                if (v instanceof Instruction) {\n                                        instructions.add((Instruction) v);\n                                }\n                                tReturn = new Ins.TReturn(null, ret.line_col());\n                        } else {\n                                tReturn = new Ins.TReturn(v, ret.line_col());\n                        }\n                }\n                instructions.add(tReturn);\n        }\n\n        /**\n         * {@link LtRuntime#putField(Object, String, Object, Class)}\n         */\n        private SMethodDef Lang_putField;\n\n        /**\n         * @return {@link LtRuntime#putField(Object, String, Object, Class)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_putField() throws SyntaxException {\n                if (null == Lang_putField) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"putField\")) {\n                                        Lang_putField = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_putField;\n        }\n\n        /**\n         * parse assignment<br>\n         * the rules are very simple, +=,-=,*=,/=,%= are converted to a=a+b/a-b/a*b/a/b/a%b<br>\n         * the parsed result is filled into the given instruction list<br>\n         * it's NOT directly invoked in {@link #parseStatement(Statement, STypeDef, SemanticScope, List, List, lt.compiler.semantic.Ins.Nop, lt.compiler.semantic.Ins.Nop, boolean)}<br>\n         * but in {@link #parseValueFromAssignment(AST.Assignment, SemanticScope)}<br>\n         * the instructions should be {@link ValuePack} instruction list\n         *\n         * @param assignTo     assignTo -- the value before \"=\"\n         * @param assignFrom   the value after \"=\"\n         * @param scope        current scope\n         * @param instructions instruction list\n         * @param lineCol      lineCol\n         * @throws SyntaxException compile error\n         */\n        public void parseInstructionFromAssignment(Value assignTo,\n                                                   Value assignFrom,\n                                                   SemanticScope scope,\n                                                   List<Instruction> instructions,\n                                                   LineCol lineCol) throws SyntaxException {\n                // []= means Tastore or <set(?,?) or put(?,?)> ==> (reflectively invoke)\n                // []+= means TALoad then Tastore, or get(?) then <set(?,?) or put(?,?)> ==> then set/put step would be invoked reflectively\n\n                // else\n                // simply assign `assignFrom` to `assignTo`\n                // the following actions would be assign work\n                if (isPointerType(assignTo.type())) {\n                        if (assignFrom.type() instanceof PrimitiveTypeDef) {\n                                assignFrom = boxPrimitive(assignFrom, lineCol);\n                        }\n                        instructions.add(invokePointerSet(assignTo, assignFrom, lineCol));\n                } else if (assignTo instanceof Ins.GetField) {\n                        // field\n                        instructions.add(new Ins.PutField(\n                                ((Ins.GetField) assignTo).field(),\n                                ((Ins.GetField) assignTo).object(),\n                                cast(((Ins.GetField) assignTo).field().type(), assignFrom, scope.type(), ((Ins.GetField) assignTo).line_col()),\n                                lineCol, err));\n                } else if (assignTo instanceof Ins.GetStatic) {\n                        // static\n                        instructions.add(new Ins.PutStatic(\n                                ((Ins.GetStatic) assignTo).field(),\n                                cast(((Ins.GetStatic) assignTo).field().type(), assignFrom, scope.type(), ((Ins.GetStatic) assignTo).line_col()),\n                                lineCol, err));\n                } else if (assignTo instanceof Ins.TALoad) {\n                        // arr[?]\n                        Ins.TALoad TALoad = (Ins.TALoad) assignTo;\n                        SArrayTypeDef arrayType = (SArrayTypeDef) TALoad.arr().type();\n                        if (arrayType.dimension() > 1) {\n                                // dimension>1 so it's AASTORE\n                                // object[] AASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.AASTORE,\n                                        TALoad.index(),\n                                        cast(arrayType.type(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(IntTypeDef.get())) {\n                                // int[] IASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.IASTORE,\n                                        TALoad.index(),\n                                        cast(IntTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(LongTypeDef.get())) {\n                                // long[] LASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.LASTORE,\n                                        TALoad.index(),\n                                        cast(LongTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(ShortTypeDef.get())) {\n                                // short[] SASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.SASTORE,\n                                        TALoad.index(),\n                                        cast(ShortTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(ByteTypeDef.get()) || arrayType.type().equals(BoolTypeDef.get())) {\n                                // byte[]/boolean[] BASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.BASTORE,\n                                        TALoad.index(),\n                                        cast(ByteTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(FloatTypeDef.get())) {\n                                // float[] FASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.FASTORE,\n                                        TALoad.index(),\n                                        cast(FloatTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(DoubleTypeDef.get())) {\n                                // double[] DASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.DASTORE,\n                                        TALoad.index(),\n                                        cast(DoubleTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else if (arrayType.type().equals(CharTypeDef.get())) {\n                                // char[] CASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.CASTORE,\n                                        TALoad.index(),\n                                        cast(CharTypeDef.get(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        } else {\n                                // object[] AASTORE\n                                instructions.add(new Ins.TAStore(\n                                        TALoad.arr(),\n                                        Ins.TAStore.AASTORE,\n                                        TALoad.index(),\n                                        cast(arrayType.type(), assignFrom, scope.type(), lineCol),\n                                        lineCol));\n                        }\n                } else if (assignTo instanceof Ins.TLoad) {\n                        // local variable\n                        instructions.add(new Ins.TStore(\n                                ((Ins.TLoad) assignTo).value(),\n                                cast(\n                                        assignTo.type(),\n                                        assignFrom,\n                                        scope.type(),\n                                        lineCol),\n                                scope, lineCol, err));\n                } else if (assignTo instanceof Ins.InvokeStatic) {\n                        // assignTo should be lt.runtime.LtRuntime.getField(o,name)\n                        // which means\n                        Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) assignTo;\n                        if (isGetFieldAtRuntime(invokeStatic)) {\n                                // dynamically get field\n                                // invoke lt.runtime.LtRuntime.putField(o,name,value)\n                                SMethodDef putField = getLang_putField();\n                                Ins.InvokeStatic invoke = new Ins.InvokeStatic(putField, lineCol);\n                                invoke.arguments().add(invokeStatic.arguments().get(0));\n                                invoke.arguments().add(invokeStatic.arguments().get(1));\n\n                                if (assignFrom.type() instanceof PrimitiveTypeDef) {\n                                        assignFrom = boxPrimitive(assignFrom, LineCol.SYNTHETIC);\n                                }\n\n                                invoke.arguments().add(assignFrom);\n                                invoke.arguments().add(\n                                        new Ins.GetClass(scope.type(),\n                                                (SClassDef) getTypeWithName(\"java.lang.Class\", lineCol)));\n\n                                // add into instructin list\n                                instructions.add(invoke);\n\n                                return;\n                        } else if (isInvokeAtRuntime(invokeStatic)) {\n                                // invoke get(?)\n                                // list[?1]=?2\n                                // or\n                                // map[?1]=?2\n                                Ins.InvokeStatic invoke = (Ins.InvokeStatic) assignTo;\n                                if (((StringConstantValue) invoke.arguments().get(INDEX_invoke_method)).getStr().equals(\"get\")\n                                        && ((Ins.ANewArray) invoke.arguments().get(INDEX_invoke_args)).initValues().size() > 0) {\n                                        // the method to invoke should be set\n                                        Ins.GetClass cls = (Ins.GetClass) invoke.arguments().get(0); // class\n                                        Value target = invoke.arguments().get(1);\n\n                                        // args\n                                        List<Value> list = new ArrayList<Value>();\n                                        list.addAll(((Ins.ANewArray) invoke.arguments().get(INDEX_invoke_args)).initValues());\n                                        list.add(assignFrom);\n\n                                        instructions.add((Instruction) invokeMethodWithArgs(\n                                                lineCol,\n                                                cls.targetType(),\n                                                target,\n                                                \"set\",\n                                                list,\n                                                scope));\n                                        return;\n                                }\n                                err.SyntaxException(\"cannot assign\", lineCol);\n                                // code won't reach here\n                        }\n                        err.SyntaxException(\"cannot assign\", lineCol);\n                        // code won't reach here\n                } else if (assignTo instanceof Ins.InvokeWithTarget) {\n                        // the method name should be 'get(?1)'\n                        Ins.InvokeWithTarget invoke = (Ins.InvokeWithTarget) assignTo;\n                        if (invoke.invokable() instanceof SMethodDef) {\n                                SMethodDef method = (SMethodDef) invoke.invokable();\n                                if (method.name().equals(\"get\")) {\n                                        // the method to invoke should be `set(?1,?2)`\n                                        List<Value> list = new ArrayList<Value>();\n                                        list.addAll(invoke.arguments());\n                                        list.add(assignFrom);\n                                        instructions.add((Instruction) invokeMethodWithArgs(\n                                                lineCol,\n                                                invoke.target().type(),\n                                                invoke.target(),\n                                                \"set\",\n                                                list,\n                                                scope));\n                                        return;\n                                }\n                        }\n                        err.SyntaxException(\"cannot assign\", lineCol);\n                        // code won't reach here\n                } else {\n                        err.SyntaxException(\"cannot assign\", lineCol);\n                        // code won't reach here\n                }\n        }\n\n        /**\n         * parse variable def\n         *\n         * @param variableDef variable definition\n         * @param scope       current scope\n         * @return retrieved Value or null if no initValue is assigned\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromVariableDef(VariableDef variableDef, SemanticScope scope) throws SyntaxException {\n                // generic type map\n                Map<String, STypeDef> genericTypeMap = getGenericMap(scope.type());\n\n                // handle\n                List<Import> imports = fileNameToImport.get(variableDef.line_col().fileName);\n\n                STypeDef type = variableDef.getType() == null\n\n                        ? getTypeWithName(\n                        \"java.lang.Object\",\n                        variableDef.line_col())\n\n                        : getTypeWithAccess(\n                        variableDef.getType(),\n                        genericTypeMap,\n                        imports);\n                STypeDef rawType = type;\n\n                // try to find field and putField/putStatic\n                SFieldDef field = findFieldFromTypeDef(variableDef.getName(), scope.type(), scope.type(),\n                        scope.getThis() == null ? FIND_MODE_STATIC : FIND_MODE_ANY,\n                        false);\n\n                boolean isLocalVar = false;\n                if (field == null) {\n                        // field is null, define local variable\n                        if (scope.getLeftValue(variableDef.getName()) == null) {\n                                isLocalVar = true;\n                        } else {\n                                err.SyntaxException(variableDef.getName() + \" is already defined\", variableDef.line_col());\n                                return null;\n                        }\n                }\n\n                if (variableDef.getInit() != null || isLocalVar) {\n                        boolean nonnull = false;\n                        boolean nonempty = false;\n                        // variable def with a init value\n\n                        Value v;\n\n                        ValuePack pack = new ValuePack(true);\n                        if (isLocalVar) {\n                                boolean canChange = true;\n                                for (Modifier m : variableDef.getModifiers()) {\n                                        if (m.modifier.equals(Modifier.Available.VAL)) {\n                                                canChange = false;\n                                        } else if (m.modifier.equals(Modifier.Available.NONNULL)) {\n                                                nonnull = true;\n                                        } else if (m.modifier.equals(Modifier.Available.NONEMPTY)) {\n                                                nonempty = true;\n                                        } else if (!m.modifier.equals(Modifier.Available.VAR)) {\n                                                err.SyntaxException(\"invalid modifier for local variable \"\n                                                        + m.modifier.name().toLowerCase(), m.line_col());\n                                        }\n                                }\n\n                                AST.Access typeAccess = variableDef.getType();\n                                type = getTypeWithAccess(new AST.Access(typeAccess, \"*\", typeAccess == null ? LineCol.SYNTHETIC : typeAccess.line_col()), genericTypeMap, imports);\n\n                                LocalVariable localVariable = new LocalVariable(type, canChange);\n                                scope.putLeftValue(variableDef.getName(), localVariable);\n\n                                Ins.TStore storePtr = new Ins.TStore(localVariable,\n                                        constructPointer(nonnull, nonempty), scope, LineCol.SYNTHETIC, err);\n                                storePtr.flag |= Consts.IS_POINTER_NEW;\n                                pack.instructions().add(storePtr);\n                        }\n\n                        if (variableDef.getInit() == null) {\n                                if (rawType instanceof PrimitiveTypeDef) {\n                                        if (rawType instanceof IntTypeDef) {\n                                                v = new IntValue(0);\n                                        } else if (rawType instanceof ShortTypeDef || rawType instanceof ByteTypeDef) {\n                                                v = new ValueAnotherType(type, new IntValue(0), LineCol.SYNTHETIC);\n                                        } else if (rawType instanceof LongTypeDef) {\n                                                v = new LongValue(0);\n                                        } else if (rawType instanceof FloatTypeDef) {\n                                                v = new FloatValue(0);\n                                        } else if (rawType instanceof DoubleTypeDef) {\n                                                v = new DoubleValue(0);\n                                        } else if (rawType instanceof BoolTypeDef) {\n                                                v = new BoolValue(false);\n                                        } else if (rawType instanceof CharTypeDef) {\n                                                v = new CharValue((char) 0);\n                                        } else throw new LtBug(\"unknown primitive type \" + type);\n                                } else {\n                                        v = NullValue.get();\n                                }\n                        } else {\n                                v = parseValueFromExpression(\n                                        variableDef.getInit(),\n                                        rawType,\n                                        scope);\n                        }\n\n                        if (null != field) {\n                                if (field.modifiers().contains(SModifier.STATIC)) {\n                                        // putStatic\n                                        pack.instructions().add(new Ins.PutStatic(field, v, variableDef.line_col(), err));\n                                        Ins.GetStatic getStatic = new Ins.GetStatic(field, variableDef.line_col());\n                                        pack.instructions().add(getStatic);\n                                } else {\n                                        // putField\n                                        pack.instructions().add(new Ins.PutField(field, scope.getThis(), v, variableDef.line_col(), err));\n                                        Ins.GetField getField = new Ins.GetField(field, scope.getThis(), variableDef.line_col());\n                                        pack.instructions().add(getField);\n                                }\n                        } else {\n                                assert isPointerType(type);\n                                // else field not found\n                                /*\n                                 * tload\n                                 * get and set\n                                 */\n                                LocalVariable localVariable = (LocalVariable) scope.getLeftValue(variableDef.getName());\n\n                                Ins.InvokeVirtual invokeSet = invokePointerSet(\n                                        new Ins.TLoad(localVariable, scope, LineCol.SYNTHETIC),\n                                        v, variableDef.line_col());\n                                pack.instructions().add(invokeSet);\n\n                                Value get = invokePointerGet(new Ins.TLoad(localVariable, scope, variableDef.line_col()),\n                                        variableDef.line_col());\n                                pack.instructions().add((Instruction) get);\n                                localVariable.alreadyAssigned();\n\n                                if (!localVariable.canChange()) {\n                                        // set type for val values\n                                        PointerType tmp = new PointerType(v.type());\n                                        if (types.containsKey(tmp.toString())) {\n                                                tmp = (PointerType) types.get(tmp.toString());\n                                        } else {\n                                                types.put(tmp.toString(), tmp);\n                                        }\n                                        localVariable.setType(tmp);\n                                }\n\n                                // nonnull and nonempty check\n                                if (nonempty || nonnull) {\n                                        scope.getMeta().pointerLocalVar.add(localVariable);\n                                }\n                        }\n                        return pack;\n                }\n\n                // else ignore the var def\n                return null;\n        }\n\n        private SConstructorDef Pointer_con;\n\n        public SConstructorDef getPointer_con() throws SyntaxException {\n                if (Pointer_con == null) {\n                        SClassDef Pointer = (SClassDef) getTypeWithName(\"lt.lang.Pointer\", LineCol.SYNTHETIC);\n                        for (SConstructorDef con : Pointer.constructors()) {\n                                if (con.getParameters().size() == 2\n                                        && con.getParameters().get(0).type().equals(BoolTypeDef.get())\n                                        && con.getParameters().get(1).type().equals(BoolTypeDef.get())) {\n                                        Pointer_con = con;\n                                        break;\n                                }\n                        }\n                }\n                return Pointer_con;\n        }\n\n        public Ins.New constructPointer(boolean nonnull, boolean nonempty) throws SyntaxException {\n                Ins.New aNew = new Ins.New(getPointer_con(), LineCol.SYNTHETIC);\n                aNew.args().add(new BoolValue(nonnull));\n                aNew.args().add(new BoolValue(nonempty));\n                return aNew;\n        }\n\n        private SMethodDef Pointer_set;\n\n        public SMethodDef getPointer_set() throws SyntaxException {\n                if (Pointer_set == null) {\n                        SClassDef Pointer = (SClassDef) getTypeWithName(\"lt.lang.Pointer\", LineCol.SYNTHETIC);\n                        for (SMethodDef m : Pointer.methods()) {\n                                if (m.name().equals(\"set\") && m.getParameters().size() == 1) {\n                                        Pointer_set = m;\n                                        break;\n                                }\n                        }\n                }\n                return Pointer_set;\n        }\n\n        public Ins.InvokeVirtual invokePointerSet(Value target, Value valueToSet, LineCol lineCol) throws SyntaxException {\n                assert isPointerType(target.type());\n                Ins.InvokeVirtual set = new Ins.InvokeVirtual(\n                        target,\n                        getPointer_set(),\n                        lineCol);\n                if (valueToSet.type() instanceof PrimitiveTypeDef) {\n                        valueToSet = boxPrimitive(valueToSet, LineCol.SYNTHETIC);\n                }\n                set.arguments().add(valueToSet);\n                set.flag |= Consts.IS_POINTER_SET;\n                return set;\n        }\n\n        private SMethodDef Pointer_get;\n\n        public SMethodDef getPointer_get() throws SyntaxException {\n                if (Pointer_get == null) {\n                        SClassDef Pointer = (SClassDef) getTypeWithName(\"lt.lang.Pointer\", LineCol.SYNTHETIC);\n                        for (SMethodDef m : Pointer.methods()) {\n                                if (m.name().equals(\"get\") && m.getParameters().isEmpty()) {\n                                        Pointer_get = m;\n                                        break;\n                                }\n                        }\n                }\n                return Pointer_get;\n        }\n\n        public Value invokePointerGet(Value target, LineCol lineCol) throws SyntaxException {\n                assert isPointerType(target.type());\n                STypeDef pointingType = getPointingType(target.type());\n\n                Ins.InvokeVirtual get = new Ins.InvokeVirtual(\n                        target, getPointer_get(), lineCol);\n                get.flag |= Consts.IS_POINTER_GET;\n\n                if (pointingType instanceof PrimitiveTypeDef) {\n                        Value after = cast(pointingType, get, null, lineCol);\n                        return new Ins.PointerGetCastHelper(after, get);\n                } else {\n                        return new Ins.CheckCast(get, pointingType, lineCol);\n                }\n        }\n\n        public STypeDef getPointingType(STypeDef pointerT) throws SyntaxException {\n                STypeDef pointingType;\n                if (pointerT instanceof PointerType) {\n                        pointingType = ((PointerType) pointerT).getPointingType();\n                } else {\n                        pointingType = getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC);\n                }\n                return pointingType;\n        }\n\n        private SMethodDef LtRuntime_destruct;\n\n        public SMethodDef getLtRuntime_destruct() throws SyntaxException {\n                if (LtRuntime_destruct == null) {\n                        SClassDef c = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert c != null;\n                        for (SMethodDef m : c.methods()) {\n                                if (m.name().equals(\"destruct\")) {\n                                        LtRuntime_destruct = m;\n                                        break;\n                                }\n                        }\n                }\n                assert LtRuntime_destruct != null;\n                return LtRuntime_destruct;\n        }\n\n        private SMethodDef List_get;\n\n        public SMethodDef getList_get() throws SyntaxException {\n                if (List_get == null) {\n                        SInterfaceDef ListDef = (SInterfaceDef) getTypeWithName(\"java.util.List\", LineCol.SYNTHETIC);\n                        for (SMethodDef m : ListDef.methods()) {\n                                if (m.name().equals(\"get\") && m.getParameters().size() == 1\n                                        && m.getParameters().get(0).type().equals(IntTypeDef.get())) {\n                                        List_get = m;\n                                        break;\n                                }\n                        }\n                }\n                assert List_get != null;\n                return List_get;\n        }\n\n        private SMethodDef Map_get;\n\n        private SMethodDef getMap_get() throws SyntaxException {\n                if (Map_get == null) {\n                        SInterfaceDef MapDef = (SInterfaceDef) getTypeWithName(\"java.util.Map\", LineCol.SYNTHETIC);\n                        for (SMethodDef m : MapDef.methods()) {\n                                if (m.name().equals(\"get\") && m.getParameters().size() == 1\n                                        && m.getParameters().get(0).type().equals(getObject_Class())) {\n                                        Map_get = m;\n                                        break;\n                                }\n                        }\n                }\n                assert Map_get != null;\n                return Map_get;\n        }\n\n        private boolean destructCanChangeInLocalVariable(AST.Destruct d) throws SyntaxException {\n                if (d.modifiers.size() > 1) {\n                        err.SyntaxException(\"modifier for destruct should only be `var` or `val`\", d.line_col());\n                }\n                boolean isVar = false;\n                boolean isVal = false;\n                for (Modifier m : d.modifiers) {\n                        if (m.modifier == Modifier.Available.VAR) {\n                                isVar = true;\n                        } else if (m.modifier == Modifier.Available.VAL) {\n                                isVal = true;\n                        }\n                }\n                if (!isVal && !isVar && d.modifiers.size() > 0) {\n                        err.SyntaxException(\"modifier for destruct should only be `var` or `val`\", d.line_col());\n                }\n                return isVar;\n        }\n\n        /**\n         * parse destruct\n         *\n         * @param destruct AST destruct\n         * @param scope    scope\n         * @return bool result\n         * @throws SyntaxException compiling error\n         */\n        public Value parseValueFromDestruct(AST.Destruct destruct, SemanticScope scope) throws SyntaxException {\n                // generic type map\n                Map<String, STypeDef> genericTypeMap = getGenericMap(scope.type());\n\n                // imports\n                List<Import> imports = fileNameToImport.get(destruct.line_col().fileName);\n\n                // init value pack\n                ValuePack pack = new ValuePack(true);\n\n                Map<String, SFieldDef> nameToField = new HashMap<String, SFieldDef>(); // not used when pattern variables are defined as local variables\n                // define variables\n                for (AST.Pattern p : destruct.pattern.subPatterns) {\n                        assert (p instanceof AST.Pattern_Default || p instanceof AST.Pattern_Define);\n\n                        if (p instanceof AST.Pattern_Default) continue;\n                        AST.Pattern_Define pd = (AST.Pattern_Define) p;\n\n                        SFieldDef f = findFieldFromTypeDef(pd.name, scope.type(), scope.type(),\n                                scope.getThis() == null ? FIND_MODE_STATIC : FIND_MODE_NON_STATIC, true);\n                        if (f == null) {\n                                STypeDef type = getTypeWithAccess(new AST.Access(pd.type, \"*\", destruct.line_col()), genericTypeMap, imports);\n\n                                LocalVariable localVariable = new LocalVariable(type, destructCanChangeInLocalVariable(destruct));\n                                scope.putLeftValue(pd.name, localVariable);\n\n                                Ins.TStore storePtr = new Ins.TStore(localVariable,\n                                        constructPointer(false, false), scope, LineCol.SYNTHETIC, err);\n                                storePtr.flag |= Consts.IS_POINTER_NEW;\n                                pack.instructions().add(storePtr);\n                        } else {\n                                nameToField.put(pd.name, f);\n                        }\n                }\n\n                // unapply result list local variable\n                LocalVariable listLocalVar = new LocalVariable(getTypeWithName(\"java.util.List\", LineCol.SYNTHETIC), false);\n                scope.putLeftValue(scope.generateTempName(), listLocalVar);\n\n                // get result list\n                Ins.InvokeStatic getResList = new Ins.InvokeStatic(getLtRuntime_destruct(), destruct.line_col());\n                getResList.arguments().add(new IntValue(destruct.pattern.subPatterns.size())); // count\n                // destructClass\n                if (destruct.pattern.type == null) {\n                        getResList.arguments().add(NullValue.get());\n                } else {\n                        getResList.arguments().add(new Ins.GetClass(getTypeWithAccess(destruct.pattern.type, genericTypeMap, imports),\n                                (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                }\n                getResList.arguments().add(parseValueFromExpression(destruct.exp, null, scope)); // o\n                getResList.arguments().add(new Ins.GetClass(scope.type(),\n                        (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC))); // invoker\n\n                // store result list\n                Ins.TStore storeList = new Ins.TStore(listLocalVar,\n                        getResList, scope, LineCol.SYNTHETIC, err);\n                pack.instructions().add(storeList);\n\n                // init bool result value\n                LocalVariable boolResult = new LocalVariable(BoolTypeDef.get(), true);\n                scope.putLeftValue(scope.generateTempName(), boolResult);\n                Ins.TStore storeBoolResult = new Ins.TStore(boolResult, new BoolValue(false), scope, LineCol.SYNTHETIC, err);\n                pack.instructions().add(storeBoolResult);\n\n                // check list is null ?\n                Ins.Nop flagWhenEnd = new Ins.Nop();\n                // is null jump to flagWhenListIsNull\n                Ins.IfNull ifNull = new Ins.IfNull(new Ins.TLoad(listLocalVar, scope, LineCol.SYNTHETIC),\n                        flagWhenEnd, LineCol.SYNTHETIC);\n                pack.instructions().add(ifNull);\n\n                int index = -1;\n                for (AST.Pattern p : destruct.pattern.subPatterns) {\n                        ++index;\n                        if (p instanceof AST.Pattern_Default) continue;\n                        assert p instanceof AST.Pattern_Define;\n\n                        // assign value\n                        AST.Pattern_Define define = (AST.Pattern_Define) p;\n\n                        // List#get(int)\n                        SMethodDef get = getList_get();\n                        Ins.InvokeInterface invokeInterface = new Ins.InvokeInterface(\n                                new Ins.TLoad(listLocalVar, scope, destruct.line_col()),\n                                get, destruct.line_col());\n                        invokeInterface.arguments().add(new IntValue(index));\n\n                        // set value\n                        if (nameToField.containsKey(((AST.Pattern_Define) p).name)) {\n                                SFieldDef f = nameToField.get(((AST.Pattern_Define) p).name);\n                                if (scope.getThis() == null) {\n                                        pack.instructions().add(\n                                                new Ins.PutStatic(\n                                                        f,\n                                                        invokeInterface,\n                                                        LineCol.SYNTHETIC, err)\n                                        );\n                                } else {\n                                        pack.instructions().add(\n                                                new Ins.PutField(\n                                                        f,\n                                                        scope.getThis(),\n                                                        invokeInterface,\n                                                        LineCol.SYNTHETIC, err)\n                                        );\n                                }\n                        } else {\n                                LeftValue leftValue = scope.getLeftValue(define.name);\n                                leftValue.assign();\n                                Ins.TLoad tLoad = new Ins.TLoad(leftValue, scope, LineCol.SYNTHETIC);\n                                pack.instructions().add(invokePointerSet(\n                                        tLoad,\n                                        invokeInterface, destruct.line_col()\n                                ));\n                                // this is considered as `captured` for that\n                                // it's defined before they actually get assigned\n                                // and they might be used inside an if expression\n                                scope.getMeta().pointerLocalVar.add(tLoad.value());\n                        }\n                }\n\n                // store result as true\n                pack.instructions().add(new Ins.TStore(boolResult, new BoolValue(true), scope, LineCol.SYNTHETIC, err));\n\n                // flag when end\n                pack.instructions().add(flagWhenEnd);\n\n                // get result\n                pack.instructions().add(new Ins.TLoad(boolResult, scope, LineCol.SYNTHETIC));\n                return pack;\n        }\n\n        private boolean isAssignable(STypeDef sTypeDef, String typeName) throws SyntaxException {\n                return sTypeDef.isAssignableFrom(getTypeWithName(typeName, LineCol.SYNTHETIC));\n        }\n\n        private Value primitiveOrBoxed(STypeDef required, Value primitive) throws SyntaxException {\n                if (required instanceof PrimitiveTypeDef) {\n                        return primitive;\n                } else {\n                        return boxPrimitive(primitive, LineCol.SYNTHETIC);\n                }\n        }\n\n        /**\n         * parse value from expression<br>\n         * <ul>\n         * <li>{@link NumberLiteral} =&gt; different kinds of Numbers</li>\n         * <li>{@link BoolLiteral} =&gt; {@link BoolValue}</li>\n         * <li>{@link StringLiteral} =&gt; {@link StringConstantValue} or {@link CharValue}</li>\n         * <li>{@link VariableDef}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Invocation} =&gt; {@link lt.compiler.semantic.Ins.New} or {@link lt.compiler.semantic.Ins.Invoke}</li>\n         * <li>{@link lt.compiler.syntactic.AST.AsType}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Access}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Index}</li>\n         * <li>{@link OneVariableOperation} {@link UnaryOneVariableOperation}</li>\n         * <li>{@link TwoVariableOperation}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Assignment}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Null}</li>\n         * <li>{@link lt.compiler.syntactic.AST.ArrayExp} =&gt; array/java.util.LinkedList</li>\n         * <li>{@link lt.compiler.syntactic.AST.MapExp} =&gt; java.util.LinkedHashMap</li>\n         * <li>{@link lt.compiler.syntactic.AST.Procedure}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Lambda}</li>\n         * <li>{@link lt.compiler.syntactic.AST.TypeOf} =&gt; {@link lt.compiler.semantic.Ins.GetClass}</li>\n         * <li>{@link lt.compiler.syntactic.AST.AnnoExpression}</li>\n         * <li>{@link lt.compiler.syntactic.AST.Require}</li>\n         * </ul>\n         *\n         * @param exp          expression\n         * @param requiredType required type (null means no type limit)\n         * @param scope        a scope that contains local variables and local methods\n         * @return parsed result\n         * @throws SyntaxException exception\n         */\n        public Value parseValueFromExpression(Expression exp, STypeDef requiredType, SemanticScope scope) throws SyntaxException {\n                // generic type map\n                Map<String, STypeDef> genericTypeMap = scope == null ? Collections.<String, STypeDef>emptyMap() : getGenericMap(scope.type());\n                // handle\n                if (requiredType != null && isPointerType(requiredType)) {\n                        requiredType = getPointingType(requiredType);\n                }\n\n                List<Import> imports = fileNameToImport.get(exp.line_col().fileName);\n\n                Value v; // retrieved value without type check\n                // literals:\n                if (exp instanceof NumberLiteral) {\n                        try {\n                                if (isInt(requiredType, (NumberLiteral) exp, exp.line_col())) {\n                                        IntValue intValue = new IntValue(Integer.parseInt(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return intValue;\n                                        } else {\n                                                return boxPrimitive(intValue, exp.line_col());\n                                        }\n                                } else if (isLong(requiredType, (NumberLiteral) exp, exp.line_col())) {\n                                        LongValue longValue = new LongValue(Long.parseLong(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return longValue;\n                                        } else {\n                                                return boxPrimitive(longValue, exp.line_col());\n                                        }\n                                } else if (isShort(requiredType, (NumberLiteral) exp, exp.line_col())) {\n                                        ShortValue shortValue = new ShortValue(Short.parseShort(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return shortValue;\n                                        } else {\n                                                return boxPrimitive(shortValue, exp.line_col());\n                                        }\n                                } else if (isByte(requiredType, (NumberLiteral) exp, exp.line_col())) {\n                                        ByteValue byteValue = new ByteValue(Byte.parseByte(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return byteValue;\n                                        } else {\n                                                return boxPrimitive(byteValue, exp.line_col());\n                                        }\n                                } else if (isDouble(requiredType, exp.line_col())) {\n                                        DoubleValue doubleValue = new DoubleValue(Double.parseDouble(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return doubleValue;\n                                        } else {\n                                                return boxPrimitive(doubleValue, exp.line_col());\n                                        }\n                                } else if (isFloat(requiredType, exp.line_col())) {\n                                        FloatValue floatValue = new FloatValue(Float.parseFloat(((NumberLiteral) exp).literal()));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return floatValue;\n                                        } else {\n                                                return boxPrimitive(floatValue, exp.line_col());\n                                        }\n                                } else if (requiredType != null && (\n                                        requiredType.equals(BoolTypeDef.get()) ||\n                                                isAssignable(requiredType, \"java.lang.Boolean\")\n                                )) {\n                                        double dbl = Double.parseDouble(((NumberLiteral) exp).literal());\n                                        return primitiveOrBoxed(requiredType, new BoolValue(dbl != 0d));\n                                } else if (requiredType != null && (\n                                        requiredType.equals(CharTypeDef.get()) ||\n                                                isAssignable(requiredType, \"java.lang.Character\")\n                                )) {\n                                        int anInt = Integer.parseInt(((NumberLiteral) exp).literal());\n                                        return primitiveOrBoxed(requiredType, new CharValue((char) anInt));\n                                } else {\n                                        assert requiredType != null;\n                                        err.SyntaxException(exp + \" cannot be converted into \" + requiredType.fullName(), exp.line_col());\n                                        return null;\n                                }\n                        } catch (NumberFormatException e) {\n                                err.SyntaxException(exp + \" is not valid \" + requiredType, exp.line_col());\n                                return null;\n                        }\n                } else if (exp instanceof BoolLiteral) {\n                        if (isBool(requiredType, exp.line_col())) {\n                                String literal = ((BoolLiteral) exp).literal();\n                                boolean b;\n                                if (literal.equals(\"true\") || literal.equals(\"yes\")) {\n                                        b = true;\n                                } else if (literal.equals(\"false\") || literal.equals(\"no\")) {\n                                        b = false;\n                                } else {\n                                        throw new LtBug(literal + \" for bool literal\");\n                                }\n                                BoolValue boolValue = new BoolValue(b);\n                                if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                        return boolValue;\n                                } else {\n                                        return boxPrimitive(boolValue, exp.line_col());\n                                }\n                        } else {\n                                err.SyntaxException(exp + \" cannot be converted into \" + requiredType, exp.line_col());\n                                return null;\n                        }\n                } else if (exp instanceof StringLiteral) {\n                        String str = ((StringLiteral) exp).literal();\n                        // remove \"\" or ''\n                        str = str.substring(1);\n                        str = str.substring(0, str.length() - 1);\n                        str = unescape(str, exp.line_col());\n                        if (isChar(requiredType, (StringLiteral) exp, exp.line_col())) {\n                                assert str != null;\n                                if (str.length() == 1) {\n                                        CharValue charValue = new CharValue(str.charAt(0));\n                                        if (requiredType == null || requiredType instanceof PrimitiveTypeDef) {\n                                                return charValue;\n                                        } else {\n                                                return boxPrimitive(charValue, exp.line_col());\n                                        }\n                                } else {\n                                        err.SyntaxException(exp + \" cannot be converted into char, char must hold one character\", exp.line_col());\n                                        return null;\n                                }\n                        } else if (requiredType == null || requiredType.isAssignableFrom(getTypeWithName(\"java.lang.String\", exp.line_col()))) {\n                                return generateStringConcat(str, scope, exp.line_col());\n                        } else if (requiredType.equals(BoolTypeDef.get()) || isAssignable(requiredType, \"java.lang.Boolean\")) {\n                                return primitiveOrBoxed(requiredType, new BoolValue(!str.isEmpty()));\n                        } else {\n                                if (((StringLiteral) exp).literal().startsWith(\"'\") && str.length() == 1) {\n                                        // is char literal\n                                        int num = (int) str.charAt(0);\n                                        if (requiredType.equals(IntTypeDef.get()) || isAssignable(requiredType, \"java.lang.Integer\")) {\n                                                return primitiveOrBoxed(requiredType, new IntValue(num));\n                                        } else if (requiredType.equals(LongTypeDef.get()) || isAssignable(requiredType, \"java.lang.Long\")) {\n                                                return primitiveOrBoxed(requiredType, new LongValue(num));\n                                        } else if (requiredType.equals(FloatTypeDef.get()) || isAssignable(requiredType, \"java.lang.Float\")) {\n                                                return primitiveOrBoxed(requiredType, new FloatValue(num));\n                                        } else if (requiredType.equals(DoubleTypeDef.get()) || isAssignable(requiredType, \"java.lang.Double\")) {\n                                                return primitiveOrBoxed(requiredType, new DoubleValue(num));\n                                        } else if (requiredType.equals(ByteTypeDef.get()) || isAssignable(requiredType, \"java.lang.Byte\")) {\n                                                return primitiveOrBoxed(requiredType, new ByteValue((byte) num));\n                                        } else if (requiredType.equals(ShortTypeDef.get()) || isAssignable(requiredType, \"java.lang.Short\")) {\n                                                return primitiveOrBoxed(requiredType, new ShortValue((short) num));\n                                        }\n                                }\n                                err.SyntaxException(exp + \" cannot be converted into \" + requiredType, exp.line_col());\n                                return null;\n                        }\n                } else if (exp instanceof VariableDef) {\n                        // variable def\n                        // putField/putStatic/TStore\n                        v = parseValueFromVariableDef((VariableDef) exp, scope);\n                } else if (exp instanceof AST.Destruct) {\n                        v = parseValueFromDestruct((AST.Destruct) exp, scope);\n                } else if (exp instanceof AST.Invocation) {\n                        // parse invocation\n                        // the result can be invokeXXX or new\n                        if (((AST.Invocation) exp).invokeWithNames) {\n                                v = parseValueFromInvocationWithNames((AST.Invocation) exp, scope);\n                        } else if (((AST.Invocation) exp).exp instanceof AST.Access) {\n                                v = parseValueFromInvocation((AST.Invocation) exp, scope);\n                        } else {\n                                v = parseValueFromInvocationFunctionalObject((AST.Invocation) exp, scope);\n                        }\n                } else if (exp instanceof AST.AsType) {\n                        AST.AsType asType = (AST.AsType) exp;\n                        v = parseValueFromExpression(asType.exp, getTypeWithAccess(asType.type, genericTypeMap, imports), scope);\n                } else if (exp instanceof AST.Access) {\n                        // parse access\n                        if (((AST.Access) exp).name == null) {\n                                // name is null, then only parse the expression\n                                v = parseValueFromExpression(((AST.Access) exp).exp, requiredType, scope);\n                        } else {\n                                // the result can be getField/getStatic/xload/invokeStatic(dynamically get field)\n                                v = parseValueFromAccess((AST.Access) exp, scope, false);\n                        }\n                } else if (exp instanceof AST.Index) {\n                        // parse index\n                        // the result can be xxload/invokeStatic(dynatically get index)\n                        v = parseValueFromIndex((AST.Index) exp, scope);\n                } else if (exp instanceof OneVariableOperation | exp instanceof UnaryOneVariableOperation) {\n                        // parse one variable operation\n                        v = parseValueFromOneVarOp((Operation) exp, scope);\n                } else if (exp instanceof TwoVariableOperation) {\n                        // parse two variable operation\n                        v = parseValueFromTwoVarOp((TwoVariableOperation) exp, scope);\n                } else if (exp instanceof AST.Assignment) {\n                        v = parseValueFromAssignment((AST.Assignment) exp, scope);\n                } else if (exp instanceof AST.Null) {\n                        v = NullValue.get();\n                } else if (exp instanceof AST.ArrayExp) {\n                        v = parseValueFromArrayExp((AST.ArrayExp) exp, requiredType, scope);\n                } else if (exp instanceof AST.MapExp) {\n                        v = parseValueFromMapExp((AST.MapExp) exp, scope);\n                } else if (exp instanceof AST.Procedure) {\n                        v = parseValueFromProcedure((AST.Procedure) exp, requiredType, scope);\n                } else if (exp instanceof AST.Lambda) {\n                        v = parseValueFromLambda((AST.Lambda) exp, requiredType, scope);\n                } else if (exp instanceof AST.TypeOf) {\n                        STypeDef t = getTypeWithAccess(((AST.TypeOf) exp).type, genericTypeMap, imports);\n                        if (t.fullName().equals(\"lt.lang.Unit\")) {\n                                t = VoidType.get();\n                        }\n                        v = new Ins.GetClass(\n                                t, (SClassDef) getTypeWithName(\n                                \"java.lang.Class\",\n                                LineCol.SYNTHETIC\n                        ));\n                } else if (exp instanceof AST.AnnoExpression) {\n                        SAnno anno = new SAnno();\n                        AST.Anno astAnno = ((AST.AnnoExpression) exp).anno;\n                        STypeDef type = getTypeWithAccess(astAnno.anno, genericTypeMap, imports);\n                        if (!(type instanceof SAnnoDef)) {\n                                err.SyntaxException(type + \" is not annotation type\", astAnno.anno.line_col());\n                                return null;\n                        }\n                        anno.setAnnoDef((SAnnoDef) type);\n                        annotationRecorder.put(anno, astAnno);\n                        parseAnnoValues(Collections.singleton(anno));\n                        v = anno;\n                } else if (exp instanceof AST.Require) {\n                        // invoke LtRuntime.require(?,?)\n                        SMethodDef method = getLang_require();\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, exp.line_col());\n                        // caller class\n                        assert scope != null;\n                        invokeStatic.arguments().add(new Ins.GetClass(\n                                scope.type(),\n                                (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)\n                        ));\n                        // require file\n                        invokeStatic.arguments().add(parseValueFromExpression(\n                                ((AST.Require) exp).required,\n                                getTypeWithName(\"java.lang.String\", ((AST.Require) exp).required.line_col()),\n                                scope));\n                        v = invokeStatic;\n                } else if (exp instanceof AST.New) {\n                        v = parseValueFromNew((AST.New) exp, scope);\n                } else if (exp instanceof AST.GeneratorSpec) {\n                        v = parseValueFromGeneratorSpec((AST.GeneratorSpec) exp, requiredType, scope);\n                } else if (exp instanceof AST.PatternMatching) {\n                        v = parseValueFromPatternMatching((AST.PatternMatching) exp, requiredType, scope);\n                } else {\n                        throw new LtBug(\"unknown expression \" + exp);\n                }\n                return cast(requiredType, v, scope == null ? null : scope.type(), exp.line_col());\n        }\n\n        public Value parseValueFromPatternMatching(AST.PatternMatching pm,\n                                                   STypeDef requiredType,\n                                                   SemanticScope scope) throws SyntaxException {\n                // no patterns\n                if (pm.patternsToStatements.size() == 0) {\n                        // simply expand the value and return an Unit\n                        ValuePack vp = new ValuePack(true);\n\n                        // store the value\n                        Value valueToMatch = parseValueFromExpression(pm.expToMatch, null, scope);\n                        if (valueToMatch instanceof Instruction) {\n                                vp.instructions().add((Instruction) valueToMatch);\n                        }\n                        vp.instructions().add(invoke_Unit_get(LineCol.SYNTHETIC));\n                        return vp;\n                }\n\n                String fileName = pm.line_col().fileName;\n\n                // transform the `PatternMatching` into `Procedure`\n                // and invoke parseValueFromProcedure\n                List<Statement> stmts = new ArrayList<Statement>();\n                AST.Procedure procedure = new AST.Procedure(stmts, pm.line_col());\n\n                // store the expToMatch\n                // vExp = expToMatch\n                Expression exp = pm.expToMatch;\n                VariableDef vExp = new VariableDef(scope.generateTempName(), Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC_WITH_FILE(fileName));\n                vExp.setInit(exp);\n                procedure.statements.add(vExp);\n\n                // define some inner methods\n                // def patternMatching${hashCode}${count}\n                List<MethodDef> patternMethods = new ArrayList<MethodDef>();\n                int index = -1;\n                for (AST.PatternCondition ignore : pm.patternsToStatements.keySet()) {\n                        ++index;\n                        MethodDef methodDef = new MethodDef(\n                                \"patternMatching$\" + Integer.toHexString(Math.abs(pm.hashCode())) + \"$\" + index,\n                                Collections.<Modifier>emptySet(),\n                                null,\n                                Collections.singletonList(\n                                        new VariableDef(\"**\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC_WITH_FILE(fileName))\n                                ),\n                                Collections.<AST.Anno>emptySet(),\n                                new ArrayList<Statement>(),\n                                LineCol.SYNTHETIC_WITH_FILE(fileName)\n                        );\n                        patternMethods.add(methodDef);\n                }\n                for (int i = patternMethods.size() - 1; i >= 0; --i) {\n                        procedure.statements.add(patternMethods.get(i));\n                }\n\n                // parse these methods\n                index = -1;\n                for (Map.Entry<AST.PatternCondition, List<Statement>> patternListEntry : pm.patternsToStatements.entrySet()) {\n                        ++index;\n                        MethodDef currentMethod = patternMethods.get(index);\n                        MethodDef nextMethod = null;\n                        if (index + 1 < patternMethods.size()) {\n                                nextMethod = patternMethods.get(index + 1);\n                        }\n                        parsePatternMatchingMethod(patternListEntry, currentMethod, nextMethod, pm.line_col().fileName);\n                }\n\n                // invoke first method\n                AST.Invocation invocation = new AST.Invocation(\n                        new AST.Access(null, patternMethods.get(0).name, LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                        Collections.<Expression>singletonList(new AST.Access(null, vExp.getName(), LineCol.SYNTHETIC_WITH_FILE(fileName))),\n                        false, pm.line_col()\n                );\n                procedure.statements.add(invocation);\n\n                return parseValueFromProcedure(procedure, requiredType, scope);\n        }\n\n        private interface PatternMatchingParser {\n                List<Statement> parse(\n                        AST.Pattern pattern,\n                        List<Statement> statements,\n                        AST.If.IfPair anElse,\n                        String varName,\n                        String fileName\n                );\n        }\n\n        private class PatternMatchingDefaultParser implements PatternMatchingParser {\n                @Override\n                public List<Statement> parse(AST.Pattern pattern, List<Statement> statements, AST.If.IfPair anElse, String varName, String fileName) {\n                        return statements;\n                }\n        }\n\n        private class PatternMatchingTypeParser implements PatternMatchingParser {\n                @Override\n                public List<Statement> parse(AST.Pattern pattern, List<Statement> statements, AST.If.IfPair anElse, String varName, String fileName) {\n                        AST.If.IfPair testClass = new AST.If.IfPair(\n                                new TwoVariableOperation(\n                                        \"is\",\n                                        new AST.Access(null, varName, LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                        new AST.TypeOf(\n                                                ((AST.Pattern_Type) pattern).type,\n                                                LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                        LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                ), statements, LineCol.SYNTHETIC_WITH_FILE(fileName)\n                        );\n                        AST.If anIf = new AST.If(Arrays.asList(testClass, anElse), LineCol.SYNTHETIC_WITH_FILE(fileName));\n                        return Collections.<Statement>singletonList(anIf);\n                }\n        }\n\n        private class PatternMatchingValueParser implements PatternMatchingParser {\n                @Override\n                public List<Statement> parse(AST.Pattern pattern, List<Statement> statements, AST.If.IfPair anElse, String varName, String fileName) {\n                        AST.If.IfPair testValue = new AST.If.IfPair(\n                                new TwoVariableOperation(\n                                        \"is\",\n                                        new AST.Access(null, varName, LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                        ((AST.Pattern_Value) pattern).exp,\n                                        LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                ), statements, LineCol.SYNTHETIC_WITH_FILE(fileName)\n                        );\n                        AST.If anIf = new AST.If(Arrays.asList(testValue, anElse), LineCol.SYNTHETIC_WITH_FILE(fileName));\n                        return Collections.<Statement>singletonList(anIf);\n                }\n        }\n\n        private class PatternMatchingDefineParser implements PatternMatchingParser {\n                @Override\n                public List<Statement> parse(AST.Pattern pattern, List<Statement> statements, AST.If.IfPair anElse, String varName, String fileName) {\n                        // define value and assign it with **\n                        List<Statement> theList;\n                        if (!((AST.Pattern_Define) pattern).name.equals(varName)) {\n                                // val v = **\n                                VariableDef v = new VariableDef(((AST.Pattern_Define) pattern).name,\n                                        Collections.singleton(new Modifier(Modifier.Available.VAL, LineCol.SYNTHETIC_WITH_FILE(fileName))),\n                                        Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC_WITH_FILE(fileName));\n                                v.setType(((AST.Pattern_Define) pattern).type);\n                                v.setInit(new AST.Access(null, varName, LineCol.SYNTHETIC_WITH_FILE(fileName)));\n                                theList = new ArrayList<Statement>();\n                                theList.add(v);\n                                theList = new BindList<Statement>(theList, statements);\n                        } else {\n                                theList = statements;\n                        }\n\n                        if (((AST.Pattern_Define) pattern).type != null) {\n                                AST.If.IfPair testClass = new AST.If.IfPair(\n                                        new TwoVariableOperation(\n                                                \"is\",\n                                                new AST.Access(null, varName, LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                                new AST.TypeOf(\n                                                        ((AST.Pattern_Define) pattern).type,\n                                                        LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                                LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                        ), theList, LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                );\n                                AST.If anIf = new AST.If(Arrays.asList(testClass, anElse), LineCol.SYNTHETIC_WITH_FILE(fileName));\n                                return Collections.<Statement>singletonList(anIf);\n                        } else {\n                                return statements;\n                        }\n                }\n        }\n\n        private class PatternMatchingDestructParser implements PatternMatchingParser {\n                private final int initialCount;\n\n                private PatternMatchingDestructParser(int initialCount) {\n                        this.initialCount = initialCount;\n                }\n\n                @Override\n                public List<Statement> parse(AST.Pattern pattern, List<Statement> statements, AST.If.IfPair anElse, String varName, String fileName) {\n                        // check if null\n                        List<Statement> stmtsInCheckNull = new ArrayList<Statement>();\n                        AST.If checkNull = new AST.If(Arrays.asList(\n                                new AST.If.IfPair(\n                                        new TwoVariableOperation(\n                                                \"not\",\n                                                new AST.Access(null, varName, LineCol.SYNTHETIC),\n                                                new AST.Null(LineCol.SYNTHETIC),\n                                                LineCol.SYNTHETIC\n                                        ),\n                                        stmtsInCheckNull,\n                                        LineCol.SYNTHETIC\n                                ),\n                                anElse\n                        ), LineCol.SYNTHETIC);\n\n                        // use destruct <-\n                        AST.Pattern_Destruct patternDestruct = (AST.Pattern_Destruct) pattern;\n                        // construct a destruct without type def\n                        // arg index\n                        int count = initialCount;\n                        // tmpName count\n                        int tmpNameCount = 0;\n                        List<AST.Pattern> tmpList = new ArrayList<AST.Pattern>();\n                        for (AST.Pattern p : patternDestruct.subPatterns) {\n                                ++count;\n                                ++tmpNameCount;\n\n                                if (p.patternType == AST.PatternType.TYPE) {\n                                        tmpList.add(new AST.Pattern_Define(\"**\" + count, null));\n                                        continue;\n                                }\n                                if (p.patternType == AST.PatternType.DEFINE && ((AST.Pattern_Define) p).type != null) {\n                                        tmpList.add(new AST.Pattern_Define(((AST.Pattern_Define) p).name, null));\n                                        continue;\n                                }\n                                if (p.patternType == AST.PatternType.VALUE) {\n                                        tmpList.add(new AST.Pattern_Define(\"**\" + count, null));\n                                        continue;\n                                }\n                                if (p.patternType == AST.PatternType.DESTRUCT) {\n                                        tmpList.add(new AST.Pattern_Define(\"**\" + count, null));\n                                        continue;\n                                }\n\n                                --tmpNameCount;\n                                tmpList.add(p);\n                        }\n                        AST.Pattern_Destruct patternDestructWithoutTypeDef = new AST.Pattern_Destruct(\n                                patternDestruct.type,\n                                tmpList\n                        );\n\n                        AST.Destruct doDestruct = new AST.Destruct(Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(),\n                                patternDestructWithoutTypeDef, new AST.Access(null, varName, LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                        List<Statement> stmtsInDestruct;\n                        if (tmpNameCount > 0) {\n                                stmtsInDestruct = new ArrayList<Statement>();\n                        } else {\n                                stmtsInDestruct = statements;\n                        }\n                        AST.If destructIf = new AST.If(\n                                Arrays.asList(\n                                        new AST.If.IfPair(doDestruct, stmtsInDestruct, LineCol.SYNTHETIC),\n                                        anElse\n                                ), LineCol.SYNTHETIC\n                        );\n                        stmtsInCheckNull.add(destructIf);\n\n                        if (tmpNameCount > 0) {\n                                // apply patterns on these variables\n                                List<Statement> currentStmts = stmtsInDestruct;\n                                for (int i = 0; i < patternDestruct.subPatterns.size(); ++i) {\n                                        AST.Pattern sub = patternDestruct.subPatterns.get(i);\n                                        AST.Pattern x = patternDestructWithoutTypeDef.subPatterns.get(i);\n                                        String tmpName = null;\n                                        if (x instanceof AST.Pattern_Define) {\n                                                tmpName = ((AST.Pattern_Define) x).name;\n                                        }\n                                        PatternMatchingParser parser;\n                                        if (sub.patternType == AST.PatternType.TYPE) {\n                                                parser = new PatternMatchingTypeParser();\n                                        } else if (sub.patternType == AST.PatternType.DEFINE) {\n                                                AST.Access type = ((AST.Pattern_Define) sub).type;\n                                                if (type == null) continue;\n                                                parser = new PatternMatchingDefineParser();\n                                        } else if (sub.patternType == AST.PatternType.VALUE) {\n                                                parser = new PatternMatchingValueParser();\n                                        } else if (sub.patternType == AST.PatternType.DESTRUCT) {\n                                                parser = new PatternMatchingDestructParser(count);\n                                        } else continue;\n\n                                        // handle\n                                        assert tmpName != null;\n                                        --tmpNameCount;\n\n                                        List<Statement> list;\n                                        if (tmpNameCount == 0) {\n                                                list = statements;\n                                        } else {\n                                                list = new ArrayList<Statement>();\n                                        }\n                                        currentStmts.addAll(parser.parse(\n                                                sub, list, anElse, tmpName, fileName\n                                        ));\n\n                                        currentStmts = list;\n                                }\n                        }\n\n                        return Collections.<Statement>singletonList(checkNull);\n                }\n        }\n\n        private void parsePatternMatchingMethod(Map.Entry<AST.PatternCondition, List<Statement>> patternListEntry,\n                                                MethodDef currentMethod,\n                                                MethodDef nextMethod,\n                                                String fileName) throws SyntaxException {\n                AST.PatternCondition p = patternListEntry.getKey();\n                List<Statement> statements = patternListEntry.getValue();\n\n                AST.If.IfPair anElse;\n                if (nextMethod == null) {\n                        // throw when else\n                        anElse = new AST.If.IfPair(\n                                null,\n                                Collections.<Statement>singletonList(\n                                        new AST.Throw(\n                                                new AST.Invocation(\n                                                        new AST.Access(\n                                                                new AST.PackageRef(\"lt::runtime\", LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                                                \"MatchError\",\n                                                                LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                                        Collections.<Expression>emptyList(),\n                                                        false,\n                                                        LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                                ), LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                        )\n                                ),\n                                LineCol.SYNTHETIC_WITH_FILE(fileName));\n                } else {\n                        // invoke nextMethod\n                        anElse = new AST.If.IfPair(\n                                null,\n                                Collections.<Statement>singletonList(\n                                        new AST.Return(\n                                                new AST.Invocation(\n                                                        new AST.Access(null, nextMethod.name, LineCol.SYNTHETIC_WITH_FILE(fileName)),\n                                                        Collections.<Expression>singletonList(\n                                                                new AST.Access(null, \"**\", LineCol.SYNTHETIC_WITH_FILE(fileName))\n                                                        ),\n                                                        false,\n                                                        LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                                ),\n                                                LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                        )\n                                ),\n                                LineCol.SYNTHETIC_WITH_FILE(fileName));\n                }\n                // statements should be packed into `if condition` if the condition exists\n                if (p.condition != null) {\n                        statements = Collections.<Statement>singletonList(\n                                new AST.If(\n                                        Arrays.asList(\n                                                new AST.If.IfPair(p.condition, statements, p.condition.line_col()),\n                                                anElse\n                                        ), LineCol.SYNTHETIC_WITH_FILE(fileName)\n                                )\n                        );\n                }\n\n                PatternMatchingParser patternMatchingParser;\n                switch (p.pattern.patternType) {\n                        case DEFAULT:\n                                patternMatchingParser = new PatternMatchingDefaultParser();\n                                break;\n                        case TYPE:\n                                patternMatchingParser = new PatternMatchingTypeParser();\n                                break;\n                        case VALUE:\n                                patternMatchingParser = new PatternMatchingValueParser();\n                                break;\n                        case DEFINE:\n                                patternMatchingParser = new PatternMatchingDefineParser();\n                                break;\n                        case DESTRUCT:\n                                patternMatchingParser = new PatternMatchingDestructParser(-1);\n                                break;\n                        default:\n                                throw new LtBug(\"unknown pattern matching type \" + p.pattern.patternType);\n                }\n                currentMethod.body.addAll(patternMatchingParser.parse(\n                        p.pattern, statements, anElse, \"**\", fileName\n                ));\n        }\n\n        public Value parseValueFromGeneratorSpec(AST.GeneratorSpec gs, STypeDef requiredType, SemanticScope scope) throws SyntaxException {\n                STypeDef type = getTypeWithAccess(gs.type, getGenericMap(scope.type()), fileNameToImport.get(gs.line_col().fileName));\n                if (type instanceof SClassDef && !((SClassDef) type).modifiers().contains(SModifier.ABSTRACT)) {\n                        Class<?> c;\n                        try {\n                                c = loadClass(type.fullName());\n                        } catch (ClassNotFoundException e) {\n                                err.SyntaxException(type.fullName() + \" has not been compiled\", gs.type.line_col());\n                                return null;\n                        }\n                        if (!SourceGenerator.class.isAssignableFrom(c)) {\n                                err.SyntaxException(type.fullName() + \" is not implementation of lt::generator::SourceGenerator\", gs.type.line_col());\n                                return null;\n                        }\n                        Constructor<?> con;\n                        try {\n                                con = c.getConstructor();\n                        } catch (NoSuchMethodException e) {\n                                err.SyntaxException(\"cannot find constructor : \" + type.fullName() + \"()\", gs.type.line_col());\n                                return null;\n                        }\n                        SourceGenerator sourceGen;\n                        try {\n                                sourceGen = (SourceGenerator) con.newInstance();\n                        } catch (InvocationTargetException t) {\n                                if (t.getTargetException() instanceof SyntaxException) {\n                                        throw (SyntaxException) t.getTargetException();\n                                } else {\n                                        throw new LtBug(\"caught exception in generator\", t);\n                                }\n                        } catch (Throwable e) {\n                                throw new LtBug(\"caught exception in generator\", e);\n                        }\n                        sourceGen.init(gs.ast, this, scope, gs.line_col(), err);\n\n                        if (sourceGen.resultType() == SourceGenerator.EXPRESSION) {\n                                Expression exp = (Expression) sourceGen.generate();\n                                return parseValueFromExpression(exp, requiredType, scope);\n                        } else if (sourceGen.resultType() == SourceGenerator.SERIALIZE) {\n                                Serializable ser = (Serializable) sourceGen.generate();\n                                String serStr = serializeObjectToString(ser);\n                                return decodeSerExp(serStr, scope, gs.line_col());\n                        } else if (sourceGen.resultType() == SourceGenerator.VALUE) {\n                                return (Value) sourceGen.generate();\n                        } else {\n                                throw new LtBug(\"unknown resultType in \" + c);\n                        }\n                } else {\n                        err.SyntaxException(\"Generator should be a class\", gs.line_col());\n                        return null;\n                }\n        }\n\n        private String serializeObjectToString(Serializable ser) {\n                ByteArrayOutputStream baos = new ByteArrayOutputStream();\n                ObjectOutputStream oos = null;\n                try {\n                        oos = new ObjectOutputStream(baos);\n                        oos.writeObject(ser);\n                } catch (IOException e) {\n                        throw new LtBug(e);\n                } finally {\n                        if (oos != null) {\n                                try {\n                                        oos.close();\n                                } catch (IOException e) {\n                                        e.printStackTrace();\n                                }\n                        }\n                }\n                return byte2hex(baos.toByteArray());\n        }\n\n        public Value decodeSerExp(String serStr, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                String ObjectInputStream_Name = ObjectInputStream.class.getName();\n                String InputStream_Name = InputStream.class.getName();\n                String ByteArrayInputStream_Name = ByteArrayInputStream.class.getName();\n                SClassDef ObjectInputStream = (SClassDef) getTypeWithName(ObjectInputStream_Name, lineCol);\n                assert ObjectInputStream != null;\n                STypeDef InputStream = getTypeWithName(InputStream_Name, lineCol);\n                assert InputStream != null;\n                SClassDef ByteArrayInputStream = (SClassDef) getTypeWithName(ByteArrayInputStream_Name, lineCol);\n                assert ByteArrayInputStream != null;\n                STypeDef byte1Array = getTypeWithName(\"[B\", lineCol);\n                assert byte1Array != null;\n                SClassDef StringCls = (SClassDef) getTypeWithName(\"java.lang.String\", lineCol);\n                assert StringCls != null;\n                SClassDef SemanticProcessor = (SClassDef) getTypeWithName(lt.compiler.SemanticProcessor.class.getName(), lineCol);\n                assert SemanticProcessor != null;\n\n                SConstructorDef ObjectInputStream_con = null;\n                // find constructor\n                for (SConstructorDef con : ObjectInputStream.constructors()) {\n                        if (con.getParameters().size() == 1 && con.getParameters().get(0).type().equals(InputStream)) {\n                                // found constructor\n                                ObjectInputStream_con = con;\n                                break;\n                        }\n                }\n                if (ObjectInputStream_con == null)\n                        throw new LtBug(ObjectInputStream_Name + \"(\" + InputStream_Name + \") should exist\");\n                SMethodDef readObject = null;\n                // find readObject method\n                for (SMethodDef method : ObjectInputStream.methods()) {\n                        if (method.name().equals(\"readObject\") && method.getParameters().size() == 0) {\n                                readObject = method;\n                                break;\n                        }\n                }\n                if (readObject == null) throw new LtBug(ObjectInputStream_Name + \".readObject() should exist\");\n                SConstructorDef ByteArrayInputStream_con = null;\n                // find constructor\n                for (SConstructorDef con : ByteArrayInputStream.constructors()) {\n                        if (con.getParameters().size() == 1 && con.getParameters().get(0).type().equals(byte1Array)) {\n                                ByteArrayInputStream_con = con;\n                                break;\n                        }\n                }\n                if (ByteArrayInputStream_con == null)\n                        throw new LtBug(ByteArrayInputStream_Name + \"(byte[]) should exist\");\n                // find hex2byte(String)\n                SMethodDef hex2byte = null;\n                for (SMethodDef method : SemanticProcessor.methods()) {\n                        if (method.name().equals(\"hex2byte\") && method.getParameters().size() == 1 && method.getParameters().get(0).type().equals(StringCls)) {\n                                hex2byte = method;\n                                break;\n                        }\n                }\n                if (hex2byte == null)\n                        throw new LtBug(lt.compiler.SemanticProcessor.class.getName() + \".hex2byte should exist\");\n\n                // do handling\n                ValuePack vp = new ValuePack(true);\n                // theSerValue\n                StringConstantValue theSerValue = new StringConstantValue(serStr);\n                theSerValue.setType(StringCls);\n                // hex2byte(theSerValue)\n                Ins.InvokeStatic invokeHex2byte = new Ins.InvokeStatic(hex2byte, lineCol);\n                invokeHex2byte.arguments().add(theSerValue);\n                // new ByteArrayInputStream(...)\n                Ins.New aNew1 = new Ins.New(ByteArrayInputStream_con, lineCol);\n                aNew1.args().add(invokeHex2byte);\n                // new ObjectInputStream(...)\n                Ins.New aNew2 = new Ins.New(ObjectInputStream_con, lineCol);\n                aNew2.args().add(aNew1);\n                // store\n                LocalVariable local = new LocalVariable(aNew2.type(), false);\n                scope.putLeftValue(scope.generateTempName(), local);\n                Ins.TStore store = new Ins.TStore(local, aNew2, scope, lineCol, err);\n\n                vp.instructions().add(store);\n\n                // x.readObject()\n                Ins.InvokeVirtual invokeReadObject = new Ins.InvokeVirtual(\n                        new Ins.TLoad(local, scope, lineCol), readObject, lineCol);\n                vp.instructions().add(invokeReadObject);\n                return vp;\n        }\n\n        /**\n         * parse value from new\n         *\n         * @param aNew  new\n         * @param scope semantic scope\n         * @return constructing a new object\n         * @throws SyntaxException compiling error\n         */\n        public Value parseValueFromNew(AST.New aNew, SemanticScope scope) throws SyntaxException {\n                SClassDef type;\n                try {\n                        type = (SClassDef) getTypeWithAccess((AST.Access) aNew.invocation.exp,\n                                getGenericMap(scope.type()),\n                                fileNameToImport.get(aNew.line_col().fileName));\n                } catch (Throwable t) {\n                        err.SyntaxException(aNew.invocation.exp + \" is not a class\", aNew.line_col());\n                        return null;\n                }\n                assert type != null;\n                if (type.modifiers().contains(SModifier.ABSTRACT)) {\n                        err.SyntaxException(\"abstract class cannot be instantiated\", aNew.line_col());\n                        return null;\n                }\n                List<Value> argList = new ArrayList<Value>();\n                for (Expression e : aNew.invocation.args) {\n                        argList.add(parseValueFromExpression(e, null, scope));\n                }\n                return constructingNewInst(type, argList, scope, aNew.line_col());\n        }\n\n        /**\n         * {@link LtRuntime#getField(Object, String, Class)}\n         */\n        private SMethodDef Lang_require = null;\n\n        /**\n         * @return {@link LtRuntime#getField(Object, String, Class)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_require() throws SyntaxException {\n                if (Lang_require == null) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"require\")) {\n                                        Lang_require = m;\n                                        break;\n                                }\n                        }\n                }\n                if (Lang_require == null)\n                        throw new LtBug(\"lt.runtime.LtRuntime.require(Class,String) should exist\");\n                return Lang_require;\n        }\n\n        /**\n         * parse expressions like this:<br>\n         * <pre>\n         * User(id=1, name='n')\n         * </pre>\n         *\n         * @param invocation the invocation\n         * @param scope      current scope\n         * @return ValuePack, the pack result is the constructed variable\n         * @throws SyntaxException compiling error\n         */\n        public ValuePack parseValueFromInvocationWithNames(AST.Invocation invocation, SemanticScope scope) throws SyntaxException {\n                STypeDef theType;\n                try {\n                        theType = getTypeWithAccess((AST.Access) invocation.exp,\n                                getGenericMap(scope.type()),\n                                fileNameToImport.get(invocation.line_col().fileName));\n                } catch (Throwable t) {\n                        err.SyntaxException(invocation.exp + \" is not a type\", invocation.exp.line_col());\n                        return null;\n                }\n                if (theType instanceof SInterfaceDef) {\n                        err.SyntaxException(\"cannot instantiate interfaces\", invocation.line_col());\n                        return null;\n                }\n                SClassDef classType = (SClassDef) theType;\n                assert classType != null;\n\n                int count = 0;\n                List<Value> constructingArgs = new ArrayList<Value>();\n                for (Expression exp : invocation.args) {\n                        if (!(exp instanceof VariableDef)\n                                || ((VariableDef) exp).getInit() == null) {\n                                ++count;\n                                constructingArgs.add(\n                                        parseValueFromExpression(exp, null, scope)\n                                );\n                        }\n                }\n\n                ValuePack valuePack = new ValuePack(true);\n                valuePack.setType(theType);\n\n                LocalVariable local = new LocalVariable(theType, false);\n                String name = scope.generateTempName();\n                scope.putLeftValue(name, local);\n\n                Value aNew = constructingNewInst(classType, constructingArgs, scope, invocation.line_col());\n                Ins.TStore store = new Ins.TStore(local, aNew, scope, invocation.line_col(), err);\n                valuePack.instructions().add(store);\n\n                for (int i = count; i < invocation.args.size(); ++i) {\n                        Expression exp = invocation.args.get(i);\n                        VariableDef v = (VariableDef) exp;\n                        Expression initValue = v.getInit();\n\n                        String n = v.getName();\n                        // ?.x = initValue\n                        AST.Assignment ass = new AST.Assignment(\n                                new AST.Access(\n                                        new AST.Access(null, name, invocation.line_col()),\n                                        n,\n                                        LineCol.SYNTHETIC\n                                ),\n                                \"=\",\n                                initValue,\n                                LineCol.SYNTHETIC\n                        );\n\n                        parseStatement(\n                                ass, null, scope, valuePack.instructions(), null, null, null, false\n                        );\n                }\n\n                valuePack.instructions().add(new Ins.TLoad(local, scope, invocation.line_col()));\n                return valuePack;\n        }\n\n        /**\n         * get interfaces defined in package `lt.lang.function`\n         *\n         * @param argCount argument count\n         * @param lineCol  line-col\n         * @return Function0 to Function 26\n         * @throws SyntaxException exception\n         */\n        public SInterfaceDef getDefaultLambdaFunction(int argCount, LineCol lineCol) throws SyntaxException {\n                if (argCount > 26) {\n                        err.SyntaxException(\"too may arguments for a lambda expression, maximum arg count is 26\", lineCol);\n                        return null;\n                }\n                String className = \"lt.lang.function.Function\" + argCount;\n                return (SInterfaceDef) getTypeWithName(className, lineCol);\n        }\n\n        /**\n         * retrieve abstract method and possible constructor for the lambda\n         *\n         * @param requiredType                         required type\n         * @param constructorWithZeroParamAndCanAccess the constructor, use array[0] to store the constructor, maybe null\n         * @param methodToOverride                     the method to override, use array[0] to store the method, not null\n         * @return true if lambda can be used on the required type. false otherwise\n         */\n        public boolean getMethodForLambda(STypeDef requiredType,\n                                          SConstructorDef[] constructorWithZeroParamAndCanAccess,\n                                          SMethodDef[] methodToOverride) {\n                if (requiredType instanceof SClassDef) {\n                        if (((SClassDef) requiredType).modifiers().contains(SModifier.ABSTRACT)) {\n                                SClassDef c = (SClassDef) requiredType;\n                                // check constructors\n                                for (SConstructorDef con : c.constructors()) {\n                                        if (con.getParameters().size() == 0) {\n                                                // 0 param\n                                                if (con.modifiers().contains(SModifier.PUBLIC)) {\n                                                        // constructor can access\n                                                        constructorWithZeroParamAndCanAccess[0] = con;\n                                                        break;\n                                                }\n                                        }\n                                }\n                                if (constructorWithZeroParamAndCanAccess[0] != null) {\n\n                                        // check unimplemented methods\n                                        int count = 0;\n                                        // record all abstract classes\n                                        List<SClassDef> classes = new ArrayList<SClassDef>();\n                                        while (c.modifiers().contains(SModifier.ABSTRACT)) {\n                                                classes.add(c);\n                                                c = c.parent();\n                                        }\n                                        // check class abstract methods\n                                        out:\n                                        for (SClassDef cls : classes) {\n                                                for (SMethodDef m : cls.methods()) {\n                                                        if (m.modifiers().contains(SModifier.ABSTRACT)) {\n                                                                boolean isOverridden = false;\n                                                                for (SMethodDef o : m.overridden()) {\n                                                                        //noinspection SuspiciousMethodCalls\n                                                                        if (classes.contains(o.declaringType())) {\n                                                                                isOverridden = true;\n                                                                                break;\n                                                                        }\n                                                                }\n                                                                if (!isOverridden) {\n                                                                        ++count;\n                                                                        if (count > 1) break out;\n                                                                        methodToOverride[0] = m;\n                                                                }\n                                                        }\n                                                }\n                                        }\n                                        if (count <= 1) {\n                                                // record all interfaces\n                                                Set<SInterfaceDef> interfaces = new HashSet<SInterfaceDef>();\n                                                Queue<SInterfaceDef> q = new ArrayDeque<SInterfaceDef>();\n                                                for (SInterfaceDef i : ((SClassDef) requiredType).superInterfaces()) {\n                                                        q.add(i);\n                                                        interfaces.add(i);\n                                                }\n                                                while (!q.isEmpty()) {\n                                                        SInterfaceDef i = q.remove();\n                                                        for (SInterfaceDef ii : i.superInterfaces()) {\n                                                                interfaces.add(ii);\n                                                                q.add(ii);\n                                                        }\n                                                }\n                                                // check interfaces\n                                                out:\n                                                for (SInterfaceDef i : interfaces) {\n                                                        for (SMethodDef m : i.methods()) {\n                                                                if (m.modifiers().contains(SModifier.ABSTRACT)) {\n                                                                        boolean isOverridden = false;\n                                                                        for (SMethodDef o : m.overridden()) {\n                                                                                //noinspection SuspiciousMethodCalls\n                                                                                if (interfaces.contains(o.declaringType())\n                                                                                        ||\n                                                                                        classes.contains(o.declaringType())) {\n                                                                                        isOverridden = true;\n                                                                                        break;\n                                                                                }\n                                                                        }\n                                                                        if (!isOverridden) {\n                                                                                ++count;\n                                                                                if (count > 1) break out;\n                                                                                methodToOverride[0] = m;\n                                                                        }\n                                                                }\n                                                        }\n                                                }\n                                        }\n                                        if (count == 1) return true;\n                                }\n                        }\n                } else if (requiredType instanceof SInterfaceDef) {\n                        int count = 0;\n                        // record all super interfaces\n                        Set<SInterfaceDef> interfaces = new HashSet<SInterfaceDef>();\n                        Queue<SInterfaceDef> q = new ArrayDeque<SInterfaceDef>();\n                        q.add((SInterfaceDef) requiredType);\n                        interfaces.add((SInterfaceDef) requiredType);\n                        while (!q.isEmpty()) {\n                                SInterfaceDef i = q.remove();\n                                for (SInterfaceDef ii : i.superInterfaces()) {\n                                        interfaces.add(ii);\n                                        q.add(ii);\n                                }\n                        }\n                        // check interfaces\n                        out:\n                        for (SInterfaceDef i : interfaces) {\n                                for (SMethodDef m : i.methods()) {\n                                        if (m.modifiers().contains(SModifier.ABSTRACT)) {\n                                                // check whether it's overridden\n                                                boolean isOverridden = false;\n                                                for (SMethodDef o : m.overridden()) {\n                                                        //noinspection SuspiciousMethodCalls\n                                                        if (interfaces.contains(o.declaringType())) {\n                                                                // overridden\n                                                                isOverridden = true;\n                                                        }\n                                                }\n                                                if (!isOverridden) {\n                                                        ++count;\n                                                        if (count > 1) break out;\n                                                        methodToOverride[0] = m;\n                                                }\n                                        }\n                                }\n                        }\n                        if (count == 1) return true;\n                }\n\n                return false;\n        }\n\n        /**\n         * parse lambda<br>\n         * it creates a new class for the lambda<br>\n         * <pre>\n         * class LambdaClassName extends SomeFunctionalAbstractClass { // may be implements SomeFunctionalInterface\n         *         Object o;\n         *         List local;\n         *         LambdaClassName(Object o, List local){\n         *                 this.o=o;\n         *                 this.local=local;\n         *         }\n         *         public Object theAbstractMethodToImpl(Object x,Object y) {\n         *                 return o.someMethod(x, y, local.get(0), local.get(1), ... )\n         *         }\n         * }\n         * </pre>\n         *\n         * @param lambda       lambda\n         * @param requiredType required type\n         * @param scope        current scope\n         * @return return the new instance\n         * @throws SyntaxException compile error\n         * @see #buildAClassForLambda(STypeDef, boolean, SMethodDef, SConstructorDef, SInterfaceDef, boolean, int, SMethodDef)\n         */\n        public Value parseValueFromLambda(AST.Lambda lambda, STypeDef requiredType, SemanticScope scope) throws SyntaxException {\n                SMethodDef methodToOverride;\n                SConstructorDef constructorWithZeroParamAndCanAccess = null;\n                if (requiredType == null || requiredType.fullName().equals(\"java.lang.Object\")) {\n                        SInterfaceDef interfaceDef = getDefaultLambdaFunction(lambda.params.size(), lambda.line_col());\n                        assert interfaceDef != null;\n\n                        requiredType = interfaceDef;\n                        methodToOverride = interfaceDef.methods().get(0);\n                } else {\n                        // examine whether it's a functional interface\n                        // or it's an abstract class with only one unimplemented method and accessible constructor with no params\n                        SConstructorDef[] cons_arr = new SConstructorDef[1];\n                        SMethodDef[] method_arr = new SMethodDef[1];\n                        boolean valid = getMethodForLambda(requiredType, cons_arr, method_arr);\n                        methodToOverride = method_arr[0];\n                        constructorWithZeroParamAndCanAccess = cons_arr[0];\n\n                        if (!valid) {\n                                err.SyntaxException(\"lambda should be subtype of functional interface or abstract class with only one unimplemented method and a constructor with no params, but got \" + requiredType, lambda.line_col());\n                                return null;\n                        }\n                }\n\n                if (methodToOverride == null) throw new LtBug(\"methodToOverride should not be null\");\n                if (methodToOverride.getParameters().size() != lambda.params.size()) {\n                        err.SyntaxException(\"lambda parameter count differs from \" + methodToOverride, lambda.line_col());\n                        return null;\n                }\n\n                String methodName = methodToOverride.name() + \"$lambda$\";\n                int i = 0;\n                while (scope.getInnerMethod(methodName + i) != null) ++i;\n                methodName += i;\n                STypeDef returnType = methodToOverride.getReturnType();\n                MethodDef methodDef = new MethodDef(\n                        methodName,\n                        Collections.<Modifier>emptySet(),\n                        new AST.Access(\n                                returnType.pkg() == null\n                                        ? null\n                                        : new AST.PackageRef(returnType.pkg(), LineCol.SYNTHETIC),\n                                returnType.fullName().contains(\".\")\n                                        ? returnType.fullName().substring(returnType.fullName().lastIndexOf('.') + 1)\n                                        : returnType.fullName(),\n                                LineCol.SYNTHETIC\n                        ),\n                        lambda.params,\n                        Collections.<AST.Anno>emptySet(),\n                        lambda.statements,\n                        LineCol.SYNTHETIC\n                );\n                SMethodDef innerMethod = parseInnerMethod(methodDef, scope, true);\n                assert innerMethod != null;\n                innerMethod.modifiers().remove(SModifier.PRIVATE); // it should be package access\n                methodToStatements.put(innerMethod, lambda.statements);\n\n                List<Ins.TLoad> args = new ArrayList<Ins.TLoad>();\n                for (LeftValue l : scope.getLeftValues(innerMethod.getParameters().size() - lambda.params.size(), true)) {\n                        args.add(new Ins.TLoad(l, scope, LineCol.SYNTHETIC));\n                }\n\n                if (constructorWithZeroParamAndCanAccess == null && !(requiredType instanceof SInterfaceDef))\n                        throw new LtBug(\"constructorWithZeroParamAndCanAccess should not be null\");\n                // construct a class\n                // class XXX(methodHandle:MethodHandle, o:Object, local:List) : C\n                //     public self = this\n                //     methodToOverride(xxx)\n                //         local.add(?)\n                //         ...\n                //         methodHandle.invokeExact(o,local)\n\n                // constructor arguments\n                List<Value> consArgs = new ArrayList<Value>();\n                // o\n                if (scope.getThis() != null) consArgs.add(scope.getThis());\n                // local\n                Ins.NewMap newMap = new Ins.NewMap(getTypeWithName(HashMap.class.getName(), LineCol.SYNTHETIC));\n                for (int index = 0; index < args.size(); ++index) {\n                        Value arg = args.get(index);\n                        if (!innerMethod.getParameters().get(index).isUsed()) {\n                                continue;\n                        }\n\n                        // mark the variable as `captured by lambda`\n                        scope.getMeta().pointerLocalVar.add(((Ins.TLoad) arg).value());\n\n                        if (arg.type() instanceof PrimitiveTypeDef) {\n                                arg = boxPrimitive(arg, LineCol.SYNTHETIC);\n                        }\n                        newMap.initValues().put(boxPrimitive(new IntValue(index), LineCol.SYNTHETIC), arg);\n                }\n                consArgs.add(newMap);\n\n                boolean isInterface = requiredType instanceof SInterfaceDef;\n                SClassDef builtClass = buildAClassForLambda(\n                        scope.type(), scope.getThis() == null, methodToOverride,\n                        constructorWithZeroParamAndCanAccess,\n                        isInterface ? (SInterfaceDef) requiredType : null,\n                        isInterface, args.size(),\n                        innerMethod);\n\n                SConstructorDef cons = builtClass.constructors().get(0);\n                Ins.New aNew = new Ins.New(cons, LineCol.SYNTHETIC);\n                aNew.args().addAll(consArgs);\n\n                return aNew;\n        }\n\n        private SClassDef Object_Class;\n\n        public SClassDef getObject_Class() throws SyntaxException {\n                if (Object_Class == null) {\n                        Object_Class = (SClassDef) getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC);\n                }\n                return Object_Class;\n        }\n\n        /**\n         * build a class for lambda<br>\n         * see {@link #parseValueFromLambda(AST.Lambda, STypeDef, SemanticScope)} to see the class structure\n         *\n         * @param lambdaClassType  the caller method's declaring type\n         * @param isStatic         the method is static (then omit the 2nd param)\n         * @param methodToOverride the chosen method to override\n         * @param superConstructor the constructor to invoke (or null if it's interface)\n         * @param interfaceType    the interface type (or null if it's class)\n         * @param isInterface      the type to extend/implement is interface\n         * @param localVarCount    local variable count\n         * @param innerMethod      the inner method for the lambda to invoke\n         * @return generated class (SClassDef form)\n         * @throws SyntaxException compile error\n         */\n        public SClassDef buildAClassForLambda(STypeDef lambdaClassType, boolean isStatic, SMethodDef methodToOverride,\n                                              SConstructorDef superConstructor,\n                                              SInterfaceDef interfaceType,\n                                              boolean isInterface, int localVarCount,\n                                              SMethodDef innerMethod) throws SyntaxException {\n                // class\n                SClassDef sClassDef = new SClassDef(SClassDef.NORMAL, LineCol.SYNTHETIC);\n                typeDefSet.add(sClassDef);\n                SemanticScope scope = new SemanticScope(sClassDef, null);\n\n                if (isInterface) {\n                        sClassDef.setParent((SClassDef) getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC));\n                        sClassDef.superInterfaces().add(interfaceType);\n                } else {\n                        sClassDef.setParent((SClassDef) methodToOverride.declaringType());\n                }\n                sClassDef.setPkg(lambdaClassType.pkg());\n                String className = lambdaClassType.fullName() + \"$Latte$Lambda$\";\n                int i = 0;\n                while (typeExists(className + i)) ++i;\n                className += i;\n                sClassDef.setFullName(className);\n                types.put(className, sClassDef);\n\n                sClassDef.modifiers().add(SModifier.PUBLIC);\n\n                // fields\n                // o\n                SFieldDef f2 = null;\n                if (!isStatic) {\n                        f2 = new SFieldDef(LineCol.SYNTHETIC);\n                        f2.setName(\"o\");\n                        f2.setType(lambdaClassType);\n                        sClassDef.fields().add(f2);\n                        f2.setDeclaringType(sClassDef);\n                }\n                // local\n                SFieldDef f3 = new SFieldDef(LineCol.SYNTHETIC);\n                f3.setName(\"local\");\n                f3.setType(getTypeWithName(\"java.util.Map\", LineCol.SYNTHETIC));\n                sClassDef.fields().add(f3);\n                f3.setDeclaringType(sClassDef);\n                // self\n                SFieldDef f4 = new SFieldDef(LineCol.SYNTHETIC);\n                f4.setName(\"self\");\n                f4.setType(getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC));\n                sClassDef.fields().add(f4);\n                f4.setDeclaringType(sClassDef);\n                f4.modifiers().add(SModifier.PUBLIC);\n\n                // constructor\n                SConstructorDef con = new SConstructorDef(LineCol.SYNTHETIC);\n                sClassDef.constructors().add(con);\n                con.setDeclaringType(sClassDef);\n                SemanticScope conScope = new SemanticScope(scope, con.meta());\n                conScope.setThis(new Ins.This(sClassDef));\n                if (isInterface) {\n                        con.statements().add(new Ins.InvokeSpecial(\n                                conScope.getThis(),\n                                getObject_Class().constructors().get(0),\n                                LineCol.SYNTHETIC\n                        ));\n                } else {\n                        con.statements().add(new Ins.InvokeSpecial(\n                                conScope.getThis(),\n                                superConstructor,\n                                LineCol.SYNTHETIC\n                        ));\n                }\n                // self = this\n                con.statements().add(new Ins.PutField(\n                        f4, new Ins.This(sClassDef),\n                        new Ins.This(sClassDef), LineCol.SYNTHETIC, err));\n                con.modifiers().add(SModifier.PUBLIC);\n                // p2\n                if (!isStatic) {\n                        SParameter p2 = new SParameter();\n                        p2.setType(lambdaClassType);\n                        con.getParameters().add(p2);\n                        conScope.putLeftValue(\"p2\", p2);\n                        con.statements().add(new Ins.PutField(\n                                f2,\n                                conScope.getThis(),\n                                new Ins.TLoad(p2, conScope, LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC, err\n                        ));\n                }\n                // p3\n                SParameter p3 = new SParameter();\n                p3.setType(getTypeWithName(\"java.util.Map\", LineCol.SYNTHETIC));\n                con.getParameters().add(p3);\n                conScope.putLeftValue(\"p3\", p3);\n                con.statements().add(new Ins.PutField(\n                        f3,\n                        conScope.getThis(),\n                        new Ins.TLoad(p3, conScope, LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC, err\n                ));\n\n                // method\n                SMethodDef theMethod = new SMethodDef(LineCol.SYNTHETIC);\n                SemanticScope meScope = new SemanticScope(scope, theMethod.meta());\n                meScope.setThis(new Ins.This(sClassDef));\n                sClassDef.methods().add(theMethod);\n                theMethod.setDeclaringType(sClassDef);\n                theMethod.setName(methodToOverride.name());\n                theMethod.setReturnType(methodToOverride.getReturnType());\n                theMethod.modifiers().add(SModifier.PUBLIC);\n                for (SParameter param : methodToOverride.getParameters()) {\n                        SParameter mp = new SParameter();\n                        mp.setType(param.type());\n                        theMethod.getParameters().add(mp);\n\n                        String name = meScope.generateTempName();\n                        meScope.putLeftValue(name, mp);\n                        mp.setName(name);\n                }\n                // the lambda USED to be using MethodHandle to invoke the method\n                // now it directly invokes that method\n                List<Value> capturedValues = new ArrayList<Value>();\n                // add local variables in list\n                for (int index = 0; index < localVarCount; ++index) {\n                        Ins.InvokeInterface ii = new Ins.InvokeInterface(\n                                new Ins.GetField(f3, meScope.getThis(), LineCol.SYNTHETIC),\n                                getMap_get(), LineCol.SYNTHETIC\n                        );\n                        ii.arguments().add(boxPrimitive(new IntValue(index), LineCol.SYNTHETIC));\n                        Ins.CheckCast cc = new Ins.CheckCast(ii, innerMethod.getParameters().get(index).type(), LineCol.SYNTHETIC);\n                        capturedValues.add(cc);\n                }\n                List<Value> methodArgs = new ArrayList<Value>();\n                // add parameters\n                for (SParameter p : theMethod.getParameters()) {\n                        methodArgs.add(new Ins.TLoad(\n                                p, meScope, LineCol.SYNTHETIC\n                        ));\n                }\n                // add the functional object it self\n                methodArgs.add(new Ins.GetField(f4, meScope.getThis(), LineCol.SYNTHETIC));\n                Instruction theStmt;\n                if (isStatic) {\n                        Ins.InvokeWithCapture iwc = new Ins.InvokeWithCapture(null, innerMethod, true, LineCol.SYNTHETIC);\n                        iwc.capturedArguments().addAll(capturedValues);\n                        iwc.arguments().addAll(methodArgs);\n                        theStmt = iwc;\n                } else {\n                        Ins.InvokeWithCapture iwc = new Ins.InvokeWithCapture(\n                                new Ins.GetField(f2, meScope.getThis(), LineCol.SYNTHETIC),\n                                innerMethod,\n                                false, LineCol.SYNTHETIC\n                        );\n                        iwc.capturedArguments().addAll(capturedValues);\n                        iwc.arguments().addAll(methodArgs);\n                        theStmt = iwc;\n                }\n                // return if it's not `void`\n                if (!theMethod.getReturnType().equals(VoidType.get())) {\n                        theStmt = new Ins.TReturn((Value) theStmt, LineCol.SYNTHETIC);\n                }\n                theMethod.statements().add(theStmt);\n\n                return sClassDef;\n        }\n\n        /**\n         * parse procedure<br>\n         * first create an inner method, then invoke it\n         *\n         * @param procedure    the procedure\n         * @param requiredType required type\n         * @param scope        current scope\n         * @return the invocation of the inner method\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromProcedure(AST.Procedure procedure, STypeDef requiredType, SemanticScope scope) throws SyntaxException {\n                String methodName = \"procedure$0\";\n                int i = 1;\n                while (scope.getInnerMethod(methodName) != null) {\n                        methodName = \"procedure$\" + i;\n                        ++i;\n                }\n\n                if (requiredType == null) {\n                        requiredType = getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC);\n                }\n\n                assert requiredType != null;\n                MethodDef methodDef = new MethodDef(\n                        methodName, Collections.<Modifier>emptySet(),\n                        new AST.Access(\n                                requiredType.pkg() == null ? null : new AST.PackageRef(requiredType.pkg(), LineCol.SYNTHETIC),\n                                requiredType.fullName().contains(\".\")\n                                        ? requiredType.fullName().substring(requiredType.fullName().lastIndexOf('.') + 1)\n                                        : requiredType.fullName(),\n                                LineCol.SYNTHETIC\n                        )\n                        , Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(),\n                        procedure.statements, procedure.line_col()\n                );\n                parseInnerMethod(methodDef, scope, false);\n                AST.Invocation invocation = new AST.Invocation(\n                        new AST.Access(null, methodName, procedure.line_col()), Collections.<Expression>emptyList(), false, procedure.line_col());\n                return parseValueFromInvocation(invocation, scope);\n        }\n\n        /**\n         * parse MapExp<br>\n         * details are handled by {@link CodeGenerator#buildNewMap(MethodVisitor, CodeInfo, Ins.NewMap)}\n         *\n         * @param mapExp map expression (json format)\n         * @param scope  current scope\n         * @return {@link lt.compiler.semantic.Ins.NewMap}\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromMapExp(AST.MapExp mapExp, SemanticScope scope) throws SyntaxException {\n                Ins.NewMap newMap = new Ins.NewMap(getTypeWithName(\"java.util.LinkedHashMap\", mapExp.line_col()));\n\n                SClassDef Object_type = (SClassDef) getTypeWithName(\"java.lang.Object\", mapExp.line_col());\n                for (Map.Entry<Expression, Expression> expEntry : mapExp.map.entrySet()) {\n                        Value key = parseValueFromExpression(expEntry.getKey(), Object_type, scope);\n                        Value value = parseValueFromExpression(expEntry.getValue(), Object_type, scope);\n                        assert key != null;\n                        assert value != null;\n\n                        if (key.type() instanceof PrimitiveTypeDef) {\n                                key = boxPrimitive(key, LineCol.SYNTHETIC);\n                        }\n                        if (value.type() instanceof PrimitiveTypeDef) {\n                                value = boxPrimitive(value, LineCol.SYNTHETIC);\n                        }\n                        newMap.initValues().put(key, value);\n                }\n                return newMap;\n        }\n\n        /**\n         * parse ArrayExp<br>\n         * the array could be <tt>int[]</tt> or <tt>int[][]</tt> or <tt>Object[]</tt>,<br>\n         * and can also be {@link lt.compiler.semantic.Ins.NewList} (LinkedList)<br>\n         * it's based on the <tt>requiredType</tt>, LinkedList is the default\n         *\n         * @param arrayExp     array expression\n         * @param requiredType required type\n         * @param scope        current scope\n         * @return new array or new list\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromArrayExp(AST.ArrayExp arrayExp, STypeDef requiredType, SemanticScope scope) throws SyntaxException {\n                // first build an array\n                if (requiredType instanceof SArrayTypeDef\n                        && ((SArrayTypeDef) requiredType).dimension() == 1\n                        && ((SArrayTypeDef) requiredType).type() instanceof PrimitiveTypeDef) {\n                        STypeDef type = ((SArrayTypeDef) requiredType).type();\n                        IntValue count = new IntValue(arrayExp.list.size());\n\n                        int mode;\n                        int storeMode;\n                        if (type.equals(IntTypeDef.get())) {\n                                mode = Ins.NewArray.NewIntArray;\n                                storeMode = Ins.TAStore.IASTORE;\n                        } else if (type.equals(LongTypeDef.get())) {\n                                mode = Ins.NewArray.NewLongArray;\n                                storeMode = Ins.TAStore.LASTORE;\n                        } else if (type.equals(ShortTypeDef.get())) {\n                                mode = Ins.NewArray.NewShortArray;\n                                storeMode = Ins.TAStore.SASTORE;\n                        } else if (type.equals(ByteTypeDef.get())) {\n                                mode = Ins.NewArray.NewByteArray;\n                                storeMode = Ins.TAStore.BASTORE;\n                        } else if (type.equals(BoolTypeDef.get())) {\n                                mode = Ins.NewArray.NewBoolArray;\n                                storeMode = Ins.TAStore.BASTORE;\n                        } else if (type.equals(CharTypeDef.get())) {\n                                mode = Ins.NewArray.NewCharArray;\n                                storeMode = Ins.TAStore.CASTORE;\n                        } else if (type.equals(FloatTypeDef.get())) {\n                                mode = Ins.NewArray.NewFloatArray;\n                                storeMode = Ins.TAStore.FASTORE;\n                        } else if (type.equals(DoubleTypeDef.get())) {\n                                mode = Ins.NewArray.NewDoubleArray;\n                                storeMode = Ins.TAStore.DASTORE;\n                        } else throw new LtBug(\"unknown primitive type \" + type);\n\n                        Ins.NewArray newArray = new Ins.NewArray(count, mode, storeMode, requiredType);\n                        for (Expression exp : arrayExp.list) {\n                                newArray.initValues().add(parseValueFromExpression(exp, type, scope));\n                        }\n                        return newArray;\n                } else if (requiredType instanceof SArrayTypeDef) {\n                        // ANewArray\n                        SArrayTypeDef arrayTypeDef = (SArrayTypeDef) requiredType;\n                        STypeDef componentType;\n                        if (arrayTypeDef.dimension() == 1) {\n                                componentType = arrayTypeDef.type();\n                        } else {\n                                StringBuilder sb = new StringBuilder();\n                                for (int i = 0; i < arrayTypeDef.dimension() - 1; ++i) sb.append(\"[\");\n                                if (arrayTypeDef.type().equals(IntTypeDef.get())) {\n                                        sb.append(\"I\");\n                                } else if (arrayTypeDef.type().equals(LongTypeDef.get())) {\n                                        sb.append(\"J\");\n                                } else if (arrayTypeDef.type().equals(ShortTypeDef.get())) {\n                                        sb.append(\"S\");\n                                } else if (arrayTypeDef.type().equals(BoolTypeDef.get())) {\n                                        sb.append(\"Z\");\n                                } else if (arrayTypeDef.type().equals(ByteTypeDef.get())) {\n                                        sb.append(\"B\");\n                                } else if (arrayTypeDef.type().equals(CharTypeDef.get())) {\n                                        sb.append(\"C\");\n                                } else if (arrayTypeDef.type().equals(FloatTypeDef.get())) {\n                                        sb.append(\"F\");\n                                } else if (arrayTypeDef.type().equals(DoubleTypeDef.get())) {\n                                        sb.append(\"D\");\n                                } else {\n                                        sb.append(\"L\").append(arrayTypeDef.type().fullName()).append(\";\");\n                                }\n                                componentType = getTypeWithName(sb.toString(), arrayExp.line_col());\n                        }\n                        Ins.ANewArray aNewArray = new Ins.ANewArray(arrayTypeDef, componentType, new IntValue(arrayExp.list.size()));\n                        for (Expression exp : arrayExp.list) {\n                                aNewArray.initValues().add(\n                                        parseValueFromExpression(exp, componentType, scope)\n                                );\n                        }\n                        return aNewArray;\n                } else {\n                        // construct an ArrayList\n                        Ins.NewList newList = new Ins.NewList(\n                                getTypeWithName(\"java.util.LinkedList\", arrayExp.line_col())\n                        );\n                        SClassDef Object_type = (SClassDef) getTypeWithName(\"java.lang.Object\", arrayExp.line_col());\n                        // init values\n                        for (Expression exp : arrayExp.list) {\n                                Value v = parseValueFromExpression(exp, Object_type, scope);\n                                assert v != null;\n                                if (v.type() instanceof PrimitiveTypeDef) {\n                                        v = boxPrimitive(v, LineCol.SYNTHETIC);\n                                }\n                                newList.initValues().add(\n                                        v\n                                );\n                        }\n                        return newList;\n                }\n        }\n\n        /**\n         * parse assignment<br>\n         * generate a ValuePack, then invoke {@link #parseInstructionFromAssignment(Value, Value, SemanticScope, List, LineCol)}<br>\n         * then add a retrieve expression to the pack\n         *\n         * @param exp   assignment expression\n         * @param scope current scope\n         * @return ValuePack\n         * @throws SyntaxException compile error\n         */\n        public ValuePack parseValueFromAssignment(AST.Assignment exp, SemanticScope scope) throws SyntaxException {\n                ValuePack pack = new ValuePack(true); // value pack\n                // assignment\n                // =/+=/-=/*=//=/%=\n                Value assignFrom = parseValueFromExpression(exp.assignFrom, null, scope);\n                Value assignTo;\n                if (exp.assignTo.name == null) {\n                        assignTo = parseValueFromExpression(exp.assignTo, null, scope);\n                } else {\n                        assignTo = __parseValueFromAccess(exp.assignTo, scope, true);\n                }\n                if (!exp.op.equals(\"=\")) {\n                        assignFrom = parseValueFromTwoVarOp(\n                                parseValueFromExpression(exp.assignTo, null, scope), // the `assignTo` is calculated, so it should be final extracted value.\n                                exp.op.substring(0, exp.op.length() - 1),\n                                assignFrom, scope, LineCol.SYNTHETIC);\n                }\n\n                assert assignFrom != null;\n                LocalVariable local = new LocalVariable(assignFrom.type(), false);\n                scope.putLeftValue(scope.generateTempName(), local);\n\n                Ins.TStore tStore = new Ins.TStore(local, assignFrom, scope, LineCol.SYNTHETIC, err);\n                pack.instructions().add(tStore);\n\n                Ins.TLoad tLoad = new Ins.TLoad(local, scope, LineCol.SYNTHETIC);\n\n                if (tLoad.mode() == Ins.TLoad.Aload) {\n                        parseInstructionFromAssignment(assignTo,\n                                new Ins.CheckCast(tLoad, assignFrom.type(), LineCol.SYNTHETIC),\n                                scope, pack.instructions(), exp.line_col());\n                } else {\n                        parseInstructionFromAssignment(assignTo, tLoad,\n                                scope, pack.instructions(), exp.line_col());\n                }\n\n\n                pack.instructions().add(new Ins.TLoad(local, scope, LineCol.SYNTHETIC));\n\n                return pack;\n        }\n\n        /**\n         * {@link Unit#get()}\n         */\n        private SMethodDef Unit_get;\n\n        /**\n         * invoke {@link Unit#get()}\n         *\n         * @param lineCol caller's line and column\n         * @return InvokeStatic\n         * @throws SyntaxException exception\n         */\n        public Ins.InvokeStatic invoke_Unit_get(LineCol lineCol) throws SyntaxException {\n                if (Unit_get == null) {\n                        SClassDef UndefiendClass = (SClassDef) getTypeWithName(\"lt.lang.Unit\", lineCol);\n                        assert UndefiendClass != null;\n                        for (SMethodDef m : UndefiendClass.methods()) {\n                                if (m.name().equals(\"get\")) {\n                                        Unit_get = m;\n                                        break;\n                                }\n                        }\n                        Unit_get.setReturnType(getTypeWithName(\"lt.lang.Unit\", lineCol));\n                }\n                return new Ins.InvokeStatic(Unit_get, lineCol);\n        }\n\n        /**\n         * parse two var op<br>\n         * if two values are primitive, then use jvm instruction to finish this<br>\n         * otherwise, invoke bond methods\n         *\n         * @param tvo   two variable operation\n         * @param scope current scope\n         * @return the result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromTwoVarOp(TwoVariableOperation tvo, SemanticScope scope) throws SyntaxException {\n                String op = tvo.operator();\n                Value left = parseValueFromExpression(tvo.expressions().get(0), null, scope);\n                Value right = parseValueFromExpression(tvo.expressions().get(1), null, scope);\n                return parseValueFromTwoVarOp(left, op, right, scope, tvo.line_col());\n        }\n\n        /**\n         * invoke method with given arguments<br>\n         * <code>a.method(args)</code><br>\n         * first find method candidates, if not found, then invoke dynamic<br>\n         * if found, then select the best match to invoke\n         *\n         * @param lineCol    line column info\n         * @param targetType the type to invoke methods on (if the method is static, target type is this parameter. else the target type is invokeOn.getClass())\n         * @param invokeOn   invokeOn (a)\n         * @param methodName name of the method\n         * @param args       arguments\n         * @param scope      current scope\n         * @return a subclass of {@link lt.compiler.semantic.Ins.Invoke}\n         * @throws SyntaxException compile error\n         */\n        public Value invokeMethodWithArgs(LineCol lineCol, STypeDef targetType, Value invokeOn, String methodName, List<Value> args, SemanticScope scope) throws SyntaxException {\n                List<SMethodDef> methods = new ArrayList<SMethodDef>();\n                int FIND_MODE;\n                if (invokeOn.equals(NullValue.get())) {\n                        FIND_MODE = FIND_MODE_STATIC;\n                } else {\n                        FIND_MODE = FIND_MODE_NON_STATIC;\n                }\n                if (targetType.equals(NullTypeDef.get())) {\n                        targetType = getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC);\n                }\n                findMethodFromTypeWithArguments(lineCol, methodName, args, scope.type(), targetType, FIND_MODE, methods, true);\n                if (methods.isEmpty()) {\n                        return invoke_Dynamic_invoke(\n                                targetType,\n                                invokeOn,\n                                false,\n                                NullValue.get(),\n                                scope.type(),\n                                methodName,\n                                args, false,\n                                lineCol\n                        );\n                } else {\n                        SMethodDef method = findBestMatch(args, methods, lineCol);\n                        args = castArgsForMethodInvoke(args, method.getParameters(), lineCol);\n                        if (method.modifiers().contains(SModifier.STATIC)) {\n                                // invoke static\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                                invokeStatic.arguments().addAll(args);\n\n                                if (invokeStatic.type().equals(VoidType.get())) {\n                                        return new ValueAnotherType(\n                                                getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                invokeStatic, invokeStatic.line_col()\n                                        );\n                                }\n\n                                return invokeStatic;\n                        } else if (method.modifiers().contains(SModifier.PRIVATE)) {\n                                // invoke special\n                                Ins.InvokeSpecial invokeSpecial = new Ins.InvokeSpecial(invokeOn, method, lineCol);\n                                invokeSpecial.arguments().addAll(args);\n\n                                if (invokeSpecial.type().equals(VoidType.get())) {\n                                        return new ValueAnotherType(\n                                                getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                invokeSpecial, invokeSpecial.line_col()\n                                        );\n                                }\n\n                                return invokeSpecial;\n                        } else if (method.declaringType() instanceof SInterfaceDef) {\n                                // invoke interface\n                                Ins.InvokeInterface invokeInterface = new Ins.InvokeInterface(invokeOn, method, lineCol);\n                                invokeInterface.arguments().addAll(args);\n\n                                if (invokeInterface.type().equals(VoidType.get())) {\n                                        return new ValueAnotherType(\n                                                getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                invokeInterface, invokeInterface.line_col()\n                                        );\n                                }\n\n                                return invokeInterface;\n                        } else {\n                                // invoke virtual\n                                Ins.InvokeVirtual invokeVirtual = new Ins.InvokeVirtual(invokeOn, method, lineCol);\n                                invokeVirtual.arguments().addAll(args);\n\n                                if (invokeVirtual.type().equals(VoidType.get())) {\n                                        return new ValueAnotherType(\n                                                getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                invokeVirtual, invokeVirtual.line_col()\n                                        );\n                                }\n\n                                return invokeVirtual;\n                        }\n                }\n        }\n\n        /**\n         * parse two variable operation for int/long/float/double\n         *\n         * @param left       the value on the left of the operator\n         * @param baseOp     base operation, long op = baseOp+1, float op = baseOp+2, double op = baseOp + 3\n         * @param methodName if requires method invocation, use this method to invoke\n         * @param right      the value on the right of the operator\n         * @param scope      current scope\n         * @param lineCol    line column info\n         * @return the result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromTwoVarOpILFD(Value left, int baseOp, String methodName, Value right, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                if (left.type() instanceof PrimitiveTypeDef) {\n                        if (right.type() instanceof PrimitiveTypeDef) {\n                                if (left.type().equals(DoubleTypeDef.get()) || right.type().equals(DoubleTypeDef.get())) {\n                                        // cast to double\n                                        Value a = cast(DoubleTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(DoubleTypeDef.get(), right, scope.type(), lineCol);\n                                        return new Ins.TwoVarOp(a, b, baseOp + 3, DoubleTypeDef.get(), lineCol);\n                                } else if (left.type().equals(FloatTypeDef.get()) || right.type().equals(FloatTypeDef.get())) {\n                                        // cast to float\n                                        Value a = cast(FloatTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(FloatTypeDef.get(), right, scope.type(), lineCol);\n                                        return new Ins.TwoVarOp(a, b, baseOp + 2, FloatTypeDef.get(), lineCol);\n                                } else if (left.type().equals(LongTypeDef.get()) || right.type().equals(LongTypeDef.get())) {\n                                        // cast to long\n                                        Value a = cast(LongTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(LongTypeDef.get(), right, scope.type(), lineCol);\n                                        return new Ins.TwoVarOp(a, b, baseOp + 1, LongTypeDef.get(), lineCol);\n                                } else {\n                                        if ((baseOp == Ins.TwoVarOp.Iand || baseOp == Ins.TwoVarOp.Ior || baseOp == Ins.TwoVarOp.Ixor)\n                                                && left.type().equals(BoolTypeDef.get()) && right.type().equals(BoolTypeDef.get())) {\n                                                return new Ins.TwoVarOp(left, right, baseOp, BoolTypeDef.get(), lineCol);\n                                        } else {\n                                                // cast to int\n                                                Value a = cast(IntTypeDef.get(), left, scope.type(), lineCol);\n                                                Value b = cast(IntTypeDef.get(), right, scope.type(), lineCol);\n                                                return new Ins.TwoVarOp(a, b, baseOp, IntTypeDef.get(), lineCol);\n                                        }\n                                }\n                        } else {\n                                // box 'left' and give result\n                                return parseValueFromTwoVarOpILFD(\n                                        boxPrimitive(left, lineCol),\n                                        baseOp, methodName, right, scope, lineCol);\n                        }\n                } else {\n                        List<Value> args = new ArrayList<Value>();\n                        args.add(right);\n                        return invokeMethodWithArgs(lineCol, left.type(), left, methodName, args, scope);\n                }\n        }\n\n        /**\n         * {@link LtRuntime#compare(int, int)}\n         */\n        private SMethodDef Lang_compare;\n\n        /**\n         * @return {@link LtRuntime#compare(int, int)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_compare() throws SyntaxException {\n                if (Lang_compare == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"compare\")\n                                        && m.getParameters().size() == 2\n                                        && m.getParameters().get(0).type().equals(IntTypeDef.get())\n                                        && m.getParameters().get(1).type().equals(IntTypeDef.get())\n                                        && m.modifiers().contains(SModifier.STATIC)) {\n                                        Lang_compare = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_compare;\n        }\n\n        /**\n         * {@link Comparable#compareTo(Object)}\n         */\n        private SMethodDef Comparable_compareTo;\n\n        /**\n         * @return {@link Comparable#compareTo(Object)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getComparable_compareTo() throws SyntaxException {\n                if (null == Comparable_compareTo) {\n                        SInterfaceDef comparable = (SInterfaceDef) getTypeWithName(\"java.lang.Comparable\", LineCol.SYNTHETIC);\n                        assert comparable != null;\n                        for (SMethodDef m : comparable.methods()) {\n                                if (m.name().equals(\"compareTo\")\n                                        && m.getParameters().size() == 1) {\n                                        Comparable_compareTo = m;\n                                        break;\n                                }\n                        }\n                }\n                return Comparable_compareTo;\n        }\n\n        /**\n         * parse value from two var op compare\n         *\n         * @param left         the value of the left of the operator\n         * @param compare_mode compare_mode {@link #COMPARE_MODE_EQ} {@link #COMPARE_MODE_GT} {@link #COMPARE_MODE_LT}\n         * @param methodName   if requires method invocation, use this method to invoke\n         * @param right        the value of the right of the operator\n         * @param scope        current scope\n         * @param lineCol      line column info\n         * @return the result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromTwoVarOpCompare(Value left, int compare_mode, String methodName, Value right, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                if (left.type() instanceof PrimitiveTypeDef) {\n                        if (right.type() instanceof PrimitiveTypeDef) {\n                                Ins.TwoVarOp twoVarOp;\n                                if (left.type().equals(DoubleTypeDef.get()) || right.type().equals(DoubleTypeDef.get())) {\n                                        // cast to double\n                                        Value a = cast(DoubleTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(DoubleTypeDef.get(), right, scope.type(), lineCol);\n                                        twoVarOp = new Ins.TwoVarOp(a, b, Ins.TwoVarOp.Dcmpg, IntTypeDef.get(), lineCol);\n                                } else if (left.type().equals(FloatTypeDef.get()) || right.type().equals(FloatTypeDef.get())) {\n                                        // cast to float\n                                        Value a = cast(FloatTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(FloatTypeDef.get(), right, scope.type(), lineCol);\n                                        twoVarOp = new Ins.TwoVarOp(a, b, Ins.TwoVarOp.Fcmpg, IntTypeDef.get(), lineCol);\n                                } else {\n                                        // cast to long\n                                        Value a = cast(LongTypeDef.get(), left, scope.type(), lineCol);\n                                        Value b = cast(LongTypeDef.get(), right, scope.type(), lineCol);\n                                        twoVarOp = new Ins.TwoVarOp(a, b, Ins.TwoVarOp.Lcmp, IntTypeDef.get(), lineCol);\n                                }\n                                SMethodDef compare = getLang_compare();\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(compare, lineCol);\n                                invokeStatic.arguments().add(twoVarOp);\n                                invokeStatic.arguments().add(new IntValue(compare_mode));\n                                return invokeStatic;\n                        } else {\n                                return parseValueFromTwoVarOpCompare(\n                                        boxPrimitive(left, lineCol),\n                                        compare_mode, methodName, right, scope, lineCol);\n                        }\n                } else {\n                        STypeDef comparable = getTypeWithName(\"java.lang.Comparable\", lineCol);\n                        assert comparable != null;\n                        if (comparable.isAssignableFrom(left.type())) { // Comparable\n                                // left.compareTo(right)\n                                SMethodDef m = getComparable_compareTo();\n                                Ins.InvokeInterface invokeInterface = new Ins.InvokeInterface(left, m, lineCol);\n                                if (right.type() instanceof PrimitiveTypeDef) {\n                                        right = boxPrimitive(right, lineCol);\n                                }\n                                invokeInterface.arguments().add(right);\n\n                                // LtRuntime.compare(left.compareTo(right), compare_mode)\n                                SMethodDef compare = getLang_compare();\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(compare, lineCol);\n                                invokeStatic.arguments().add(invokeInterface);\n                                invokeStatic.arguments().add(new IntValue(compare_mode));\n                                return invokeStatic;\n                        } else {\n                                List<Value> args = new ArrayList<Value>();\n                                args.add(right);\n                                return invokeMethodWithArgs(lineCol, left.type(), left, methodName, args, scope);\n                        }\n                }\n        }\n\n        /**\n         * {@link LtRuntime#compareRef(Object, Object)}\n         */\n        private SMethodDef Lang_compareRef;\n\n        /**\n         * @return {@link LtRuntime#compareRef(Object, Object)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_compareRef() throws SyntaxException {\n                if (Lang_compareRef == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"compareRef\")\n                                        && m.getParameters().size() == 2\n                                        && m.modifiers().contains(SModifier.STATIC)) {\n                                        Lang_compareRef = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_compareRef;\n        }\n\n        /**\n         * if a &gt; b then return true.\n         */\n        public static final int COMPARE_MODE_GT = 1; // 0b001\n        /**\n         * if a == b then return true.\n         */\n        public static final int COMPARE_MODE_EQ = 2; // 0b010\n        /**\n         * if a &lt; b then return true.\n         */\n        public static final int COMPARE_MODE_LT = 4; // 0b100\n\n        /**\n         * parse value from two variable operation<br>\n         * invoke {@link #parseValueFromTwoVarOpILFD(Value, int, String, Value, SemanticScope, LineCol)}\n         * and {@link #parseValueFromTwoVarOpCompare(Value, int, String, Value, SemanticScope, LineCol)}<br>\n         * invoked by {@link #parseValueFromTwoVarOp(TwoVariableOperation, SemanticScope)}\n         *\n         * @param left    the value of the left of the operator\n         * @param op      operator\n         * @param right   the value of the right of the operator\n         * @param scope   current scope\n         * @param lineCol line column info\n         * @return result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromTwoVarOp(Value left, String op, Value right, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                if (op.equals(\":::\")) {\n                        List<Value> arg = new ArrayList<Value>();\n                        arg.add(right);\n                        return invokeMethodWithArgs(lineCol, left.type(), left, \"concat\", arg, scope);\n                } else if (op.equals(\"^^\")) {\n                        List<Value> arg;\n                        arg = new ArrayList<Value>();\n                        arg.add(right);\n                        if (left.type() instanceof PrimitiveTypeDef) {\n                                left = boxPrimitive(left, LineCol.SYNTHETIC);\n                        }\n                        return invokeMethodWithArgs(lineCol, left.type(), left, \"pow\", arg, scope);\n                } else if (op.equals(\"*\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Imul, \"multiply\", right, scope, lineCol);\n                } else if (op.equals(\"/\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Idiv, \"divide\", right, scope, lineCol);\n                } else if (op.equals(\"%\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Irem, \"remainder\", right, scope, lineCol);\n                } else if (op.equals(\"+\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Iadd, \"add\", right, scope, lineCol);\n                } else if (op.equals(\"-\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Isub, \"subtract\", right, scope, lineCol);\n                } else if (op.equals(\"<<\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Ishl, \"shiftLeft\", right, scope, lineCol);\n                } else if (op.equals(\">>\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Ishr, \"shiftRight\", right, scope, lineCol);\n                } else if (op.equals(\">>>\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Iushr, \"unsignedShiftRight\", right, scope, lineCol);\n                } else if (op.equals(\">\")) {\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_GT, \"gt\", right, scope, lineCol);\n                } else if (op.equals(\"<\")) {\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_LT, \"lt\", right, scope, lineCol);\n                } else if (op.equals(\">=\")) {\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_GT | COMPARE_MODE_EQ, \"ge\", right, scope, lineCol);\n                } else if (op.equals(\"<=\")) {\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_LT | COMPARE_MODE_EQ, \"le\", right, scope, lineCol);\n                } else if (op.equals(\"==\")) {// null check\n                        if (left.equals(NullValue.get()) || right.equals(NullValue.get())) {\n                                if (right.equals(NullValue.get())) {\n                                        Value tmp = left;\n                                        left = right;\n                                        right = tmp;\n                                }\n                                return parseValueFromTwoVarOp(left, \"is\", right, scope, lineCol);\n                        }\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_EQ, \"eq\", right, scope, lineCol);\n                } else if (op.equals(\"!=\")) {// null check\n                        if (left.equals(NullValue.get()) || right.equals(NullValue.get())) {\n                                if (right.equals(NullValue.get())) {\n                                        Value tmp = left;\n                                        left = right;\n                                        right = tmp;\n                                }\n                                return parseValueFromTwoVarOp(left, \"not\", right, scope, lineCol);\n                        }\n                        return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_GT | COMPARE_MODE_LT, \"ne\", right, scope, lineCol);\n                } else if (op.equals(\"===\")) {\n                        if (left.type() instanceof PrimitiveTypeDef && right.type() instanceof PrimitiveTypeDef) {\n                                return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_EQ, null, right, scope, lineCol);\n                        } else {\n                                if (left.type() instanceof PrimitiveTypeDef || right.type() instanceof PrimitiveTypeDef) {\n                                        err.SyntaxException(\"reference type cannot compare to primitive type\", lineCol);\n                                        return null;\n                                } else {\n                                        SMethodDef m = getLang_compareRef();\n                                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(m, lineCol);\n                                        invokeStatic.arguments().add(left);\n                                        invokeStatic.arguments().add(right);\n                                        return invokeStatic;\n                                }\n                        }\n                } else if (op.equals(\"!==\")) {\n                        if (left.type() instanceof PrimitiveTypeDef && right.type() instanceof PrimitiveTypeDef) {\n                                return parseValueFromTwoVarOpCompare(left, COMPARE_MODE_LT | COMPARE_MODE_GT, null, right, scope, lineCol);\n                        } else {\n                                if (left.type() instanceof PrimitiveTypeDef || right.type() instanceof PrimitiveTypeDef) {\n                                        err.SyntaxException(\"reference type cannot compare to primitive type\", lineCol);\n                                        return null;\n                                } else {\n                                        // LtRuntime.compareRef(left,right)\n                                        SMethodDef m = getLang_compareRef();\n                                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(m, lineCol);\n                                        invokeStatic.arguments().add(left);\n                                        invokeStatic.arguments().add(right);\n\n                                        // ! LtRuntime.compareRef(left,right)\n                                        return parseValueFromTwoVarOpILFD(invokeStatic, Ins.TwoVarOp.Ixor, null, new BoolValue(true), scope, lineCol);\n                                }\n                        }\n                } else if (op.equals(\"is\")) {\n                        if (right instanceof Ins.GetClass) {\n                                // is type XXX\n                                // use instance of\n                                if (left.type() instanceof PrimitiveTypeDef) {\n                                        left = boxPrimitive(left, lineCol);\n                                }\n                                return new Ins.InstanceOf(left, (Ins.GetClass) right, lineCol);\n                        } else {\n                                // invoke static LtRuntime.is\n                                SMethodDef m = getLang_is();\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(m, lineCol);\n                                if (left.type() instanceof PrimitiveTypeDef) {\n                                        left = boxPrimitive(left, lineCol);\n                                }\n                                if (right.type() instanceof PrimitiveTypeDef) {\n                                        right = boxPrimitive(right, lineCol);\n                                }\n                                invokeStatic.arguments().add(left);\n                                invokeStatic.arguments().add(right);\n                                invokeStatic.arguments().add(\n                                        new Ins.GetClass(scope.type(),\n                                                (SClassDef) getTypeWithName(\n                                                        \"java.lang.Class\",\n                                                        invokeStatic.line_col()))\n                                );\n                                return invokeStatic;\n                        }\n                } else if (op.equals(\"not\")) {\n                        if (right instanceof Ins.GetClass) {\n                                // not type XXX\n                                // use instanceof\n                                if (left.type() instanceof PrimitiveTypeDef) {\n                                        left = boxPrimitive(left, lineCol);\n                                }\n                                return new Ins.TwoVarOp(\n                                        new Ins.TwoVarOp(\n                                                new Ins.InstanceOf(left, (Ins.GetClass) right, lineCol),\n                                                new IntValue(1),\n                                                Ins.TwoVarOp.Iand, BoolTypeDef.get(),\n                                                lineCol),\n                                        new IntValue(1),\n                                        Ins.TwoVarOp.Ixor,\n                                        BoolTypeDef.get(),\n                                        lineCol);\n                        } else {\n                                // invoke static LtRuntime.not\n                                SMethodDef m = getLang_not();\n                                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(m, lineCol);\n                                if (left.type() instanceof PrimitiveTypeDef) {\n                                        left = boxPrimitive(left, lineCol);\n                                }\n                                if (right.type() instanceof PrimitiveTypeDef) {\n                                        right = boxPrimitive(right, lineCol);\n                                }\n                                invokeStatic.arguments().add(left);\n                                invokeStatic.arguments().add(right);\n                                invokeStatic.arguments().add(\n                                        new Ins.GetClass(scope.type(),\n                                                (SClassDef) getTypeWithName(\n                                                        \"java.lang.Class\",\n                                                        invokeStatic.line_col()))\n                                );\n                                return invokeStatic;\n                        }\n                } else if (op.equals(\"in\")) {\n                        List<Value> args = new ArrayList<Value>();\n                        args.add(left);\n                        if (right.type() instanceof PrimitiveTypeDef) {\n                                right = boxPrimitive(right, lineCol);\n                        }\n                        return invokeMethodWithArgs(lineCol, right.type(), right, \"contains\", args, scope);\n                } else if (op.equals(\"&\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Iand, \"and\", right, scope, lineCol);\n                } else if (op.equals(\"^\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Ixor, \"xor\", right, scope, lineCol);\n                } else if (op.equals(\"|\")) {\n                        return parseValueFromTwoVarOpILFD(left, Ins.TwoVarOp.Ior, \"or\", right, scope, lineCol);\n                } else if (op.equals(\"&&\") || op.equals(\"and\")) {// logic and with short cut\n                        return new Ins.LogicAnd(\n                                cast(BoolTypeDef.get(), left, scope.type(), lineCol),\n                                cast(BoolTypeDef.get(), right, scope.type(), lineCol),\n                                lineCol);\n                } else if (op.equals(\"||\") || op.equals(\"or\")) {// logic or with short cut\n                        if (left.type() instanceof PrimitiveTypeDef) {\n                                left = boxPrimitive(left, lineCol);\n                        }\n                        if (right.type() instanceof PrimitiveTypeDef) {\n                                right = boxPrimitive(right, lineCol);\n                        }\n                        return new Ins.LogicOr(\n                                getLang_castToBool(),\n                                left, right,\n                                getCommonParent(left.type(), right.type()),\n                                lineCol\n                        );\n                } else if (op.equals(\":=\")) {\n                        List<Value> args;// assign\n                        args = new ArrayList<Value>();\n                        args.add(right);\n                        return invokeMethodWithArgs(lineCol, left.type(), left, \"assign\", args, scope);\n                } else {\n                        err.SyntaxException(\"unknown two variable operator \" + op, lineCol);\n                        return null;\n                }\n        }\n\n        /**\n         * get common parent type\n         *\n         * @param type1 type1\n         * @param type2 type2\n         * @return the common super type of type1 and type2. the super type is type1 or type2 or java.lang.Object or super class of type1/type2\n         * @throws SyntaxException compiling error\n         */\n        public STypeDef getCommonParent(STypeDef type1, STypeDef type2) throws SyntaxException {\n                if (type1.equals(type2)) return type1;\n                if (type1.isAssignableFrom(type2)) return type1;\n                if (type2.isAssignableFrom(type1)) return type2;\n                if (type1 instanceof SClassDef && type2 instanceof SClassDef) {\n                        SClassDef c1 = (SClassDef) type1;\n                        SClassDef c2 = (SClassDef) type2;\n                        while (c1 != null) {\n                                if (c1.isAssignableFrom(c2)) return c1;\n                                c1 = c1.parent();\n                        }\n                }\n                return getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC);\n        }\n\n        /**\n         * {@link LtRuntime#is(Object, Object, Class)}\n         */\n        private SMethodDef Lang_is;\n\n        /**\n         * @return {@link LtRuntime#is(Object, Object, Class)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_is() throws SyntaxException {\n                if (Lang_is == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"is\")\n                                        && m.getParameters().size() == 3\n                                        && m.modifiers().contains(SModifier.STATIC)) {\n                                        Lang_is = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_is;\n        }\n\n        /**\n         * {@link LtRuntime#not(Object, Object, Class)}\n         */\n        private SMethodDef Lang_not;\n\n        /**\n         * @return {@link LtRuntime#not(Object, Object, Class)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_not() throws SyntaxException {\n                if (Lang_not == null) {\n                        SClassDef cls = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert cls != null;\n                        for (SMethodDef m : cls.methods()) {\n                                if (m.name().equals(\"not\")\n                                        && m.getParameters().size() == 3\n                                        && m.modifiers().contains(SModifier.STATIC)) {\n                                        Lang_not = m;\n                                        break;\n                                }\n                        }\n                }\n                return Lang_not;\n        }\n\n        /**\n         * parse one variable operation<br>\n         * can only be <code>\n         * ++, unary++, --\n         * </code><br>\n         * simply change the expression to assignment and invoke {@link #parseValueFromAssignment(AST.Assignment, SemanticScope)}\n         *\n         * @param exp   one variable operation\n         * @param scope current scope\n         * @return result\n         * @throws SyntaxException compile error\n         */\n        public Value parseSelfOneVarOp(Operation exp, SemanticScope scope) throws SyntaxException {\n                Expression e = exp.expressions().get(0);\n                if (!(e instanceof AST.Access)) {\n                        err.SyntaxException(exp.operator() + \" cannot operate on \" + e, exp.line_col());\n                        return null;\n                }\n\n                if (exp.operator().equals(\"++\")) {\n                        AST.Assignment assignment = new AST.Assignment(\n                                (AST.Access) e,\n                                \"+=\",\n                                new NumberLiteral(\"1\", exp.line_col()),\n                                exp.line_col());\n                        ValuePack valuePack = parseValueFromAssignment(assignment, scope);\n                        if (!exp.isUnary()) {\n                                /*\n                                 * get value\n                                 * invoke +=\n                                 * pop result\n                                 * // the stack top value would be original value\n                                 */\n                                ValuePack thePackToReturn = new ValuePack(false);\n\n                                Value v = parseValueFromAccess((AST.Access) e, scope, true);\n                                assert v instanceof Instruction;\n                                thePackToReturn.instructions().add((Instruction) v);\n                                thePackToReturn.instructions().add(valuePack);\n                                thePackToReturn.instructions().add(new Ins.Pop());\n\n                                STypeDef type = valuePack.type();\n                                thePackToReturn.setType(type);\n\n                                return thePackToReturn;\n                        } else {\n                                return valuePack;\n                        }\n                } else if (exp.operator().equals(\"--\")) {\n                        AST.Assignment assignment = new AST.Assignment(\n                                (AST.Access) e,\n                                \"-=\",\n                                new NumberLiteral(\"1\", exp.line_col()),\n                                exp.line_col());\n                        ValuePack valuePack = parseValueFromAssignment(assignment, scope);\n                        if (!exp.isUnary()) {\n                                /*\n                                 * get value\n                                 * invoke -=\n                                 * pop result\n                                 * // the stack top value would be original value\n                                 */\n                                ValuePack thePackToReturn = new ValuePack(false);\n\n                                Value v = parseValueFromAccess((AST.Access) e, scope, true);\n                                assert v instanceof Instruction;\n                                thePackToReturn.instructions().add((Instruction) v);\n                                thePackToReturn.instructions().add(valuePack);\n                                thePackToReturn.instructions().add(new Ins.Pop());\n\n                                STypeDef type = valuePack.type();\n                                thePackToReturn.setType(type);\n\n                                return thePackToReturn;\n                        } else {\n                                return valuePack;\n                        }\n                } else throw new LtBug(\"this method only supports ++ and --, but got unknown op \" + exp.operator());\n        }\n\n        /**\n         * parse one variable operation\n         *\n         * @param exp   one variable operation\n         * @param scope current scope\n         * @return result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromOneVarOp(Operation exp, SemanticScope scope) throws SyntaxException {\n                String op = exp.operator();\n                boolean unary = exp.isUnary();\n\n                if (op.equals(\"++\")) {\n\n                        return parseSelfOneVarOp(exp, scope);\n\n                } else if (op.equals(\"--\")) {\n\n                        return parseSelfOneVarOp(exp, scope);\n\n                } else if (op.equals(\"!\") && unary) {\n                        // !b (bool:not ; other: invoke logicNot())\n                        Value v = parseValueFromExpression(exp.expressions().get(0), null, scope);\n                        assert v != null;\n                        if (v.type().equals(BoolTypeDef.get()) || v.type().fullName().equals(\"java.lang.Boolean\")) {\n                                v = cast(BoolTypeDef.get(), v, scope.type(), exp.line_col());\n                                // v is bool\n                                // (v & 1) ^ 1\n                                return new Ins.TwoVarOp(\n                                        new Ins.TwoVarOp(\n                                                v,\n                                                new IntValue(1),\n                                                Ins.TwoVarOp.Iand, BoolTypeDef.get(),\n                                                exp.line_col()),\n                                        new IntValue(1),\n                                        Ins.TwoVarOp.Ixor,\n                                        BoolTypeDef.get(),\n                                        exp.line_col());\n                        } else {\n                                if (v.type() instanceof PrimitiveTypeDef) {\n                                        v = boxPrimitive(v, exp.line_col());\n                                }\n                                // v is object\n                                // invoke `logicNot`\n                                return invokeMethodWithArgs(exp.line_col(), v.type(), v, \"logicNot\", new ArrayList<Value>(), scope);\n                        }\n\n                } else if (op.equals(\"~\") && unary) {\n                        // ~i (int:xor(-1);long:xor(-1L);other:invoke not())\n                        Value v = parseValueFromExpression(exp.expressions().get(0), null, scope);\n                        assert v != null;\n                        if (v.type() instanceof IntTypeDef || v.type().fullName().equals(\"java.lang.Integer\")\n                                ||\n                                v.type() instanceof ByteTypeDef || v.type().fullName().equals(\"java.lang.Byte\")\n                                ||\n                                v.type() instanceof ShortTypeDef || v.type().fullName().equals(\"java.lang.Short\")\n                                ) {\n                                v = cast(IntTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.TwoVarOp(\n                                        v,\n                                        new IntValue(-1),\n                                        Ins.TwoVarOp.Ixor,\n                                        IntTypeDef.get(),\n                                        exp.line_col());\n                        } else if (v.type() instanceof LongTypeDef || v.type().fullName().equals(\"java.lang.Long\")) {\n                                v = cast(LongTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.TwoVarOp(\n                                        v,\n                                        new LongValue(-1),\n                                        Ins.TwoVarOp.Lxor,\n                                        IntTypeDef.get(),\n                                        exp.line_col());\n                        } else {\n                                if (v.type() instanceof PrimitiveTypeDef) {\n                                        v = boxPrimitive(v, exp.line_col());\n                                }\n                                // v is object\n                                // invoke `bitwiseNot`\n                                return invokeMethodWithArgs(exp.line_col(), v.type(), v, \"not\", new ArrayList<Value>(), scope);\n                        }\n                } else if (op.equals(\"+\") && unary) {\n                        // +i (do nothing)\n                        return parseValueFromExpression(exp.expressions().get(0), null, scope);\n                } else if (op.equals(\"-\") && unary) {\n                        // -i (number:negative; other:invoke negate())\n                        Value v = parseValueFromExpression(exp.expressions().get(0), null, scope);\n                        assert v != null;\n                        if (v.type() instanceof IntTypeDef || v.type().fullName().equals(\"java.lang.Integer\")\n                                ||\n                                v.type() instanceof ByteTypeDef || v.type().fullName().equals(\"java.lang.Byte\")\n                                ||\n                                v.type() instanceof ShortTypeDef || v.type().fullName().equals(\"java.lang.Short\")\n                                ) {\n                                v = cast(IntTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.OneVarOp(\n                                        v,\n                                        Ins.OneVarOp.Ineg,\n                                        IntTypeDef.get(),\n                                        exp.line_col());\n                        } else if (v.type() instanceof LongTypeDef || v.type().fullName().equals(\"java.lang.Long\")) {\n                                v = cast(LongTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.OneVarOp(\n                                        v,\n                                        Ins.OneVarOp.Lneg,\n                                        LongTypeDef.get(),\n                                        exp.line_col());\n                        } else if (v.type() instanceof FloatTypeDef || v.type().fullName().equals(\"java.lang.Float\")) {\n                                v = cast(FloatTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.OneVarOp(\n                                        v,\n                                        Ins.OneVarOp.Fneg,\n                                        FloatTypeDef.get(),\n                                        exp.line_col());\n                        } else if (v.type() instanceof DoubleTypeDef || v.type().fullName().equals(\"java.lang.Double\")) {\n                                v = cast(DoubleTypeDef.get(), v, scope.type(), exp.line_col());\n                                return new Ins.OneVarOp(\n                                        v,\n                                        Ins.OneVarOp.Dneg,\n                                        DoubleTypeDef.get(),\n                                        exp.line_col());\n                        } else {\n                                if (v.type() instanceof PrimitiveTypeDef) {\n                                        v = boxPrimitive(v, exp.line_col());\n                                }\n                                // v is object\n                                // invoke `negate`\n                                return invokeMethodWithArgs(exp.line_col(), v.type(), v, \"negate\", new ArrayList<Value>(), scope);\n                        }\n                } else {\n                        err.SyntaxException(\"unknown one variable operator \" + (unary ? (op + \"v\") : (\"v\" + op)), exp.line_col());\n                        return null;\n                }\n        }\n\n        /**\n         * get arguments\n         *\n         * @param args  args(expression)\n         * @param scope scope\n         * @return list\n         * @throws SyntaxException exception\n         */\n        public List<Value> parseArguments(List<Expression> args, SemanticScope scope) throws SyntaxException {\n                List<Value> list = new ArrayList<Value>();\n                for (Expression exp : args) {\n                        Value a = parseValueFromExpression(exp, null, scope);\n                        if (a == null) {\n                                err.SyntaxException(exp + \" is not method argument\", exp.line_col());\n                                return null;\n                        }\n                        list.add(a);\n                }\n                return list;\n        }\n\n        /**\n         * parse value from Index<br>\n         * <code>arr[i]</code>\n         *\n         * @param index AST.Index\n         * @param scope current scope\n         * @return result\n         * @throws SyntaxException compile error\n         */\n        public Value parseValueFromIndex(AST.Index index, SemanticScope scope) throws SyntaxException {\n                Value v = parseValueFromExpression(index.exp, null, scope);\n                assert v != null;\n\n                List<Value> list = parseArguments(index.args, scope);\n\n                assert list != null;\n                if (v.type() instanceof SArrayTypeDef && !list.isEmpty()) {\n                        try {\n                                Value result = v;\n                                for (int ii = 0; ii < list.size(); ++ii) {\n                                        Value i = cast(IntTypeDef.get(), list.get(ii), scope.type(), index.args.get(ii).line_col());\n                                        result = new Ins.TALoad(result, i, index.line_col(), getTypes());\n                                }\n                                return result;\n                        } catch (Throwable ignore) {\n                                // cast failed\n                        }\n                }\n                // not array\n                // do invoke\n                return invokeMethodWithArgs(\n                        index.line_col(),\n                        v.type(),\n                        v,\n                        \"get\",\n                        list,\n                        scope);\n        }\n\n        /**\n         * parse value from access (the access represents a type).\n         *\n         * @param access      the type\n         * @param imports     imports\n         * @param currentType caller type\n         * @return New instruction or get_static\n         * @throws SyntaxException exception\n         */\n        public Value parseValueFromAccessType(AST.Access access, List<Import> imports, STypeDef currentType) throws SyntaxException {\n                SClassDef type = (SClassDef) getTypeWithAccess(access, getGenericMap(currentType), imports);\n                assert type != null;\n                SConstructorDef zeroParamCons = null;\n                for (SConstructorDef c : type.constructors()) {\n                        if (c.getParameters().isEmpty()) {\n                                if (c.modifiers().contains(SModifier.PRIVATE)) {\n                                        if (!type.equals(currentType) && type.classType() != SClassDef.OBJECT) continue;\n                                } else if (c.modifiers().contains(SModifier.PROTECTED)) {\n                                        if (!type.pkg().equals(currentType.pkg())\n                                                && !type.isAssignableFrom(currentType))\n                                                continue;\n                                } else if (!c.modifiers().contains(SModifier.PUBLIC)) {\n                                        if (!type.pkg().equals(currentType.pkg()))\n                                                continue;\n                                }\n                                zeroParamCons = c;\n                                break;\n                        }\n                }\n                if (zeroParamCons == null) {\n                        err.SyntaxException(type + \" do not have zero parameter constructor\", access.line_col());\n                        return null;\n                } else if (type.classType() == SClassDef.OBJECT) {\n                        SFieldDef singletonInstance = null;\n                        for (SFieldDef f : type.fields()) {\n                                if (f.name().equals(CompileUtil.SingletonFieldName)) {\n                                        singletonInstance = f;\n                                        break;\n                                }\n                        }\n                        if (singletonInstance == null)\n                                throw new LtBug(\"object class should have field \" + CompileUtil.SingletonFieldName);\n                        return new Ins.GetStatic(singletonInstance, access.line_col());\n                } else {\n                        return new Ins.New(zeroParamCons, access.line_col());\n                }\n        }\n\n        /**\n         * proxy for parsing value from access {@link #__parseValueFromAccess(AST.Access, SemanticScope, boolean)}\n         *\n         * @param access           access\n         * @param scope            scope\n         * @param isTryingToAssign isTryingToAssign\n         * @return result that will extract value from the object if it's a pointer\n         * @throws SyntaxException compiling error\n         */\n        public Value parseValueFromAccess(AST.Access access, SemanticScope scope, boolean isTryingToAssign) throws SyntaxException {\n                Value v = __parseValueFromAccess(access, scope, isTryingToAssign);\n                assert v != null;\n                if (isPointerType(v.type())) {\n                        v = invokePointerGet(v, access.line_col());\n                }\n                return v;\n        }\n\n        /**\n         * parse value from access object<br>\n         * the access object can be : (null,fieldName),(null,localVariableName),(this,fieldName),(Type,fieldName),((Type,this),fieldName),(exp,fieldName)\n         *\n         * @param access           access object\n         * @param scope            scope that contains localvariables\n         * @param isTryingToAssign the value is retrieved to assign new value\n         * @return retrieved value can be getField/getStatic/TLoad/arraylength\n         * @throws SyntaxException compiling error\n         */\n        private Value __parseValueFromAccess(AST.Access access, SemanticScope scope, boolean isTryingToAssign) throws SyntaxException {\n                // get generic type map\n                Map<String, STypeDef> genericTypeMap = scope == null ? Collections.<String, STypeDef>emptyMap() : getGenericMap(scope.type());\n                // handle\n                access = transformAccess(access);\n                List<Import> imports = fileNameToImport.get(access.line_col().fileName);\n                if (access.exp == null) {\n                        // Access(null,name)\n                        assert scope != null;\n                        if (access.name.equals(\"this\")) {\n                                if (scope.getThis() == null) {\n                                        err.SyntaxException(\"static scope do not have `this` to access\", access.line_col());\n                                        return null;\n                                }\n                                return scope.getThis();\n                        }\n                        LeftValue v = scope.getLeftValue(access.name);\n                        if (null == v) {\n                                // cannot find value from local variables\n                                // try to get from this or ThisClass or import static\n                                // try this and ThisClass\n                                SFieldDef f = findFieldFromTypeDef(access.name, scope.type(), scope.type(), FIND_MODE_ANY, true);\n                                if (null != f) {\n                                        if (f.modifiers().contains(SModifier.STATIC)) {\n                                                return new Ins.GetStatic(f, access.line_col());\n                                        } else {\n                                                return new Ins.GetField(f, scope.getThis(), access.line_col());\n                                        }\n                                }\n\n                                // get from import static\n                                for (Import im : imports) {\n                                        if (im.importAll) {\n                                                if (im.pkg == null) {\n                                                        // import static\n                                                        f = findFieldFromTypeDef(\n                                                                access.name,\n                                                                getTypeWithAccess(im.access, genericTypeMap, imports),\n                                                                scope.type(),\n                                                                FIND_MODE_STATIC,\n                                                                true);\n                                                        if (null != f) {\n                                                                return new Ins.GetStatic(f, access.line_col());\n                                                        }\n                                                }\n                                        }\n                                }\n                        } else {\n                                // value is local variable\n                                if (isTryingToAssign) {\n                                        // check whether it's final\n                                        if (!v.canChange()) {\n                                                err.SyntaxException(\"cannot assign an immutable variable\", access.line_col());\n                                        }\n                                }\n                                return new Ins.TLoad(v, scope, access.line_col());\n                        }\n\n                        if (enableTypeAccess) {\n                                // check whether it's a type and construct a new object\n                                try {\n                                        return parseValueFromAccessType(access, imports, scope.type());\n                                } catch (Throwable ignore) {\n                                }\n                        }\n\n                        // still not found\n                        // check whether it's a non-static field\n                        if (scope.getThis() == null) {\n                                err.SyntaxException(\"cannot find static field \" + scope.type().fullName() + \".\" + access.name, access.line_col());\n                                return null;\n                        } else {\n                                // get field at runtime\n                                return invokeGetField(scope.getThis(), access.name, scope.type(), access.line_col());\n                        }\n\n                } else {\n                        // Access(...,fieldName)\n                        if (access.exp instanceof AST.Access) {\n                                AST.Access access1 = (AST.Access) access.exp;\n                                if (access1.exp == null && access1.name.equals(\"this\")) {\n                                        // this.fieldName\n                                        assert scope != null;\n                                        if (scope.getThis() == null) {\n                                                err.SyntaxException(\"static methods don't have `this` variable\", access1.line_col());\n                                                return null;\n                                        }\n                                        SFieldDef f = findFieldFromTypeDef(access.name, scope.type(), scope.type(), FIND_MODE_NON_STATIC, true);\n                                        if (null != f) {\n                                                return new Ins.GetField(f, scope.getThis(), access.line_col());\n                                        }\n\n                                        // not found\n                                        // get field at runtime\n                                        return invokeGetField(scope.getThis(), access.name, scope.type(), access.line_col());\n                                } else if (access1.exp instanceof AST.Access && access1.name.equals(\"this\")) {\n                                        // SuperClass.this.fieldName\n                                        STypeDef type = getTypeWithAccess((AST.Access) access1.exp, genericTypeMap, imports);\n                                        assert type != null;\n\n                                        assert scope != null;\n                                        if (!type.isAssignableFrom(scope.type())) {\n                                                err.SyntaxException(\"`SuperClass` in SuperClass.this should be super class of this class\", access1.line_col());\n                                                return null;\n                                        }\n                                        SFieldDef f = findFieldFromTypeDef(access.name, type, scope.type(), FIND_MODE_NON_STATIC, false);\n                                        if (null != f) {\n                                                return new Ins.GetField(f, scope.getThis(), access.line_col());\n                                        } else {\n                                                err.SyntaxException(\"cannot find static field `\" + access.name + \"` in \" + type, access.line_col());\n                                                return null;\n                                        }\n                                }\n                        } else if (access.exp instanceof AST.PackageRef && enableTypeAccess) {\n                                try {\n                                        assert scope != null;\n                                        return parseValueFromAccessType(access, imports, scope.type());\n                                } catch (Throwable ignore) {\n                                }\n                        }\n                        // other conditions\n                        // the access.exp should be a Type or value\n                        // SomeClass.fieldName or value.fieldName\n\n                        // try to find type\n                        STypeDef type = null;\n                        // not value, then try to find type\n                        if (access.exp instanceof AST.Access) {\n                                try {\n                                        type = getTypeWithAccess((AST.Access) access.exp, genericTypeMap, imports);\n                                } catch (Throwable ignore) {\n                                        // type not found or wrong Access format\n                                }\n                        }\n\n                        Value v = null;\n                        // try to get value\n                        SyntaxException ex = null; // the exception would be recorded\n                        // and would be thrown if `type` can not be found\n                        try {\n                                if (type != null) {\n                                        // the access.exp can be type, so in this step firstly try not constructing the object\n                                        // if it cannot be type, the inner part of access.exp might need to construct.\n                                        enableTypeAccess = false;\n                                }\n                                v = parseValueFromExpression(access.exp, null, scope);\n                        } catch (Throwable e) {\n                                if (e instanceof SyntaxException)\n                                        ex = (SyntaxException) e;\n                        } finally {\n                                if (type != null) {\n                                        enableTypeAccess = true;\n                                }\n                        }\n\n                        // value found, then ignore the `type`\n                        if (v != null && !isGetFieldAtRuntime(v))\n                                type = null;\n\n                        // handle\n                        if (type != null) {\n                                // SomeClass.fieldName -- getStatic\n                                SFieldDef f = findFieldFromTypeDef(access.name, type, scope == null ? null : scope.type(), FIND_MODE_STATIC, true);\n                                if (null != f) {\n                                        return new Ins.GetStatic(f, access.line_col());\n                                } else {\n                                        try {\n                                                assert scope != null;\n                                                v = parseValueFromAccessType((AST.Access) access.exp, imports, scope.type());\n                                        } catch (Throwable ignore) {\n                                                err.SyntaxException(\"cannot find accessible static field `\" + access.name + \"` in \" + type, access.line_col());\n                                                return null;\n                                        }\n                                }\n                        }\n                        if (v != null) {\n                                // value.fieldName -- getField\n                                // (exp,fieldName)\n                                if (v.type() instanceof SArrayTypeDef) {\n                                        // array field can be `length`\n                                        if (access.name.equals(\"length\"))\n                                                return new Ins.ArrayLength(v, access.line_col());\n                                        else {\n                                                assert scope != null;\n                                                return invokeGetField(v, access.name, scope.type(), access.line_col());\n                                        }\n                                } else {\n                                        // check primitive\n                                        if (v.type() instanceof PrimitiveTypeDef) {\n                                                v = boxPrimitive(v, access.line_col());\n                                        }\n                                        assert scope != null;\n                                        SFieldDef f = findFieldFromTypeDef(access.name, v.type(), scope.type(), FIND_MODE_NON_STATIC, true);\n                                        if (null == f) {\n                                                return invokeGetField(v, access.name, scope.type(), access.line_col());\n                                        } else {\n                                                return new Ins.GetField(f, v, access.line_col());\n                                        }\n                                }\n                        }\n                        // type and value are not found\n                        if (ex == null) {\n                                err.SyntaxException(\"cannot parse \" + access, access.line_col());\n                                return null;\n                        } else\n                                throw ex;\n                }\n        }\n\n        /**\n         * invoke {@link LtRuntime#getField(Object, String, Class)}\n         *\n         * @param target      1st arg\n         * @param name        2nd arg\n         * @param callerClass 3rd arg\n         * @param lineCol     line and column info\n         * @return InvokeStatic\n         * @throws SyntaxException exception\n         */\n        public Ins.InvokeStatic invokeGetField(Value target, String name, STypeDef callerClass, LineCol lineCol) throws SyntaxException {\n                SMethodDef m = getLang_getField();\n                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(m, lineCol);\n                invokeStatic.arguments().add(target);\n                StringConstantValue s = new StringConstantValue(name);\n                s.setType((SClassDef) getTypeWithName(\"java.lang.String\", lineCol));\n                invokeStatic.arguments().add(s);\n                invokeStatic.arguments().add(new Ins.GetClass(callerClass, (SClassDef) getTypeWithName(\"java.lang.Class\", lineCol)));\n                return invokeStatic;\n        }\n\n        /**\n         * {@link LtRuntime#getField(Object, String, Class)}\n         */\n        private SMethodDef Lang_getField = null;\n\n        /**\n         * @return {@link LtRuntime#getField(Object, String, Class)}\n         * @throws SyntaxException exception\n         */\n        public SMethodDef getLang_getField() throws SyntaxException {\n                if (Lang_getField == null) {\n                        SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                        assert Lang != null;\n\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"getField\")) {\n                                        Lang_getField = m;\n                                        break;\n                                }\n                        }\n                }\n                if (Lang_getField == null)\n                        throw new LtBug(\"lt.runtime.LtRuntime.getField(Object,String,Class) should exist\");\n                return Lang_getField;\n        }\n\n        /**\n         * get SFieldDef from the given type\n         *\n         * @param fieldName  field name\n         * @param targetType type to search\n         * @param callerType caller type(used to check accessiblility)\n         * @param mode       {@link #FIND_MODE_ANY} {@link #FIND_MODE_NON_STATIC} {@link #FIND_MODE_STATIC}\n         * @param checkSuper check the super class/interfaces if it's set to true\n         * @return retrieved SFieldDef or null if not found\n         */\n        public SFieldDef findFieldFromTypeDef(String fieldName, STypeDef targetType, STypeDef callerType, int mode, boolean checkSuper) {\n                if (targetType instanceof SClassDef) {\n                        return findFieldFromClassDef(fieldName, (SClassDef) targetType, callerType, mode, checkSuper);\n                } else if (targetType instanceof SInterfaceDef) {\n                        return findFieldFromInterfaceDef(fieldName, (SInterfaceDef) targetType, checkSuper);\n                } else throw new LtBug(\"the type to get field from cannot be \" + targetType);\n        }\n\n        /**\n         * get SField from the class\n         *\n         * @param fieldName  field name\n         * @param theClass   class to search\n         * @param type       caller type\n         * @param mode       {@link #FIND_MODE_ANY} {@link #FIND_MODE_NON_STATIC} {@link #FIND_MODE_STATIC}\n         * @param checkSuper check the super class/interfaces if it's set to true\n         * @return retrieved SFieldDef or null if not found\n         */\n        public SFieldDef findFieldFromClassDef(String fieldName, SClassDef theClass, STypeDef type, int mode, boolean checkSuper) {\n                for (SFieldDef f : theClass.fields()) {\n                        if (mode == FIND_MODE_STATIC) {\n                                if (!f.modifiers().contains(SModifier.STATIC)) continue;\n                                // ignore all non static\n                        } else if (mode == FIND_MODE_NON_STATIC) {\n                                if (f.modifiers().contains(SModifier.STATIC)) continue;\n                                // ignore all static\n                        }\n\n                        if (f.name().equals(fieldName)) {\n                                if (f.modifiers().contains(SModifier.PUBLIC)) return f;\n                                else {\n                                        if (type != null) {\n                                                if (f.modifiers().contains(SModifier.PROTECTED)) {\n                                                        if (theClass.isAssignableFrom(type) // type is subclass of theClass\n                                                                ||\n                                                                theClass.pkg().equals(type.pkg()) // same package\n                                                                ) return f;\n                                                } else if (f.modifiers().contains(SModifier.PRIVATE)) {\n                                                        if (theClass.equals(type)) return f;\n                                                } else {\n                                                        // package access\n                                                        if (theClass.pkg().equals(type.pkg())) return f;\n                                                }\n                                        }\n                                }\n                        }\n                }\n\n                if (checkSuper) {\n                        SFieldDef f = null;\n                        if (theClass.parent() != null) {\n                                f = findFieldFromClassDef(fieldName, theClass.parent(), type, mode, true);\n                        }\n                        if (null == f) {\n                                if (mode != FIND_MODE_NON_STATIC) {\n                                        for (SInterfaceDef i : theClass.superInterfaces()) {\n                                                if (f != null) return f;\n                                                f = findFieldFromInterfaceDef(fieldName, i, true);\n                                        }\n                                }\n                        }\n                }\n\n                return null;\n        }\n\n        /**\n         * get SField from the interface\n         *\n         * @param fieldName    field name\n         * @param theInterface interface\n         * @param checkSuper   check the super interfaces if it's set to true\n         * @return retrieved SFieldDef or null if not found\n         */\n        public SFieldDef findFieldFromInterfaceDef(String fieldName, SInterfaceDef theInterface, boolean checkSuper) {\n                for (SFieldDef f : theInterface.fields()) {\n                        if (f.name().equals(fieldName)) return f;\n                }\n\n                if (checkSuper) {\n                        SFieldDef f = null;\n                        for (SInterfaceDef i : theInterface.superInterfaces()) {\n                                if (f != null) return f;\n                                f = findFieldFromInterfaceDef(fieldName, i, true);\n                        }\n                }\n\n                return null;\n        }\n\n        /**\n         * cast retrieved value to required type\n         *\n         * @param requiredType required type. null means no type limit\n         * @param v            value\n         * @param callerClass  callerClass\n         * @param lineCol      file_line_col\n         * @return casted value\n         * @throws SyntaxException exception\n         */\n        public Value cast(STypeDef requiredType, Value v, STypeDef callerClass, LineCol lineCol) throws SyntaxException {\n                if (requiredType != null && isPointerType(requiredType)) {\n                        requiredType = getPointingType(requiredType);\n                }\n\n                // if v is instance of requiredType, return\n                if (requiredType == null\n                        ||\n                        (!(requiredType instanceof PrimitiveTypeDef) // not primitive\n                                &&                                      // and\n                                requiredType.isAssignableFrom(v.type()) // v instanceof requiredType\n                        )\n                        ||\n                        requiredType.equals(v.type()) // requiredType is v.type\n                        ) return v;\n                Value resultVal;\n                if (requiredType instanceof PrimitiveTypeDef) {\n                        // requiredType is primitive\n                        if (v.type() instanceof PrimitiveTypeDef) {\n                                if (v.type().equals(IntTypeDef.get())\n                                        || v.type().equals(ShortTypeDef.get())\n                                        || v.type().equals(ByteTypeDef.get())\n                                        || v.type().equals(CharTypeDef.get())) {\n\n                                        if (requiredType.equals(IntTypeDef.get())) {\n                                                // int\n                                                return new ValueAnotherType(requiredType, v, lineCol);\n                                        } else if (requiredType.equals(ShortTypeDef.get())) {\n                                                // to short\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_SHORT, lineCol);\n                                        } else if (requiredType.equals(ByteTypeDef.get())) {\n                                                // to byte\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_BYTE, lineCol);\n                                        } else if (requiredType.equals(CharTypeDef.get())) {\n                                                // to char\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_CHAR, lineCol);\n                                        } else if (requiredType instanceof LongTypeDef) {\n                                                // int to long\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_LONG, lineCol);\n                                        } else if (requiredType instanceof FloatTypeDef) {\n                                                // int to float\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_FLOAT, lineCol);\n                                        } else if (requiredType instanceof DoubleTypeDef) {\n                                                // int to double\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_INT_TO_DOUBLE, lineCol);\n                                        } else if (requiredType instanceof BoolTypeDef) {\n                                                return castObjToPrimitive(\n                                                        BoolTypeDef.get(),\n                                                        boxPrimitive(\n                                                                v,\n                                                                lineCol),\n                                                        lineCol);\n                                        } else\n                                                throw new LtBug(\"unknown primitive requiredType \" + requiredType);\n                                } else if (v.type().equals(LongTypeDef.get())) {\n                                        if (requiredType instanceof IntTypeDef) {\n                                                // long to int\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_LONG_TO_INT, lineCol);\n                                        } else if (requiredType instanceof ShortTypeDef) {\n                                                // long to int and int to short\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_LONG_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_SHORT, lineCol);\n                                        } else if (requiredType instanceof ByteTypeDef) {\n                                                // long to int and int to byte\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_LONG_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_BYTE, lineCol);\n                                        } else if (requiredType instanceof CharTypeDef) {\n                                                // long to int and int to char\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_LONG_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_CHAR, lineCol);\n                                        } else if (requiredType instanceof FloatTypeDef) {\n                                                // long to float\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_LONG_TO_FLOAT, lineCol);\n                                        } else if (requiredType instanceof DoubleTypeDef) {\n                                                // long to double\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_LONG_TO_DOUBLE, lineCol);\n                                        } else if (requiredType instanceof BoolTypeDef) {\n                                                return castObjToPrimitive(\n                                                        BoolTypeDef.get(),\n                                                        boxPrimitive(\n                                                                v,\n                                                                lineCol),\n                                                        lineCol);\n                                        } else\n                                                throw new LtBug(\"unknown primitive requiredType \" + requiredType);\n                                } else if (v.type().equals(FloatTypeDef.get())) {\n                                        if (requiredType instanceof IntTypeDef) {\n                                                // float to int\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_FLOAT_TO_INT, lineCol);\n                                        } else if (requiredType instanceof ShortTypeDef) {\n                                                // float to int and int to short\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_FLOAT_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_SHORT, lineCol);\n                                        } else if (requiredType instanceof ByteTypeDef) {\n                                                // float to int and int to byte\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_FLOAT_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_BYTE, lineCol);\n                                        } else if (requiredType instanceof CharTypeDef) {\n                                                // float to int and int to char\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_FLOAT_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_CHAR, lineCol);\n                                        } else if (requiredType instanceof LongTypeDef) {\n                                                // float to long\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_FLOAT_TO_LONG, lineCol);\n                                        } else if (requiredType instanceof DoubleTypeDef) {\n                                                // float to double\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_FLOAT_TO_DOUBLE, lineCol);\n                                        } else if (requiredType instanceof BoolTypeDef) {\n                                                return castObjToPrimitive(\n                                                        BoolTypeDef.get(),\n                                                        boxPrimitive(\n                                                                v,\n                                                                lineCol),\n                                                        lineCol);\n                                        } else\n                                                throw new LtBug(\"unknown primitive requiredType \" + requiredType);\n                                } else if (v.type().equals(DoubleTypeDef.get())) {\n                                        if (requiredType instanceof IntTypeDef) {\n                                                // double to int\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_DOUBLE_TO_INT, lineCol);\n                                        } else if (requiredType instanceof ShortTypeDef) {\n                                                // double to int and int to short\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_DOUBLE_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_SHORT, lineCol);\n                                        } else if (requiredType instanceof ByteTypeDef) {\n                                                // double to int and int to byte\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_DOUBLE_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_BYTE, lineCol);\n                                        } else if (requiredType instanceof CharTypeDef) {\n                                                // double to int and int to char\n                                                Ins.Cast c1 = new Ins.Cast(IntTypeDef.get(), v, Ins.Cast.CAST_DOUBLE_TO_INT, lineCol);\n                                                return new Ins.Cast(requiredType, c1, Ins.Cast.CAST_INT_TO_CHAR, lineCol);\n                                        } else if (requiredType instanceof FloatTypeDef) {\n                                                // double to float\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_DOUBLE_TO_FLOAT, lineCol);\n                                        } else if (requiredType instanceof LongTypeDef) {\n                                                // double to long\n                                                return new Ins.Cast(requiredType, v, Ins.Cast.CAST_DOUBLE_TO_LONG, lineCol);\n                                        } else if (requiredType instanceof BoolTypeDef) {\n                                                return castObjToPrimitive(\n                                                        BoolTypeDef.get(),\n                                                        boxPrimitive(\n                                                                v,\n                                                                lineCol),\n                                                        lineCol);\n                                        } else\n                                                throw new LtBug(\"unknown primitive requiredType \" + requiredType);\n                                } else if (v.type().equals(BoolTypeDef.get())) {\n                                        err.SyntaxException(\"cannot cast from boolean to other primitives\", lineCol);\n                                        return null;\n                                } else throw new LtBug(\"unknown primitive value \" + v);\n                        } else {\n                                // cast obj to primitive\n                                return castObjToPrimitive((PrimitiveTypeDef) requiredType, v, lineCol);\n                        }\n                } else {\n                        // requiredType is not primitive\n                        if (v.type() instanceof PrimitiveTypeDef) {\n                                // v is primitive\n                                v = boxPrimitive(v, lineCol);\n                                // box then check cast\n                                if (requiredType.isAssignableFrom(v.type())) return v;\n                                // invoke cast(Object)\n                                resultVal = castObjToObj(requiredType, v, callerClass, lineCol);\n                        } else {\n                                // cast object to object\n                                resultVal = castObjToObj(requiredType, v, callerClass, lineCol);\n                        }\n                }\n                return new Ins.CheckCast(resultVal, requiredType, lineCol);\n        }\n\n        /**\n         * invoke {@link LtRuntime#cast(Object, Class, Class)}<br>\n         * note that the result object is always `java.lang.Object` when compiling,<br>\n         * use {@link lt.compiler.semantic.Ins.CheckCast} to cast to required type to avoid some error when runtime validates the class file\n         *\n         * @param type        2nd arg\n         * @param v           1st arg\n         * @param callerClass 3rd arg\n         * @param lineCol     line column info\n         * @return casted value\n         * @throws SyntaxException exception\n         */\n        public Value castObjToObj(STypeDef type, Value v, STypeDef callerClass, LineCol lineCol) throws SyntaxException {\n                SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", lineCol);\n                assert Lang != null;\n\n                SMethodDef method = null;\n                for (SMethodDef m : Lang.methods()) {\n                        if (m.name().equals(\"cast\")) {\n                                method = m;\n                                break;\n                        }\n                }\n                if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToInt(Object,Class,Class) should exist\");\n                Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                invokeStatic.arguments().add(v);\n                invokeStatic.arguments().add(\n                        new Ins.GetClass(\n                                type,\n                                (SClassDef) getTypeWithName(\"java.lang.Class\", lineCol))\n                );\n                invokeStatic.arguments().add(\n                        callerClass == null\n                                ? NullValue.get()\n                                : new Ins.GetClass(callerClass, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC))\n                );\n                return invokeStatic;\n        }\n\n        /**\n         * invoke castToX methods defined in lt.runtime.LtRuntime\n         *\n         * @param type    the primitive type\n         * @param v       value to cast\n         * @param lineCol line and column info\n         * @return casted value\n         * @throws SyntaxException exception\n         */\n        public Value castObjToPrimitive(PrimitiveTypeDef type, Value v, LineCol lineCol) throws SyntaxException {\n                SClassDef Lang = (SClassDef) getTypeWithName(\"lt.runtime.LtRuntime\", LineCol.SYNTHETIC);\n                assert Lang != null;\n\n                SMethodDef method = null;\n                if (type instanceof IntTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToInt\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToInt(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof LongTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToLong\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToLong(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof ShortTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToShort\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToShort(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof ByteTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToByte\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToByte(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof FloatTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToFloat\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToFloat(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof DoubleTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToDouble\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToDouble(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof BoolTypeDef) {\n                        method = getLang_castToBool();\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToBool(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else if (type instanceof CharTypeDef) {\n                        for (SMethodDef m : Lang.methods()) {\n                                if (m.name().equals(\"castToChar\")) {\n                                        method = m;\n                                        break;\n                                }\n                        }\n                        if (method == null) throw new LtBug(\"lt.runtime.LtRuntime.castToChar(Object) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(method, lineCol);\n                        invokeStatic.arguments().add(v);\n                        return invokeStatic;\n                } else throw new LtBug(\"unknown primitive type \" + type);\n        }\n\n        /**\n         * check whether the method is overridden by list methods\n         *\n         * @param method     method\n         * @param methodList method list\n         * @return true/false\n         * @throws SyntaxException compiling error\n         */\n        public boolean whetherTheMethodIsOverriddenByMethodsInTheList(SMethodDef method, List<SMethodDef> methodList) throws SyntaxException {\n                // methodList is null\n                // return false\n                if (methodList == null) return false;\n                if (method.modifiers().contains(SModifier.STATIC)) return false;\n                /*\n                // foreach m in methodList\n                for (SMethodDef m : methodList) {\n                        // equals means overridden\n                        if (method.equals(m)) return true;\n                        // check m.overRide methods\n                        if (whetherTheMethodIsOverriddenByMethodsInTheList(method, m.overRide())) return true;\n                }\n                */\n                // check signature\n                if (null != findMethodWithSameSignature(method, methodList, true)) return true;\n                // still not found, return false\n                return false;\n        }\n\n        /**\n         * search for static and non-static\n         */\n        public static final int FIND_MODE_ANY = 0;\n        /**\n         * only search for static\n         */\n        public static final int FIND_MODE_STATIC = 1;\n        /**\n         * only search for non-static\n         */\n        public static final int FIND_MODE_NON_STATIC = 2;\n\n        /**\n         * find method from interface and it's super interfaces\n         *\n         * @param name           method name\n         * @param argList        argument list\n         * @param sInterfaceDef  interface definition(where to find method from)\n         * @param mode           find_method_mode {@link #FIND_MODE_ANY} {@link #FIND_MODE_NON_STATIC} {@link #FIND_MODE_STATIC}\n         * @param matchedMethods matched methods\n         * @param checkSuper     whether to check super types\n         * @throws SyntaxException compiling error\n         */\n        public void findMethodFromInterfaceWithArguments(String name, List<Value> argList, SInterfaceDef sInterfaceDef, int mode, List<SMethodDef> matchedMethods, boolean checkSuper) throws SyntaxException {\n                out:\n                for (SMethodDef m : sInterfaceDef.methods()) {\n                        // check name\n                        if (!m.name().equals(name)) continue;\n\n                        if (mode == FIND_MODE_STATIC) {\n                                if (!m.modifiers().contains(SModifier.STATIC)) continue;\n                        } else if (mode == FIND_MODE_NON_STATIC) {\n                                if (m.modifiers().contains(SModifier.STATIC)) continue;\n                        }\n\n                        List<SParameter> parameters = m.getParameters();\n                        if (parameters.size() == argList.size()) {\n                                // parameter size match\n                                for (int i = 0; i < parameters.size(); ++i) {\n                                        SParameter param = parameters.get(i);\n                                        Value v = argList.get(i);\n\n                                        if (!param.type().isAssignableFrom(v.type())) {\n                                                if (!(param.type() instanceof PrimitiveTypeDef)\n                                                        && v.type() instanceof PrimitiveTypeDef) {\n                                                        v = boxPrimitive(v, LineCol.SYNTHETIC);\n                                                        if (!param.type().isAssignableFrom(v.type()))\n                                                                continue out;\n                                                } else continue out;\n                                        }\n                                }\n\n                                if (!whetherTheMethodIsOverriddenByMethodsInTheList(m, matchedMethods))\n                                        matchedMethods.add(m);\n                        }\n                }\n\n                if (checkSuper) {\n                        // recursively get super interfaces' method\n                        for (SInterfaceDef i : sInterfaceDef.superInterfaces()) {\n                                findMethodFromInterfaceWithArguments(name, argList, i, mode, matchedMethods, true);\n                        }\n                }\n        }\n\n        /**\n         * find method from class and it's super class and super interfaces\n         *\n         * @param name           method name\n         * @param argList        argument list or null\n         * @param invokeOn       the invoker's class\n         * @param sClassDef      class definition(where to find method from)\n         * @param mode           find_method_mode {@link #FIND_MODE_ANY} {@link #FIND_MODE_NON_STATIC} {@link #FIND_MODE_STATIC}\n         * @param matchedMethods matched methods, the final result would be chosen from the list\n         * @param checkSuper     whether to check super types\n         * @throws SyntaxException compiling error\n         */\n        public void findMethodFromClassWithArguments(String name, List<Value> argList, STypeDef invokeOn, SClassDef sClassDef, int mode, List<SMethodDef> matchedMethods, boolean checkSuper) throws SyntaxException {\n                // prevent invalid class access\n                if (!sClassDef.modifiers().contains(SModifier.PUBLIC)) {\n                        if (sClassDef.modifiers().contains(SModifier.PROTECTED)) {\n                                if (!sClassDef.isAssignableFrom(invokeOn) && !sClassDef.pkg().equals(invokeOn.pkg()))\n                                        return;\n                        } else if (sClassDef.modifiers().contains(SModifier.PRIVATE)) return;\n                        else {\n                                // package\n                                if (!sClassDef.pkg().equals(invokeOn.pkg())) return;\n                        }\n                }\n                out:\n                for (SMethodDef m : sClassDef.methods()) {\n                        // check name\n                        if (!m.name().equals(name)) continue;\n\n                        if (mode == FIND_MODE_STATIC) {\n                                if (!m.modifiers().contains(SModifier.STATIC)) continue;\n                        } else if (mode == FIND_MODE_NON_STATIC) {\n                                if (m.modifiers().contains(SModifier.STATIC)) continue;\n                        }\n\n                        List<SParameter> parameters = m.getParameters();\n                        if (parameters.size() == argList.size()) {\n                                // parameter size match\n                                for (int i = 0; i < parameters.size(); ++i) {\n                                        SParameter param = parameters.get(i);\n                                        Value v = argList.get(i);\n\n                                        if (!param.type().isAssignableFrom(v.type())) {\n                                                if (!(param.type() instanceof PrimitiveTypeDef)\n                                                        && v.type() instanceof PrimitiveTypeDef) {\n                                                        v = boxPrimitive(v, LineCol.SYNTHETIC);\n                                                        if (!param.type().isAssignableFrom(v.type()))\n                                                                continue out;\n                                                } else continue out;\n                                        }\n                                }\n\n                                // check accessible\n                                if (m.modifiers().contains(SModifier.PRIVATE)) {\n                                        // private then ignore\n                                        if (!invokeOn.equals(sClassDef))\n                                                continue;\n                                } else if (m.modifiers().contains(SModifier.PROTECTED)) {\n                                        // protected\n                                        // subclass or same package\n                                        if (!sClassDef.isAssignableFrom(invokeOn) && !sClassDef.pkg().equals(invokeOn.pkg()))\n                                                continue;\n                                } else if (!m.modifiers().contains(SModifier.PUBLIC)) {\n                                        // package access, check package\n                                        if (!sClassDef.pkg().equals(invokeOn.pkg())) continue;\n                                }\n\n                                // check overridden\n                                if (!whetherTheMethodIsOverriddenByMethodsInTheList(m, matchedMethods)) {\n                                        // check return type accessible\n                                        STypeDef type = m.getReturnType();\n                                        boolean canAccess = false;\n\n                                        if (type instanceof SClassDef) {\n                                                if (((SClassDef) type).modifiers().contains(SModifier.PUBLIC)) {\n                                                        canAccess = true;\n                                                } else if (((SClassDef) type).modifiers().contains(SModifier.PROTECTED)) {\n                                                        if (type.isAssignableFrom(invokeOn) || type.pkg().equals(invokeOn.pkg())) {\n                                                                canAccess = true;\n                                                        }\n                                                } else if (!((SClassDef) type).modifiers().contains(SModifier.PUBLIC)) {\n                                                        if (type.pkg().equals(invokeOn.pkg())) {\n                                                                canAccess = true;\n                                                        }\n                                                }\n                                        } else {\n                                                canAccess = true;\n                                        }\n\n                                        if (canAccess) {\n                                                matchedMethods.add(m);\n                                        }\n                                }\n                        }\n                }\n\n                if (checkSuper) {\n                        if (sClassDef.parent() != null) {\n                                findMethodFromClassWithArguments(name, argList, invokeOn, sClassDef.parent(), mode, matchedMethods, true);\n                        }\n                        for (SInterfaceDef i : sClassDef.superInterfaces()) {\n                                findMethodFromInterfaceWithArguments(name, argList, i, mode, matchedMethods, true);\n                        }\n                }\n        }\n\n        /**\n         * find method from type with arguments<br>\n         * it redirects to {@link #findMethodFromClassWithArguments(String, List, STypeDef, SClassDef, int, List, boolean)}<br>\n         * or {@link #findMethodFromInterfaceWithArguments(String, List, SInterfaceDef, int, List, boolean)}<br>\n         * or get methods from annotation\n         *\n         * @param lineCol        file_line_col\n         * @param name           method name\n         * @param argList        argument list\n         * @param invokeOn       invoker's type\n         * @param sTypeDef       type definition\n         * @param mode           find_method_mode {@link #FIND_MODE_ANY} {@link #FIND_MODE_NON_STATIC} {@link #FIND_MODE_STATIC}\n         * @param matchedMethods matched methods\n         * @param checkSuper     whether to check super types\n         * @throws SyntaxException exception\n         */\n        public void findMethodFromTypeWithArguments(LineCol lineCol, String name, List<Value> argList, STypeDef invokeOn, STypeDef sTypeDef, int mode, List<SMethodDef> matchedMethods, boolean checkSuper) throws SyntaxException {\n                if (name.equals(\"clone\") && sTypeDef.fullName().equals(\"java.lang.Object\")) {\n                        // ignore any invocation on `Object#clone` at compile time\n                        return;\n                }\n                if (sTypeDef instanceof SClassDef) {\n                        findMethodFromClassWithArguments(name, argList, invokeOn, (SClassDef) sTypeDef, mode, matchedMethods, checkSuper);\n                } else if (sTypeDef instanceof SInterfaceDef) {\n                        findMethodFromInterfaceWithArguments(name, argList, (SInterfaceDef) sTypeDef, mode, matchedMethods, checkSuper);\n                } else if (sTypeDef instanceof SAnnoDef) {\n                        if (argList.size() != 0) {\n                                err.SyntaxException(\"invoking methods in annotation should contain no arguments\", lineCol);\n                                return;\n                        }\n                        for (SAnnoField f : ((SAnnoDef) sTypeDef).annoFields()) {\n                                if (f.name().equals(name)) {\n                                        matchedMethods.add(f);\n                                }\n                        }\n                } else throw new LtBug(\"sTypeDef can only be SClassDef or SInterfaceDef or SAnnoDef\");\n        }\n\n        /**\n         * constructing new instances\n         *\n         * @param classDef class definition\n         * @param argList  argument list\n         * @param scope    current scope\n         * @param lineCol  line col\n         * @return {@link lt.compiler.semantic.Ins.New} or {@link lt.compiler.semantic.Ins.InvokeStatic}\n         * @throws SyntaxException exception\n         */\n        public Value constructingNewInst(SClassDef classDef, List<Value> argList, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                out:\n                for (SConstructorDef con : classDef.constructors()) {\n                        // foreach constructor, check its parameters\n                        List<SParameter> params = con.getParameters();\n                        if (argList.size() == params.size()) {\n                                // length match\n                                for (int i = 0; i < argList.size(); ++i) {\n                                        Value v = argList.get(i);\n                                        SParameter param = params.get(i);\n\n                                        if (!param.type().isAssignableFrom(v.type())) {\n                                                // not assignable\n                                                // see whether the v.type is primitive\n                                                if (!(param.type() instanceof PrimitiveTypeDef)\n                                                        &&\n                                                        v.type() instanceof PrimitiveTypeDef) {\n                                                        v = boxPrimitive(v, LineCol.SYNTHETIC);\n                                                        if (!param.type().isAssignableFrom(v.type())) {\n                                                                continue out;\n                                                        }\n                                                } else continue out;\n                                        }\n                                }\n                                // all matches\n                                Ins.New aNew = new Ins.New(con, lineCol);\n                                argList = castArgsForMethodInvoke(argList, con.getParameters(), lineCol);\n                                aNew.args().addAll(argList);\n                                return aNew;\n                        }\n                }\n                // not found\n\n                // add current class into arg list\n                return invoke_Dynamic_construct(classDef, scope.type(), argList, lineCol);\n        }\n\n        /**\n         * call the functional object just like calling a method.\n         *\n         * @param invocation invocation object. the invocation.exp is any expression but AST.Access.\n         * @param scope      scope that contains local variables and local methods.\n         * @return The invocation result. Usually the result is InvokeDynamic.\n         * @throws SyntaxException compiling error.\n         * @see #parseValueFromInvocation(AST.Invocation, SemanticScope)\n         * @see #parseValueFromInvocationWithNames(AST.Invocation, SemanticScope)\n         */\n        public Value parseValueFromInvocationFunctionalObject(AST.Invocation invocation, SemanticScope scope) throws SyntaxException {\n                Expression exp = invocation.exp;\n                Value possibleFunctionalObject = parseValueFromExpression(exp, null, scope);\n\n                List<Value> arguments = new ArrayList<Value>();\n                for (Expression e : invocation.args) {\n                        arguments.add(parseValueFromExpression(e, null, scope));\n                }\n\n                return callFunctionalObject(possibleFunctionalObject, scope.type(), arguments, invocation.line_col());\n        }\n\n        private SClassDef DYNAMIC_CLASS;\n\n        public SClassDef getDynamicClass() throws SyntaxException {\n                if (DYNAMIC_CLASS == null) {\n                        DYNAMIC_CLASS = (SClassDef) getTypeWithName(DYNAMIC_CLASS_NAME, LineCol.SYNTHETIC);\n                }\n                return DYNAMIC_CLASS;\n        }\n\n        private SMethodDef DYNAMIC_callFunctionalObject;\n\n        public SMethodDef getDYNAMIC_callFunctionalObject() throws SyntaxException {\n                if (DYNAMIC_callFunctionalObject == null) {\n                        SClassDef DYNAMIC = getDynamicClass();\n                        for (SMethodDef m : DYNAMIC.methods()) {\n                                if (m.name().equals(\"callFunctionalObject\") && m.getParameters().size() == 3) {\n                                        DYNAMIC_callFunctionalObject = m;\n                                        break;\n                                }\n                        }\n                }\n                return DYNAMIC_callFunctionalObject;\n        }\n\n        private SMethodDef DYNAMIC_invoke;\n\n        public SMethodDef getDYNAMIC_invoke() throws SyntaxException {\n                if (DYNAMIC_invoke == null) {\n                        SClassDef DYNAMIC = getDynamicClass();\n                        for (SMethodDef m : DYNAMIC.methods()) {\n                                if (m.name().equals(\"invoke\") && m.getParameters().size() == 9) {\n                                        DYNAMIC_invoke = m;\n                                        break;\n                                }\n                        }\n                }\n                return DYNAMIC_invoke;\n        }\n\n        private SMethodDef DYNAMIC_construct;\n\n        public SMethodDef getDYNAMIC_construct() throws SyntaxException {\n                if (DYNAMIC_construct == null) {\n                        SClassDef DYNAMIC = getDynamicClass();\n                        for (SMethodDef m : DYNAMIC.methods()) {\n                                if (m.name().equals(\"construct\") && m.getParameters().size() == 4) {\n                                        DYNAMIC_construct = m;\n                                        break;\n                                }\n                        }\n                }\n                return DYNAMIC_construct;\n        }\n\n        /**\n         * call a functional object\n         *\n         * @param object      the functional object\n         * @param callerClass caller class\n         * @param arguments   arguments\n         * @param lineCol     lineCol\n         * @return the invocation\n         * @throws SyntaxException compiling error\n         */\n        public Value callFunctionalObject(Value object, STypeDef callerClass, List<Value> arguments, LineCol lineCol) throws SyntaxException {\n                Ins.InvokeStatic is = new Ins.InvokeStatic(\n                        getDYNAMIC_callFunctionalObject(), lineCol\n                );\n                is.arguments().add(object);\n                is.arguments().add(new Ins.GetClass(callerClass, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                is.arguments().add(packListValuesIntoObjectArray(arguments));\n                return is;\n        }\n\n        /**\n         * pack a list of values into []Object\n         *\n         * @param values values to pack\n         * @return a value represents the object array\n         * @throws SyntaxException compiling error\n         */\n        private Value packListValuesIntoObjectArray(List<Value> values) throws SyntaxException {\n                Ins.ANewArray aNewArray = new Ins.ANewArray(\n                        (SArrayTypeDef) getTypeWithName(\"[Ljava.lang.Object;\", LineCol.SYNTHETIC),\n                        getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC),\n                        new IntValue(values.size()));\n                for (Value v : values) {\n                        if (v.type() instanceof PrimitiveTypeDef) {\n                                v = boxPrimitive(v, LineCol.SYNTHETIC);\n                        }\n                        aNewArray.initValues().add(v);\n                }\n                return aNewArray;\n        }\n\n        /**\n         * pack a list of values into []boolean\n         *\n         * @param values values to pack\n         * @return a value represents the object array\n         * @throws SyntaxException compiling error\n         */\n        private Value packListValuesIntoBooleanArray(List<Value> values) throws SyntaxException {\n                Ins.NewArray newArray = new Ins.NewArray(\n                        new IntValue(values.size()), Ins.NewArray.NewBoolArray, Ins.TAStore.BASTORE,\n                        getTypeWithName(\"[B\", LineCol.SYNTHETIC)\n                );\n                newArray.initValues().addAll(values);\n                return newArray;\n        }\n\n        private Ins.InvokeStatic invoke_Dynamic_invoke(STypeDef targetClass, Value o, boolean isStatic, Value functionalObject,\n                                                       STypeDef invoker, String method, List<Value> args, boolean canInvokeImport,\n                                                       LineCol lineCol) throws SyntaxException {\n                Ins.InvokeStatic is = new Ins.InvokeStatic(\n                        getDYNAMIC_invoke(), lineCol\n                );\n                is.arguments().add(new Ins.GetClass(targetClass, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                is.arguments().add(o);\n                is.arguments().add(new BoolValue(isStatic));\n                is.arguments().add(functionalObject);\n                is.arguments().add(new Ins.GetClass(invoker, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                is.arguments().add(new StringConstantValue(method));\n                List<Value> primitives = new ArrayList<Value>();\n                for (Value a : args) {\n                        primitives.add(new BoolValue(a.type() instanceof PrimitiveTypeDef));\n                }\n                is.arguments().add(packListValuesIntoBooleanArray(primitives));\n                is.arguments().add(packListValuesIntoObjectArray(args));\n                is.arguments().add(new BoolValue(canInvokeImport));\n                return is;\n        }\n\n        private Ins.InvokeStatic invoke_Dynamic_construct(STypeDef targetClass, STypeDef invoker,\n                                                          List<Value> args,\n                                                          LineCol lineCol) throws SyntaxException {\n                Ins.InvokeStatic is = new Ins.InvokeStatic(\n                        getDYNAMIC_construct(), lineCol\n                );\n                is.arguments().add(new Ins.GetClass(targetClass, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                is.arguments().add(new Ins.GetClass(invoker, (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC)));\n                List<Value> primitives = new ArrayList<Value>();\n                for (Value v : args) {\n                        primitives.add(new BoolValue(v.type() instanceof PrimitiveTypeDef));\n                }\n                is.arguments().add(packListValuesIntoBooleanArray(primitives));\n                is.arguments().add(packListValuesIntoObjectArray(args));\n                return is;\n        }\n\n        /**\n         * get value from Invocation<br>\n         * the Invocation may<br>\n         * <ol>\n         * <li>invoke methods on `this` -- Access(`this`,methodName) / Access(null,methodName)</li>\n         * <li>invoke methods from ThisClass (static) -- Access(ThisClass,methodName) / Access(null,methodName)</li>\n         * <li>invoke methods from import static -- Access(null,methodName)</li>\n         * <li>invoke methods on values -- Access(value,methodName)</li>\n         * <li>invoke methods from SomeClass -- Access(SomeClass,methodName)</li>\n         * <li>invoke methods on `this` but invoke methods in super class/interface (invoke special) -- Access(Access(SuperClass,`this`),methodName)</li>\n         * <li>construct an object -- {@link #getTypeWithAccess(AST.Access, Map, List)}</li>\n         * </ol>\n         *\n         * @param invocation invocation object. invocation.exp should be AST.Access when calling this method.\n         *                   and invocation.invokeWithNames should be false.\n         * @param scope      scope that contains local variables and local methods\n         * @return Invoke object or New object(represents invokeXXX or new instruction)\n         * @throws SyntaxException exceptions\n         * @see #parseValueFromInvocationWithNames(AST.Invocation, SemanticScope)\n         * @see #parseValueFromInvocationFunctionalObject(AST.Invocation, SemanticScope)\n         */\n        public Value parseValueFromInvocation(AST.Invocation invocation, SemanticScope scope) throws SyntaxException {\n                // generic type map\n                Map<String, STypeDef> genericTypeMap = getGenericMap(scope.type());\n                // parse args\n                List<Value> argList = new ArrayList<Value>();\n                boolean tmpEnableTypeAccess = enableTypeAccess;\n                for (Expression arg : invocation.args) {\n                        enableTypeAccess = true;\n                        Value v;\n                        try {\n                                v = parseValueFromExpression(arg, null, scope);\n                        } finally {\n                                enableTypeAccess = tmpEnableTypeAccess;\n                        }\n                        if (v == null) {\n                                err.SyntaxException(arg + \" is not method argument\", arg.line_col());\n                                return null;\n                        }\n                        argList.add(v);\n                }\n\n                List<SMethodDef> methodsToInvoke = new ArrayList<SMethodDef>();\n                SemanticScope.MethodRecorder innerMethod = null; // inner method ?\n                Value target = null;\n                // get method and target\n                // get import\n                List<Import> imports = fileNameToImport.get(invocation.line_col().fileName);\n                AST.Access access = (AST.Access) invocation.exp;\n                access = transformAccess(access);\n                if (access.exp == null) {\n                        // access structure should be\n                        // Access(null, methodName)\n                        // the method could be this.methodName(...)\n                        // or ThisClass.methodName(...) (invokeStatic)\n                        // or invoke from `import static`\n                        // or inner method\n\n                        // access.name should be method name\n                        // try inner method\n                        SemanticScope.MethodRecorder r = scope.getInnerMethod(access.name);\n                        if (null != r) {\n                                SMethodDef m = r.method;\n                                if (r.paramCount == argList.size()) {\n                                        int inc = m.getParameters().size() - r.paramCount;\n                                        boolean canUse = true;\n                                        for (int i = 0; i < r.paramCount; ++i) {\n                                                STypeDef pType = m.getParameters().get(i + inc).type();\n                                                STypeDef aType = argList.get(i).type();\n                                                if (!pType.isAssignableFrom(aType)) {\n                                                        if (aType instanceof PrimitiveTypeDef) {\n                                                                if (pType.isAssignableFrom(boxPrimitive(\n                                                                        argList.get(i),\n                                                                        LineCol.SYNTHETIC\n                                                                ).type())) {\n                                                                        continue;\n                                                                }\n                                                        }\n                                                        canUse = false;\n                                                        break;\n                                                }\n                                        }\n                                        if (canUse) {\n                                                innerMethod = r;\n                                        }\n                                }\n                        }\n\n                        // this.methodName or ThisClass.methodName\n                        findMethodFromTypeWithArguments(\n                                access.line_col(),\n                                access.name,\n                                argList,\n                                scope.getThis() == null\n                                        ? scope.type()\n                                        : scope.getThis().type(),\n                                scope.type(),\n                                FIND_MODE_ANY,\n                                methodsToInvoke,\n                                true);\n\n                        if (methodsToInvoke.isEmpty()) {\n                                // try to invoke from `import static`\n                                for (Import im : imports) {\n                                        if (!methodsToInvoke.isEmpty()) break;\n                                        if (im.importAll && im.pkg == null) {\n                                                // this import type is import static\n\n                                                STypeDef type = getTypeWithAccess(im.access, genericTypeMap, imports);\n                                                findMethodFromTypeWithArguments(\n                                                        access.line_col(),\n                                                        access.name,\n                                                        argList,\n                                                        null,\n                                                        type,\n                                                        FIND_MODE_STATIC,\n                                                        methodsToInvoke,\n                                                        true);\n                                        }\n                                }\n                        }\n                }\n\n                boolean doInvokeSpecial = false;\n\n                if (methodsToInvoke.isEmpty()) {\n                        // not found or access.exp is not null\n                        if (access.exp != null) {\n                                // the access structure should be\n                                // Access(Access(type,`this`),methodName)\n                                // or\n                                // Access(type,methodName)\n                                // or\n                                // Access(value,methodName)\n                                if (access.exp instanceof AST.Access && ((AST.Access) access.exp).name.equals(\"this\")) {\n                                        // Access(Access(type or null,`this`),methodName)\n\n                                        // access1 represents access.exp\n                                        // access1.exp == access.exp.exp\n                                        AST.Access access1 = (AST.Access) access.exp;\n                                        if (access1.exp == null) {\n                                                // represents `this`\n                                                findMethodFromTypeWithArguments(\n                                                        access.line_col(),\n                                                        access.name, argList,\n                                                        scope.getThis() == null\n                                                                ? scope.type()\n                                                                : scope.getThis().type(),\n                                                        scope.type(),\n                                                        FIND_MODE_NON_STATIC,\n                                                        methodsToInvoke,\n                                                        true);\n                                        } else if (access1.exp instanceof AST.Access) {\n                                                // represents invoke methods in super classes/interfaces\n\n                                                doInvokeSpecial = true;\n\n                                                STypeDef type = getTypeWithAccess((AST.Access) access1.exp, genericTypeMap, imports);\n                                                assert type != null;\n                                                // type should be assignable from scope.type()\n                                                if (!type.isAssignableFrom(scope.type())) {\n                                                        err.SyntaxException(\"invokespecial type should be assignable from current class\", access1.line_col());\n                                                        return null;\n                                                }\n                                                findMethodFromTypeWithArguments(\n                                                        access.line_col(),\n                                                        access.name,\n                                                        argList,\n                                                        scope.getThis() == null\n                                                                ? scope.type()\n                                                                : scope.getThis().type(),\n                                                        type,\n                                                        FIND_MODE_NON_STATIC,\n                                                        methodsToInvoke,\n                                                        false); // only find method in given interface\n                                        } else {\n                                                err.SyntaxException(\"`Type` in Type.this.methodName should be Class/Interface name\", access1.exp.line_col());\n                                                return null;\n                                        }\n                                } else if (!(access.exp instanceof AST.PackageRef)) {\n                                        // check whether access.exp is type\n                                        STypeDef type = null;\n                                        if (access.exp instanceof AST.Access) {\n                                                try {\n                                                        type = getTypeWithAccess((AST.Access) access.exp, genericTypeMap, imports);\n                                                } catch (Throwable ignore) {\n                                                }\n                                                if (type != null) {\n                                                        if (type instanceof SClassDef && ((SClassDef) type).classType() == SClassDef.OBJECT) {\n                                                                findMethodFromTypeWithArguments(\n                                                                        access.line_col(),\n                                                                        access.name,\n                                                                        argList,\n                                                                        scope.type(),\n                                                                        type,\n                                                                        FIND_MODE_NON_STATIC,\n                                                                        methodsToInvoke,\n                                                                        true);\n                                                        } else {\n                                                                findMethodFromTypeWithArguments(\n                                                                        access.line_col(),\n                                                                        access.name,\n                                                                        argList,\n                                                                        scope.type(),\n                                                                        type,\n                                                                        FIND_MODE_STATIC,\n                                                                        methodsToInvoke,\n                                                                        true);\n                                                        }\n                                                }\n                                        }\n                                        // then:\n                                        // assume access.exp is value\n                                        // Access(value, methodName)\n                                        boolean isValue = true;\n                                        Throwable throwableWhenTryValue = null;\n                                        try {\n                                                if (type != null) {\n                                                        enableTypeAccess = false;\n                                                }\n                                                target = parseValueFromExpression(access.exp, null, scope);\n                                        } catch (Throwable e) {\n                                                // parse from value failed\n                                                isValue = false;\n                                                throwableWhenTryValue = e;\n                                        } finally {\n                                                if (type != null) {\n                                                        enableTypeAccess = true;\n                                                }\n                                        }\n\n                                        if (target == null) {\n                                                if (type != null && methodsToInvoke.isEmpty()) {\n                                                        try {\n                                                                // try to instantiate the class\n                                                                target = parseValueFromAccessType(\n                                                                        (AST.Access) access.exp, imports, scope.type());\n                                                        } catch (Throwable t) {\n                                                                // failed then it's not a value\n                                                                isValue = false;\n                                                        }\n                                                } else {\n                                                        isValue = false;\n                                                }\n                                        } else if (isGetFieldAtRuntime(target)) {\n                                                if (type != null) isValue = false;\n                                        }\n\n                                        if (isValue) {\n                                                assert target != null;\n\n                                                methodsToInvoke.clear();\n                                                if (target.type() instanceof SClassDef || target.type() instanceof SInterfaceDef) {\n                                                        findMethodFromTypeWithArguments(\n                                                                access.line_col(),\n                                                                access.name,\n                                                                argList,\n                                                                scope.type(),\n                                                                target.type(),\n                                                                FIND_MODE_NON_STATIC,\n                                                                methodsToInvoke,\n                                                                true);\n                                                } else if (target.type() instanceof SAnnoDef) {\n                                                        if (argList.size() != 0) {\n                                                                err.SyntaxException(\"Annotation don't have methods with non zero parameters\", access.exp.line_col());\n                                                                return null;\n                                                        }\n                                                        findMethodFromTypeWithArguments(\n                                                                access.exp.line_col(),\n                                                                access.name,\n                                                                argList,\n                                                                scope.type(),\n                                                                target.type(),\n                                                                FIND_MODE_NON_STATIC,\n                                                                methodsToInvoke,\n                                                                true\n                                                        ); // this method will find method from annotation\n                                                        if (methodsToInvoke.isEmpty()) {\n                                                                err.SyntaxException(\"cannot find \" + access.name + \" in \" + target.type(), access.exp.line_col());\n                                                                return null;\n                                                        }\n                                                } else if (target.type() instanceof PrimitiveTypeDef) {\n                                                        // box primitive then invoke\n                                                        target = boxPrimitive(target, access.exp.line_col());\n                                                        findMethodFromTypeWithArguments(\n                                                                access.line_col(),\n                                                                access.name,\n                                                                argList,\n                                                                scope.type(),\n                                                                target.type(),\n                                                                FIND_MODE_NON_STATIC,\n                                                                methodsToInvoke,\n                                                                true);\n                                                } else {\n                                                        throw new LtBug(\"type should not be \" + target.type());\n                                                }\n                                        } else if (access.exp instanceof AST.Access && type != null) {\n                                                // access.exp is type\n                                                if (methodsToInvoke.isEmpty()) {\n                                                        // try to get static field\n                                                        // which could be functional object\n                                                        SFieldDef field = findFieldFromTypeDef(access.name, type, scope.type(), FIND_MODE_STATIC, true);\n\n                                                        return invoke_Dynamic_invoke(\n                                                                type, NullValue.get(),\n                                                                true,\n                                                                field == null\n                                                                        ? NullValue.get()\n                                                                        : new Ins.GetStatic(field, invocation.line_col()),\n                                                                scope.type(),\n                                                                access.name,\n                                                                argList, false,\n                                                                invocation.line_col()\n                                                        );\n                                                }\n                                        } else {\n                                                if (throwableWhenTryValue == null) {\n                                                        err.SyntaxException(\n                                                                \"method access structure should only be \" +\n                                                                        \"(type,methodName)\" +\n                                                                        \"/((type or null,\\\"this\\\"),methodName)\" +\n                                                                        \"/(null,methodName)/(value,methodName) \" +\n                                                                        \"but got \" + invocation.exp, access.exp.line_col());\n                                                        return null;\n                                                } else {\n                                                        if (throwableWhenTryValue instanceof SyntaxException) {\n                                                                err.SyntaxException(((SyntaxException) throwableWhenTryValue).msg, ((SyntaxException) throwableWhenTryValue).lineCol);\n                                                        } else {\n                                                                throw new LtBug(throwableWhenTryValue);\n                                                        }\n                                                        return null;\n                                                }\n                                        }\n                                }\n                        }\n                }\n\n                // no method found\n                if (methodsToInvoke.isEmpty() && innerMethod == null) {\n                        // try to find constructor\n                        STypeDef type = null;\n                        try {\n                                type = getTypeWithAccess(access, genericTypeMap, imports);\n                        } catch (Throwable ignore) {\n                                // not found or not type format\n                        }\n                        if (type instanceof SClassDef) {\n                                // only SClassDef have constructors\n                                // check whether the type is a function\n                                if (((SClassDef) type).classType() == SClassDef.FUN) {\n                                        return callFunctionalObject(\n                                                constructingNewInst((SClassDef) type, Collections.<Value>emptyList(), scope, invocation.line_col()),\n                                                scope.type(),\n                                                argList,\n                                                invocation.line_col()\n                                        );\n                                } else {\n                                        return constructingNewInst((SClassDef) type, argList, scope, invocation.line_col());\n                                }\n                        }\n                }\n\n                if (access.exp instanceof AST.PackageRef) {\n                        // should be constructor\n                        // but not found\n                        err.SyntaxException(\"cannot find constructor \" + invocation, invocation.line_col());\n                        return null;\n                }\n\n                if (target == null) target = scope.getThis();\n\n                if (methodsToInvoke.isEmpty() && innerMethod == null) {\n                        // invoke dynamic\n                        STypeDef targetClass = target == null ? scope.type() : target.type();\n                        Value o;\n                        if (target == null) {\n                                if (scope.getThis() == null)\n                                        o = NullValue.get();\n                                else\n                                        o = scope.getThis();\n                        } else {\n                                o = target;\n                        }\n\n                        Value functionalObject;\n                        if (access.exp == null) {\n                                // invoking method on functional objects\n                                functionalObject = findObjectInCurrentScopeWithName(access.name, scope);\n                        } else {\n                                if (target == null) {\n                                        throw new LtBug(\"code should not reach here\");\n                                } else {\n                                        // xx.method(...)\n                                        SFieldDef field = findFieldFromTypeDef(access.name, target.type(), scope.type(), FIND_MODE_ANY, true);\n                                        if (field == null) {\n                                                functionalObject = NullValue.get();\n                                        } else {\n                                                if (field.modifiers().contains(SModifier.STATIC)) {\n                                                        functionalObject = new Ins.GetStatic(field, invocation.line_col());\n                                                } else {\n                                                        functionalObject = new Ins.GetField(field, target, invocation.line_col());\n                                                }\n                                        }\n                                }\n                        }\n\n                        return invoke_Dynamic_invoke(targetClass, o, scope.getThis() == null, functionalObject, scope.type(), access.name, argList, access.exp == null, invocation.line_col());\n                } else {\n                        SMethodDef methodToInvoke;\n                        boolean invokeInnerMethod = false;\n                        if (methodsToInvoke.isEmpty()) {\n                                assert innerMethod != null;\n                                methodToInvoke = innerMethod.method;\n                                invokeInnerMethod = true;\n                        } else if (innerMethod == null) {\n                                methodToInvoke = findBestMatch(argList, methodsToInvoke, invocation.line_col());\n                        } else {\n                                methodToInvoke = findBestMatch(argList, methodsToInvoke, invocation.line_col());\n                                // choose from inner method and normal method\n                                int inc = innerMethod.method.getParameters().size() - innerMethod.paramCount;\n                                Boolean normalIsBetter = null;\n                                for (int i = 0; i < methodToInvoke.getParameters().size(); ++i) {\n                                        STypeDef innerT = innerMethod.method.getParameters().get(i + inc).type();\n                                        STypeDef normalT = methodToInvoke.getParameters().get(i).type();\n                                        if (normalT.isAssignableFrom(innerT)) {\n                                                if (normalIsBetter == null) {\n                                                        normalIsBetter = false;\n                                                } else if (normalIsBetter) {\n                                                        err.SyntaxException(\"cannot choose between \" + methodToInvoke + \" and \" + innerMethod.method + \" with args \" + argList, invocation.line_col());\n                                                        return null;\n                                                }\n                                        } else if (innerT.isAssignableFrom(normalT)) {\n                                                if (normalIsBetter == null) {\n                                                        normalIsBetter = true;\n                                                } else if (!normalIsBetter) {\n                                                        err.SyntaxException(\"cannot choose between \" + methodToInvoke + \" and \" + innerMethod.method + \" with args \" + argList, invocation.line_col());\n                                                        return null;\n                                                }\n                                        }\n                                }\n                                if (normalIsBetter == null || !normalIsBetter) {\n                                        invokeInnerMethod = true;\n                                        methodToInvoke = innerMethod.method;\n                                }\n                        }\n\n                        if (invokeInnerMethod) {\n                                List<Value> values = new ArrayList<Value>();\n                                List<Ins.TLoad> capturedValues = new ArrayList<Ins.TLoad>();\n                                int inc = innerMethod.method.getParameters().size() - innerMethod.paramCount;\n                                for (int i = 0; i < argList.size(); ++i) {\n                                        STypeDef requiredType = innerMethod.method.getParameters().get(i + inc).type();\n                                        values.add(cast(\n                                                requiredType,\n                                                argList.get(i),\n                                                scope.type(),\n                                                invocation.line_col()\n                                        ));\n                                }\n\n                                Ins.InvokeWithCapture invoke;\n                                if (innerMethod.method.modifiers().contains(SModifier.STATIC)) {\n                                        invoke = new Ins.InvokeWithCapture(null, innerMethod.method, true, invocation.line_col());\n                                } else {\n                                        invoke = new Ins.InvokeWithCapture(scope.getThis(), innerMethod.method, false, invocation.line_col());\n                                }\n                                int requiredLocalVariableCount = innerMethod.method.getParameters().size() - innerMethod.paramCount;\n                                List<LeftValue> leftValues = scope.getLeftValues(requiredLocalVariableCount, false);\n                                if (leftValues.size() != requiredLocalVariableCount)\n                                        throw new LtBug(\"require \" + requiredLocalVariableCount + \" local variable(s), got \" + leftValues.size());\n\n                                for (LeftValue v : leftValues) {\n                                        capturedValues.add(new Ins.TLoad(v, scope, LineCol.SYNTHETIC));\n                                }\n                                invoke.arguments().addAll(values);\n                                invoke.capturedArguments().addAll(capturedValues);\n                                for (int i = 0; i < innerMethod.method.getParameters().size() - innerMethod.paramCount; ++i) {\n                                        SParameter p = innerMethod.method.getParameters().get(i);\n                                        assert p.isCapture();\n                                        if (p.isUsed()) {\n                                                Ins.TLoad v = capturedValues.get(i);\n                                                scope.getMeta().pointerLocalVar.add(v.value());\n                                        }\n                                }\n\n                                if (invoke.type().equals(VoidType.get()))\n                                        return new ValueAnotherType(\n                                                getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                invoke, invoke.line_col()\n                                        );\n\n                                return invoke;\n                        } else {\n                                argList = castArgsForMethodInvoke(argList, methodToInvoke.getParameters(), invocation.line_col());\n\n                                if (methodToInvoke.modifiers().contains(SModifier.STATIC)) {\n                                        // invoke static\n                                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(methodToInvoke, invocation.line_col());\n                                        invokeStatic.arguments().addAll(argList);\n\n                                        if (invokeStatic.type().equals(VoidType.get()))\n                                                return new ValueAnotherType(\n                                                        getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                        invokeStatic, invokeStatic.line_col()\n                                                );\n\n                                        return invokeStatic;\n                                } else if (methodToInvoke.declaringType() instanceof SInterfaceDef || methodToInvoke.declaringType() instanceof SAnnoDef) {\n                                        // invoke interface\n                                        if (target == null) {\n                                                err.SyntaxException(\"invoke interface should have an invoke target\", invocation.line_col());\n                                                return null;\n                                        }\n                                        Ins.InvokeInterface invokeInterface = new Ins.InvokeInterface(target, methodToInvoke, invocation.line_col());\n                                        invokeInterface.arguments().addAll(argList);\n\n                                        if (invokeInterface.type().equals(VoidType.get()))\n                                                return new ValueAnotherType(\n                                                        getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                        invokeInterface, invokeInterface.line_col()\n                                                );\n\n                                        return invokeInterface;\n                                } else if (doInvokeSpecial || methodToInvoke.modifiers().contains(SModifier.PRIVATE)) {\n                                        // invoke special\n                                        if (target == null) {\n                                                err.SyntaxException(\"invoke special should have an invoke target\", invocation.line_col());\n                                                return null;\n                                        }\n                                        Ins.InvokeSpecial invokeSpecial = new Ins.InvokeSpecial(target, methodToInvoke, invocation.line_col());\n                                        invokeSpecial.arguments().addAll(argList);\n\n                                        if (invokeSpecial.type().equals(VoidType.get()))\n                                                return new ValueAnotherType(\n                                                        getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                        invokeSpecial, invokeSpecial.line_col()\n                                                );\n\n                                        return invokeSpecial;\n                                } else {\n                                        // invoke virtual\n                                        if (target == null) {\n                                                STypeDef declaringType = methodToInvoke.declaringType();\n                                                if (declaringType instanceof SClassDef && ((SClassDef) declaringType).classType() == SClassDef.OBJECT) {\n                                                        target = parseValueFromAccess((AST.Access) access.exp, scope, false);\n                                                } else {\n                                                        err.SyntaxException(\"invoke virtual should have an invoke target\", invocation.line_col());\n                                                        return null;\n                                                }\n                                        }\n                                        Ins.InvokeVirtual invokeVirtual = new Ins.InvokeVirtual(target, methodToInvoke, invocation.line_col());\n                                        invokeVirtual.arguments().addAll(argList);\n\n                                        if (invokeVirtual.type().equals(VoidType.get()))\n                                                return new ValueAnotherType(\n                                                        getTypeWithName(\"lt.lang.Unit\", LineCol.SYNTHETIC),\n                                                        invokeVirtual, invokeVirtual.line_col()\n                                                );\n\n                                        return invokeVirtual;\n                                }\n                        }\n                }\n        }\n\n        /**\n         * check whether the `target` is <code>invokeStatic lt.runtime.LtRuntime.getField</code>\n         *\n         * @param target target\n         * @return true or false\n         */\n        public boolean isGetFieldAtRuntime(Value target) {\n                if (target instanceof Ins.InvokeStatic) {\n                        Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) target;\n                        if (invokeStatic.invokable() instanceof SMethodDef) {\n                                SMethodDef m = (SMethodDef) invokeStatic.invokable();\n                                if (\n                                        (\n                                                m.name().equals(\"getField\")\n                                        )\n                                                && m.declaringType().fullName().equals(\"lt.runtime.LtRuntime\")) {\n                                        return true;\n                                }\n                        }\n                }\n                return false;\n        }\n\n        /**\n         * check whether the `target` is <code>invokeStatic {@link #DYNAMIC_CLASS_NAME}</code>\n         *\n         * @param target target\n         * @return true or false\n         */\n        public boolean isInvokeAtRuntime(Value target) {\n                if (target instanceof Ins.InvokeStatic) {\n                        Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) target;\n                        if (invokeStatic.invokable() instanceof SMethodDef) {\n                                SMethodDef m = (SMethodDef) invokeStatic.invokable();\n                                if (\n                                        (m.name().equals(\"invoke\"))\n                                                && m.declaringType().fullName().equals(DYNAMIC_CLASS_NAME)\n                                        ) {\n                                        return true;\n                                }\n                        }\n                }\n                return false;\n        }\n\n        // the following 3 SWAPs are used when choosing the best method to invoke\n        /**\n         * no swap info\n         */\n        public static final int SWAP_NONE = 0;\n        /**\n         * do swap\n         */\n        public static final int SWAP_SWAP = 1;\n        /**\n         * do not swap\n         */\n        public static final int SWAP_NO_SWAP = 2;\n\n        /**\n         * find best match\n         *\n         * @param argList argList\n         * @param methods methods to choose from\n         * @param lineCol file_line_col\n         * @return selected method\n         * @throws SyntaxException exception\n         */\n        public SMethodDef findBestMatch(List<Value> argList, List<SMethodDef> methods, LineCol lineCol) throws SyntaxException {\n                if (null == methods || methods.isEmpty()) return null;\n                Iterator<SMethodDef> it = methods.iterator();\n                SMethodDef method = it.next();\n                while (it.hasNext()) {\n                        int swap = SWAP_NONE;\n                        SMethodDef methodCurrent = it.next();\n\n                        for (int i = 0; i < argList.size(); ++i) {\n                                SParameter paramLast = method.getParameters().get(i);\n                                SParameter paramCurrent = methodCurrent.getParameters().get(i);\n\n                                if (!paramLast.type().equals(paramCurrent.type())) {\n                                        if (paramLast.type().isAssignableFrom(paramCurrent.type()) && !paramLast.type().equals(paramCurrent.type())) {\n                                                // assignable\n                                                if (swap == SWAP_NONE) {\n                                                        swap = SWAP_SWAP;\n                                                } else if (swap == SWAP_NO_SWAP) {\n                                                        err.SyntaxException(\"cannot choose between \" + method + \" and \" + methodCurrent + \" with args \" + argList, lineCol);\n                                                        return null;\n                                                }\n                                        } else {\n                                                // not assignable\n                                                if (swap == SWAP_NONE) {\n                                                        swap = SWAP_NO_SWAP;\n                                                } else if (swap == SWAP_SWAP) {\n                                                        err.SyntaxException(\"cannot choose between \" + method + \" and \" + methodCurrent + \" with args \" + argList, lineCol);\n                                                        return null;\n                                                }\n                                        }\n                                }\n                        }\n\n                        if (swap == SWAP_SWAP) {\n                                method = methodCurrent;\n                        }\n                }\n                return method;\n        }\n\n        /**\n         * cast every argument to the method parameter type\n         *\n         * @param args       arguments\n         * @param parameters parameters\n         * @param lineCol    line column info\n         * @return a new list containing modified arguments\n         * @throws SyntaxException compile error\n         */\n        public List<Value> castArgsForMethodInvoke(List<Value> args, List<SParameter> parameters, LineCol lineCol) throws SyntaxException {\n                List<Value> result = new ArrayList<Value>();\n\n                for (int i = 0; i < parameters.size(); ++i) {\n                        Value v = args.get(i);\n                        SParameter param = parameters.get(i);\n\n                        result.add(cast(param.type(), v, null, lineCol));\n                }\n\n                return result;\n        }\n\n        public Value findObjectInCurrentScopeWithName(String name, SemanticScope scope) throws SyntaxException {\n                Value v = __findObjectInCurrentScopeWithName(name, scope);\n                if (isPointerType(v.type())) {\n                        return invokePointerGet(v, LineCol.SYNTHETIC);\n                } else return v;\n        }\n\n        /**\n         * get object in current scope.\n         *\n         * @param name  the local variable or field's name\n         * @param scope current scope\n         * @return TLoad or GetField or GetStatic or NullValue\n         */\n        public Value __findObjectInCurrentScopeWithName(String name, SemanticScope scope) {\n                LeftValue v = scope.getLeftValue(name);\n                if (v != null) return new Ins.TLoad(v, scope, LineCol.SYNTHETIC);\n\n                // try to get field\n                Ins.This aThis = scope.getThis();\n                if (aThis != null) {\n                        // search for static and non-static\n                        SFieldDef field = findFieldFromTypeDef(name, aThis.type(), aThis.type(), FIND_MODE_ANY, true);\n                        if (field == null) return NullValue.get();\n                        return new Ins.GetField(field, aThis, LineCol.SYNTHETIC);\n                } else {\n                        // search for static\n                        SFieldDef field = findFieldFromTypeDef(name, scope.type(), scope.type(), FIND_MODE_STATIC, true);\n                        if (field == null) return NullValue.get();\n                        return new Ins.GetStatic(field, LineCol.SYNTHETIC);\n                }\n        }\n\n        /**\n         * change primitive into its box type\n         *\n         * @param primitive primitive value\n         * @param lineCol   file_line_col\n         * @return InvokeStatic (all operations must invoke box type's static valueOf(..) method)\n         * @throws SyntaxException exception\n         */\n        public Ins.InvokeStatic boxPrimitive(Value primitive, LineCol lineCol) throws SyntaxException {\n                assert primitive.type() instanceof PrimitiveTypeDef;\n                if (primitive.type() instanceof ByteTypeDef) {\n                        SClassDef aByte = (SClassDef) getTypeWithName(\"java.lang.Byte\", lineCol);\n                        assert aByte != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aByte.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(ByteTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Byte.valueOf(byte) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof BoolTypeDef) {\n                        SClassDef aBoolean = (SClassDef) getTypeWithName(\"java.lang.Boolean\", lineCol);\n                        assert aBoolean != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aBoolean.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(BoolTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Boolean.valueOf(boolean) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof CharTypeDef) {\n                        SClassDef integer = (SClassDef) getTypeWithName(\"java.lang.Character\", lineCol);\n                        assert integer != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : integer.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(CharTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Character.valueOf(char) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof DoubleTypeDef) {\n                        SClassDef aDouble = (SClassDef) getTypeWithName(\"java.lang.Double\", lineCol);\n                        assert aDouble != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aDouble.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(DoubleTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Double.valueOf(double) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof FloatTypeDef) {\n                        SClassDef aFloat = (SClassDef) getTypeWithName(\"java.lang.Float\", lineCol);\n                        assert aFloat != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aFloat.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(FloatTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Float.valueOf(float) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof IntTypeDef) {\n                        SClassDef integer = (SClassDef) getTypeWithName(\"java.lang.Integer\", lineCol);\n                        assert integer != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : integer.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(IntTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Integer.valueOf(int) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof LongTypeDef) {\n                        SClassDef aLong = (SClassDef) getTypeWithName(\"java.lang.Long\", lineCol);\n                        assert aLong != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aLong.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(LongTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Long.valueOf(long) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else if (primitive.type() instanceof ShortTypeDef) {\n                        SClassDef aShort = (SClassDef) getTypeWithName(\"java.lang.Short\", lineCol);\n                        assert aShort != null;\n\n                        SMethodDef valueOf = null;\n                        for (SMethodDef m : aShort.methods()) {\n                                if (m.name().equals(\"valueOf\") && m.getParameters().size() == 1 && m.getParameters().get(0).type().equals(ShortTypeDef.get())) {\n                                        valueOf = m;\n                                }\n                        }\n                        if (valueOf == null) throw new LtBug(\"java.lang.Short.valueOf(short) should exist\");\n                        Ins.InvokeStatic invokeStatic = new Ins.InvokeStatic(valueOf, lineCol);\n                        invokeStatic.arguments().add(primitive);\n                        return invokeStatic;\n                } else throw new LtBug(\"primitive can only be byte/boolean/char/double/float/int/long/short\");\n        }\n\n        /**\n         * unescape the string<br>\n         * unescape \\n,\\t,\\r,\\',\\\",\\\\\n         *\n         * @param s       the string to unescape\n         * @param lineCol file_line_col\n         * @return unescaped string\n         * @throws SyntaxException exception\n         */\n        public String unescape(String s, LineCol lineCol) throws SyntaxException {\n                char[] chars = s.toCharArray();\n                char[] preResult = new char[chars.length];\n                int j = 0;\n                for (int i = 0; i < chars.length; ++i, ++j) {\n                        char c = chars[i];\n                        if (c == '\\\\') {\n                                char anotherChar = chars[++i];\n                                if (anotherChar == 'n') preResult[j] = '\\n';\n                                else if (anotherChar == 't') preResult[j] = '\\t';\n                                else if (anotherChar == 'r') preResult[j] = '\\r';\n                                else if (anotherChar == '\\'') preResult[j] = '\\'';\n                                else if (anotherChar == '\\\\') preResult[j] = '\\\\';\n                                else if (anotherChar == '\\\"') preResult[j] = '\\\"';\n                                else {\n                                        err.SyntaxException(\"cannot unescape \\\\\" + anotherChar, lineCol);\n                                        return null;\n                                }\n                        } else {\n                                preResult[j] = c;\n                        }\n                }\n                char[] result = new char[j];\n                System.arraycopy(preResult, 0, result, 0, j);\n                return new String(result);\n        }\n\n        /**\n         * generate string that concat expressions inside the string which is surrounded by `${ }`\n         *\n         * @param str     raw string\n         * @param scope   semantic scope\n         * @param lineCol lineCol info\n         * @return result from {@link #concatValuesToString(List, SemanticScope, LineCol)}\n         * @throws SyntaxException compiling error\n         */\n        public Value generateStringConcat(String str, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                char[] chars = str.toCharArray();\n                SClassDef STRING = (SClassDef) getTypeWithName(\"java.lang.String\", lineCol);\n\n                List<Value> elemsToConcat = new ArrayList<Value>();\n                StringBuilder sb = new StringBuilder();\n                StringBuilder evalStr = new StringBuilder();\n\n                Stack<Object> evaluatingStack = new Stack<Object>();\n                boolean isEvaluating = false;\n                Object flag = new Object();\n                for (int i = 0; i < chars.length; i++) {\n                        char c = chars[i];\n                        if (c == '$' && i < chars.length - 1 && chars[i + 1] == '{') {\n                                evaluatingStack.push(flag);\n                                ++i;\n                        } else if (c == '}') {\n                                if (!evaluatingStack.isEmpty()) evaluatingStack.pop();\n                        }\n\n                        if (evaluatingStack.isEmpty()) {\n                                if (isEvaluating) {\n                                        String expStr = evalStr.toString();\n                                        evalStr.delete(0, evalStr.length());\n                                        List<Statement> statements;\n                                        try {\n                                                ErrorManager subErr = new ErrorManager(true);\n                                                Scanner scanner = new ScannerSwitcher(\"eval\",\n                                                        new StringReader(expStr), new Properties(), subErr);\n                                                Parser parser = new Parser(scanner.scan(), subErr);\n                                                statements = parser.parse();\n                                        } catch (IOException e) {\n                                                // this can never happen for the reader is a StringReader\n                                                throw new LtBug(e);\n                                        }\n                                        if (statements.size() != 1 || !(statements.get(0) instanceof Expression)) {\n                                                err.SyntaxException(\"the string can only concat an expression, but got \" + statements, lineCol);\n                                                throw new LtBug(\"code won't reach here\");\n                                        }\n                                        Expression exp = (Expression) statements.get(0);\n                                        elemsToConcat.add(parseValueFromExpression(exp, null, scope));\n                                } else {\n                                        sb.append(c);\n                                }\n                                isEvaluating = false;\n                        } else {\n                                if (isEvaluating) {\n                                        if (c == '\\n' || c == '\\t' || c == '\\r' || c == '\\\"' || c == '\\'' || c == '\\\\') {\n                                                err.SyntaxException(\"invalid char \" + c + \" for expression in string \" + str, lineCol);\n                                                throw new LtBug(\"code won't reach here\");\n                                        }\n                                        evalStr.append(c);\n                                } else {\n                                        StringConstantValue s = new StringConstantValue(sb.toString());\n                                        s.setType(STRING);\n                                        elemsToConcat.add(s);\n                                        sb.delete(0, sb.length());\n                                }\n                                isEvaluating = true;\n                        }\n                }\n                if (sb.length() != 0 || elemsToConcat.isEmpty()) {\n                        // append last piece of value to the list\n                        StringConstantValue s = new StringConstantValue(sb.toString());\n                        s.setType(STRING);\n                        elemsToConcat.add(s);\n                }\n\n                return concatValuesToString(elemsToConcat, scope, lineCol);\n        }\n\n        /**\n         * concat the values as one string\n         *\n         * @param values  value list\n         * @param scope   scope\n         * @param lineCol lineCol\n         * @return StringConstantValue or 'xx+yy+zz+...'\n         * @throws SyntaxException compiling error\n         */\n        public Value concatValuesToString(List<Value> values, SemanticScope scope, LineCol lineCol) throws SyntaxException {\n                if (values.size() == 1 && values.get(0) instanceof StringConstantValue) {\n                        // plain string\n                        return values.get(0);\n                } else {\n                        if (!(values.get(0) instanceof StringConstantValue) && !(values.get(1) instanceof StringConstantValue)) {\n                                StringConstantValue emptyString = new StringConstantValue(\"\");\n                                emptyString.setType((SClassDef) getTypeWithName(\"java.lang.String\", LineCol.SYNTHETIC));\n                                values.add(0, emptyString);\n                        }\n                        Iterator<Value> it = values.iterator();\n                        Value finalValue = it.next();\n                        while (it.hasNext()) {\n                                finalValue = parseValueFromTwoVarOp(finalValue, \"+\", it.next(), scope, lineCol);\n                        }\n                        STypeDef STRING = getTypeWithName(\"java.lang.String\", LineCol.SYNTHETIC);\n                        if (finalValue.type().equals(STRING)) {\n                                return finalValue;\n                        } else {\n                                return new Ins.CheckCast(finalValue, STRING, LineCol.SYNTHETIC);\n                        }\n                }\n        }\n\n        /**\n         * parse value from object<br>\n         * the object can be<br>\n         * <ul>\n         * <li>Integer</li>\n         * <li>Long</li>\n         * <li>Character</li>\n         * <li>Short</li>\n         * <li>Byte</li>\n         * <li>Boolean</li>\n         * <li>Float</li>\n         * <li>Double</li>\n         * <li>String</li>\n         * <li>enum</li>\n         * <li>Class</li>\n         * <li>Annotation</li>\n         * <li>Array of all above types</li>\n         * </ul>\n         *\n         * @param o the input object\n         * @return Value object.<br>\n         * <ul>\n         * <li>IntValue</li>\n         * <li>LongValue</li>\n         * <li>CharValue</li>\n         * <li>ShortValue</li>\n         * <li>ByteValue</li>\n         * <li>BoolValue</li>\n         * <li>FloatValue</li>\n         * <li>DoubleValue</li>\n         * <li>StringConstantValue</li>\n         * <li>EnumValue</li>\n         * <li>Ins.GetClass</li>\n         * <li>SAnno</li>\n         * <li>SArrayValue</li>\n         * </ul>\n         * @throws SyntaxException exception\n         */\n        public Value parseValueFromObject(Object o) throws SyntaxException {\n                // primitives\n                if (o instanceof Integer) {\n                        return new IntValue((Integer) o);\n                } else if (o instanceof Long) {\n                        return new LongValue((Long) o);\n                } else if (o instanceof Character) {\n                        return new CharValue((Character) o);\n                } else if (o instanceof Short) {\n                        return new ShortValue((Short) o);\n                } else if (o instanceof Byte) {\n                        return new ByteValue((Byte) o);\n                } else if (o instanceof Boolean) {\n                        return new BoolValue((Boolean) o);\n                } else if (o instanceof Float) {\n                        return new FloatValue((Float) o);\n                } else if (o instanceof Double) {\n                        return new DoubleValue((Double) o);\n                } else if (o instanceof String) {\n                        // string\n                        StringConstantValue v = new StringConstantValue((String) o);\n                        v.setType((SClassDef) getTypeWithName(\"java.lang.String\", LineCol.SYNTHETIC));\n                        return v;\n                } else if (o.getClass().isEnum()) {\n                        // enum\n                        EnumValue e = new EnumValue();\n                        e.setType(getTypeWithName(o.getClass().getName(), LineCol.SYNTHETIC));\n                        e.setEnumStr(o.toString());\n                        return e;\n                } else if (o instanceof Class) {\n                        // class\n                        return new Ins.GetClass(\n                                getTypeWithName(((Class) o).getName(), LineCol.SYNTHETIC),\n                                (SClassDef) getTypeWithName(\"java.lang.Class\", LineCol.SYNTHETIC));\n                } else if (o instanceof Annotation) {\n                        // annotation\n                        SAnno a = new SAnno();\n                        Class<?> annoCls = o.getClass().getInterfaces()[0];\n                        a.setAnnoDef((SAnnoDef) getTypeWithName(annoCls.getName(), LineCol.SYNTHETIC));\n                        Map<SAnnoField, Value> map = new HashMap<SAnnoField, Value>();\n                        for (SAnnoField f : a.type().annoFields()) {\n                                try {\n                                        Object obj = invokeAnnotationMethod((Annotation) o, annoCls.getMethod(f.name()));\n                                        Value v = parseValueFromObject(obj);\n                                        v = checkAndCastAnnotationValues(v, LineCol.SYNTHETIC);\n                                        map.put(f, v);\n                                } catch (Exception e) {\n                                        throw new LtBug(e);\n                                }\n                        }\n                        a.values().putAll(map);\n\n                        return a;\n                } else if (o.getClass().isArray()) {\n                        // array\n                        assert !o.getClass().getComponentType().isArray();\n\n                        SArrayValue arr = new SArrayValue();\n                        int length = Array.getLength(o);\n                        Value[] values = new Value[length];\n                        for (int i = 0; i < length; ++i) {\n                                Object elem = Array.get(o, i);\n                                Value v = parseValueFromObject(elem);\n                                values[i] = v;\n                        }\n                        arr.setType((SArrayTypeDef) getTypeWithName(o.getClass().getName(), LineCol.SYNTHETIC));\n                        arr.setDimension(1);\n                        arr.setValues(values);\n\n                        return arr;\n                } else if (o instanceof DummyValue) {\n                        return (Value) o;\n                } else throw new LtBug(\"cannot parse \" + o + \" into Value\");\n        }\n\n        /**\n         * record abstract methods for override check. methods are retrieved from interfaces.\n         *\n         * @param i               the interface to retrieve method from\n         * @param abstractMethods record abstract methods\n         * @param visitedMethods  already visited methods\n         * @param visitedType     already visited types\n         * @throws SyntaxException exception\n         */\n        public void recordAbstractMethodsForOverrideCheck_interface(SInterfaceDef i,\n                                                                    List<SMethodDef> abstractMethods,\n                                                                    List<SMethodDef> visitedMethods,\n                                                                    Set<SInterfaceDef> visitedType) throws SyntaxException {\n                // check only when it's not visited\n                if (visitedType.add(i)) {\n                        for (SMethodDef m : i.methods()) {\n                                if (m.modifiers().contains(SModifier.ABSTRACT)) {\n                                        if (null == findMethodWithSameSignature(m, visitedMethods, true)) {\n                                                abstractMethods.add(m);\n                                        }\n                                }\n                                visitedMethods.add(m);\n                        }\n                        // check super interfaces\n                        for (SInterfaceDef ii : i.superInterfaces()) {\n                                recordAbstractMethodsForOverrideCheck_interface(\n                                        ii, abstractMethods, visitedMethods, visitedType\n                                );\n                        }\n                }\n        }\n\n        /**\n         * record abstract methods for override check. methods are retrieved from classes.\n         *\n         * @param c               the class to retrieve method from\n         * @param abstractMethods recorded abstract methods\n         * @param visitedMethods  already visited methods\n         * @param visitedType     already visited types\n         * @throws SyntaxException exception\n         */\n        public void recordAbstractMethodsForOverrideCheck_class(SClassDef c,\n                                                                List<SMethodDef> abstractMethods,\n                                                                List<SMethodDef> visitedMethods,\n                                                                Set<SInterfaceDef> visitedType) throws SyntaxException {\n                if (c == null || !c.modifiers().contains(SModifier.ABSTRACT)) return;\n                // check the class\n                for (SMethodDef m : c.methods()) {\n                        if (m.modifiers().contains(SModifier.ABSTRACT)) {\n                                if (null == findMethodWithSameSignature(m, visitedMethods, true)) {\n                                        abstractMethods.add(m);\n                                }\n                        }\n                        visitedMethods.add(m);\n                }\n                // check parent class\n                recordAbstractMethodsForOverrideCheck_class(c.parent(), abstractMethods, visitedMethods, visitedType);\n                // check interfaces\n                for (SInterfaceDef i : c.superInterfaces()) {\n                        recordAbstractMethodsForOverrideCheck_interface(\n                                i, abstractMethods, visitedMethods, visitedType\n                        );\n                }\n        }\n\n        /**\n         * record abstract methods for override check.\n         *\n         * @param c               the base class\n         * @param abstractMethods record abstract methods\n         * @throws SyntaxException exception\n         */\n        public void recordAbstractMethodsForOverrideCheck(SClassDef c, List<SMethodDef> abstractMethods) throws SyntaxException {\n                List<SMethodDef> visitedMethods = new ArrayList<SMethodDef>();\n                Set<SInterfaceDef> visitedTypes = new HashSet<SInterfaceDef>();\n                recordAbstractMethodsForOverrideCheck_class(\n                        c.parent(),\n                        abstractMethods,\n                        visitedMethods,\n                        visitedTypes);\n                for (SInterfaceDef i : c.superInterfaces()) {\n                        recordAbstractMethodsForOverrideCheck_interface(\n                                i, abstractMethods, visitedMethods, visitedTypes\n                        );\n                }\n        }\n\n        /**\n         * check whether the overridden method is modified with final.\n         * if not, the overridden/override list would be added with corresponding value\n         *\n         * @param method           method in current type\n         * @param overriddenMethod method in super class/interface\n         * @throws SyntaxException compiling error\n         */\n        public void checkFinalAndOverride(SMethodDef method, SMethodDef overriddenMethod) throws SyntaxException {\n                if (overriddenMethod.modifiers().contains(SModifier.FINAL)) {\n                        err.SyntaxException(overriddenMethod + \" cannot be overridden\", method.line_col());\n                        return;\n                }\n\n                if (!overriddenMethod.getReturnType().isAssignableFrom(method.getReturnType())) {\n                        err.SyntaxException(\"Trying to override \" + overriddenMethod + \" but return type mismatch\", method.line_col());\n                }\n\n                overriddenMethod.overridden().add(method);\n                method.overRide().add(overriddenMethod);\n        }\n\n        /**\n         * check whether the method overrides method in the class (and its parent classes and interfaces)\n         *\n         * @param method       method\n         * @param sClassDef    class\n         * @param visitedTypes types already visited\n         * @throws SyntaxException exception\n         */\n        public void checkOverride_class(SMethodDef method,\n                                        SClassDef sClassDef,\n                                        Set<STypeDef> visitedTypes) throws SyntaxException {\n                if (visitedTypes.contains(sClassDef)) return;\n                visitedTypes.add(sClassDef);\n\n                SMethodDef methodInSuper = findMethodWithSameSignature(method, sClassDef.methods(), false);\n                if (methodInSuper == null) {\n                        // check super class\n                        if (sClassDef.parent() != null) {\n                                checkOverride_class(method, sClassDef.parent(), visitedTypes);\n                        }\n                        // check super interfaces\n                        for (SInterfaceDef i : sClassDef.superInterfaces()) {\n                                checkOverride_interface(method, i, visitedTypes);\n                        }\n                } else {\n                        checkFinalAndOverride(method, methodInSuper);\n                }\n        }\n\n        /**\n         * check whether the method overrides method in the interface (and its super interfaces)\n         *\n         * @param method        method\n         * @param sInterfaceDef interface\n         * @param visitedTypes  types already visited\n         * @throws SyntaxException exception\n         */\n        public void checkOverride_interface(SMethodDef method,\n                                            SInterfaceDef sInterfaceDef,\n                                            Set<STypeDef> visitedTypes) throws SyntaxException {\n                if (visitedTypes.contains(sInterfaceDef)) return;\n                visitedTypes.add(sInterfaceDef);\n\n                SMethodDef methodInSuper = findMethodWithSameSignature(method, sInterfaceDef.methods(), false);\n                if (methodInSuper == null) {\n                        // check super interfaces\n                        for (SInterfaceDef i : sInterfaceDef.superInterfaces()) {\n                                checkOverride_interface(method, i, visitedTypes);\n                        }\n                } else {\n                        checkFinalAndOverride(method, methodInSuper);\n                }\n        }\n\n        /**\n         * check whether the class already overrides all abstract methods in super class/interfaces\n         *\n         * @param sTypeDef type to be checked\n         * @throws SyntaxException exception\n         */\n        public void checkOverride(STypeDef sTypeDef) throws SyntaxException {\n                if (sTypeDef instanceof SClassDef) {\n                        for (SMethodDef m : ((SClassDef) sTypeDef).methods()) {\n                                checkOverride_class(m, ((SClassDef) sTypeDef).parent(), new HashSet<STypeDef>());\n                                for (SInterfaceDef i : ((SClassDef) sTypeDef).superInterfaces()) {\n                                        checkOverride_interface(m, i, new HashSet<STypeDef>());\n                                }\n                        }\n                } else if (sTypeDef instanceof SInterfaceDef) {\n                        for (SMethodDef m : ((SInterfaceDef) sTypeDef).methods()) {\n                                for (SInterfaceDef i : ((SInterfaceDef) sTypeDef).superInterfaces()) {\n                                        checkOverride_interface(m, i, new HashSet<STypeDef>());\n                                }\n                        }\n                } else {\n                        throw new LtBug(\"wrong STypeDefType \" + sTypeDef.getClass());\n                }\n        }\n\n        /**\n         * check whether the interface extends itself\n         *\n         * @param toCheck  the interface to be checked\n         * @param current  list of super interfaces\n         * @param recorder a queue of interfaces to be checked\n         * @throws SyntaxException exception\n         */\n        public void checkInterfaceCircularInheritance(final SInterfaceDef toCheck, List<SInterfaceDef> current, List<SInterfaceDef> recorder) throws SyntaxException {\n                for (SInterfaceDef i : current) {\n                        recorder.add(i);\n                        if (i.equals(toCheck)) {\n                                err.SyntaxException(\"circular inheritance \" + recorder, LineCol.SYNTHETIC);\n                                return;\n                        }\n                        checkInterfaceCircularInheritance(toCheck, i.superInterfaces(), recorder);\n                        recorder.remove(recorder.size() - 1);\n                }\n        }\n\n        /**\n         * find method with same signature<br>\n         * method name and arguments should be the same<br>\n         * if the above conditions are matched, the found return type should be assignable from return type of the method to be checked\n         *\n         * @param method             the method to be checked\n         * @param methodList         super methods\n         * @param onlyCheckSignature only check signature, doesn't check modifier and return type\n         * @return found method or null\n         * @throws SyntaxException exception\n         */\n        public SMethodDef findMethodWithSameSignature(SMethodDef method,\n                                                      List<SMethodDef> methodList,\n                                                      boolean onlyCheckSignature) throws SyntaxException {\n                outer:\n                for (SMethodDef m : methodList) {\n                        // same name\n                        if (m.name().equals(method.name())) {\n                                // same param length\n                                if (m.getParameters().size() == method.getParameters().size()) {\n                                        // same type\n                                        for (int i = 0; i < m.getParameters().size(); ++i) {\n                                                SParameter p = m.getParameters().get(i);\n                                                SParameter param = method.getParameters().get(i);\n                                                if (!p.type().equals(param.type())) {\n                                                        continue outer;\n                                                }\n                                        }\n\n                                        if (!onlyCheckSignature) {\n\n                                                // method\n                                                // check access modifier\n                                                // super is private, continue\n                                                if (m.modifiers().contains(SModifier.PRIVATE)) continue;\n                                                if (\n                                                        // super is public, this is not public\n                                                        (m.modifiers().contains(SModifier.PUBLIC)\n                                                                && !method.modifiers().contains(SModifier.PUBLIC)\n                                                        )\n                                                                ||\n                                                                // super is protected, this is not public/protected\n                                                                (m.modifiers().contains(SModifier.PROTECTED)\n                                                                        && !m.modifiers().contains(SModifier.PUBLIC)\n                                                                        && !m.modifiers().contains(SModifier.PROTECTED)\n                                                                )\n                                                                ||\n                                                                // super is package access, (this is private or they are not in same pkg)\n                                                                (!m.modifiers().contains(SModifier.PUBLIC)\n                                                                        && !m.modifiers().contains(SModifier.PROTECTED)\n                                                                        && !m.modifiers().contains(SModifier.PRIVATE)\n                                                                        &&\n                                                                        (\n                                                                                method.modifiers().contains(SModifier.PRIVATE)\n                                                                                        ||\n                                                                                        !m.declaringType().pkg().equals(method.declaringType().pkg())\n                                                                        )\n                                                                )\n                                                        ) {\n                                                        err.SyntaxException(method + \" cannot override \" + m, method.line_col());\n                                                        return null;\n                                                }\n\n                                                if (!m.getReturnType().isAssignableFrom(method.getReturnType())\n                                                        &&\n                                                        !method.getReturnType().isAssignableFrom(m.getReturnType())) {\n                                                        err.SyntaxException(m + \" return type should be assignable from \" + method + \" 's\", method.line_col());\n                                                        return null;\n                                                }\n\n                                        }\n\n                                        return m;\n                                }\n                        }\n                }\n                return null;\n        }\n\n        public Map<SAnno, AST.Anno> annotationRecorder = new HashMap<SAnno, AST.Anno>();\n\n        /**\n         * parse the annotations<br>\n         * but the <tt>annotationFields</tt> won't be set\n         *\n         * @param annos                 a set of annotations\n         * @param annotationPresentable the annotation is presented on the object\n         * @param imports               imports\n         * @param type                  the annotation accepts element type\n         * @param checkTheseWhenFail    if type not matches, then check this list, if contains then it won't throw an exception\n         * @throws SyntaxException exception\n         */\n        public void parseAnnos(Set<AST.Anno> annos,\n                               SAnnotationPresentable annotationPresentable,\n                               List<Import> imports,\n                               ElementType type,\n                               List<ElementType> checkTheseWhenFail) throws SyntaxException {\n                for (AST.Anno anno : annos) {\n                        SAnnoDef annoType;\n                        if (annotationPresentable instanceof SMember) {\n                                annoType = (SAnnoDef) getTypeWithAccess(anno.anno, getGenericMap(((SMember) annotationPresentable).declaringType()), imports);\n                        } else {\n                                annoType = (SAnnoDef) getTypeWithAccess(anno.anno, Collections.<String, STypeDef>emptyMap(), imports);\n                        }\n                        assert annoType != null;\n\n                        if (annoType.canPresentOn(type)) {\n                                SAnno s = new SAnno();\n                                s.setAnnoDef(annoType);\n                                s.setPresent(annotationPresentable);\n                                annotationPresentable.annos().add(s);\n\n                                annotationRecorder.put(s, anno);\n                        } else {\n                                boolean fail = true;\n                                for (ElementType t : checkTheseWhenFail) {\n                                        if (annoType.canPresentOn(t)) {\n                                                fail = false;\n                                                break;\n                                        }\n                                }\n                                if (fail) {\n                                        err.SyntaxException(\"annotation \" + annoType + \" cannot present on \" + type, anno.line_col());\n                                        return;\n                                }\n                        }\n                }\n        }\n\n        /**\n         * parse parameters\n         *\n         * @param variableDefList     a list of parameters (in the form of VariableDef)\n         * @param i                   parameter length (invokes the method with i+1 parameters)\n         * @param invokable           the parameters belong to this object\n         * @param imports             imports\n         * @param allowAccessModifier allow access modifier\n         * @throws SyntaxException exceptions\n         */\n        public void parseParameters(List<VariableDef> variableDefList, int i, SInvokable invokable, List<Import> imports,\n                                    boolean allowAccessModifier) throws SyntaxException {\n                for (int j = 0; j < i; ++j) {\n                        // foreach variable\n                        // set their name|target(constructor)|type|modifier(val)|anno_general\n                        // and add into parameter list\n\n                        VariableDef v = variableDefList.get(j);\n                        SParameter param = new SParameter();\n                        param.setName(v.getName());\n                        param.setTarget(invokable);\n                        STypeDef type;\n                        if (v.getType() == null) {\n                                type = getTypeWithName(\"java.lang.Object\",\n                                        v.line_col());\n                        } else {\n                                type = getTypeWithAccess(v.getType(), getGenericMap(invokable.declaringType()), imports);\n                        }\n                        param.setType(type);\n\n                        for (Modifier m : v.getModifiers()) {\n                                switch (m.modifier) {\n                                        case VAL:\n                                                param.setCanChange(false);\n                                                break;\n                                        case PUBLIC:\n                                        case PRIVATE:\n                                        case PROTECTED:\n                                        case PKG:\n                                                if (!allowAccessModifier) {\n                                                        err.SyntaxException(\"access modifiers for parameters are only allowed on class constructing parameters\",\n                                                                m.line_col());\n                                                        return;\n                                                }\n                                                break;\n                                        case NONNULL:\n                                                param.setNotNull(true);\n                                                break;\n                                        case NONEMPTY:\n                                                param.setNotEmpty(true);\n                                                break;\n                                        default:\n                                                err.UnexpectedTokenException(\"valid modifier for parameters (val)\", m.toString(), m.line_col());\n                                                return;\n                                }\n                        }\n\n                        parseAnnos(v.getAnnos(), param, imports, ElementType.PARAMETER,\n                                // the modifier may be field\n                                allowAccessModifier\n                                        ? Collections.singletonList(ElementType.FIELD)\n                                        : Collections.<ElementType>emptyList()\n                        );\n\n                        invokable.getParameters().add(param);\n                }\n        }\n\n        /**\n         * parse fields from Destruct\n         *\n         * @param d        destruct ast object\n         * @param type     the type to add\n         * @param isStatic whether is static\n         * @throws SyntaxException exception\n         */\n        public void parseFieldsFromDestruct(AST.Destruct d, SRefTypeDef type, boolean isStatic) throws SyntaxException {\n                for (AST.Pattern p : d.pattern.subPatterns) {\n                        if (p instanceof AST.Pattern_Default) continue;\n                        assert p instanceof AST.Pattern_Define;\n\n                        AST.Pattern_Define pd = (AST.Pattern_Define) p;\n                        SFieldDef fieldDef = new SFieldDef(LineCol.SYNTHETIC);\n                        fieldDef.setName(pd.name);\n                        fieldDef.setType(getObject_Class());\n                        fieldDef.setDeclaringType(type);\n                        // modifiers\n                        parseFieldModifiers(fieldDef, d.modifiers, type instanceof SInterfaceDef, isStatic, false);\n                        // annos\n                        parseAnnos(d.annos, fieldDef, fileNameToImport.get(type.line_col().fileName),\n                                ElementType.FIELD, Collections.<ElementType>emptyList());\n\n                        type.fields().add(fieldDef);\n                }\n        }\n\n        private void parseFieldModifiers(SFieldDef fieldDef, Set<Modifier> modifiers,\n                                         boolean isInterface, boolean isStatic, boolean isParam) throws SyntaxException {\n                // try to get access flags\n                boolean hasAccessModifier = false;\n                for (Modifier m : modifiers) {\n                        if (m.modifier.equals(Modifier.Available.PUBLIC)\n                                || m.modifier.equals(Modifier.Available.PRIVATE)\n                                || m.modifier.equals(Modifier.Available.PROTECTED)\n                                || m.modifier.equals(Modifier.Available.PKG)) {\n                                hasAccessModifier = true;\n                        }\n                }\n                if (!hasAccessModifier) {\n                        if (isInterface) {\n                                fieldDef.modifiers().add(SModifier.PUBLIC);\n                                fieldDef.modifiers().add(SModifier.STATIC);\n                        } else {\n                                if (isStatic) {\n                                        fieldDef.modifiers().add(SModifier.PUBLIC); // default modifier for static field is public\n                                } else {\n                                        fieldDef.modifiers().add(SModifier.PRIVATE); // default modifier for instance field is private\n                                }\n                        }\n                }\n                // modifiers\n                for (Modifier m : modifiers) {\n                        switch (m.modifier) {\n                                case PUBLIC:\n                                        fieldDef.modifiers().add(SModifier.PUBLIC);\n                                        break;\n                                case PRIVATE:\n                                        if (isInterface) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString().toLowerCase(), m.line_col());\n                                                return;\n                                        }\n                                        fieldDef.modifiers().add(SModifier.PRIVATE);\n                                        break;\n                                case PROTECTED:\n                                        if (isInterface) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString().toLowerCase(), m.line_col());\n                                                return;\n                                        }\n                                        fieldDef.modifiers().add(SModifier.PROTECTED);\n                                        break;\n                                case PKG: // no need to assign modifier\n                                        if (isInterface) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString().toLowerCase(), m.line_col());\n                                                return;\n                                        }\n                                        break;\n                                case VAL:\n                                        fieldDef.modifiers().add(SModifier.FINAL);\n                                        break;\n                                case VAR:\n                                        if (!isInterface) break;\n                                case NONNULL:\n                                        if (isParam) break;\n                                case NONEMPTY:\n                                        if (isParam) break;\n                                default:\n                                        err.UnexpectedTokenException(\"valid modifier for fields (class:(public|private|protected|internal|val)|interface:(pub|val))\", m.toString().toLowerCase(), m.line_col());\n                                        return;\n                        }\n                }\n                if (isInterface && !fieldDef.modifiers().contains(SModifier.FINAL)) {\n                        fieldDef.modifiers().add(SModifier.FINAL);\n                }\n                if (isStatic && !isInterface) {\n                        fieldDef.modifiers().add(SModifier.STATIC);\n                }\n        }\n\n        /**\n         * parse field<br>\n         * the field would be added into the type\n         *\n         * @param v        field (in the form of VariableDef)\n         * @param type     the field is defined in this type\n         * @param imports  imports\n         * @param mode     {@link #PARSING_CLASS} {@link #PARSING_INTERFACE}\n         * @param isStatic whether the field is static\n         * @param isParam  the field is parsed from param\n         * @throws SyntaxException exception\n         */\n        public void parseField(VariableDef v, STypeDef type, List<Import> imports, int mode, boolean isStatic, boolean isParam) throws SyntaxException {\n                // field, set its name|type|modifier|annos|declaringClass\n                SFieldDef fieldDef = new SFieldDef(v.line_col());\n                fieldDef.setName(v.getName()); // name\n\n                // type\n                fieldDef.setType(\n                        v.getType() == null\n                                ? getTypeWithName(\"java.lang.Object\", v.line_col())\n                                : getTypeWithAccess(v.getType(), getGenericMap(type), imports)\n                );\n                fieldDef.setDeclaringType(type); // declaringClass\n\n                // modifiers\n                parseFieldModifiers(fieldDef, v.getModifiers(), mode == PARSING_INTERFACE, isStatic, isParam);\n                // annos\n                parseAnnos(v.getAnnos(), fieldDef, imports, ElementType.FIELD, Collections.singletonList(ElementType.PARAMETER));\n\n                // check whether the field has already been defined\n                List<SFieldDef> fields;\n                if (mode == PARSING_CLASS) {\n                        fields = ((SClassDef) type).fields();\n                } else if (mode == PARSING_INTERFACE) {\n                        fields = ((SInterfaceDef) type).fields();\n                } else throw new LtBug(Integer.toString(mode)); // no else\n                for (SFieldDef f : fields) {\n                        if (fieldDef.name().equals(f.name())) {\n                                err.DuplicateVariableNameException(v.getName(), v.line_col());\n                                return;\n                        }\n                }\n\n                // add into class/interface\n                if (mode == PARSING_CLASS) {\n                        ((SClassDef) type).fields().add(fieldDef);\n                } else {\n                        // mode == PARSING_INTERFACE;\n                        ((SInterfaceDef) type).fields().add(fieldDef);\n                }\n        }\n\n        /**\n         * parse method<br>\n         * the method would be added into the type\n         *\n         * @param m          method (in the form of MethodDef)\n         * @param i          parameter length to parse\n         * @param type       the method is defined in this type\n         * @param lastMethod the last parsed method (with i+1 parameter length)\n         * @param imports    imports\n         * @param mode       {@link #PARSING_CLASS} {@link #PARSING_INTERFACE}\n         * @param isStatic   whether the method is static\n         * @throws SyntaxException exception\n         */\n        public void parseMethod(MethodDef m, int i, STypeDef type, SMethodDef lastMethod, List<Import> imports, int mode, boolean isStatic) throws SyntaxException {\n                // method name|declaringType|returnType|parameters|modifier|anno\n                SMethodDef methodDef = new SMethodDef(m.line_col());\n                methodDef.setName(m.name);\n                methodDef.setDeclaringType(type);\n                methodDef.setReturnType(\n                        m.returnType == null\n                                ? getTypeWithName(\"java.lang.Object\", m.line_col())\n                                : getRealReturnType(getTypeWithAccess(m.returnType, getGenericMap(type), imports), true)\n                );\n                parseParameters(m.params, i, methodDef, imports, false);\n\n                // modifier\n                // try to get access flags\n                boolean hasAccessModifier = false;\n                // implicit modifier\n                boolean isImplicit = false;\n                for (Modifier mod : m.modifiers) {\n                        if (mod.modifier.equals(Modifier.Available.PUBLIC)\n                                || mod.modifier.equals(Modifier.Available.PRIVATE)\n                                || mod.modifier.equals(Modifier.Available.PROTECTED)\n                                || mod.modifier.equals(Modifier.Available.PKG)) {\n                                hasAccessModifier = true;\n                        }\n                }\n                if (!hasAccessModifier) {\n                        methodDef.modifiers().add(SModifier.PUBLIC); // default modifier is public\n                }\n                for (Modifier mod : m.modifiers) {\n                        switch (mod.modifier) {\n                                case PUBLIC:\n                                        methodDef.modifiers().add(SModifier.PUBLIC);\n                                        break;\n                                case PRIVATE:\n                                        if (mode == PARSING_INTERFACE) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString(), m.line_col());\n                                                return;\n                                        }\n                                        methodDef.modifiers().add(SModifier.PRIVATE);\n                                        break;\n                                case PROTECTED:\n                                        if (mode == PARSING_INTERFACE) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString(), m.line_col());\n                                                return;\n                                        }\n                                        methodDef.modifiers().add(SModifier.PROTECTED);\n                                        break;\n                                case PKG: // no need to assign modifier\n                                        if (mode == PARSING_INTERFACE) {\n                                                err.UnexpectedTokenException(\"valid modifier for interface fields (public|val)\", m.toString(), m.line_col());\n                                                return;\n                                        }\n                                        break;\n                                case VAL:\n                                        methodDef.modifiers().add(SModifier.FINAL);\n                                        break;\n                                case ABSTRACT:\n                                        methodDef.modifiers().add(SModifier.ABSTRACT);\n                                        // check method body. it should no have body\n                                        if (!m.body.isEmpty()) {\n                                                err.SyntaxException(\"abstract methods cannot have body\", m.line_col());\n                                                return;\n                                        }\n                                        break;\n                                case SYNCHRONIZED:\n                                        methodDef.modifiers().add(SModifier.SYNCHRONIZED);\n                                        break;\n                                case DEF:\n                                        // a flag for defining a method\n                                        break;\n                                case IMPLICIT:\n                                        isImplicit = true;\n                                        break;\n                                default:\n                                        err.UnexpectedTokenException(\"valid modifier for methods (class:(public|private|protected|internal|val)|interface:(pub|val))\", m.toString(), m.line_col());\n                                        return;\n                        }\n                }\n                if (isStatic) {\n                        methodDef.modifiers().add(SModifier.STATIC);\n                }\n                if (mode == PARSING_INTERFACE && !methodDef.modifiers().contains(SModifier.ABSTRACT) && m.body.isEmpty()) {\n                        methodDef.modifiers().add(SModifier.ABSTRACT);\n                }\n\n                // annos\n                parseAnnos(m.annos, methodDef, imports, ElementType.METHOD, Collections.<ElementType>emptyList());\n\n                if (isImplicit) {\n                        checkAndAddImplicitAnno(methodDef);\n                }\n\n                // check can be added into class\n                List<SMethodDef> methods;\n                if (mode == PARSING_CLASS) {\n                        methods = ((SClassDef) type).methods();\n                } else if (mode == PARSING_INTERFACE) {\n                        methods = ((SInterfaceDef) type).methods();\n                } else throw new LtBug(\"invalid mode \" + mode);\n                for (SMethodDef builtMethod : methods) {\n                        if (builtMethod.name().equals(methodDef.name())) {\n                                // names are the same\n                                // check param length\n                                if (builtMethod.getParameters().size() == methodDef.getParameters().size()) {\n                                        // sizes are the same\n                                        // check types\n                                        int size = methodDef.getParameters().size();\n                                        List<SParameter> builtParam = builtMethod.getParameters();\n                                        List<SParameter> current = methodDef.getParameters();\n                                        boolean passCheck = false;\n                                        for (int in = 0; in < size; ++in) {\n                                                if (builtParam.get(in).type() != current.get(in).type()) {\n                                                        passCheck = true;\n                                                        break;\n                                                }\n                                        }\n                                        if (!passCheck) {\n                                                err.SyntaxException(\"method signature check failed on \" + methodDef, m.line_col());\n                                                return;\n                                        }\n                                }\n                        }\n                }\n\n                if (null != lastMethod) {\n                        Map<SInvokable, Expression> invoke = new HashMap<SInvokable, Expression>();\n                        invoke.put(lastMethod, m.params.get(i).getInit());\n                        defaultParamInvokable.put(methodDef, invoke);\n                }\n\n                // add into class/interface\n                if (mode == PARSING_CLASS) {\n                        ((SClassDef) type).methods().add(methodDef);\n                } else {\n                        // mode == PARSING_INTERFACE;\n                        ((SInterfaceDef) type).methods().add(methodDef);\n                }\n        }\n\n        /**\n         * get Import/ClassDef/InterfaceDef/FunDef from Statement object\n         *\n         * @param stmt           the statement\n         * @param imports        import list\n         * @param classDefs      classDef list\n         * @param interfaceDefs  interfaceDef list\n         * @param funDefs        functionDef list\n         * @param objectDefs     objectDef list\n         * @param annotationDefs annotationDef list\n         * @throws UnexpectedTokenException the statement is not import/class/interface\n         */\n        public void select_import_class_interface_fun_object(Statement stmt,\n                                                             List<Import> imports,\n                                                             List<ClassDef> classDefs,\n                                                             List<InterfaceDef> interfaceDefs,\n                                                             List<FunDef> funDefs,\n                                                             List<ObjectDef> objectDefs,\n                                                             List<AnnotationDef> annotationDefs) throws UnexpectedTokenException {\n                if (stmt instanceof Import) {\n                        imports.add((Import) stmt);\n                } else if (stmt instanceof ClassDef) {\n                        classDefs.add((ClassDef) stmt);\n                } else if (stmt instanceof InterfaceDef) {\n                        interfaceDefs.add((InterfaceDef) stmt);\n                } else if (stmt instanceof FunDef) {\n                        funDefs.add((FunDef) stmt);\n                } else if (stmt instanceof ObjectDef) {\n                        objectDefs.add((ObjectDef) stmt);\n                } else if (stmt instanceof AnnotationDef) {\n                        annotationDefs.add((AnnotationDef) stmt);\n                } else {\n                        err.UnexpectedTokenException(\"class/interface/object definition or import\", stmt.toString(), stmt.line_col());\n                        // code won't reach here\n                }\n        }\n\n        /**\n         * get type by class name\n         *\n         * @param clsName class name\n         * @param lineCol file_line_col\n         * @return STypeDef (not null)\n         * @throws SyntaxException exception\n         */\n        public STypeDef getTypeWithName(String clsName, LineCol lineCol) throws SyntaxException {\n                return getTypeWithName(clsName, Collections.<STypeDef>emptyList(), false, lineCol);\n        }\n\n        private String buildTemplateAppliedName(String clsName, List<? extends STypeDef> generics) {\n                if (generics.isEmpty()) {\n                        return clsName;\n                }\n                StringBuilder sb = new StringBuilder();\n                sb.append(clsName);\n                for (STypeDef t : generics) {\n                        sb.append(Consts.GENERIC_NAME_SPLIT).append(t.fullName().replaceAll(\"\\\\.\", \"_\"));\n                }\n                return sb.toString();\n        }\n\n        /**\n         * get type by class name\n         *\n         * @param clsName        class name\n         * @param generics       a list of generic types\n         * @param allowException if true, then no syntax exception would be thrown\n         * @param lineCol        file_line_col\n         * @return STypeDef (not null)\n         * @throws SyntaxException exception\n         */\n        public STypeDef getTypeWithName(String clsName, List<? extends STypeDef> generics, boolean allowException, LineCol lineCol) throws SyntaxException {\n                clsName = buildTemplateAppliedName(clsName, generics);\n                if (types.containsKey(clsName)) {\n                        return types.get(clsName);\n                } else {\n                        // check already compiled class\n                        try {\n                                Class<?> cls = loadClass(clsName);\n                                if (cls.isArray()) {\n                                        String name = cls.getName();\n                                        int dimension = 0;\n                                        while (cls.isArray()) {\n                                                ++dimension;\n                                                cls = cls.getComponentType();\n                                        }\n                                        SArrayTypeDef arrType = new SArrayTypeDef();\n                                        arrType.setFullName(name);\n                                        putNameAndTypeDef(arrType, lineCol);\n                                        arrType.setDimension(dimension);\n                                        arrType.setType(getTypeWithName(cls.getName(), lineCol));\n\n                                        return arrType;\n                                } else {\n                                        if (cls.isAnnotationPresent(GenericTemplate.class)) {\n                                                // it's a generic template\n                                                // retrieve and record the AST\n                                                Field astField;\n                                                try {\n                                                        astField = cls.getField(Consts.AST_FIELD);\n                                                } catch (NoSuchFieldException e) {\n                                                        throw new LtBug(\"the generic template doesn't have \" + Consts.AST_FIELD + \" field\");\n                                                }\n                                                if (astField.getType() != String.class) {\n                                                        throw new LtBug(\"the ast field is not of String type\");\n                                                }\n                                                String s;\n                                                try {\n                                                        s = (String) astField.get(null);\n                                                } catch (IllegalAccessException e) {\n                                                        throw new LtBug(\"the generic template field is not public\", e);\n                                                }\n                                                byte[] serializedBytes = hex2byte(s);\n                                                Definition defi;\n                                                ObjectInputStream ois = null;\n                                                try {\n                                                        ois = new ObjectInputStream(new ByteArrayInputStream(serializedBytes));\n                                                        defi = (Definition) ois.readObject();\n                                                } catch (ClassCastException e) {\n                                                        throw new LtBug(\"the generic template field is not a definition\", e);\n                                                } catch (IOException e) {\n                                                        throw new LtBug(e);\n                                                } finally {\n                                                        if (ois != null) {\n                                                                try {\n                                                                        ois.close();\n                                                                } catch (IOException e) {\n                                                                        //noinspection ThrowFromFinallyBlock\n                                                                        throw new LtBug(e);\n                                                                }\n                                                        }\n                                                }\n                                                if (!(defi instanceof ClassDef) && !(defi instanceof InterfaceDef) && !(defi instanceof ObjectDef)\n                                                        && !(defi instanceof FunDef) && !(defi instanceof AnnotationDef)) {\n                                                        throw new LtBug(\"invalid definition for generic template type: \" + defi);\n                                                }\n                                                String pkg;\n                                                if (cls.getPackage() != null) {\n                                                        pkg = cls.getPackage().getName();\n                                                } else if (cls.getName().contains(\".\")) {\n                                                        pkg = cls.getName();\n                                                        pkg = pkg.substring(pkg.lastIndexOf('.'));\n                                                } else {\n                                                        pkg = \"\";\n                                                }\n                                                if (defi instanceof ClassDef) {\n                                                        recordClass((ClassDef) defi, pkg, Collections.<STypeDef>emptyList(), true);\n                                                } else if (defi instanceof InterfaceDef) {\n                                                        recordInterface((InterfaceDef) defi, pkg, Collections.<STypeDef>emptyList(), true);\n                                                } else if (defi instanceof ObjectDef) {\n                                                        recordObject((ObjectDef) defi, pkg, Collections.<STypeDef>emptyList(), true);\n                                                } else if (defi instanceof FunDef) {\n                                                        recordFun((FunDef) defi, pkg, Collections.<STypeDef>emptyList(), true);\n                                                } else /*if (defi instanceof AnnotationDef)*/ {\n                                                        recordAnnotation((AnnotationDef) defi, pkg, Collections.<STypeDef>emptyList(), true);\n                                                }\n                                        }\n\n                                        List<SModifier> modifiers; // modifiers\n                                        STypeDef typeDef;\n                                        if (cls.isAnnotation()) {\n                                                SAnnoDef a = new SAnnoDef(LineCol.SYNTHETIC);\n                                                a.setFullName(clsName);\n\n                                                typeDef = a;\n                                                modifiers = a.modifiers();\n                                        } else if (cls.isInterface()) {\n                                                SInterfaceDef i = new SInterfaceDef(LineCol.SYNTHETIC);\n                                                i.setFullName(clsName);\n\n                                                typeDef = i;\n                                                modifiers = i.modifiers();\n                                        } else { // class\n                                                // check class type (normal/fun/object)\n                                                int classType;\n                                                if (cls.isAnnotationPresent(LatteFun.class)) classType = SClassDef.FUN;\n                                                else if (cls.isAnnotationPresent(LatteObject.class))\n                                                        classType = SClassDef.OBJECT;\n                                                else classType = SClassDef.NORMAL;\n                                                SClassDef c = new SClassDef(classType, LineCol.SYNTHETIC);\n                                                c.setFullName(clsName);\n\n                                                typeDef = c;\n                                                modifiers = c.modifiers();\n                                        }\n                                        if (cls.getPackage() != null) {\n                                                typeDef.setPkg(cls.getPackage().getName());\n                                        }\n                                        // put into map\n                                        putNameAndTypeDef(typeDef, lineCol);\n                                        // annos\n                                        getAnnotationFromAnnotatedElement(cls, typeDef);\n                                        // modifiers\n                                        getModifierFromClass(cls, modifiers);\n\n                                        if (typeDef instanceof SInterfaceDef) {\n                                                SInterfaceDef i = (SInterfaceDef) typeDef;\n                                                // super interfaces\n                                                getSuperInterfaceFromClass(cls, i.superInterfaces());\n                                                // fields methods\n                                                getFieldsAndMethodsFromClass(cls, i, i.fields(), i.methods());\n                                        } else if (typeDef instanceof SClassDef) {\n                                                SClassDef c = (SClassDef) typeDef;\n                                                // super interfaces\n                                                getSuperInterfaceFromClass(cls, ((SClassDef) typeDef).superInterfaces());\n                                                if (cls != Object.class) {\n                                                        // super class\n                                                        ((SClassDef) typeDef).setParent((SClassDef) getTypeWithName(cls.getSuperclass().getName(), lineCol));\n                                                }\n                                                // fields methods\n                                                getFieldsAndMethodsFromClass(cls, c, c.fields(), c.methods());\n                                                // constructors\n                                                for (Constructor<?> con : cls.getDeclaredConstructors()) {\n                                                        SConstructorDef constructorDef = new SConstructorDef(LineCol.SYNTHETIC);\n                                                        constructorDef.setDeclaringType(c);\n\n                                                        getAnnotationFromAnnotatedElement(con, constructorDef);\n                                                        getParameterFromClassArray(con.getParameterTypes(), constructorDef);\n                                                        getModifierFromMember(con, constructorDef);\n\n                                                        c.constructors().add(constructorDef);\n                                                }\n                                        } else {\n                                                // typeDef instanceof SAnnoDef;\n\n                                                SAnnoDef annoDef = (SAnnoDef) typeDef;\n                                                // parse anno fields\n                                                for (Method annoM : cls.getDeclaredMethods()) {\n                                                        assert annoM.getParameterTypes().length == 0;\n                                                        SAnnoField annoField = new SAnnoField();\n                                                        annoField.setName(annoM.getName());\n                                                        annoField.setType(getTypeWithName(annoM.getReturnType().getName(), lineCol));\n\n                                                        annoDef.annoFields().add(annoField);\n                                                }\n                                        }\n                                        return typeDef;\n                                }\n                        } catch (ClassNotFoundException e) {\n                                if (!allowException) {\n                                        err.SyntaxException(\"undefined class \" + clsName, lineCol);\n                                }\n                                return null;\n                        }\n                }\n        }\n\n        /**\n         * parse the annotations\n         *\n         * @param elem        java AnnotatedElement\n         * @param presentable compiler presentable object\n         * @throws SyntaxException exception\n         */\n        public void getAnnotationFromAnnotatedElement(AnnotatedElement elem, SAnnotationPresentable presentable) throws SyntaxException {\n                for (Annotation a : elem.getAnnotations()) {\n                        Class<?> aClass = a.getClass();\n                        while (aClass != null && !aClass.isAnnotation() && aClass.getInterfaces().length != 0) {\n                                aClass = aClass.getInterfaces()[0];\n                        }\n                        if (aClass != null && aClass.isAnnotation()) {\n                                SAnno sAnno = new SAnno();\n                                sAnno.setPresent(presentable);\n                                sAnno.setAnnoDef((SAnnoDef) getTypeWithName(aClass.getName(), LineCol.SYNTHETIC));\n\n                                presentable.annos().add(sAnno);\n\n                                // retrieve annotation keys and values\n                                for (Method m : aClass.getDeclaredMethods()) {\n                                        assert m.getParameterTypes().length == 0;\n                                        try {\n                                                sAnno.alreadyCompiledAnnotationValueMap().put(m.getName(), invokeAnnotationMethod(a, m));\n                                        } catch (Throwable e) {\n                                                // the exception should never occur\n                                                throw new LtBug(e);\n                                        }\n                                }\n                        }\n                }\n        }\n\n        private Object invokeAnnotationMethod(Annotation a, Method m) throws InvocationTargetException, SyntaxException {\n                try {\n                        return m.invoke(a);\n                } catch (IllegalAccessException e) {\n                        // annotation methods are public\n                        // the exception won't occur only when java 9 module did not export the type\n                        // simply ignore the exception and replace the result with a dummy value\n                        return new DummyValue(\n                                getTypeWithName(m.getReturnType().getName(), LineCol.SYNTHETIC)\n                        );\n                }\n        }\n\n        /**\n         * get modifier from class object<br>\n         * and add them into the list\n         *\n         * @param cls       class object\n         * @param modifiers modifiers\n         */\n        public void getModifierFromClass(Class<?> cls, List<SModifier> modifiers) {\n                int ms = cls.getModifiers();\n                if (java.lang.reflect.Modifier.isAbstract(ms)) {\n                        modifiers.add(SModifier.ABSTRACT);\n                }\n                if (java.lang.reflect.Modifier.isFinal(ms)) {\n                        modifiers.add(SModifier.FINAL);\n                }\n                if (java.lang.reflect.Modifier.isNative(ms)) {\n                        modifiers.add(SModifier.NATIVE);\n                }\n                if (java.lang.reflect.Modifier.isPrivate(ms)) {\n                        modifiers.add(SModifier.PRIVATE);\n                }\n                if (java.lang.reflect.Modifier.isProtected(ms)) {\n                        modifiers.add(SModifier.PROTECTED);\n                }\n                if (java.lang.reflect.Modifier.isPublic(ms)) {\n                        modifiers.add(SModifier.PUBLIC);\n                }\n                if (java.lang.reflect.Modifier.isStatic(ms)) {\n                        modifiers.add(SModifier.STATIC);\n                }\n                if (java.lang.reflect.Modifier.isStrict(ms)) {\n                        modifiers.add(SModifier.STRICT);\n                }\n                if (java.lang.reflect.Modifier.isSynchronized(ms)) {\n                        modifiers.add(SModifier.SYNCHRONIZED);\n                }\n                if (java.lang.reflect.Modifier.isTransient(ms)) {\n                        modifiers.add(SModifier.TRANSIENT);\n                }\n                if (java.lang.reflect.Modifier.isVolatile(ms)) {\n                        modifiers.add(SModifier.VOLATILE);\n                }\n        }\n\n        /**\n         * get modifiers from Member<br>\n         * and append them to the SMember object\n         *\n         * @param member  member\n         * @param sMember sMember\n         */\n        public void getModifierFromMember(Member member, SMember sMember) {\n                int ms = member.getModifiers();\n                List<SModifier> modifiers = sMember.modifiers();\n                if (java.lang.reflect.Modifier.isAbstract(ms)) {\n                        modifiers.add(SModifier.ABSTRACT);\n                }\n                if (java.lang.reflect.Modifier.isFinal(ms)) {\n                        modifiers.add(SModifier.FINAL);\n                }\n                if (java.lang.reflect.Modifier.isNative(ms)) {\n                        modifiers.add(SModifier.NATIVE);\n                }\n                if (java.lang.reflect.Modifier.isPrivate(ms)) {\n                        modifiers.add(SModifier.PRIVATE);\n                }\n                if (java.lang.reflect.Modifier.isProtected(ms)) {\n                        modifiers.add(SModifier.PROTECTED);\n                }\n                if (java.lang.reflect.Modifier.isPublic(ms)) {\n                        modifiers.add(SModifier.PUBLIC);\n                }\n                if (java.lang.reflect.Modifier.isStatic(ms)) {\n                        modifiers.add(SModifier.STATIC);\n                }\n                if (java.lang.reflect.Modifier.isStrict(ms)) {\n                        modifiers.add(SModifier.STRICT);\n                }\n                if (java.lang.reflect.Modifier.isSynchronized(ms)) {\n                        modifiers.add(SModifier.SYNCHRONIZED);\n                }\n                if (java.lang.reflect.Modifier.isTransient(ms)) {\n                        modifiers.add(SModifier.TRANSIENT);\n                }\n                if (java.lang.reflect.Modifier.isVolatile(ms)) {\n                        modifiers.add(SModifier.VOLATILE);\n                }\n        }\n\n        /**\n         * get suepr interface from class\n         *\n         * @param cls        class\n         * @param interfaces interfaces\n         * @throws SyntaxException exception\n         */\n        public void getSuperInterfaceFromClass(Class<?> cls, List<SInterfaceDef> interfaces) throws SyntaxException {\n                for (Class<?> i : cls.getInterfaces()) {\n                        if (!i.isAnnotation()) {\n                                interfaces.add((SInterfaceDef) getTypeWithName(i.getName(), LineCol.SYNTHETIC));\n                        }\n                }\n        }\n\n        /**\n         * get field and methods from class object\n         *\n         * @param cls           class object\n         * @param declaringType field/method is defined in this type\n         * @param fields        field list\n         * @param methods       method list\n         * @throws SyntaxException exceptions\n         */\n        public void getFieldsAndMethodsFromClass(Class<?> cls, STypeDef declaringType, List<SFieldDef> fields, List<SMethodDef> methods) throws SyntaxException {\n                for (Field f : cls.getDeclaredFields()) {\n                        SFieldDef fieldDef = new SFieldDef(LineCol.SYNTHETIC);\n                        fieldDef.setName(f.getName());\n                        fieldDef.setType(getTypeWithName(f.getType().getName(), LineCol.SYNTHETIC));\n                        getModifierFromMember(f, fieldDef);\n\n                        getAnnotationFromAnnotatedElement(f, fieldDef);\n\n                        fieldDef.setDeclaringType(declaringType);\n                        fields.add(fieldDef);\n                }\n\n                for (Method m : cls.getDeclaredMethods()) {\n                        SMethodDef methodDef = new SMethodDef(LineCol.SYNTHETIC);\n                        methodDef.setName(m.getName());\n                        methodDef.setDeclaringType(declaringType);\n                        if (m.getReturnType().equals(Void.TYPE)) {\n                                methodDef.setReturnType(VoidType.get());\n                        } else {\n                                methodDef.setReturnType(\n                                        getRealReturnType(getTypeWithName(m.getReturnType().getName(), LineCol.SYNTHETIC), true));\n                        }\n\n                        getAnnotationFromAnnotatedElement(m, methodDef);\n\n                        getModifierFromMember(m, methodDef);\n\n                        // parameters\n                        getParameterFromClassArray(m.getParameterTypes(), methodDef);\n\n                        methods.add(methodDef);\n                }\n        }\n\n        /**\n         * get parameter from class array<br>\n         * the array is from getParameterTypes();\n         *\n         * @param paramTypes parameter types\n         * @param invokable  the parameters belong to this invokable\n         * @throws SyntaxException exception\n         */\n        public void getParameterFromClassArray(Class<?>[] paramTypes, SInvokable invokable) throws SyntaxException {\n                for (Class<?> paramType : paramTypes) {\n                        SParameter param = new SParameter();\n                        param.setName(\"?\");\n                        param.setTarget(invokable);\n                        param.setType(getTypeWithName(paramType.getName(), LineCol.SYNTHETIC));\n\n                        getAnnotationFromAnnotatedElement(paramType, param);\n\n                        invokable.getParameters().add(param);\n                }\n        }\n\n        /**\n         * check whether the type exists<br>\n         * first check types to compile, then check existing types\n         *\n         * @param type class name\n         * @return true/false\n         */\n        public boolean typeExists(String type) {\n                if (!types.containsKey(type)) {\n                        try {\n                                loadClass(type);\n                        } catch (ClassNotFoundException e) {\n                                return false;\n                        } catch (NoClassDefFoundError e) {\n                                return false;\n                        }\n                }\n                return true;\n        }\n\n        /**\n         * get class name from Access object.<br>\n         * the access object may contain package or class only\n         *\n         * @param access access\n         * @return retrieved class name\n         * @throws SyntaxException compile error\n         */\n        public String getClassNameFromAccess(AST.Access access) throws SyntaxException {\n                access = transformAccess(access);\n                String pre;\n                if (access.exp instanceof AST.Access) {\n                        pre = getClassNameFromAccess((AST.Access) access.exp) + \"$\";\n                } else if (access.exp instanceof AST.PackageRef) {\n                        pre = ((AST.PackageRef) access.exp).pkg.replace(\"::\", \".\") + \".\";\n                } else {\n                        pre = \"\";\n                }\n                return pre + access.name;\n        }\n\n        /**\n         * find class name with import statements\n         *\n         * @param name    the simple name or full name to be found\n         * @param imports import statements\n         * @return found class name or <tt>null</tt> if not found\n         * @throws SyntaxException compile error\n         */\n        public String findClassNameWithImport(String name, List<Import> imports) throws SyntaxException {\n                if (typeExists(name)) return name;\n                // first try to find those classes with the same simple name\n                // e.g. import java.util.List\n                for (Import i : imports) {\n                        if (!i.importAll) {\n                                if (i.access.name.equals(name)) {\n                                        // use this name\n                                        return getClassNameFromAccess(i.access);\n                                }\n                        }\n                }\n                // try to find `import all`\n                for (Import i : imports) {\n                        if (i.importAll && i.pkg != null) {\n                                String possibleClassName = i.pkg.pkg.replace(\"::\", \".\") + \".\" + name;\n                                if (typeExists(possibleClassName)) return possibleClassName;\n                        }\n                }\n\n                return null;\n        }\n\n        /**\n         * get type with access\n         *\n         * @param access     access object\n         * @param genericMap generic types stored in a map of name to type\n         * @param imports    import list\n         * @return retrieved STypeDef (not null)\n         * @throws SyntaxException exception\n         */\n        public STypeDef getTypeWithAccess(AST.Access access, Map<String, STypeDef> genericMap, List<Import> imports) throws SyntaxException {\n                return getTypeWithAccess(access, genericMap, imports, false);\n        }\n\n        /**\n         * get type with access\n         *\n         * @param access         access object\n         * @param genericMap     generic info\n         * @param imports        import list\n         * @param allowException if true, then syntax exception would be ignored\n         * @return retrieved STypeDef (not null)\n         * @throws SyntaxException exception\n         */\n        public STypeDef getTypeWithAccess(AST.Access access, Map<String, STypeDef> genericMap, List<Import> imports, boolean allowException) throws SyntaxException {\n                assert access.exp == null || access.exp instanceof AST.Access\n                        || access.exp instanceof AST.PackageRef || \"[]\".equals(access.name) || \"*\".equals(access.name);\n\n                access = transformAccess(access);\n                boolean isPointer = false;\n                if (\"*\".equals(access.name)) {\n                        if (access.exp == null) {\n                                return new PointerType(getTypeWithName(\"java.lang.Object\", LineCol.SYNTHETIC));\n                        }\n\n                        isPointer = true;\n                        assert access.exp instanceof AST.Access;\n                        access = (AST.Access) access.exp;\n                }\n\n                STypeDef resultType;\n                if (\"[]\".equals(access.name)) {\n                        assert access.exp instanceof AST.Access;\n                        STypeDef type = getTypeWithAccess((AST.Access) access.exp, genericMap, imports);\n                        int dimension;\n                        if (type instanceof SArrayTypeDef) {\n                                SArrayTypeDef a = (SArrayTypeDef) type;\n                                type = a.type();\n                                dimension = a.dimension() + 1;\n                        } else {\n                                dimension = 1;\n                        }\n                        SArrayTypeDef a = new SArrayTypeDef();\n                        a.setType(type);\n                        a.setDimension(dimension);\n                        if (types.containsKey(a.fullName())) {\n                                resultType = types.get(a.fullName());\n                        } else {\n                                putNameAndTypeDef(a, access.line_col());\n                                resultType = a;\n                        }\n                } else {\n                        String className = accessToClassName(access, genericMap, imports, allowException);\n                        if (className == null) {\n                                // if the classname not found\n                                if (!allowException) {\n                                        err.SyntaxException(\"Type not found: \" + access, access.line_col());\n                                }\n                                return null;\n                        }\n                        resultType = getTypeWithName(className, Collections.<STypeDef>emptyList(), allowException, access.line_col());\n                }\n\n                if (isPointer) {\n                        resultType = new PointerType(resultType);\n                }\n                return resultType;\n        }\n\n        /**\n         * put {fileName:TypeDef} into the map\n         *\n         * @param type    STypeDef object\n         * @param lineCol file_line_col\n         * @throws SyntaxException exception\n         */\n        public void putNameAndTypeDef(STypeDef type, LineCol lineCol) throws SyntaxException {\n                if (types.containsKey(type.fullName())) {\n                        err.SyntaxException(\"duplicate type names \" + type.fullName(), lineCol);\n                        // code won't reach here\n                } else {\n                        types.put(type.fullName(), type);\n                }\n        }\n\n        /**\n         * load a class\n         *\n         * @param name class name\n         * @return load a class\n         * @throws ClassNotFoundException exception\n         */\n        public Class<?> loadClass(String name) throws ClassNotFoundException {\n                int dimensions = 0; // 0 means not an array\n                if (name.startsWith(\"[\") && name.endsWith(\";\")) {\n                        int i = 0;\n                        char[] chars = name.toCharArray();\n                        for (; i < chars.length; ++i) {\n                                if (chars[i] == '[') {\n                                        ++dimensions;\n                                } else {\n                                        break;\n                                }\n                        }\n                        name = name.substring(i + 1); // chars[i] should be `L`\n                        name = name.substring(0, name.length() - 1); // remove `;`\n                }\n\n                Class<?> cls;\n                try {\n                        cls = Class.forName(name);\n                } catch (ClassNotFoundException e) {\n                        cls = classLoader.loadClass(name);\n                }\n\n                if (dimensions == 0) {\n                        return cls;\n                } else {\n                        int[] d = new int[dimensions];\n                        return Array.newInstance(cls, d).getClass();\n                }\n        }\n\n        /**\n         * the given type is a pointer type (SClassDef lt.lang.Pointer) or (PointerType)\n         *\n         * @param type type\n         * @return true/false\n         */\n        public boolean isPointerType(STypeDef type) {\n                return type instanceof PointerType || \"lt.lang.Pointer\".equals(type.fullName());\n        }\n\n        /**\n         * cast the `return` type to \"void\" if type is Unit and doCast is true\n         *\n         * @param type   type\n         * @param doCast do cast if type is Unit\n         * @return the final result\n         */\n        public STypeDef getRealReturnType(STypeDef type, boolean doCast) {\n                if (doCast && type.fullName().equals(\"lt.lang.Unit\")) {\n                        return VoidType.get();\n                }\n                return type;\n        }\n\n        /**\n         * transform the AST.Access object<br>\n         * the part that may represent a `type` will be converted into package ref and typeSimpleName<br>\n         * e.g. java.lang.Object => (((null, java), lang), Object) => ((java::lang), Object)<br>\n         * <br>\n         * this method doesn't care about whether it's a generic type.\n         *\n         * @param access access object\n         * @return original access object or a new one depending on the input\n         */\n        private AST.Access transformAccess(AST.Access access) throws SyntaxException {\n                if (null == access) return null;\n                if (null == access.exp) return access;\n                if (!(access.exp instanceof AST.Access)) return access;\n                // use ArrayList for that it requires random access\n                ArrayList<String> maybePackages = new ArrayList<String>();\n                ArrayList<LineCol> lineColInfo = new ArrayList<LineCol>();\n                maybePackages.add(access.name);\n                lineColInfo.add(access.line_col());\n                AST.Access tmp = (AST.Access) access.exp;\n                while (true) {\n                        maybePackages.add(tmp.name);\n                        lineColInfo.add(tmp.line_col());\n                        Expression exp = tmp.exp;\n                        if (null == exp) break;\n                        if (!(exp instanceof AST.Access)) return access;\n                        tmp = (AST.Access) exp;\n                }\n                Collections.reverse(maybePackages);\n                Collections.reverse(lineColInfo);\n                for (int i = 1; i < maybePackages.size(); ++i) {\n                        StringBuilder clsNameBuilder = new StringBuilder();\n                        for (int j = 0; j <= i; ++j) {\n                                if (j != 0) {\n                                        clsNameBuilder.append(\".\");\n                                }\n                                clsNameBuilder.append(maybePackages.get(j));\n                        }\n                        String clsName = clsNameBuilder.toString();\n                        STypeDef type = getTypeWithName(clsName, Collections.<STypeDef>emptyList(), true, access.line_col());\n                        if (null == type) {\n                                continue;\n                        }\n                        // type found, build a new access object\n                        String fullName = type.fullName();\n                        String packageName;\n                        if (fullName.contains(\".\")) {\n                                packageName = fullName.substring(0, fullName.lastIndexOf(\".\")).replace(\".\", \"::\");\n                        } else {\n                                packageName = fullName;\n                        }\n                        AST.Access result = new AST.Access(new AST.PackageRef(\n                                packageName, lineColInfo.get(i - 1)\n                        ), maybePackages.get(i), lineColInfo.get(i));\n                        for (int j = i + 1; j < maybePackages.size(); ++j) {\n                                result = new AST.Access(result, maybePackages.get(j), lineColInfo.get(j));\n                        }\n                        return result;\n                }\n\n                // cannot be a package.type.*\n                return access;\n        }\n\n        private String accessToClassName(AST.Access access, Map<String, STypeDef> genericMap, List<Import> imports, boolean allowException) throws SyntaxException {\n                String className;\n                if (access.exp instanceof AST.Access) {\n                        boolean withPackage = false;\n                        AST.Access tmp = access;\n                        StringBuilder innerClassName = new StringBuilder(); // only used if it's inner class ref\n                        while (tmp.exp != null) {\n                                assert tmp.exp instanceof AST.Access || tmp.exp instanceof AST.PackageRef;\n                                if (tmp.exp instanceof AST.PackageRef) {\n                                        withPackage = true;\n                                        break;\n                                }\n                                innerClassName.insert(0, \"$\" + tmp.name);\n                                tmp = (AST.Access) tmp.exp;\n                        }\n\n                        if (withPackage) {\n                                className = getClassNameFromAccess(access);\n                                if (null == className || !typeExists(className)) {\n                                        if (!allowException) {\n                                                err.SyntaxException(\"type \" + className + \" not defined\", access.line_col());\n                                        }\n                                        return null;\n                                }\n                        } else {\n                                className = findClassNameWithImport(tmp.name, imports) + innerClassName;\n                                if (!typeExists(className)) {\n                                        if (!allowException) {\n                                                err.SyntaxException(\"type \" + innerClassName + \" not defined\", access.line_col());\n                                        }\n                                        return null;\n                                }\n                        }\n                } else {\n                        assert access.exp == null || access.exp instanceof AST.PackageRef;\n\n                        AST.PackageRef pkg = (AST.PackageRef) access.exp;\n                        String name = access.name;\n\n                        if (pkg == null) {\n                                if (genericMap.containsKey(name)) {\n                                        className = genericMap.get(name).fullName();\n                                } else {\n                                        className = findClassNameWithImport(name, imports);\n                                }\n                        } else {\n                                className = pkg.pkg.replace(\"::\", \".\") + \".\" + name;\n                        }\n\n                        if (null == className || !typeExists(className)) {\n                                if (!allowException) {\n                                        err.SyntaxException(\"type \" + name + \" not defined\", access.line_col());\n                                }\n                                return null;\n                        }\n                }\n                // check the access.generics\n                if (access.generics.isEmpty()) {\n                        return className;\n                } else {\n                        List<AST.Access> genericASTList = access.generics;\n                        List<STypeDef> genericTypeList = new ArrayList<STypeDef>();\n                        for (AST.Access e : genericASTList) {\n                                STypeDef t = getTypeWithAccess(e, genericMap, imports, allowException);\n                                if (t == null) {\n                                        return null; // the type not found, and allowException is true\n                                }\n                                genericTypeList.add(t);\n                        }\n                        return buildTemplateAppliedName(className, genericTypeList);\n                }\n        }\n\n        private Map<String, STypeDef> getGenericMap(STypeDef t) throws SyntaxException {\n                if (t instanceof SClassDef) {\n                        return getGenericMap((SClassDef) t);\n                } else if (t instanceof SInterfaceDef) {\n                        return getGenericMap((SInterfaceDef) t);\n                } else if (t instanceof SAnnoDef) {\n                        return Collections.emptyMap();\n                } else {\n                        throw new LtBug(\"unknown STypeDef \" + t);\n                }\n        }\n\n        private Map<String, STypeDef> getGenericMap(SClassDef c) {\n                List<STypeDef> genericArgs;\n                List<AST.Access> genericParams;\n                if (c.classType() == SClassDef.NORMAL) {\n                        ASTGHolder<ClassDef> holder = originalClasses.get(c.fullName());\n                        ClassDef classDef = holder.s;\n                        genericArgs = holder.generics;\n                        genericParams = classDef.generics;\n                } else if (c.classType() == SClassDef.OBJECT) {\n                        ASTGHolder<ObjectDef> holder = originalObjects.get(c.fullName());\n                        ObjectDef objectDef = holder.s;\n                        genericArgs = holder.generics;\n                        genericParams = objectDef.generics;\n                } else if (c.classType() == SClassDef.FUN) {\n                        return Collections.emptyMap();\n                } else {\n                        throw new LtBug(\"unknown classType \" + c.classType());\n                }\n                LinkedHashMap<String, STypeDef> ret = new LinkedHashMap<String, STypeDef>();\n                for (int i = 0; i < genericParams.size(); ++i) {\n                        ret.put(genericParams.get(i).name, genericArgs.get(i));\n                }\n                return ret;\n        }\n\n        private Map<String, STypeDef> getGenericMap(SInterfaceDef interf) {\n                ASTGHolder<InterfaceDef> holder = originalInterfaces.get(interf.fullName());\n                InterfaceDef interfaceDef = holder.s;\n                List<STypeDef> genericArgs = holder.generics;\n                List<AST.Access> genericParams = interfaceDef.generics;\n                LinkedHashMap<String, STypeDef> ret = new LinkedHashMap<String, STypeDef>();\n                for (int i = 0; i < genericParams.size(); ++i) {\n                        ret.put(genericParams.get(i).name, genericArgs.get(i));\n                }\n                return ret;\n        }\n\n        private boolean isGenericTemplateType(STypeDef t) {\n                if (t instanceof SClassDef) {\n                        SClassDef c = (SClassDef) t;\n                        if (c.classType() == SClassDef.NORMAL) {\n                                ASTGHolder<ClassDef> holder = originalClasses.get(t.fullName());\n                                return holder.generics.isEmpty() && !holder.s.generics.isEmpty();\n                        } else if (c.classType() == SClassDef.OBJECT) {\n                                ASTGHolder<ObjectDef> holder = originalObjects.get(t.fullName());\n                                return holder.generics.isEmpty() && !holder.s.generics.isEmpty();\n                        } else if (c.classType() == SClassDef.FUN) {\n                                // functions are never generic template types\n                                return false;\n                        } else {\n                                throw new LtBug(\"unknown classType \" + c.classType());\n                        }\n                } else if (t instanceof SInterfaceDef) {\n                        ASTGHolder<InterfaceDef> holder = originalInterfaces.get(t.fullName());\n                        return holder.generics.isEmpty() && !holder.s.generics.isEmpty();\n                } else if (t instanceof SAnnoDef) {\n                        // annotations are never generic template types\n                        return false;\n                } else {\n                        throw new LtBug(\"unknown STypeDef \" + t);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/SemanticScope.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.*;\nimport lt.compiler.semantic.builtin.DoubleTypeDef;\nimport lt.compiler.semantic.builtin.LongTypeDef;\n\nimport java.util.*;\n\n/**\n * semantic scope\n */\npublic class SemanticScope {\n        public static class MethodRecorder {\n                public final SMethodDef method;\n                public final int paramCount;\n\n                public MethodRecorder(SMethodDef method, int paramCount) {\n                        this.method = method;\n                        this.paramCount = paramCount;\n                }\n        }\n\n        public final SemanticScope parent;\n\n        private final InvokableMeta meta;\n\n        private final Map<String, LeftValue> leftValueMap = new LinkedHashMap<String, LeftValue>();\n        private final Map<String, MethodRecorder> innerMethodMap = new HashMap<String, MethodRecorder>();\n\n        private final STypeDef sTypeDef;\n\n        private Ins.This aThis;\n\n        public SemanticScope(SemanticScope parent, InvokableMeta meta) {\n                this.parent = parent;\n                sTypeDef = null;\n                this.meta = meta;\n        }\n\n        public SemanticScope(STypeDef sTypeDef, InvokableMeta meta) {\n                this.sTypeDef = sTypeDef;\n                parent = null;\n                this.meta = meta;\n        }\n\n        public InvokableMeta getMeta() {\n                return meta;\n        }\n\n        public LeftValue getLeftValue(String name) {\n                if (leftValueMap.containsKey(name)) {\n                        return leftValueMap.get(name);\n                } else if (parent != null) {\n                        return parent.getLeftValue(name);\n                } else {\n                        return null;\n                }\n        }\n\n        public LinkedHashMap<String, STypeDef> getLocalVariables() {\n                LinkedHashMap<String, STypeDef> map;\n                if (parent != null) {\n                        map = parent.getLocalVariables();\n                } else {\n                        map = new LinkedHashMap<String, STypeDef>();\n                }\n                for (Map.Entry<String, LeftValue> entry : leftValueMap.entrySet()) {\n                        String k = entry.getKey();\n                        LeftValue v = entry.getValue();\n                        map.put(k, v.type());\n                }\n                return map;\n        }\n\n        public LinkedHashMap<String, LeftValue> getRawLocalVariables() {\n                LinkedHashMap<String, LeftValue> map;\n                if (parent != null) {\n                        map = parent.getRawLocalVariables();\n                } else {\n                        map = new LinkedHashMap<String, LeftValue>();\n                }\n                for (Map.Entry<String, LeftValue> entry : leftValueMap.entrySet()) {\n                        String k = entry.getKey();\n                        LeftValue v = entry.getValue();\n                        map.put(k, v);\n                }\n                return map;\n        }\n\n        public void putLeftValue(String name, LeftValue v) {\n                leftValueMap.put(name, v);\n        }\n\n        public void addMethodDef(String name, MethodRecorder innerMethod) {\n                innerMethodMap.put(name, innerMethod);\n        }\n\n        /**\n         * get a list of leftValue\n         *\n         * @param count       size of the required list (may be less, but won't be more)\n         * @param lambdaParam lambda param\n         * @return a list of LeftValue(s)\n         */\n        public List<LeftValue> getLeftValues(int count, boolean lambdaParam) {\n                List<LeftValue> list;\n                if (parent != null) list = parent.getLeftValues(count, lambdaParam);\n                else list = new ArrayList<LeftValue>();\n                Iterator<Map.Entry<String, LeftValue>> it = leftValueMap.entrySet().iterator();\n                while (list.size() != count && it.hasNext()) {\n                        Map.Entry<String, LeftValue> entry = it.next();\n                        if ((!lambdaParam || !entry.getKey().equals(\"$\"))\n                                && CompileUtil.isValidName(entry.getKey())) {\n                                list.add(entry.getValue());\n                        }\n                }\n                return list;\n        }\n\n        public MethodRecorder getInnerMethod(String name) {\n                if (innerMethodMap.containsKey(name)) {\n                        return innerMethodMap.get(name);\n                } else if (parent == null) {\n                        return null;\n                } else return parent.getInnerMethod(name);\n        }\n\n        public Map<String, MethodRecorder> getInnerMethods() {\n                Map<String, MethodRecorder> recorders = new HashMap<String, MethodRecorder>();\n                SemanticScope scope = this;\n                while (scope != null) {\n                        recorders.putAll(scope.innerMethodMap);\n                        scope = scope.parent;\n                }\n                return recorders;\n        }\n\n        public boolean containsInnerMethod(String name) {\n                return innerMethodMap.containsKey(name);\n        }\n\n        public STypeDef type() {\n                if (sTypeDef != null)\n                        return sTypeDef;\n                if (parent != null) return parent.type();\n                return null;\n        }\n\n        public void setThis(Ins.This aThis) {\n                this.aThis = aThis;\n        }\n\n        public Ins.This getThis() {\n                if (aThis != null)\n                        return aThis;\n                if (parent != null) return parent.getThis();\n                return null;\n        }\n\n        public String generateTempName() {\n                int i = 0;\n                while (getLeftValue(\"*\" + i) != null) ++i;\n                return \"*\" + i;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/SyntaxException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * wrong syntax\n */\npublic class SyntaxException extends CompileException {\n        public final LineCol lineCol;\n        public final String msg;\n        public final String lineMsg;\n\n        public SyntaxException(String lineMsg, String msg, LineCol lineCol) {\n                super(lineMsg + msg +\n                        (lineCol == LineCol.SYNTHETIC\n                                ? \"\"\n                                : (\" at \" + lineCol.fileName + \"(\" + lineCol.line + \",\" + lineCol.column + \")\")) +\n                        (lineCol.useDefine.isEmpty()\n                                ? \"\"\n                                : \"\\nThis line uses defined replacement (\" + lineCol.useDefine + \"), the column might not be precise\"));\n                this.lineMsg = lineMsg;\n                this.msg = msg;\n                this.lineCol = lineCol;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/UnexpectedEndException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * unexpected end\n */\npublic class UnexpectedEndException extends SyntaxException {\n        public UnexpectedEndException(String lineMsg, LineCol lineCol) {\n                super(lineMsg, \"unexpected end\", lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/UnexpectedTokenException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * unexpected token\n */\npublic class UnexpectedTokenException extends SyntaxException {\n\n        public UnexpectedTokenException(String lineMsg, String expected, String got, LineCol lineCol) {\n                super(lineMsg, \"expecting \" + expected + \", but got \" + got, lineCol);\n        }\n\n        public UnexpectedTokenException(String lineMsg, String token, LineCol lineCol) {\n                super(lineMsg, \"unexpected token \" + token, lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/Args.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.LtBug;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.Stack;\n\npublic class Args {\n        public String fileName;\n        /**\n         * previous node\n         */\n        public Node previous;\n        /**\n         * current line to parse\n         */\n        public int currentLine;\n        /**\n         * current line to parse\n         */\n        public int currentCol;\n        /**\n         * element start nodes\n         */\n        public Stack<ElementStartNode> startNodeStack = new Stack<ElementStartNode>();\n        /**\n         * pair stack\n         */\n        public Stack<PairEntry> pairEntryStack = new Stack<PairEntry>();\n\n        /**\n         * @return a new LineCol object containing current file, line, column and whether it uses define command\n         */\n        public LineCol generateLineCol() {\n                LineCol res = new LineCol(fileName, currentLine, currentCol);\n                res.useDefine.putAll(useDefine);\n                return res;\n        }\n\n        public int getLastNonFlexIndent() {\n                for (int i = startNodeStack.size() - 1; i >= 0; --i) {\n                        ElementStartNode node = startNodeStack.elementAt(i);\n                        int indent = node.getIndent().getIndent();\n                        if (indent != Indent.FLEX) {\n                                return indent;\n                        }\n                }\n                throw new LtBug(\"should not reach here!\");\n        }\n\n        /**\n         * the defined strings\n         */\n        public Map<String, String> defined = new LinkedHashMap<String, String>();\n        /**\n         * whether this line uses define\n         */\n        public Map<String, String> useDefine = new LinkedHashMap<String, String>();\n        /**\n         * is parsing multiple line comment\n         */\n        public boolean multipleLineComment = false;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/Element.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\nimport lt.compiler.CompileUtil;\n\n/**\n * element\n */\npublic class Element extends Node {\n        private String content;\n\n        public Element(Args args, String content, TokenType tokenType) {\n                super(args, tokenType);\n                this.content = content;\n                getLineCol().length = this.content.length();\n        }\n\n        public String getContent() {\n                return content;\n        }\n\n        public void setContent(String content) {\n                this.content = content;\n        }\n\n        public void checkWhetherIsValidName() {\n                if (getTokenType() == TokenType.VALID_NAME) {\n                        content = CompileUtil.validateValidName(content);\n                }\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n                if (!super.equals(o)) return false;\n\n                Element element = (Element) o;\n\n                return !(content != null ? !content.equals(element.content) : element.content != null);\n        }\n\n        @Override\n        public String toString(int indent) {\n                StringBuilder sb = new StringBuilder();\n                for (int i = 0; i < indent; ++i) {\n                        sb.append(\" \");\n                }\n                sb.append(content).append(\"    \").append(getTokenType()).append(\"\\n\");\n                if (hasNext()) {\n                        sb.append(next().toString(indent));\n                }\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equalsIgnoreIndent(Node o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n                if (!super.equalsIgnoreIndent(o)) return false;\n\n                Element element = (Element) o;\n\n                return !(content != null ? !content.equals(element.content) : element.content != null);\n        }\n\n        @Override\n        public String toString() {\n                return content;\n        }\n\n        @Override\n        public void remove() {\n                throw new UnsupportedOperationException();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/ElementStartNode.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\n/**\n * starts an element\n */\npublic class ElementStartNode extends Node {\n        private final Indent indent;\n        private Node linkedNode;\n\n        public ElementStartNode(Args args, Indent indent) {\n                super(args, TokenType.ElementStartNode);\n                this.indent = indent;\n        }\n\n        public Indent getIndent() {\n                return indent;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n                if (!super.equals(o)) return false;\n\n                ElementStartNode that = (ElementStartNode) o;\n\n                return !(linkedNode != null ? !linkedNode.equals(that.linkedNode) : that.linkedNode != null) && this.getIndent().equals(that.getIndent());\n        }\n\n        @Override\n        public String toString(int indent) {\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"StartNode(\").append(this.indent).append(\")\\n\");\n                if (hasLinkedNode()) {\n                        sb.append(getLinkedNode().toString(indent + 4));\n                }\n                if (hasNext()) {\n                        sb.append(next().toString(indent));\n                }\n                return sb.toString();\n        }\n\n        public boolean hasLinkedNode() {\n                return linkedNode != null;\n        }\n\n        public void setLinkedNode(Node linkedNode) {\n                this.linkedNode = linkedNode;\n        }\n\n        public Node getLinkedNode() {\n                return linkedNode;\n        }\n\n        @Override\n        public String toString() {\n                return \"NewLayer\";\n        }\n\n        @Override\n        public void remove() {\n                throw new UnsupportedOperationException();\n        }\n\n        @Override\n        public boolean equalsIgnoreIndent(Node o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n                if (!super.equalsIgnoreIndent(o)) return false;\n\n                ElementStartNode that = (ElementStartNode) o;\n\n                return !(linkedNode != null ? !linkedNode.equalsIgnoreIndent(that.linkedNode) : that.linkedNode != null);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/EndingNode.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\n/**\n * ends a expression or statement\n */\npublic class EndingNode extends Node {\n        public static final int STRONG = 0;\n        public static final int WEAK = 1;\n        public static final int SYNTHETIC = 2;\n\n        private int type;\n\n        public EndingNode(Args args, int type) {\n                super(args, type == STRONG ? TokenType.EndingNodeStrong : TokenType.EndingNode);\n                if (type != STRONG && type != WEAK && type != SYNTHETIC) {\n                        throw new IllegalArgumentException(\"unexpected type number \" + type + \", use EndingNode.STRONG or EndingNode.WEAK\");\n                }\n                this.type = type;\n        }\n\n        public int getType() {\n                return type;\n        }\n\n        @Override\n        public String toString(int indent) {\n                StringBuilder sb = new StringBuilder();\n                for (int i = 0; i < indent; ++i) {\n                        sb.append(\" \");\n                }\n                sb.append(\"(\").append(type == STRONG ? \"STRONG\" : \"WEAK\").append(\")\\n\");\n                if (hasNext()) {\n                        sb.append(next().toString(indent));\n                }\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equalsIgnoreIndent(Node node) {\n                return super.equalsIgnoreIndent(node);\n        }\n\n        @Override\n        public String toString() {\n                return (type == STRONG ? \",\" : \"NewLine\");\n        }\n\n        @Override\n        public void remove() {\n                throw new UnsupportedOperationException();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/IllegalIndentationException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.Properties;\nimport lt.compiler.SyntaxException;\n\n/**\n * illegal indent.\n */\npublic class IllegalIndentationException extends SyntaxException {\n        public IllegalIndentationException(String lineMsg, int _INDENT, LineCol lineCol) {\n                super(lineMsg, \"the indentation should be \" + _INDENT + \" spaces\", lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/Indent.java",
    "content": "package lt.compiler.lexical;\n\n/**\n * indentation\n */\npublic class Indent {\n        public static final int FLEX = -1;\n\n        private int indent;\n\n        public Indent(int indent) {\n                this.indent = indent;\n        }\n\n        public int getIndent() {\n                return indent;\n        }\n\n        public void setIndent(int indent) {\n                this.indent = indent;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                Indent indent1 = (Indent) o;\n\n                return indent == indent1.indent;\n        }\n\n        @Override\n        public int hashCode() {\n                return indent;\n        }\n\n        @Override\n        public String toString() {\n                return \"Indent(\" + indent + \")\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/Node.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.LtBug;\n\nimport java.util.Iterator;\n\n/**\n * parsed node from plain jes text. the nodes are chained up\n */\npublic abstract class Node implements Iterator<Node>, Iterable {\n        private LineCol lineCol;\n        private Node next;\n        private Node previous;\n\n        private final TokenType tokenType;\n\n        public Node(Args args, TokenType tokenType) {\n                if (tokenType == null) throw new LtBug(\"tokenType should not be null\");\n                this.tokenType = tokenType;\n                lineCol = args.generateLineCol();\n                this.previous = args.previous;\n\n                if (hasPrevious()) {\n                        assert previous != null;\n                        previous.next = this;\n                } else if (!args.startNodeStack.empty()) {\n                        args.startNodeStack.lastElement().setLinkedNode(this);\n                }\n        }\n\n        public TokenType getTokenType() {\n                return tokenType;\n        }\n\n        public boolean hasNext() {\n                return next != null;\n        }\n\n        public boolean hasPrevious() {\n                return previous != null;\n        }\n\n        public LineCol getLineCol() {\n                return lineCol;\n        }\n\n        public void setLineCol(LineCol lineCol) {\n                this.lineCol = lineCol;\n        }\n\n        public Node next() {\n                return next;\n        }\n\n        public Node previous() {\n                return previous;\n        }\n\n        public void setNext(Node next) {\n                this.next = next;\n        }\n\n        public void setPrevious(Node previous) {\n                this.previous = previous;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                Node node = (Node) o;\n                return tokenType == node.tokenType && !(next != null ? !next.equals(node.next) : node.next != null);\n\n        }\n\n        @Override\n        public Iterator iterator() {\n                return this;\n        }\n\n        public abstract String toString(int indent);\n\n        public boolean equalsIgnoreIndent(Node o) {\n                return this == o || !(o == null || getClass() != o.getClass()) && tokenType == o.tokenType && !(next != null ? !next.equalsIgnoreIndent(o.next) : o.next != null);\n\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/PairEntry.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\n/**\n * pair key and start node\n */\npublic class PairEntry {\n        public final String key;\n        public final ElementStartNode startNode;\n\n        public PairEntry(String key, ElementStartNode startNode) {\n                this.key = key;\n                this.startNode = startNode;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/lexical/TokenType.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.lexical;\n\n/**\n * the type of a token\n */\npublic enum TokenType {\n        EndingNode, EndingNodeStrong, ElementStartNode,\n        STRING, NUMBER, BOOL, VALID_NAME, MODIFIER, KEY, SYMBOL\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/ConstantValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * constantValue,which can be put into constant pool\n */\npublic interface ConstantValue extends Value {\n        byte[] getByte();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/DummyValue.java",
    "content": "package lt.compiler.semantic;\n\n/**\n * a value without actual value, only a type\n */\npublic class DummyValue implements Value {\n        private final STypeDef aType;\n\n        public DummyValue(STypeDef aType) {\n                this.aType = aType;\n        }\n\n        @Override\n        public STypeDef type() {\n                return aType;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/ExceptionTable.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * exceptionTable\n */\npublic class ExceptionTable {\n        private final Instruction from;\n        private final Instruction to;\n        private final Instruction target;\n        private final STypeDef type;\n\n        public ExceptionTable(Instruction from, Instruction to, Instruction target, STypeDef type) {\n                this.from = from;\n                this.to = to;\n                this.target = target;\n                this.type = type;\n        }\n\n        public Instruction getTo() {\n                return to;\n        }\n\n        public Instruction getFrom() {\n                return from;\n        }\n\n        public Instruction getTarget() {\n                return target;\n        }\n\n        public STypeDef getType() {\n                return type;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/Ins.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.builtin.*;\n\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * abstract instructions\n */\npublic class Ins {\n        private Ins() {\n        }\n\n        /**\n         * a new array\n         */\n        public static class ANewArray implements Value {\n                private final SArrayTypeDef arrayType;\n                private final STypeDef componentType;\n                private final IntValue count;\n                private final List<Value> initValues = new ArrayList<Value>();\n\n                public ANewArray(SArrayTypeDef arrayType, STypeDef componentType, IntValue count) {\n                        this.arrayType = arrayType;\n                        this.componentType = componentType;\n                        this.count = count;\n                }\n\n                @Override\n                public SArrayTypeDef type() {\n                        return arrayType;\n                }\n\n                public STypeDef componentType() {\n                        return componentType;\n                }\n\n                public IntValue count() {\n                        return count;\n                }\n\n                public List<Value> initValues() {\n                        return initValues;\n                }\n        }\n\n        /**\n         * arrayLength\n         */\n        public static class ArrayLength implements Value, Instruction, ReadOnly {\n                private final LineCol lineCol;\n                private final Value arrayValue;\n\n                public ArrayLength(Value arrayValue, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.arrayValue = arrayValue;\n                }\n\n                public Value arrayValue() {\n                        return arrayValue;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return IntTypeDef.get();\n                }\n        }\n\n        /**\n         * throw\n         */\n        public static class AThrow implements Instruction {\n                private final Value exception;\n                private final LineCol lineCol;\n\n                public AThrow(Value exception, LineCol lineCol) {\n                        this.exception = exception;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value exception() {\n                        return exception;\n                }\n        }\n\n        /**\n         * cast\n         */\n        public static class Cast implements Value, Instruction {\n                public static final int CAST_INT_TO_LONG = 0x85;\n                public static final int CAST_INT_TO_FLOAT = 0x86;\n                public static final int CAST_INT_TO_DOUBLE = 0x87;\n\n                public static final int CAST_LONG_TO_INT = 0x88;\n                public static final int CAST_LONG_TO_FLOAT = 0x89;\n                public static final int CAST_LONG_TO_DOUBLE = 0x8A;\n\n                public static final int CAST_FLOAT_TO_INT = 0x8B;\n                public static final int CAST_FLOAT_TO_LONG = 0x8C;\n                public static final int CAST_FLOAT_TO_DOUBLE = 0x8D;\n\n                public static final int CAST_DOUBLE_TO_INT = 0x8E;\n                public static final int CAST_DOUBLE_TO_LONG = 0x8F;\n                public static final int CAST_DOUBLE_TO_FLOAT = 0x90;\n\n                public static final int CAST_INT_TO_BYTE = 0x91;\n                public static final int CAST_INT_TO_CHAR = 0x92;\n                public static final int CAST_INT_TO_SHORT = 0x93;\n\n                private final Value value;\n                private final STypeDef type;\n                private final int castMode;\n\n                private final LineCol lineCol;\n\n                public Cast(STypeDef type, Value value, int castMode, LineCol lineCol) {\n                        this.type = type;\n                        this.value = value;\n                        this.castMode = castMode;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                public int castMode() {\n                        return castMode;\n                }\n        }\n\n        /**\n         * cast the object to another type\n         */\n        public static class CheckCast implements Instruction, Value {\n                private final Value theValueToCheck;\n                private final STypeDef requiredType;\n                private final LineCol lineCol;\n\n                public CheckCast(Value theValueToCheck, STypeDef requiredType, LineCol lineCol) {\n                        this.theValueToCheck = theValueToCheck;\n                        this.requiredType = requiredType;\n                        this.lineCol = lineCol;\n                }\n\n                public Value theValueToCheck() {\n                        return theValueToCheck;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return requiredType;\n                }\n        }\n\n        /**\n         * exception store<br>\n         * this storage will be parsed into <code>AStore index</code>, the exception pushed by jvm will be stored into local variable table\n         */\n        public static class ExStore implements Instruction {\n                private final LeftValue leftValue;\n                private final SemanticScope scope;\n\n                public ExStore(LeftValue ex, SemanticScope scope) {\n                        this.leftValue = ex;\n                        this.scope = scope;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return null;\n                }\n\n                public LeftValue leftValue() {\n                        return leftValue;\n                }\n\n                public SemanticScope getScope() {\n                        return scope;\n                }\n        }\n\n        /**\n         * XXX.class\n         */\n        public static class GetClass implements Value, ReadOnly {\n                private final STypeDef targetType;\n                private final SClassDef classClassDef;\n\n                /**\n                 * @param targetType    the represented type\n                 * @param classClassDef java.lang.Class\n                 */\n                public GetClass(STypeDef targetType, SClassDef classClassDef) {\n                        this.targetType = targetType;\n                        this.classClassDef = classClassDef;\n                }\n\n                /**\n                 * this value type\n                 *\n                 * @return java.lang.Class\n                 */\n                @Override\n                public STypeDef type() {\n                        return classClassDef;\n                }\n\n                /**\n                 * something like <code>targetType.class</code>\n                 *\n                 * @return STypeDef\n                 */\n                public STypeDef targetType() {\n                        return targetType;\n                }\n        }\n\n        /**\n         * get non-static field\n         */\n        public static class GetField implements Value, Instruction, ReadOnly {\n                private final LineCol lineCol;\n                private final SFieldDef field;\n                private final Value object;\n\n                public GetField(SFieldDef field, Value object, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.field = field;\n                        this.object = object;\n                }\n\n                public Value object() {\n                        return object;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return field.type();\n                }\n\n                public SFieldDef field() {\n                        return field;\n                }\n\n                @Override\n                public String toString() {\n                        return \"get field [\" + field.toString() + \"]\";\n                }\n        }\n\n        /**\n         * get static field\n         */\n        public static class GetStatic implements Value, Instruction, ReadOnly {\n                private final LineCol lineCol;\n                private final SFieldDef field;\n\n                public GetStatic(SFieldDef field, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.field = field;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return field.type();\n                }\n\n                public SFieldDef field() {\n                        return field;\n                }\n        }\n\n        /**\n         * goto\n         */\n        public static class Goto implements Instruction {\n                private final Instruction gotoIns;\n\n                public Goto(Instruction gotoIns) {\n                        this.gotoIns = gotoIns;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return null;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n        }\n\n        /**\n         * ifACmpNe\n         */\n        public static class IfACmpNe implements Instruction {\n                private final Value value1;\n                private final Value value2;\n                private final Instruction gotoIns;\n                private final LineCol lineCol;\n\n                public IfACmpNe(Value value1, Value value2, Instruction gotoIns, LineCol lineCol) {\n                        this.value1 = value1;\n                        this.value2 = value2;\n                        this.gotoIns = gotoIns;\n                        this.lineCol = lineCol;\n                }\n\n                public Value value1() {\n                        return value1;\n                }\n\n                public Value value2() {\n                        return value2;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * ifEq (i == 0)\n         */\n        public static class IfEq implements Instruction {\n                private final Value condition;\n                private final Instruction gotoIns;\n                private final LineCol lineCol;\n\n                public IfEq(Value condition, Instruction gotoIns, LineCol lineCol) {\n                        this.condition = condition;\n                        this.gotoIns = gotoIns;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value condition() {\n                        return condition;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n        }\n\n        /**\n         * ifNe (if i != 0)\n         */\n        public static class IfNe implements Instruction {\n                private final Value condition;\n                private Instruction gotoIns;\n                private final LineCol lineCol;\n\n                public IfNe(Value condition, Instruction gotoIns, LineCol lineCol) {\n                        this.condition = condition;\n                        this.gotoIns = gotoIns;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value condition() {\n                        return condition;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n\n                public void setGotoIns(Instruction gotoIns) {\n                        this.gotoIns = gotoIns;\n                }\n        }\n\n        /**\n         * ifNonNull ( != null )\n         */\n        public static class IfNonNull implements Instruction {\n                private final Value object;\n                private final Instruction gotoIns;\n                private final LineCol lineCol;\n\n                public IfNonNull(Value object, Instruction gotoIns, LineCol lineCol) {\n                        this.object = object;\n                        this.gotoIns = gotoIns;\n                        this.lineCol = lineCol;\n                }\n\n                public Value object() {\n                        return object;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * ifNull ( = null )\n         */\n        public static class IfNull implements Instruction {\n                private final Value object;\n                private final Instruction gotoIns;\n                private final LineCol lineCol;\n\n                public IfNull(Value object, Instruction gotoIns, LineCol lineCol) {\n                        this.object = object;\n                        this.gotoIns = gotoIns;\n                        this.lineCol = lineCol;\n                }\n\n                public Value object() {\n                        return object;\n                }\n\n                public Instruction gotoIns() {\n                        return gotoIns;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * instanceof\n         */\n        public static class InstanceOf implements Instruction, Value {\n                private final Value object;\n                private final GetClass aClass;\n                private final LineCol lineCol;\n\n                public InstanceOf(Value object, GetClass aClass, LineCol lineCol) {\n                        this.object = object;\n                        this.aClass = aClass;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return BoolTypeDef.get();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value object() {\n                        return object;\n                }\n\n                public GetClass aClass() {\n                        return aClass;\n                }\n        }\n\n        /**\n         * invoke\n         */\n        public abstract static class Invoke implements Instruction, Value {\n                private final LineCol lineCol;\n\n                private SInvokable invokable;\n                private final List<Value> arguments = new ArrayList<Value>();\n\n                public Invoke(SInvokable invokable, LineCol lineCol) {\n                        setInvokable(invokable);\n                        this.lineCol = lineCol;\n                }\n\n                public void setInvokable(SInvokable invokable) {\n                        this.invokable = invokable;\n                }\n\n                public SInvokable invokable() {\n                        return invokable;\n                }\n\n                public List<Value> arguments() {\n                        return arguments;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return invokable().getReturnType();\n                }\n        }\n\n        /**\n         * invokeInterface\n         */\n        public static class InvokeInterface extends InvokeWithTarget {\n                public InvokeInterface(Value target, SInvokable invokable, LineCol lineCol) {\n                        super(target, invokable, lineCol);\n                }\n        }\n\n        /**\n         * invoke special\n         */\n        public static class InvokeSpecial extends InvokeWithTarget {\n                public InvokeSpecial(Value target, SInvokable invokable, LineCol lineCol) {\n                        super(target, invokable, lineCol);\n                }\n        }\n\n        /**\n         * invoke static\n         */\n        public static class InvokeStatic extends Invoke {\n                public InvokeStatic(SInvokable invokable, LineCol lineCol) {\n                        super(invokable, lineCol);\n                }\n        }\n\n        /**\n         * invoke special\n         */\n        public static class InvokeVirtual extends InvokeWithTarget {\n                public int flag;\n\n                public InvokeVirtual(Value target, SInvokable invokable, LineCol lineCol) {\n                        super(target, invokable, lineCol);\n                }\n        }\n\n        /**\n         * invoke lambda expression\n         */\n        public static class InvokeWithCapture extends InvokeWithTarget {\n                private final List<Value> capturedArguments = new ArrayList<Value>();\n                private final boolean isStatic;\n\n                public InvokeWithCapture(Value target, SInvokable invokable, boolean isStatic, LineCol lineCol) {\n                        super(target, invokable, lineCol);\n                        this.isStatic = isStatic;\n                }\n\n                public List<Value> capturedArguments() {\n                        return capturedArguments;\n                }\n\n                public boolean isStatic() {\n                        return isStatic;\n                }\n        }\n\n        /**\n         * invoke\n         */\n        public abstract static class InvokeWithTarget extends Invoke implements Instruction, Value {\n                private Value target;\n\n                public InvokeWithTarget(Value target, SInvokable invokable, LineCol lineCol) {\n                        super(invokable, lineCol);\n                        this.target = target;\n                }\n\n                public void setTarget(Value target) {\n                        this.target = target;\n                }\n\n                public Value target() {\n                        return target;\n                }\n        }\n\n        /**\n         * This class is only used to optimize code when getting pointer variables.\n         */\n        public static class PointerGetCastHelper implements Instruction, Value {\n                private final Value valueAfterCast;\n                private final InvokeVirtual valueBeforeCast;\n\n                public PointerGetCastHelper(Value valueAfterCast, InvokeVirtual valueBeforeCast) {\n                        this.valueAfterCast = valueAfterCast;\n                        this.valueBeforeCast = valueBeforeCast;\n                }\n\n                public Value after() {\n                        return valueAfterCast;\n                }\n\n                public InvokeVirtual before() {\n                        return valueBeforeCast;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return valueAfterCast.type();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return valueBeforeCast.line_col();\n                }\n        }\n\n        /**\n         * logic and\n         */\n        public static class LogicAnd implements Value, Instruction {\n                private final LineCol lineCol;\n                private final Value b1;\n                private final Value b2;\n\n                public LogicAnd(Value b1, Value b2, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.b1 = b1;\n                        this.b2 = b2;\n                }\n\n                public Value b1() {\n                        return b1;\n                }\n\n                public Value b2() {\n                        return b2;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return BoolTypeDef.get();\n                }\n        }\n\n        /**\n         * logic or\n         */\n        public static class LogicOr implements Value, Instruction {\n                private final LineCol lineCol;\n                private final SMethodDef castToBool;\n                private final Value v1;\n                private final Value v2;\n                private final STypeDef type;\n\n                public LogicOr(SMethodDef castToBool, Value v1, Value v2, STypeDef type, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.castToBool = castToBool;\n                        this.v1 = v1;\n                        this.v2 = v2;\n                        this.type = type;\n                }\n\n                public SMethodDef getCastToBool() {\n                        return castToBool;\n                }\n\n                public Value v1() {\n                        return v1;\n                }\n\n                public Value v2() {\n                        return v2;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n        }\n\n        /**\n         * monitor entry (synchronized)\n         */\n        public static class MonitorEnter implements Instruction {\n                private final LineCol lineCol;\n                private final Value valueToMonitor;\n                private final LeftValue leftValue;\n                private final SemanticScope scope;\n\n                public MonitorEnter(Value valueToMonitor, SemanticScope scope, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.valueToMonitor = valueToMonitor;\n                        LocalVariable localVariable = new LocalVariable(valueToMonitor.type(), false);\n                        scope.putLeftValue(scope.generateTempName(), localVariable);\n                        this.leftValue = localVariable;\n                        this.scope = scope;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value valueToMonitor() {\n                        return valueToMonitor;\n                }\n\n                public LeftValue leftValue() {\n                        return leftValue;\n                }\n\n                public SemanticScope getScope() {\n                        return scope;\n                }\n        }\n\n        /**\n         * monitor entry (synchronized)\n         */\n        public static class MonitorExit implements Instruction {\n                private final LineCol lineCol;\n                private final MonitorEnter enterInstruction;\n\n                public MonitorExit(MonitorEnter enterInstruction) {\n                        this.lineCol = enterInstruction.line_col();\n                        this.enterInstruction = enterInstruction;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public MonitorEnter enterInstruction() {\n                        return enterInstruction;\n                }\n        }\n\n        /**\n         * create an object and construct it\n         */\n        public static class New implements Value, Instruction {\n                private final SConstructorDef constructor;\n                private final List<Value> args = new ArrayList<Value>();\n\n                private final LineCol lineCol;\n\n                public New(SConstructorDef constructor, LineCol lineCol) {\n                        this.constructor = constructor;\n                        this.lineCol = lineCol;\n                }\n\n                public SConstructorDef constructor() {\n                        return constructor;\n                }\n\n                public List<Value> args() {\n                        return args;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return constructor.declaringType();\n                }\n        }\n\n        /**\n         * create a new array\n         */\n        public static class NewArray implements Value {\n                public static final int NewBoolArray = 4;\n                public static final int NewCharArray = 5;\n                public static final int NewFloatArray = 6;\n                public static final int NewDoubleArray = 7;\n                public static final int NewByteArray = 8;\n                public static final int NewShortArray = 9;\n                public static final int NewIntArray = 10;\n                public static final int NewLongArray = 11;\n\n                private final int mode;\n                private final IntValue count;\n                private final STypeDef type;\n                private final int storeMode;\n                private final List<Value> initValues = new ArrayList<Value>();\n\n                public NewArray(IntValue count, int mode, int storeMode, STypeDef type) {\n                        this.count = count;\n                        this.mode = mode;\n                        this.storeMode = storeMode;\n                        this.type = type;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n\n                public int mode() {\n                        return mode;\n                }\n\n                public IntValue count() {\n                        return count;\n                }\n\n                public int storeMode() {\n                        return storeMode;\n                }\n\n                public List<Value> initValues() {\n                        return initValues;\n                }\n        }\n\n        /**\n         * create an array list\n         */\n        public static class NewList implements Value {\n                private final STypeDef type;\n                private List<Value> initValues = new ArrayList<Value>();\n\n                public NewList(STypeDef linkedListType) {\n                        this.type = linkedListType;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n\n                public List<Value> initValues() {\n                        return initValues;\n                }\n        }\n\n        /**\n         * new map\n         */\n        public static class NewMap implements Value {\n                private final STypeDef linkedListClass;\n                private final LinkedHashMap<Value, Value> initValues = new LinkedHashMap<Value, Value>();\n\n                public NewMap(STypeDef linkedListClass) {\n                        this.linkedListClass = linkedListClass;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return linkedListClass;\n                }\n\n                public LinkedHashMap<Value, Value> initValues() {\n                        return initValues;\n                }\n        }\n\n        /**\n         * nop\n         */\n        public static class Nop implements Instruction {\n                @Override\n                public LineCol line_col() {\n                        return null;\n                }\n        }\n\n        /**\n         * one variable operation\n         */\n        public static class OneVarOp implements Value, Instruction {\n                public static final int Ineg = 0x74;\n                public static final int Lneg = 0x75;\n                public static final int Fneg = 0x76;\n                public static final int Dneg = 0x77;\n\n                private final LineCol lineCol;\n                private final int op;\n                private final Value value;\n                private final STypeDef type;\n\n                public OneVarOp(Value value, int op, STypeDef type, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.op = op;\n                        this.value = value;\n                        this.type = type;\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                public int op() {\n                        return op;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n        }\n\n        /**\n         * pop from stack\n         */\n        public static class Pop implements Instruction {\n                @Override\n                public LineCol line_col() {\n                        return null;\n                }\n        }\n\n        /**\n         * put non-static field\n         */\n        public static class PutField implements Instruction {\n                private final Value value;\n                private final SFieldDef field;\n                private final Value obj;\n                private final LineCol lineCol;\n\n                public PutField(SFieldDef field, Value obj, Value value, LineCol lineCol, ErrorManager err) throws SyntaxException {\n                        if (field.alreadyAssigned() && !field.canChange())\n                                err.SyntaxException(field + \" cannot be assigned\", lineCol);\n\n                        this.field = field;\n                        this.obj = obj;\n                        this.value = value;\n                        this.lineCol = lineCol;\n\n                        field.assign();\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                public SFieldDef field() {\n                        return field;\n                }\n\n                public Value obj() {\n                        return obj;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * put static field\n         */\n        public static class PutStatic implements Instruction {\n                private final Value value;\n                private final SFieldDef field;\n                private final LineCol lineCol;\n\n                public PutStatic(SFieldDef field, Value value, LineCol lineCol, ErrorManager err) throws SyntaxException {\n                        if (field.alreadyAssigned() && !field.canChange())\n                                err.SyntaxException(field + \" cannot be assigned\", lineCol);\n\n                        this.field = field;\n                        this.value = value;\n                        this.lineCol = lineCol;\n\n                        field.assign();\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                public SFieldDef field() {\n                        return field;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * TALoad\n         */\n        public static class TALoad implements Value, Instruction, ReadOnly {\n                public static int Iaload = 0x2e;\n                public static int Laload = 0x2f;\n                public static int Faload = 0x30;\n                public static int Daload = 0x31;\n                public static int Aaload = 0x32;\n                public static int Baload = 0x33;\n                public static int Caload = 0x34;\n                public static int Saload = 0x35;\n\n                private final LineCol lineCol;\n                private final int mode;\n                private final Value index;\n                private final Value arr;\n                private final Map<String, STypeDef> types;\n\n                public TALoad(Value arr, Value index, LineCol lineCol, Map<String, STypeDef> types) {\n                        this.arr = arr;\n                        this.index = index;\n                        this.lineCol = lineCol;\n                        this.types = types;\n\n                        if (((SArrayTypeDef) arr.type()).dimension() == 1) {\n                                STypeDef type = ((SArrayTypeDef) arr.type()).type();\n                                if (type instanceof BoolTypeDef || type instanceof ByteTypeDef) mode = Baload;\n                                else if (type instanceof ShortTypeDef) mode = Saload;\n                                else if (type instanceof IntTypeDef) mode = Iaload;\n                                else if (type instanceof LongTypeDef) mode = Laload;\n                                else if (type instanceof FloatTypeDef) mode = Faload;\n                                else if (type instanceof DoubleTypeDef) mode = Daload;\n                                else if (type instanceof CharTypeDef) mode = Caload;\n                                else mode = Aaload;\n                        } else {\n                                mode = Aaload;\n                        }\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        SArrayTypeDef arrT = (SArrayTypeDef) arr.type();\n                        STypeDef rawType = arrT.type();\n                        if (arrT.dimension() == 1) return rawType;\n\n                        SArrayTypeDef newArrT = new SArrayTypeDef();\n                        newArrT.setType(rawType);\n                        newArrT.setDimension(arrT.dimension() - 1);\n                        String name = newArrT.fullName();\n\n                        if (types.containsKey(name)) return types.get(name);\n                        else {\n                                throw new LtBug(\"code won't reach here\");\n                        }\n                }\n\n                public Value arr() {\n                        return arr;\n                }\n\n                public int mode() {\n                        return mode;\n                }\n\n                public Value index() {\n                        return index;\n                }\n        }\n\n        /**\n         * tastore\n         */\n        public static class TAStore implements Instruction {\n                public static final int IASTORE = 0x4f;\n                public static final int LASTORE = 0x50;\n                public static final int FASTORE = 0x51;\n                public static final int DASTORE = 0x52;\n                public static final int AASTORE = 0x53;\n                public static final int BASTORE = 0x54;\n                public static final int CASTORE = 0x55;\n                public static final int SASTORE = 0x56;\n\n                private final int mode;\n                private final Value index;\n                private final Value array;\n                private final Value value;\n                private final LineCol lineCol;\n\n                public TAStore(Value array, int mode, Value index, Value value, LineCol lineCol) {\n                        this.array = array;\n                        this.mode = mode;\n                        this.index = index;\n                        this.value = value;\n                        this.lineCol = lineCol;\n                }\n\n                public int mode() {\n                        return mode;\n                }\n\n                public Value index() {\n                        return index;\n                }\n\n                public Value array() {\n                        return array;\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n        }\n\n        /**\n         * this\n         */\n        public static class This implements Value, ReadOnly {\n                private final STypeDef type;\n\n                public This(STypeDef type) {\n                        this.type = type;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return type;\n                }\n        }\n\n        /**\n         * tload instruction\n         */\n        public static class TLoad implements Value, Instruction, ReadOnly {\n                public static int Iload = 0x15;\n                public static int Lload = 0x16;\n                public static int Fload = 0x17;\n                public static int Dload = 0x18;\n                public static int Aload = 0x19;\n\n                private final LineCol lineCol;\n                private final LeftValue value;\n                private final int mode;\n                private final SemanticScope scope;\n\n                public TLoad(LeftValue value, SemanticScope scope, LineCol lineCol) {\n                        this.value = value;\n                        this.lineCol = lineCol;\n\n                        if (value.type() instanceof IntTypeDef || IntTypeDef.get().isAssignableFrom(value.type())) {\n                                mode = Iload;\n                        } else if (value.type() instanceof FloatTypeDef) {\n                                mode = Fload;\n                        } else if (value.type() instanceof LongTypeDef) {\n                                mode = Lload;\n                        } else if (value.type() instanceof DoubleTypeDef) {\n                                mode = Dload;\n                        } else if (value.type() instanceof BoolTypeDef) {\n                                mode = Iload;\n                        } else\n                                mode = Aload;\n\n                        this.scope = scope;\n\n                        // set variable to 'used'\n                        value.setUsed(true);\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return value.type();\n                }\n\n                public LeftValue value() {\n                        return value;\n                }\n\n                public int mode() {\n                        return mode;\n                }\n\n                public SemanticScope getScope() {\n                        return scope;\n                }\n        }\n\n        /**\n         * return\n         */\n        public static class TReturn implements Instruction {\n                public static final int Return = 0xb1;\n                public static final int AReturn = 0xb0;\n                public static final int DReturn = 0xaf;\n                public static final int FReturn = 0xae;\n                public static final int IReturn = 0xac;\n                public static final int LReturn = 0xad;\n\n                private Value value;\n                private final int returnIns;\n                private final LineCol lineCol;\n\n                public TReturn(Value value, LineCol lineCol) {\n                        this.value = value;\n                        if (value == null) returnIns = Return;\n                        else {\n\n                                STypeDef returnType = value.type();\n                                if (returnType.equals(IntTypeDef.get()) || returnType.equals(ShortTypeDef.get())\n                                        || returnType.equals(ByteTypeDef.get()) || returnType.equals(BoolTypeDef.get())\n                                        || returnType.equals(CharTypeDef.get())) this.returnIns = IReturn;\n                                else if (returnType.equals(LongTypeDef.get())) this.returnIns = LReturn;\n                                else if (returnType.equals(FloatTypeDef.get())) this.returnIns = FReturn;\n                                else if (returnType.equals(DoubleTypeDef.get())) this.returnIns = DReturn;\n                                else this.returnIns = AReturn;\n                        }\n\n                        this.lineCol = lineCol;\n                }\n\n                public void setReturnValue(Value value) {\n                        this.value = value;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value value() {\n                        return value;\n                }\n\n                public int returnIns() {\n                        return returnIns;\n                }\n        }\n\n        /**\n         * ?store\n         */\n        public static class TStore implements Instruction {\n                public static final int Astore = 0x3a;\n                public static final int Dstore = 0x39;\n                public static final int Fstore = 0x38;\n                public static final int Lstore = 0x37;\n                public static final int Istore = 0x36;\n\n                private final LeftValue leftValue;\n                private final Value newValue;\n                private final int mode;\n                private final LineCol lineCol;\n                private final SemanticScope scope;\n\n                public int flag;\n\n                public TStore(LeftValue leftValue, Value newValue, SemanticScope scope, LineCol lineCol, ErrorManager err) throws SyntaxException {\n                        if (leftValue.alreadyAssigned() && !leftValue.canChange())\n                                err.SyntaxException(leftValue + \" cannot be assigned\", lineCol);\n\n                        this.leftValue = leftValue;\n                        this.lineCol = lineCol;\n                        this.newValue = newValue;\n                        if (newValue.type() instanceof IntTypeDef || IntTypeDef.get().isAssignableFrom(newValue.type())) {\n                                mode = Istore;\n                        } else if (newValue.type() instanceof FloatTypeDef) {\n                                mode = Fstore;\n                        } else if (newValue.type() instanceof LongTypeDef) {\n                                mode = Lstore;\n                        } else if (newValue.type() instanceof DoubleTypeDef) {\n                                mode = Dstore;\n                        } else if (newValue.type() instanceof BoolTypeDef) {\n                                mode = Istore;\n                        } else\n                                mode = Astore;\n\n                        this.scope = scope;\n\n                        leftValue.assign();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                public Value newValue() {\n                        return newValue;\n                }\n\n                @SuppressWarnings(\"unused\")\n                public LeftValue leftValue() {\n                        return leftValue;\n                }\n\n                public int mode() {\n                        return mode;\n                }\n\n                public SemanticScope getScope() {\n                        return scope;\n                }\n        }\n\n        /**\n         * add\n         */\n        public static class TwoVarOp implements Value, Instruction {\n                public static final int Iadd = 0x60;\n                public static final int Ladd = 0x61;\n                public static final int Fadd = 0x62;\n                public static final int Dadd = 0x63;\n\n                public static final int Isub = 0x64;\n                public static final int Lsub = 0x65;\n                public static final int Fsub = 0x66;\n                public static final int Dsub = 0x67;\n\n                public static final int Imul = 0x68;\n                public static final int Lmul = 0x69;\n                public static final int Fmul = 0x6a;\n                public static final int Dmul = 0x6b;\n\n                public static final int Idiv = 0x6c;\n                public static final int Ldiv = 0x6d;\n                public static final int Fdiv = 0x6e;\n                public static final int Ddiv = 0x6f;\n\n                public static final int Irem = 0x70;\n                public static final int Lrem = 0x71;\n                public static final int Frem = 0x72;\n                public static final int Drem = 0x73;\n\n                public static final int Ishl = 0x78;\n                public static final int Ishr = 0x7a;\n                public static final int Iushr = 0x7c;\n                public static final int Lshl = 0x79;\n                public static final int Lshr = 0x7b;\n                public static final int Lushr = 0x7d;\n\n                public static final int Ior = 0x80;\n                public static final int Lor = 0x81;\n\n                public static final int Iand = 0x7e;\n                public static final int Land = 0x7f;\n\n                public static final int Ixor = 0x82;\n                public static final int Lxor = 0x83;\n\n                public static final int Dcmpg = 0x98;\n                @SuppressWarnings(\"unused\")\n                public static final int Dcmpl = 0x97;\n                public static final int Fcmpg = 0x96;\n                @SuppressWarnings(\"unused\")\n                public static final int Fcmpl = 0x95;\n                public static final int Lcmp = 0x94;\n\n                private final LineCol lineCol;\n                private final STypeDef resultType;\n                private final Value a;\n                private final Value b;\n                private final int op;\n\n                public TwoVarOp(Value a, Value b, int op, STypeDef resultType, LineCol lineCol) {\n                        this.lineCol = lineCol;\n                        this.resultType = resultType;\n                        this.a = a;\n                        this.b = b;\n                        this.op = op;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public STypeDef type() {\n                        return resultType;\n                }\n\n                public Value a() {\n                        return a;\n                }\n\n                public Value b() {\n                        return b;\n                }\n\n                public int op() {\n                        return op;\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/Instruction.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.io.Serializable;\n\n/**\n * statement\n */\npublic interface Instruction extends Serializable {\n        LineCol line_col();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/InvokableMeta.java",
    "content": "package lt.compiler.semantic;\n\nimport java.util.HashSet;\nimport java.util.Set;\n\n/**\n * meta data about invokable\n */\npublic class InvokableMeta {\n        public final Set<LeftValue> pointerLocalVar = new HashSet<LeftValue>();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/LeftValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * left value\n */\npublic interface LeftValue extends Value {\n        /**\n         * whether this value is a final value (`val` in Latte)\n         *\n         * @return true/false\n         */\n        boolean canChange();\n\n        /**\n         * check whether the value is already assigned\n         *\n         * @return true/false\n         */\n        boolean alreadyAssigned();\n\n        /**\n         * assign the value, change <tt>alreadyAssigned</tt> state to true.\n         */\n        void assign();\n\n        /**\n         * whether the value is referenced\n         *\n         * @return true if it's used\n         */\n        boolean isUsed();\n\n        /**\n         * mark the variable as used\n         *\n         * @param used true if it's used\n         */\n        void setUsed(boolean used);\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/LocalVariable.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * local variable\n */\npublic class LocalVariable implements LeftValue {\n        private final boolean canChange;\n        private STypeDef type;\n        private boolean used;\n\n        private boolean alreadyAssigned = false;\n\n        private SParameter wrappingParam;\n\n        public LocalVariable(STypeDef type, boolean canChange) {\n                this.type = type;\n                this.canChange = canChange;\n        }\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        @Override\n        public boolean canChange() {\n                return canChange;\n        }\n\n        @Override\n        public boolean alreadyAssigned() {\n                return alreadyAssigned;\n        }\n\n        @Override\n        public void assign() {\n                alreadyAssigned = true;\n                setUsed(true);\n        }\n\n        @Override\n        public boolean isUsed() {\n                return used;\n        }\n\n        @Override\n        public void setUsed(boolean used) {\n                this.used = used;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        @Override\n        public String toString() {\n                return \"LocalVariable{\" +\n                        \"alreadyAssigned=\" + alreadyAssigned +\n                        \", canChange=\" + canChange +\n                        \", type=\" + type +\n                        '}';\n        }\n\n        public SParameter getWrappingParam() {\n                return wrappingParam;\n        }\n\n        public void setWrappingParam(SParameter wrappingParam) {\n                this.wrappingParam = wrappingParam;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/MethodTypeValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.util.List;\n\n/**\n * method type\n */\npublic class MethodTypeValue implements Value {\n        private final List<STypeDef> parameters;\n        private final STypeDef returnType;\n        private final STypeDef type;\n\n        /**\n         * construct a method type object\n         *\n         * @param parameters parameter types\n         * @param returnType method return type\n         * @param type       MethodHandle_Class\n         */\n        public MethodTypeValue(List<STypeDef> parameters, STypeDef returnType, STypeDef type) {\n                this.parameters = parameters;\n                this.returnType = returnType;\n                this.type = type;\n        }\n\n        public List<STypeDef> parameters() {\n                return parameters;\n        }\n\n        public STypeDef returnType() {\n                return returnType;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/PointerType.java",
    "content": "package lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\n/**\n * pointer type\n */\npublic class PointerType extends STypeDef {\n        private final STypeDef pointingType;\n\n        public PointerType(STypeDef pointingType) {\n                super(LineCol.SYNTHETIC);\n                this.pointingType = pointingType;\n                setFullName(\"lt.lang.Pointer\");\n                setPkg(\"lt.lang\");\n        }\n\n        public STypeDef getPointingType() {\n                return pointingType;\n        }\n\n        @Override\n        public String toString() {\n                return \"*\" + pointingType.fullName();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/PrimitiveTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * primitive\n */\npublic abstract class PrimitiveTypeDef extends STypeDef {\n\n        public PrimitiveTypeDef() {\n                super(LineCol.SYNTHETIC);\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return Collections.emptyList();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/PrimitiveValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * primitiveValue\n */\npublic interface PrimitiveValue extends Value {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/ReadOnly.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * Represent that the instruction or value is <b>read only</b>\n */\npublic interface ReadOnly {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.util.LinkedHashMap;\nimport java.util.Map;\n\n/**\n * annotation\n */\npublic class SAnno implements Value {\n        private SAnnoDef annoDef;\n        private final Map<SAnnoField, Value> valueMap = new LinkedHashMap<SAnnoField, Value>();\n        private final Map<String, Object> alreadyCompiledAnnotationValueMap = new LinkedHashMap<String, Object>();\n        private SAnnotationPresentable present;\n\n        public void setAnnoDef(SAnnoDef annoDef) {\n                this.annoDef = annoDef;\n        }\n\n        public void setPresent(SAnnotationPresentable present) {\n                this.present = present;\n        }\n\n        @Override\n        public SAnnoDef type() {\n                return annoDef;\n        }\n\n        public Map<SAnnoField, Value> values() {\n                return valueMap;\n        }\n\n        public SAnnotationPresentable present() {\n                return present;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"@\");\n                sb.append(type().fullName()).append(\"(\");\n                boolean isFirst = true;\n                for (SAnnoField f : valueMap.keySet()) {\n                        Value v = valueMap.get(f);\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(f.name()).append(\"=\").append(v);\n                }\n                sb.append(\")\");\n                return sb.toString();\n        }\n\n        public Map<String, Object> alreadyCompiledAnnotationValueMap() {\n                return alreadyCompiledAnnotationValueMap;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SAnnoDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.LtBug;\nimport lt.compiler.SyntaxException;\nimport lt.compiler.semantic.builtin.EnumValue;\n\nimport java.lang.annotation.Annotation;\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Target;\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * annotation definition\n */\npublic class SAnnoDef extends STypeDef {\n        private final List<SAnnoField> annoFields = new ArrayList<SAnnoField>();\n        private final List<SModifier> modifiers = new ArrayList<SModifier>();\n\n        public SAnnoDef(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public List<SAnnoField> annoFields() {\n                return annoFields;\n        }\n\n        public List<SModifier> modifiers() {\n                return modifiers;\n        }\n\n        public boolean canPresentOn(ElementType type) throws SyntaxException {\n                String name = fullName();\n                try {\n                        Class<?> cls = Class.forName(name);\n                        Annotation[] annotations = cls.getAnnotations();\n                        for (Annotation a : annotations) {\n                                if (a instanceof Target) {\n                                        Target target = (Target) a;\n                                        ElementType[] types = target.value();\n                                        for (ElementType t : types) {\n                                                if (t.equals(type)) return true;\n                                        }\n                                        return false;\n                                }\n                        }\n                        return true;\n                } catch (ClassNotFoundException e) {\n                        // annotation not compiled yet\n                        // check manually\n                        SAnno targetAnno = null;\n                        for (SAnno anno : annos()) {\n                                if (anno.type().fullName().equals(Target.class.getName())) {\n                                        targetAnno = anno;\n                                        break;\n                                }\n                        }\n                        if (null == targetAnno) return true;\n                        SAnnoField valueAnnoF = null;\n                        for (SAnnoField f : targetAnno.type().annoFields()) {\n                                if (f.name().equals(\"value\")) {\n                                        valueAnnoF = f;\n                                        break;\n                                }\n                        }\n                        if (valueAnnoF == null) throw new LtBug(\"it should not be null\");\n                        SArrayValue arrV = (SArrayValue) targetAnno.values().get(valueAnnoF);\n                        for (Value v : arrV.values()) {\n                                if (v instanceof EnumValue && v.type().fullName().equals(ElementType.class.getName())) {\n                                        if (type.name().equals(((EnumValue) v).enumStr())) return true;\n                                }\n                        }\n                        return false;\n                }\n        }\n\n        @Override\n        public String toString() {\n                return \"@\" + fullName();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SAnnoField.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\n/**\n * annotation field\n */\npublic class SAnnoField extends SMethodDef {\n        private String name;\n        private Value defaultValue;\n        private boolean bDefaultValue; // assume it has default value, but the value will be filled later\n\n        public SAnnoField() {\n                super(LineCol.SYNTHETIC);\n        }\n\n        public void setDefaultValue(Value defaultValue) {\n                this.defaultValue = defaultValue;\n        }\n\n        public void setName(String name) {\n                this.name = name;\n        }\n\n        public void setType(STypeDef type) {\n                setReturnType(type);\n        }\n\n        public String name() {\n                return name;\n        }\n\n        public STypeDef type() {\n                return getReturnType();\n        }\n\n        public Value defaultValue() {\n                return defaultValue;\n        }\n\n        public void doesHaveDefaultValue() {\n                bDefaultValue = true;\n        }\n\n        public boolean hasDefaultValue() {\n                return defaultValue() != null || bDefaultValue;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder();\n                sb.append(getReturnType().fullName()).append(\" \").append(name).append(\"()\");\n                if (defaultValue != null) {\n                        sb.append(\" default \").append(defaultValue).append(\";\");\n                }\n                return sb.toString();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SAnnotationPresentable.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.util.List;\n\n/**\n * can have annotations\n */\npublic interface SAnnotationPresentable {\n        List<SAnno> annos();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SArrayTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.semantic.builtin.*;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * arrayTypeDef\n */\npublic class SArrayTypeDef extends STypeDef {\n        private STypeDef type;\n        private int dimension;\n\n        public SArrayTypeDef() {\n                super(LineCol.SYNTHETIC);\n        }\n\n        public void setDimension(int dimension) {\n                this.dimension = dimension;\n                rebuildFullName();\n        }\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        public STypeDef type() {\n                return type;\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return Collections.emptyList();\n        }\n\n        public int dimension() {\n                return dimension;\n        }\n\n        @Override\n        public String fullName() {\n                if (super.fullName() == null) {\n                        rebuildFullName();\n                }\n\n                return super.fullName();\n        }\n\n        private void rebuildFullName() {\n                if (null == type()) return;\n                StringBuilder sb = new StringBuilder();\n                for (int i = 0; i < dimension(); ++i) {\n                        sb.append(\"[\");\n                }\n                if (type() instanceof PrimitiveTypeDef) {\n                        if (type() instanceof ByteTypeDef) {\n                                sb.append(\"B\");\n                        } else if (type() instanceof CharTypeDef) {\n                                sb.append(\"C\");\n                        } else if (type() instanceof DoubleTypeDef) {\n                                sb.append(\"D\");\n                        } else if (type() instanceof FloatTypeDef) {\n                                sb.append(\"F\");\n                        } else if (type() instanceof IntTypeDef) {\n                                sb.append(\"I\");\n                        } else if (type() instanceof LongTypeDef) {\n                                sb.append(\"L\");\n                        } else if (type() instanceof ShortTypeDef) {\n                                sb.append(\"S\");\n                        } else if (type() instanceof BoolTypeDef) {\n                                sb.append(\"Z\");\n                        }\n                } else {\n                        sb.append(\"L\").append(type().fullName()).append(\";\");\n                }\n                setFullName(sb.toString());\n        }\n\n        @Override\n        public String toString() {\n                return fullName();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SArrayValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.util.Arrays;\n\n/**\n * array value\n */\npublic class SArrayValue implements Value {\n        private int dimension;\n        private Value[] values;\n        private SArrayTypeDef type;\n\n        public void setDimension(int dimension) {\n                this.dimension = dimension;\n        }\n\n        public void setType(SArrayTypeDef type) {\n                this.type = type;\n        }\n\n        public void setValues(Value[] values) {\n                this.values = values;\n        }\n\n        public int dimension() {\n                return dimension;\n        }\n\n        public int length() {\n                return values().length;\n        }\n\n        public Value[] values() {\n                return values;\n        }\n\n        @Override\n        public SArrayTypeDef type() {\n                return type;\n        }\n\n        @Override\n        public String toString() {\n                return Arrays.toString(values());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SClassDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * class definition\n */\npublic class SClassDef extends SRefTypeDef {\n        public static final int OBJECT = 2;\n        public static final int FUN = 1;\n        public static final int NORMAL = 0;\n\n        private final int type;\n        private final List<SConstructorDef> constructors = new ArrayList<SConstructorDef>();\n        private SClassDef parent;\n        private final List<SInterfaceDef> superInterfaces = new ArrayList<SInterfaceDef>();\n        private final List<Instruction> staticStatements = new ArrayList<Instruction>();\n        private final List<ExceptionTable> staticExceptionTable = new ArrayList<ExceptionTable>();\n        private final InvokableMeta staticInvokableMeta = new InvokableMeta();\n        private boolean isDataClass;\n\n        public SClassDef(int type, LineCol lineCol) {\n                super(lineCol);\n                if (type != OBJECT && type != FUN && type != NORMAL) throw new IllegalArgumentException();\n                this.type = type;\n        }\n\n        public void setParent(SClassDef parent) {\n                this.parent = parent;\n        }\n\n        public List<SConstructorDef> constructors() {\n                return constructors;\n        }\n\n        public SClassDef parent() {\n                return parent;\n        }\n\n        public List<SInterfaceDef> superInterfaces() {\n                return superInterfaces;\n        }\n\n        public List<Instruction> staticStatements() {\n                return staticStatements;\n        }\n\n        public List<ExceptionTable> staticExceptionTable() {\n                return staticExceptionTable;\n        }\n\n        public boolean isDataClass() {\n                return isDataClass;\n        }\n\n        public void setIsDataClass(boolean isDataClass) {\n                this.isDataClass = isDataClass;\n        }\n\n        public int classType() {\n                return type;\n        }\n\n        public InvokableMeta staticMeta() {\n                return staticInvokableMeta;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder();\n                for (SModifier m : modifiers()) {\n                        sb.append(m.toString().toLowerCase()).append(\" \");\n                }\n                sb.append(\"class \").append(fullName());\n                if (parent() != null) sb.append(\" extends \").append(parent().fullName());\n                if (!superInterfaces().isEmpty())\n                        sb.append(\" implements \");\n                boolean isFirst = true;\n                for (SInterfaceDef i : superInterfaces()) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(i.fullName());\n                }\n                return sb.toString();\n        }\n\n        @Override\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n\n                // java.lang.Object is assignable from all interface types\n                if (cls instanceof SInterfaceDef && this.fullName().equals(\"java.lang.Object\")) {\n                        return true;\n                }\n\n                if (cls instanceof SClassDef) {\n                        while (cls != null) {\n                                if (cls.equals(this)) return true;\n                                cls = ((SClassDef) cls).parent();\n                        }\n                        return false;\n                }\n                return false;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SConstructorDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\n/**\n * constructor definition\n */\npublic class SConstructorDef extends SInvokable {\n        public SConstructorDef(LineCol lineCol) {\n                super(lineCol);\n                setReturnType(VoidType.get());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SFieldDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\n/**\n * field definition\n */\npublic class SFieldDef extends SMember implements LeftValue {\n        private String name;\n        private STypeDef type;\n        private boolean alreadyAssigned = false;\n        private boolean used;\n\n        public SFieldDef(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public void setName(String name) {\n                this.name = name;\n        }\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        public String name() {\n                return name;\n        }\n\n        @Override\n        public boolean canChange() {\n                return !modifiers().contains(SModifier.FINAL);\n        }\n\n        @Override\n        public boolean alreadyAssigned() {\n                return alreadyAssigned;\n        }\n\n        @Override\n        public void assign() {\n                alreadyAssigned = true;\n                setUsed(true);\n        }\n\n        @Override\n        public boolean isUsed() {\n                return used;\n        }\n\n        @Override\n        public void setUsed(boolean used) {\n                this.used = used;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder();\n                for (SModifier mod : modifiers()) {\n                        sb.append(mod.toString().toLowerCase()).append(\" \");\n                }\n                sb.append(name()).append(\" : \").append(type().fullName());\n                return sb.toString();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SInterfaceDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.*;\n\n/**\n * interface definition\n */\npublic class SInterfaceDef extends SRefTypeDef {\n        private final List<SInterfaceDef> superInterfaces = new ArrayList<SInterfaceDef>();\n\n        private final List<Instruction> staticStatements = new ArrayList<Instruction>();\n        private final List<ExceptionTable> staticExceptionTable = new ArrayList<ExceptionTable>();\n        public InvokableMeta staticInvokableMeta = new InvokableMeta();\n\n        public SInterfaceDef(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public List<SInterfaceDef> superInterfaces() {\n                return superInterfaces;\n        }\n\n        public List<Instruction> staticStatements() {\n                return staticStatements;\n        }\n\n        public List<ExceptionTable> staticExceptionTable() {\n                return staticExceptionTable;\n        }\n\n        public InvokableMeta staticMeta() {\n                return staticInvokableMeta;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder();\n                for (SModifier m : modifiers()) {\n                        sb.append(m.toString().toLowerCase()).append(\" \");\n                }\n                sb.append(\"interface \").append(fullName());\n                if (!superInterfaces().isEmpty()) {\n                        sb.append(\" extends \");\n                }\n                boolean isFirst = true;\n                for (SInterfaceDef i : superInterfaces()) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(i.fullName());\n                }\n                return sb.toString();\n        }\n\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n                Queue<SInterfaceDef> q = new ArrayDeque<SInterfaceDef>();\n                Set<SInterfaceDef> used = new HashSet<SInterfaceDef>();\n                if (cls instanceof SClassDef) {\n                        SClassDef tmp = (SClassDef) cls;\n                        while (tmp != null) {\n                                for (SInterfaceDef it : tmp.superInterfaces()) {\n                                        if (used.add(it)) {\n                                                q.add(it);\n                                        }\n                                }\n                                tmp = tmp.parent();\n                        }\n                } else if (cls instanceof SInterfaceDef) {\n                        SInterfaceDef tmp = (SInterfaceDef) cls;\n                        q.addAll(tmp.superInterfaces());\n                }\n                while (!q.isEmpty()) {\n                        SInterfaceDef i = q.remove();\n                        if (isAssignableFrom(i)) return true;\n                        q.addAll(i.superInterfaces());\n                }\n                return false;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SInvokable.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * invokable\n */\nabstract public class SInvokable extends SMember {\n        private final List<SParameter> parameters = new ArrayList<SParameter>();\n        private STypeDef returnType;\n        private final List<Instruction> statements = new ArrayList<Instruction>();\n        private final List<ExceptionTable> exceptionTables = new ArrayList<ExceptionTable>();\n        private final InvokableMeta meta = new InvokableMeta();\n\n        public SInvokable(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public void setReturnType(STypeDef returnType) {\n                this.returnType = returnType;\n        }\n\n        public List<SParameter> getParameters() {\n                return parameters;\n        }\n\n        public STypeDef getReturnType() {\n                return returnType;\n        }\n\n        public List<Instruction> statements() {\n                return statements;\n        }\n\n        public List<ExceptionTable> exceptionTables() {\n                return exceptionTables;\n        }\n\n        public InvokableMeta meta() {\n                return meta;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SMember.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * define a member\n */\nabstract public class SMember implements SAnnotationPresentable {\n        private final List<SModifier> modifiers = new ArrayList<SModifier>();\n        private STypeDef declaringType;\n        private final List<SAnno> annos = new ArrayList<SAnno>();\n        private LineCol lineCol;\n\n        public SMember(LineCol lineCol) {\n                this.lineCol = lineCol;\n        }\n\n        public void setDeclaringType(STypeDef declaringType) {\n                this.declaringType = declaringType;\n        }\n\n        public List<SModifier> modifiers() {\n                return modifiers;\n        }\n\n        public STypeDef declaringType() {\n                return declaringType;\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return annos;\n        }\n\n        public LineCol line_col() {\n                return lineCol;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SMethodDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * method definition\n */\npublic class SMethodDef extends SInvokable {\n        private String name;\n        private final List<SMethodDef> overRide = new ArrayList<SMethodDef>();\n        private final List<SMethodDef> overridden = new ArrayList<SMethodDef>();\n\n        public SMethodDef(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public void setName(String name) {\n                this.name = name;\n        }\n\n        public String name() {\n                return name;\n        }\n\n        public List<SMethodDef> overRide() {\n                return overRide;\n        }\n\n        public List<SMethodDef> overridden() {\n                return overridden;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder();\n                for (SModifier m : modifiers()) {\n                        sb.append(m.toString().toLowerCase()).append(\" \");\n                }\n                sb.append(getReturnType().fullName()).append(\" \").append(declaringType().fullName()).append(\".\").append(name).append(\"(\");\n                boolean isFirst = true;\n                for (SParameter param : getParameters()) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(param);\n                }\n                sb.append(\")\");\n                return sb.toString();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SModifier.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\n/**\n * modifier\n */\npublic enum SModifier {\n        PUBLIC(0x0001),\n        PRIVATE(0x0002),\n        PROTECTED(0x0004),\n        STATIC(0x0008),\n        FINAL(0x0010),\n        VOLATILE(0x0040),\n        TRANSIENT(0x0080),\n        ABSTRACT(0x0400),\n        SYNTHETIC(0X1000),\n        ENUM(0x4000),\n        NATIVE(0x0100),\n        STRICT(0x0800),\n        SYNCHRONIZED(0x0020);\n\n        public final int flag;\n\n        SModifier(int flag) {\n                this.flag = flag;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SParameter.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * parameter definition\n */\npublic class SParameter implements LeftValue, SAnnotationPresentable {\n        private String name;\n        private final List<SAnno> annos = new ArrayList<SAnno>();\n        private STypeDef type;\n        private SInvokable target;\n        private boolean canChange = true;\n        private boolean notNull = false;\n        private boolean notEmpty = false;\n        private boolean used = false;\n        private boolean isCapture = false;\n\n        public void setTarget(SInvokable target) {\n                this.target = target;\n        }\n\n        public void setName(String name) {\n                this.name = name;\n        }\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        public void setCanChange(boolean canChange) {\n                this.canChange = canChange;\n        }\n\n        public boolean isNotNull() {\n                return notNull;\n        }\n\n        public void setNotNull(boolean notNull) {\n                this.notNull = notNull;\n        }\n\n        public boolean isNotEmpty() {\n                return notEmpty;\n        }\n\n        public void setNotEmpty(boolean notEmpty) {\n                this.notEmpty = notEmpty;\n        }\n\n        public String name() {\n                return name;\n        }\n\n        @Override\n        public boolean canChange() {\n                return canChange;\n        }\n\n        @Override\n        public boolean alreadyAssigned() {\n                return true;\n        }\n\n        @Override\n        public void assign() {\n                // empty implementation\n                // not required\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return annos;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        public SInvokable target() {\n                return target;\n        }\n\n        @Override\n        public String toString() {\n                String str = \"\";\n                if (!canChange()) str += \"final \";\n                str += type().fullName() + \" \" + name();\n                return str;\n        }\n\n        @Override\n        public void setUsed(boolean used) {\n                this.used = used;\n        }\n\n        @Override\n        public boolean isUsed() {\n                return used;\n        }\n\n        /**\n         * check whether the parameter is a captured param\n         *\n         * @return true/false\n         */\n        public boolean isCapture() {\n                return isCapture;\n        }\n\n        /**\n         * mark the parameter whether it's a captured param\n         *\n         * @param capture true/false\n         */\n        public void setCapture(boolean capture) {\n                isCapture = capture;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/SRefTypeDef.java",
    "content": "package lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * reference types\n */\npublic abstract class SRefTypeDef extends STypeDef {\n        private final List<SFieldDef> fields = new ArrayList<SFieldDef>();\n        private final List<SMethodDef> methods = new ArrayList<SMethodDef>();\n        private final List<SModifier> modifiers = new ArrayList<SModifier>();\n\n        public SRefTypeDef(LineCol lineCol) {\n                super(lineCol);\n        }\n\n        public List<SFieldDef> fields() {\n                return fields;\n        }\n\n        public List<SMethodDef> methods() {\n                return methods;\n        }\n\n        public List<SModifier> modifiers() {\n                return modifiers;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/STypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.semantic.builtin.NullTypeDef;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * type definition\n */\npublic class STypeDef implements SAnnotationPresentable {\n        private String pkg;\n        private String fullName;\n        private List<SAnno> annos = new ArrayList<SAnno>();\n        private final LineCol lineCol;\n\n        public STypeDef(LineCol lineCol) {\n                this.lineCol = lineCol;\n        }\n\n        public void setFullName(String fullName) {\n                this.fullName = fullName;\n        }\n\n        public void setPkg(String pkg) {\n                this.pkg = pkg;\n        }\n\n        public String fullName() {\n                return fullName;\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return annos;\n        }\n\n        public String pkg() {\n                return pkg;\n        }\n\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (cls == null) throw new NullPointerException();\n                if (cls instanceof NullTypeDef)\n                        return !(this instanceof PrimitiveTypeDef);\n                return cls.equals(this);\n        }\n\n        public LineCol line_col() {\n                return lineCol;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/Value.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport java.io.Serializable;\n\n/**\n * value\n */\npublic interface Value extends Serializable {\n        STypeDef type();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/ValueAnotherType.java",
    "content": "package lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\n/**\n * value considered as another type\n */\npublic class ValueAnotherType implements Value, Instruction {\n        private final STypeDef type;\n        private final Value value;\n        private final LineCol lineCol;\n\n        public ValueAnotherType(STypeDef type, Value value, LineCol lineCol) {\n                this.type = type;\n                this.value = value;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        public Value value() {\n                return value;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/ValuePack.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * a list of instructions that finally return a value\n */\npublic class ValuePack implements Value, Instruction {\n        private final List<Instruction> instructions = new ArrayList<Instruction>();\n        private STypeDef type;\n        private final boolean autoPop;\n\n        public ValuePack(boolean autoPop) {\n                this.autoPop = autoPop;\n        }\n\n        public boolean autoPop() {\n                return autoPop;\n        }\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return instructions.isEmpty() ? LineCol.SYNTHETIC : instructions.get(instructions.size() - 1).line_col();\n        }\n\n        @Override\n        public STypeDef type() {\n                if (type == null) {\n                        if (instructions.isEmpty()) {\n                                return null;\n                        }\n                        Instruction ins = instructions.get(instructions.size() - 1);\n                        if (ins instanceof Value) {\n                                return ((Value) ins).type();\n                        } else return null;\n                } else {\n                        return type;\n                }\n        }\n\n        public List<Instruction> instructions() {\n                return instructions;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/VoidType.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic;\n\nimport lt.compiler.LineCol;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * void type\n */\npublic class VoidType extends STypeDef {\n        private VoidType() {\n                super(LineCol.SYNTHETIC);\n        }\n\n        private static VoidType v = new VoidType();\n\n        public static VoidType get() {\n                return v;\n        }\n\n        @Override\n        public String fullName() {\n                return \"void\";\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return Collections.emptyList();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/BoolTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\n\n/**\n * boolean.class\n */\npublic class BoolTypeDef extends PrimitiveTypeDef {\n        private BoolTypeDef() {\n        }\n\n        private static BoolTypeDef t = new BoolTypeDef();\n\n        public static BoolTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"boolean\";\n        }\n\n        @Override\n        public String toString() {\n                return fullName();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/BoolValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * boolean value\n */\npublic class BoolValue implements PrimitiveValue {\n        private final boolean value;\n\n        public BoolValue(boolean value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return BoolTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                BoolValue boolValue = (BoolValue) o;\n\n                return value == boolValue.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return (value ? 1 : 0);\n        }\n\n        @Override\n        public String toString() {\n                return String.valueOf(value);\n        }\n\n        public int getValue() {\n                return value ? 1 : 0;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/ByteTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\n\n/**\n * byte.class\n */\npublic class ByteTypeDef extends PrimitiveTypeDef {\n        private ByteTypeDef() {\n        }\n\n        private static ByteTypeDef t = new ByteTypeDef();\n\n        public static ByteTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"byte\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/ByteValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * byte value\n */\npublic class ByteValue implements PrimitiveValue {\n        private final byte value;\n\n        public ByteValue(byte value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return ByteTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                ByteValue byteValue = (ByteValue) o;\n\n                return value == byteValue.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return (int) value;\n        }\n\n        @Override\n        public String toString() {\n                return Byte.toString(value);\n        }\n\n        public int getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/CharTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\n\n/**\n * char.class\n */\npublic class CharTypeDef extends PrimitiveTypeDef {\n        private CharTypeDef() {\n        }\n\n        private static CharTypeDef t = new CharTypeDef();\n\n        public static CharTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"char\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/CharValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * char value\n */\npublic class CharValue implements PrimitiveValue {\n        private final char value;\n\n        public CharValue(char value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return CharTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                CharValue charValue = (CharValue) o;\n\n                return value == charValue.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return (int) value;\n        }\n\n        @Override\n        public String toString() {\n                return Character.toString(value);\n        }\n\n        public int getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/DoubleTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * double.class\n */\npublic class DoubleTypeDef extends PrimitiveTypeDef {\n        private DoubleTypeDef() {\n        }\n\n        private static DoubleTypeDef t = new DoubleTypeDef();\n\n        public static DoubleTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"double\";\n        }\n\n        @Override\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n                // cls is float or long or assignable from float\n                return cls instanceof FloatTypeDef || FloatTypeDef.get().isAssignableFrom(cls);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/DoubleValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.ConstantValue;\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * double value\n */\npublic class DoubleValue implements PrimitiveValue, ConstantValue {\n        private final double value;\n\n        public DoubleValue(double value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return DoubleTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                DoubleValue that = (DoubleValue) o;\n\n                return Double.compare(that.value, value) == 0;\n        }\n\n        @Override\n        public int hashCode() {\n                long temp = Double.doubleToLongBits(value);\n                return (int) (temp ^ (temp >>> 32));\n        }\n\n        @Override\n        public byte[] getByte() {\n                long data = Double.doubleToLongBits(value);\n                byte[] bytes = new byte[8];\n                bytes[0] = (byte) (data & 0xff);\n                bytes[1] = (byte) ((data >> 8) & 0xff);\n                bytes[2] = (byte) ((data >> 16) & 0xff);\n                bytes[3] = (byte) ((data >> 24) & 0xff);\n                bytes[4] = (byte) ((data >> 32) & 0xff);\n                bytes[5] = (byte) ((data >> 40) & 0xff);\n                bytes[6] = (byte) ((data >> 48) & 0xff);\n                bytes[7] = (byte) ((data >> 56) & 0xff);\n                return bytes;\n        }\n\n        @Override\n        public String toString() {\n                return Double.toString(value);\n        }\n\n        public double getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/EnumValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.semantic.Value;\n\n/**\n * enum value\n */\npublic class EnumValue implements Value {\n        private String enumStr;\n        private STypeDef type;\n\n        public void setType(STypeDef type) {\n                this.type = type;\n        }\n\n        public void setEnumStr(String enumStr) {\n                this.enumStr = enumStr;\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        public String enumStr() {\n                return enumStr;\n        }\n\n        @Override\n        public String toString() {\n                return type().fullName() + \".\" + enumStr();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/FloatTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * float.class\n */\npublic class FloatTypeDef extends PrimitiveTypeDef {\n        private FloatTypeDef() {\n        }\n\n        private static FloatTypeDef t = new FloatTypeDef();\n\n        public static FloatTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"float\";\n        }\n\n        @Override\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n                // cls is int or is assignable from int\n                return cls instanceof IntTypeDef || IntTypeDef.get().isAssignableFrom(cls)\n                        || cls instanceof LongTypeDef || LongTypeDef.get().isAssignableFrom(cls);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/FloatValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.ConstantValue;\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * float value\n */\npublic class FloatValue implements PrimitiveValue, ConstantValue {\n        private final float value;\n\n        public FloatValue(float value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return FloatTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                FloatValue that = (FloatValue) o;\n\n                return Float.compare(that.value, value) == 0;\n        }\n\n        @Override\n        public int hashCode() {\n                return (value != +0.0f ? Float.floatToIntBits(value) : 0);\n        }\n\n        @Override\n        public byte[] getByte() {\n                int data = Float.floatToIntBits(value);\n                byte[] bytes = new byte[4];\n                bytes[0] = (byte) (data & 0xff);\n                bytes[1] = (byte) ((data & 0xff00) >> 8);\n                bytes[2] = (byte) ((data & 0xff0000) >> 16);\n                bytes[3] = (byte) ((data & 0xff000000) >> 24);\n                return bytes;\n        }\n\n        @Override\n        public String toString() {\n                return Float.toString(value);\n        }\n\n        public float getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/IntTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * int.class\n */\npublic class IntTypeDef extends PrimitiveTypeDef {\n        private IntTypeDef() {\n        }\n\n        private static IntTypeDef t = new IntTypeDef();\n\n        public static IntTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"int\";\n        }\n\n        @Override\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n                // cls is char/byte/short\n                return cls instanceof CharTypeDef || cls instanceof ByteTypeDef || cls instanceof ShortTypeDef;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/IntValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.ConstantValue;\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * int value\n */\npublic class IntValue implements PrimitiveValue, ConstantValue {\n        private final int value;\n\n        public IntValue(int value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return IntTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                IntValue intValue = (IntValue) o;\n\n                return value == intValue.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return value;\n        }\n\n        @Override\n        public byte[] getByte() {\n                byte[] bytes = new byte[4];\n                bytes[0] = (byte) (value & 0xff);\n                bytes[1] = (byte) ((value & 0xff00) >> 8);\n                bytes[2] = (byte) ((value & 0xff0000) >> 16);\n                bytes[3] = (byte) ((value & 0xff000000) >> 24);\n                return bytes;\n        }\n\n        @Override\n        public String toString() {\n                return Integer.toString(value);\n        }\n\n        public int getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/LongTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * long.class\n */\npublic class LongTypeDef extends PrimitiveTypeDef {\n        private LongTypeDef() {\n        }\n\n        private static LongTypeDef t = new LongTypeDef();\n\n        public static LongTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"long\";\n        }\n\n        @Override\n        public boolean isAssignableFrom(STypeDef cls) {\n                if (super.isAssignableFrom(cls)) return true;\n                // cls is int or int is assignable from cls\n                return cls instanceof IntTypeDef || IntTypeDef.get().isAssignableFrom(cls);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/LongValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.ConstantValue;\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * long value\n */\npublic class LongValue implements PrimitiveValue, ConstantValue {\n        private final long value;\n\n        public LongValue(long value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return LongTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                LongValue longValue = (LongValue) o;\n\n                return value == longValue.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return (int) (value ^ (value >>> 32));\n        }\n\n        @Override\n        public byte[] getByte() {\n                byte[] bytes = new byte[8];\n                bytes[0] = (byte) (value & 0xff);\n                bytes[1] = (byte) ((value >> 8) & 0xff);\n                bytes[2] = (byte) ((value >> 16) & 0xff);\n                bytes[3] = (byte) ((value >> 24) & 0xff);\n                bytes[4] = (byte) ((value >> 32) & 0xff);\n                bytes[5] = (byte) ((value >> 40) & 0xff);\n                bytes[6] = (byte) ((value >> 48) & 0xff);\n                bytes[7] = (byte) ((value >> 56) & 0xff);\n                return bytes;\n        }\n\n        @Override\n        public String toString() {\n                return Long.toString(value);\n        }\n\n        public long getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/NullTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.semantic.SAnno;\nimport lt.compiler.semantic.STypeDef;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * null type\n */\npublic class NullTypeDef extends STypeDef {\n        private NullTypeDef() {\n                super(LineCol.SYNTHETIC);\n        }\n\n        private static NullTypeDef t = new NullTypeDef();\n\n        public static NullTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"null\";\n        }\n\n        @Override\n        public List<SAnno> annos() {\n                return Collections.emptyList();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/NullValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.semantic.Value;\n\n/**\n * null value\n */\npublic class NullValue implements Value {\n        private NullValue() {\n        }\n\n        private static NullValue nullValue = new NullValue();\n\n        public static NullValue get() {\n                return nullValue;\n        }\n\n        @Override\n        public STypeDef type() {\n                return NullTypeDef.get();\n        }\n\n        @Override\n        public String toString() {\n                return \"null\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/ShortTypeDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveTypeDef;\n\n/**\n * short.class\n */\npublic class ShortTypeDef extends PrimitiveTypeDef {\n        private ShortTypeDef() {\n        }\n\n        private static ShortTypeDef t = new ShortTypeDef();\n\n        public static ShortTypeDef get() {\n                return t;\n        }\n\n        @Override\n        public String fullName() {\n                return \"short\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/ShortValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.PrimitiveValue;\nimport lt.compiler.semantic.STypeDef;\n\n/**\n * short value\n */\npublic class ShortValue implements PrimitiveValue {\n        private final short value;\n\n        public ShortValue(short value) {\n                this.value = value;\n        }\n\n        @Override\n        public STypeDef type() {\n                return ShortTypeDef.get();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                ShortValue that = (ShortValue) o;\n\n                return value == that.value;\n        }\n\n        @Override\n        public int hashCode() {\n                return (int) value;\n        }\n\n        @Override\n        public String toString() {\n                return Short.toString(value);\n        }\n\n        public int getValue() {\n                return value;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/builtin/StringConstantValue.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.semantic.builtin;\n\nimport lt.compiler.semantic.ConstantValue;\nimport lt.compiler.semantic.SClassDef;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.semantic.Value;\n\n/**\n *\n */\npublic class StringConstantValue implements ConstantValue, Value {\n        private final String str;\n        private STypeDef type;\n\n        public StringConstantValue(String str) {\n                this.str = str;\n        }\n\n        public void setType(SClassDef type) {\n                assert type.fullName().equals(\"java.lang.String\");\n                this.type = type;\n        }\n\n        public String getStr() {\n                return str;\n        }\n\n        @Override\n        public byte[] getByte() {\n                return str.getBytes();\n        }\n\n        @Override\n        public STypeDef type() {\n                return type;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                StringConstantValue that = (StringConstantValue) o;\n\n                return str.equals(that.str);\n\n        }\n\n        @Override\n        public int hashCode() {\n                return str.hashCode();\n        }\n\n        @Override\n        public String toString() {\n                return str;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/helper/ASTGHolder.java",
    "content": "package lt.compiler.semantic.helper;\n\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\n\nimport java.util.List;\n\npublic class ASTGHolder<S extends Statement> {\n        public final S s;\n        public final List<STypeDef> generics;\n\n\n        public ASTGHolder(S s, List<STypeDef> generics) {\n                this.s = s;\n                this.generics = generics;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                ASTGHolder<?> that = (ASTGHolder<?>) o;\n\n                if (!s.equals(that.s)) return false;\n                //\n                return generics.equals(that.generics);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = s.hashCode();\n                result = 31 * result + generics.hashCode();\n                return result;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/semantic/helper/HalfAppliedTypes.java",
    "content": "package lt.compiler.semantic.helper;\n\nimport lt.compiler.LtBug;\nimport lt.compiler.SyntaxException;\nimport lt.compiler.syntactic.AST.Access;\nimport lt.lang.function.Function1;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\npublic class HalfAppliedTypes {\n        private List<Access> types = new ArrayList<Access>();\n        private Function1<Void, Access> apply;\n\n        private void doApply(Access type) throws SyntaxException {\n                try {\n                        apply.apply(type);\n                } catch (SyntaxException e) {\n                        throw e;\n                } catch (Exception e) {\n                        throw new LtBug(e);\n                }\n        }\n\n        /**\n         * @param apply function (importList, packageName, type) -&gt; void\n         * @throws SyntaxException exception\n         */\n        public void setApply(Function1<Void, Access> apply) throws SyntaxException {\n                this.apply = apply;\n                for (Access t : types) {\n                        doApply(t);\n                }\n        }\n\n        public void add(Access type) throws SyntaxException {\n                types.add(type);\n                if (apply != null) {\n                        doApply(type);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/AST.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.def.VariableDef;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.io.Serializable;\nimport java.util.ArrayList;\nimport java.util.LinkedHashMap;\nimport java.util.List;\nimport java.util.Set;\n\nimport static lt.compiler.CompileUtil.visitStmt;\n\n/**\n * a file containing all node definitions of the ast tree<br>\n */\npublic class AST {\n        private AST() {\n        }\n\n        /**\n         * access\n         */\n        public static class Access implements Expression {\n                public final Expression exp;\n                public final String name;\n                public final List<Access> generics = new ArrayList<Access>(); // len = 0 means no generic\n                private final LineCol lineCol;\n\n                public Access(Expression exp, String name, LineCol lineCol) {\n                        this.exp = exp;\n                        this.name = name;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + (exp == null ? \"\" : exp) + ((exp != null && name != null) ? \".\" : \"\") + (name == null ? \"\" : name) + (generics.size() == 0 ? \"\" : \"<:\" + generics.toString() + \":>\") + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Access access = (Access) o;\n\n                        return (exp != null ? exp.equals(access.exp) : access.exp == null) && (name != null ? name.equals(access.name) : access.name == null) && generics.equals(access.generics);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = exp != null ? exp.hashCode() : 0;\n                        result = 31 * result + (name != null ? name.hashCode() : 0);\n                        result = 31 * result + generics.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                        visitStmt(generics, f, t);\n                }\n        }\n\n        /**\n         * annotation instance\n         */\n        public static class Anno implements Statement {\n                public final Access anno;\n                public final List<Assignment> args;\n                private final LineCol lineCol;\n\n                public Anno(Access anno, List<Assignment> args, LineCol lineCol) {\n                        this.anno = anno;\n                        this.args = args;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"(@\");\n                        sb.append(anno);\n                        if (!args.isEmpty()) {\n                                sb.append(\"(\");\n                                boolean isFirst = true;\n                                for (Assignment a : args) {\n                                        if (isFirst) {\n                                                isFirst = false;\n                                        } else {\n                                                sb.append(\",\");\n                                        }\n                                        sb.append(a);\n                                }\n                                sb.append(\")\");\n                        }\n                        sb.append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Anno anno1 = (Anno) o;\n\n                        if (!anno.equals(anno1.anno)) return false;\n                        //\n                        return args.equals(anno1.args);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = anno.hashCode();\n                        result = 31 * result + args.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(anno, f, t);\n                        visitStmt(args, f, t);\n                }\n        }\n\n        /**\n         * annotation as expression\n         */\n        public static class AnnoExpression implements Expression {\n                public final Anno anno;\n\n                public AnnoExpression(Anno anno) {\n                        this.anno = anno;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return anno.line_col();\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(anno, f, t);\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        AnnoExpression that = (AnnoExpression) o;\n\n                        return anno != null ? anno.equals(that.anno) : that.anno == null;\n                }\n\n                @Override\n                public int hashCode() {\n                        return anno != null ? anno.hashCode() : 0;\n                }\n\n                @Override\n                public String toString() {\n                        return anno.toString();\n                }\n        }\n\n        /**\n         * array expression\n         */\n        public static class ArrayExp implements Expression {\n                public final List<Expression> list;\n                private final LineCol lineCol;\n\n                public ArrayExp(List<Expression> list, LineCol lineCol) {\n                        this.list = list;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"[\");\n                        boolean isFirst = true;\n                        for (Expression e : list) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(e);\n                        }\n                        sb.append(\"]\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        ArrayExp arrayExp = (ArrayExp) o;\n\n                        return list.equals(arrayExp.list);\n                }\n\n                @Override\n                public int hashCode() {\n                        return list.hashCode();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(list, f, t);\n                }\n        }\n\n        /**\n         * assignment assignTo = assignFrom\n         */\n        public static class Assignment implements Expression {\n                public final Access assignTo;\n                public final String op;\n                public final Expression assignFrom;\n                private final LineCol lineCol;\n\n                public Assignment(Access assignTo, String op, Expression assignFrom, LineCol lineCol) {\n                        this.assignTo = assignTo;\n                        this.op = op;\n                        this.assignFrom = assignFrom;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"Assignment(\" + assignTo + \" \" + op + \" \" + assignFrom + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Assignment that = (Assignment) o;\n\n                        if (!assignTo.equals(that.assignTo)) return false;\n                        if (!op.equals(that.op)) return false;\n                        //\n                        return assignFrom.equals(that.assignFrom);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = assignTo.hashCode();\n                        result = 31 * result + op.hashCode();\n                        result = 31 * result + assignFrom.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(assignTo, f, t);\n                        visitStmt(assignFrom, f, t);\n                }\n        }\n\n        /**\n         * as type<br>\n         * exp as Type\n         */\n        public static class AsType implements Expression {\n                public final Expression exp;\n                public final Access type;\n                private final LineCol lineCol;\n\n                public AsType(Expression exp, Access type, LineCol lineCol) {\n                        this.exp = exp;\n                        this.type = type;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + exp + \" as \" + type + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        AsType asType = (AsType) o;\n\n                        if (!exp.equals(asType.exp)) return false;\n                        //\n                        return type.equals(asType.type);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = exp.hashCode();\n                        result = 31 * result + type.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                        visitStmt(type, f, t);\n                }\n        }\n\n        public static class Destruct implements Expression {\n                public final Set<Modifier> modifiers;\n                public final Set<Anno> annos;\n                public final Pattern_Destruct pattern;\n                public final Expression exp;\n                private final LineCol lineCol;\n\n                public Destruct(Set<Modifier> modifiers, Set<Anno> annos, Pattern_Destruct pattern, Expression exp, LineCol lineCol) {\n                        this.modifiers = modifiers;\n                        this.annos = annos;\n                        this.pattern = pattern;\n                        this.exp = exp;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(modifiers, f, t);\n                        visitStmt(annos, f, t);\n                        visitStmt(pattern, f, t);\n                        visitStmt(exp, f, t);\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Destruct destruct = (Destruct) o;\n\n                        if (!modifiers.equals(destruct.modifiers)) return false;\n                        if (!annos.equals(destruct.annos)) return false;\n                        if (!pattern.equals(destruct.pattern)) return false;\n                        //\n                        return exp.equals(destruct.exp);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = modifiers.hashCode();\n                        result = 31 * result + annos.hashCode();\n                        result = 31 * result + pattern.hashCode();\n                        result = 31 * result + exp.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + annos + \" \" + modifiers + \" \" + pattern + \" <- \" + exp + ')';\n                }\n        }\n\n        /**\n         * pattern\n         */\n        public abstract static class Pattern implements Statement, Serializable {\n                public final PatternType patternType;\n\n                public Pattern(PatternType patternType) {\n                        this.patternType = patternType;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Pattern pattern = (Pattern) o;\n\n                        return patternType == pattern.patternType;\n\n                }\n\n                @Override\n                public int hashCode() {\n                        return patternType.hashCode();\n                }\n\n                @Override\n                public String toString() {\n                        return \"Pattern(\" + patternType + \")\";\n                }\n\n                @Override\n                public LineCol line_col() {\n                        throw new UnsupportedOperationException();\n                }\n        }\n\n        public static class Pattern_Default extends Pattern {\n                private static final Pattern_Default def = new Pattern_Default();\n\n                public static Pattern_Default get() {\n                        return def;\n                }\n\n                private Pattern_Default() {\n                        super(PatternType.DEFAULT);\n                }\n\n                @Override\n                public String toString() {\n                        return \"(_)\";\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // nothing to visit\n                }\n        }\n\n        /**\n         * something like\n         * case _:XXX\n         */\n        public static class Pattern_Type extends Pattern {\n                public final Access type;\n\n                public Pattern_Type(Access type) {\n                        super(PatternType.TYPE);\n                        this.type = type;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n                        if (!super.equals(o)) return false;\n\n                        Pattern_Type that = (Pattern_Type) o;\n\n                        return type.equals(that.type);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = super.hashCode();\n                        result = 31 * result + type.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(_:\" + type + \")\";\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(type, f, t);\n                }\n        }\n\n        /**\n         * explicit value\n         */\n        public static class Pattern_Value extends Pattern {\n                public final Expression exp;\n\n                public Pattern_Value(Expression exp) {\n                        super(PatternType.VALUE);\n                        this.exp = exp;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n                        if (!super.equals(o)) return false;\n\n                        Pattern_Value that = (Pattern_Value) o;\n\n                        return exp.equals(that.exp);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = super.hashCode();\n                        result = 31 * result + exp.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + exp + \")\";\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                }\n        }\n\n        /**\n         * destruct:\n         * case Bean(_, a, 1)\n         */\n        public static class Pattern_Destruct extends Pattern {\n                public final Access type;\n                public final List<Pattern> subPatterns;\n\n                public Pattern_Destruct(Access type, List<Pattern> subPatterns) {\n                        super(PatternType.DESTRUCT);\n                        this.type = type;\n                        this.subPatterns = subPatterns;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n                        if (!super.equals(o)) return false;\n\n                        Pattern_Destruct that = (Pattern_Destruct) o;\n\n                        if (type != null ? !type.equals(that.type) : that.type != null) return false;\n                        //\n                        return subPatterns.equals(that.subPatterns);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = super.hashCode();\n                        result = 31 * result + (type != null ? type.hashCode() : 0);\n                        result = 31 * result + subPatterns.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + type + subPatterns + \")\";\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(type, f, t);\n                        visitStmt(subPatterns, f, t);\n                }\n        }\n\n        public static class Pattern_Define extends Pattern {\n                public final String name;\n                public final Access type;\n\n                public Pattern_Define(String name, Access type) {\n                        super(PatternType.DEFINE);\n                        this.name = name;\n                        this.type = type;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n                        if (!super.equals(o)) return false;\n\n                        Pattern_Define that = (Pattern_Define) o;\n\n                        if (!name.equals(that.name)) return false;\n                        //\n                        return type != null ? type.equals(that.type) : that.type == null;\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = super.hashCode();\n                        result = 31 * result + name.hashCode();\n                        result = 31 * result + (type != null ? type.hashCode() : 0);\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + name + \":\" + type + \")\";\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(type, f, t);\n                }\n        }\n\n        public enum PatternType {\n                TYPE, VALUE, DESTRUCT, DEFAULT, DEFINE\n        }\n\n        public static class PatternCondition implements Statement {\n                public final Pattern pattern;\n                public final Expression condition;\n\n                public PatternCondition(Pattern pattern, Expression condition) {\n                        this.pattern = pattern;\n                        this.condition = condition;\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        PatternCondition that = (PatternCondition) o;\n\n                        if (!pattern.equals(that.pattern)) return false;\n                        //\n                        return condition != null ? condition.equals(that.condition) : that.condition == null;\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = pattern.hashCode();\n                        result = 31 * result + (condition != null ? condition.hashCode() : 0);\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + pattern + \" if \" + condition + \")\";\n                }\n\n                @Override\n                public LineCol line_col() {\n                        throw new UnsupportedOperationException();\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(pattern, f, t);\n                        visitStmt(condition, f, t);\n                }\n        }\n\n        /**\n         * pattern matching\n         */\n        public static class PatternMatching implements Expression {\n                public final Expression expToMatch;\n                public final LinkedHashMap<PatternCondition, List<Statement>> patternsToStatements;\n                private final LineCol lineCol;\n\n                public PatternMatching(Expression expToMatch, LinkedHashMap<PatternCondition, List<Statement>> patternsToStatements, LineCol lineCol) {\n                        this.expToMatch = expToMatch;\n                        this.patternsToStatements = patternsToStatements;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(expToMatch, f, t);\n                        visitStmt(patternsToStatements.keySet(), f, t);\n                        for (List<Statement> l : patternsToStatements.values()) {\n                                visitStmt(l, f, t);\n                        }\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        PatternMatching that = (PatternMatching) o;\n\n                        if (!expToMatch.equals(that.expToMatch)) return false;\n                        //\n                        return patternsToStatements.equals(that.patternsToStatements);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = expToMatch.hashCode();\n                        result = 31 * result + patternsToStatements.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"PatternMatching(\" + expToMatch +\n                                \", \" + patternsToStatements + ')';\n                }\n        }\n\n        /**\n         * procedure\n         */\n        public static class Procedure implements Expression {\n                public final List<Statement> statements;\n                private final LineCol lineCol;\n\n                public Procedure(List<Statement> statements, LineCol lineCol) {\n                        this.statements = statements;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + statements + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Procedure procedure = (Procedure) o;\n\n                        return statements.equals(procedure.statements);\n                }\n\n                @Override\n                public int hashCode() {\n                        return statements.hashCode();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(statements, f, t);\n                }\n        }\n\n        /**\n         * for expression\n         */\n        public static class For implements Statement {\n                public final String name;\n                public final Expression exp;\n                public final List<Statement> body;\n                private final LineCol lineCol;\n\n                public For(String name, Expression exp, List<Statement> body, LineCol lineCol) {\n                        this.name = name;\n                        this.exp = exp;\n                        this.body = body;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + \"for \" + name + \" @ \" + exp + \" \" + body + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        For aFor = (For) o;\n\n                        return !(name != null ? !name.equals(aFor.name) : aFor.name != null) && !(exp != null ? !exp.equals(aFor.exp) : aFor.exp != null) && !(body != null ? !body.equals(aFor.body) : aFor.body != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = name != null ? name.hashCode() : 0;\n                        result = 31 * result + (exp != null ? exp.hashCode() : 0);\n                        result = 31 * result + (body != null ? body.hashCode() : 0);\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                        visitStmt(body, f, t);\n                }\n        }\n\n        /**\n         * specifying a generator\n         */\n        public static class GeneratorSpec implements Expression {\n                public final Access type;\n                public final List<Statement> ast;\n                private final LineCol lineCol;\n\n                public GeneratorSpec(Access type, List<Statement> ast, LineCol lineCol) {\n                        this.type = type;\n                        this.ast = ast;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(type, f, t);\n                        visitStmt(ast, f, t);\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        GeneratorSpec that = (GeneratorSpec) o;\n\n                        if (!type.equals(that.type)) return false;\n                        //\n                        return ast.equals(that.ast);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = type.hashCode();\n                        result = 31 * result + ast.hashCode();\n                        return result;\n                }\n\n                @Override\n                public String toString() {\n                        return \"GenSpec#\" + type + \"(\" + ast + \")\";\n                }\n        }\n\n        /**\n         * if exp\n         */\n        public static class If implements Statement {\n                public static class IfPair implements Statement {\n                        public final Expression condition;\n                        public final List<Statement> body;\n                        public final LineCol lineCol;\n\n                        public IfPair(Expression condition, List<Statement> body, LineCol lineCol) {\n                                this.body = body;\n                                this.condition = condition;\n                                this.lineCol = lineCol;\n                        }\n\n                        @Override\n                        public boolean equals(Object o) {\n                                if (this == o) return true;\n                                if (o == null || getClass() != o.getClass()) return false;\n\n                                IfPair pair = (IfPair) o;\n\n                                return !(condition != null ? !condition.equals(pair.condition) : pair.condition != null) && !(body != null ? !body.equals(pair.body) : pair.body != null);\n                        }\n\n                        @Override\n                        public int hashCode() {\n                                int result = condition != null ? condition.hashCode() : 0;\n                                result = 31 * result + (body != null ? body.hashCode() : 0);\n                                return result;\n                        }\n\n                        @Override\n                        public LineCol line_col() {\n                                throw new UnsupportedOperationException();\n                        }\n\n                        @Override\n                        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                                visitStmt(condition, f, t);\n                                visitStmt(body, f, t);\n                        }\n                }\n\n                public List<IfPair> ifs;\n                private final LineCol lineCol;\n\n                public If(List<IfPair> ifs, LineCol lineCol) {\n                        this.ifs = ifs;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"(\");\n\n                        boolean isFirst = true;\n                        for (IfPair pair : ifs) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                        sb.append(\"(if (\").append(pair.condition).append(\")\").append(pair.body).append(\")\");\n                                } else {\n                                        if (pair.condition == null) {\n                                                sb.append(\"(else \").append(pair.body).append(\")\");\n                                        } else {\n                                                sb.append(\"(elseif (\").append(pair.condition).append(\")\").append(pair.body).append(\")\");\n                                        }\n                                }\n                        }\n\n                        sb.append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(ifs, f, t);\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        If anIf = (If) o;\n\n                        return !(ifs != null ? !ifs.equals(anIf.ifs) : anIf.ifs != null);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        return ifs != null ? ifs.hashCode() : 0;\n                }\n        }\n\n        /**\n         * index access\n         */\n        public static class Index implements Expression {\n                public final Expression exp;\n                public final List<Expression> args;\n                private final LineCol lineCol;\n\n                public Index(Expression exp, List<Expression> args, LineCol lineCol) {\n                        this.exp = exp;\n                        this.args = args;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"(\").append(exp).append(\"[\");\n                        boolean isFirst = true;\n                        for (Expression e : args) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(e);\n                        }\n                        sb.append(\"]\").append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Index index = (Index) o;\n\n                        if (!exp.equals(index.exp)) return false;\n                        //\n                        return args.equals(index.args);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = exp.hashCode();\n                        result = 31 * result + args.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                        visitStmt(args, f, t);\n                }\n        }\n\n        /**\n         * invocation of methods/constructors\n         */\n        public static class Invocation implements Expression {\n                public final Expression exp;\n                public final List<Expression> args;\n                public final boolean invokeWithNames;\n                private final LineCol lineCol;\n\n                public Invocation(Expression exp, List<Expression> args, boolean invokeWithNames, LineCol lineCol) {\n                        this.exp = exp;\n                        this.invokeWithNames = invokeWithNames;\n                        this.lineCol = lineCol;\n                        this.args = args;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"Invocation(\");\n                        sb.append(exp);\n                        sb.append(\"(\");\n                        boolean isFirst = true;\n                        for (Expression e : args) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(e);\n                        }\n                        sb.append(\")\");\n                        sb.append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Invocation that = (Invocation) o;\n\n                        if (invokeWithNames != that.invokeWithNames) return false;\n                        if (exp != null ? !exp.equals(that.exp) : that.exp != null) return false;\n                        //\n                        return !(args != null ? !args.equals(that.args) : that.args != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = exp != null ? exp.hashCode() : 0;\n                        result = 31 * result + (args != null ? args.hashCode() : 0);\n                        result = 31 * result + (invokeWithNames ? 1 : 0);\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                        visitStmt(args, f, t);\n                }\n        }\n\n        /**\n         * lambda expression\n         */\n        public static class Lambda implements Expression {\n                public final List<VariableDef> params;\n                public final List<Statement> statements;\n                private final LineCol lineCol;\n\n                public Lambda(List<VariableDef> params, List<Statement> statements, LineCol lineCol) {\n                        this.params = params;\n                        this.statements = statements;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"Lambda((\");\n                        boolean isFirst = true;\n                        for (VariableDef v : params) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(v);\n                        }\n                        sb.append(\")->\").append(statements).append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Lambda lambda = (Lambda) o;\n\n                        return !(params != null ? !params.equals(lambda.params) : lambda.params != null) && !(statements != null ? !statements.equals(lambda.statements) : lambda.statements != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = params != null ? params.hashCode() : 0;\n                        result = 31 * result + (statements != null ? statements.hashCode() : 0);\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(params, f, t);\n                        visitStmt(statements, f, t);\n                }\n        }\n\n        /**\n         * map expression\n         */\n        public static class MapExp implements Expression {\n                public final LinkedHashMap<Expression, Expression> map;\n                private final LineCol lineCol;\n\n                public MapExp(LinkedHashMap<Expression, Expression> map, LineCol lineCol) {\n                        this.map = map;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"{\");\n                        boolean isFirst = true;\n                        for (Expression e : map.keySet()) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(e).append(\":\").append(map.get(e));\n                        }\n                        sb.append(\"}\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        MapExp mapExp = (MapExp) o;\n\n                        return map.equals(mapExp.map);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        return map.hashCode();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(map.keySet(), f, t);\n                        visitStmt(map.values(), f, t);\n                }\n        }\n\n        /**\n         * new\n         */\n        public static class New implements Expression {\n                public final Invocation invocation;\n                private final LineCol lineCol;\n\n                public New(Invocation invocation, LineCol lineCol) {\n                        this.invocation = invocation;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(invocation, f, t);\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        New aNew = (New) o;\n\n                        return invocation.equals(aNew.invocation);\n                }\n\n                @Override\n                public int hashCode() {\n                        return invocation.hashCode();\n                }\n        }\n\n        /**\n         * null value\n         */\n        public static class Null implements Expression {\n                private final LineCol lineCol;\n\n                public Null(LineCol lineCol) {\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public boolean equals(Object obj) {\n                        return obj instanceof Null;\n                }\n\n                @Override\n                public int hashCode() {\n                        return 0;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(null)\";\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // nothing to visit\n                }\n        }\n\n        /**\n         * package\n         */\n        public static class PackageRef implements Expression {\n                public final String pkg;\n                private final LineCol lineCol;\n\n                public PackageRef(String pkg, LineCol lineCol) {\n                        this.pkg = pkg;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(\" + pkg + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        PackageRef that = (PackageRef) o;\n\n                        return !(pkg != null ? !pkg.equals(that.pkg) : that.pkg != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        return pkg != null ? pkg.hashCode() : 0;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // nothing to visit\n                }\n        }\n\n        /**\n         * pass\n         */\n        public static class Pass implements Statement {\n                private final LineCol lineCol;\n\n                public Pass(LineCol lineCol) {\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public boolean equals(Object obj) {\n                        return obj instanceof Pass;\n                }\n\n                @Override\n                public int hashCode() {\n                        return 0;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(...)\";\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // nothing to visit\n                }\n        }\n\n        /**\n         * require a lt file\n         */\n        public static class Require implements Expression {\n                public final Expression required;\n                private final LineCol lineCol;\n\n                public Require(Expression required, LineCol lineCol) {\n                        this.required = required;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(required, f, t);\n                }\n        }\n\n        /**\n         * return statement\n         */\n        public static class Return implements Statement {\n                public final Expression exp;\n                private final LineCol lineCol;\n\n                public Return(Expression exp, LineCol lineCol) {\n                        this.exp = exp;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"Return(\" + exp + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Return aReturn = (Return) o;\n\n                        return !(exp != null ? !exp.equals(aReturn.exp) : aReturn.exp != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        return exp != null ? exp.hashCode() : 0;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                }\n        }\n\n        /**\n         * static scope\n         */\n        public static class StaticScope implements Statement {\n                public final List<Statement> statements;\n                private final LineCol lineCol;\n\n                public StaticScope(List<Statement> statements, LineCol lineCol) {\n                        this.statements = statements;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"Static(\" + statements + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        StaticScope that = (StaticScope) o;\n\n                        return !(statements != null ? !statements.equals(that.statements) : that.statements != null);\n\n                }\n\n                @Override\n                public int hashCode() {\n                        return statements != null ? statements.hashCode() : 0;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(statements, f, t);\n                }\n        }\n\n        /**\n         * synchronized\n         */\n        public static class Synchronized implements Statement {\n                public final List<Expression> toSync;\n                public final List<Statement> statements;\n                private final LineCol lineCol;\n\n                public Synchronized(List<Expression> toSync, List<Statement> statements, LineCol lineCol) {\n                        this.toSync = toSync;\n                        this.statements = statements;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"(sync (\");\n                        boolean isFirst = true;\n                        for (Expression e : toSync) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(e);\n                        }\n                        sb.append(\") \").append(statements).append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Synchronized that = (Synchronized) o;\n\n                        if (!toSync.equals(that.toSync)) return false;\n                        //\n                        return statements.equals(that.statements);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = toSync.hashCode();\n                        result = 31 * result + statements.hashCode();\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(toSync, f, t);\n                        visitStmt(statements, f, t);\n                }\n        }\n\n        /**\n         * throw\n         */\n        public static class Throw implements Statement {\n                public final Expression exp;\n                private final LineCol lineCol;\n\n                public Throw(Expression exp, LineCol lineCol) {\n                        this.exp = exp;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(throw \" + exp + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Throw aThrow = (Throw) o;\n\n                        return exp.equals(aThrow.exp);\n                }\n\n                @Override\n                public int hashCode() {\n                        return exp.hashCode();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(exp, f, t);\n                }\n        }\n\n        /**\n         * try\n         */\n        public static class Try implements Statement {\n                public final List<Statement> statements;\n                public final List<Statement> catchStatements;\n                public final String varName;\n                public final List<Statement> fin;\n                private final LineCol lineCol;\n\n                public Try(List<Statement> statements, String varName, List<Statement> catchStatements, List<Statement> fin, LineCol lineCol) {\n                        this.statements = statements;\n                        this.catchStatements = catchStatements;\n                        this.varName = varName;\n                        this.fin = fin;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(try \" + statements + \" catch \" + varName + \" \" + catchStatements + \" finally \" + fin + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        Try aTry = (Try) o;\n\n                        if (statements != null ? !statements.equals(aTry.statements) : aTry.statements != null)\n                                return false;\n                        if (catchStatements != null ? !catchStatements.equals(aTry.catchStatements) : aTry.catchStatements != null)\n                                return false;\n                        if (varName != null ? !varName.equals(aTry.varName) : aTry.varName != null) return false;\n                        //\n                        return !(fin != null ? !fin.equals(aTry.fin) : aTry.fin != null);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = statements != null ? statements.hashCode() : 0;\n                        result = 31 * result + (catchStatements != null ? catchStatements.hashCode() : 0);\n                        result = 31 * result + (varName != null ? varName.hashCode() : 0);\n                        result = 31 * result + (fin != null ? fin.hashCode() : 0);\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(statements, f, t);\n                        visitStmt(catchStatements, f, t);\n                        visitStmt(fin, f, t);\n                }\n        }\n\n        /**\n         * type\n         */\n        public static class TypeOf implements Expression {\n                public final Access type;\n                private final LineCol lineCol;\n\n                public TypeOf(Access type, LineCol lineCol) {\n                        this.type = type;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        return \"(type \" + type + \")\";\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        TypeOf typeOf = (TypeOf) o;\n\n                        return type.equals(typeOf.type);\n                }\n\n                @Override\n                public int hashCode() {\n                        return type.hashCode();\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(type, f, t);\n                }\n        }\n\n        /**\n         * while\n         */\n        public static class While implements Statement {\n                public final Expression condition;\n                public final List<Statement> statements;\n                public final boolean doWhile;\n                private final LineCol lineCol;\n\n                public While(Expression condition, List<Statement> statements, boolean doWhile, LineCol lineCol) {\n                        this.condition = condition;\n                        this.statements = statements;\n                        this.doWhile = doWhile;\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public String toString() {\n                        StringBuilder sb = new StringBuilder(\"(\");\n                        if (doWhile) {\n                                sb.append(\"do \").append(statements).append(\" while \").append(condition);\n                        } else {\n                                sb.append(\"while \").append(condition).append(\" \").append(statements);\n                        }\n                        sb.append(\")\");\n                        return sb.toString();\n                }\n\n                @Override\n                public boolean equals(Object o) {\n                        if (this == o) return true;\n                        if (o == null || getClass() != o.getClass()) return false;\n\n                        While aWhile = (While) o;\n\n                        if (doWhile != aWhile.doWhile) return false;\n                        if (!condition.equals(aWhile.condition)) return false;\n                        //\n                        return statements.equals(aWhile.statements);\n                }\n\n                @Override\n                public int hashCode() {\n                        int result = condition.hashCode();\n                        result = 31 * result + statements.hashCode();\n                        result = 31 * result + (doWhile ? 1 : 0);\n                        return result;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        visitStmt(condition, f, t);\n                        visitStmt(statements, f, t);\n                }\n        }\n\n        /**\n         * continue statement\n         */\n        public static class Continue implements Statement {\n                private final LineCol lineCol;\n\n                public Continue(LineCol lineCol) {\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // do nothing\n                }\n        }\n\n        /**\n         * break statement\n         */\n        public static class Break implements Statement {\n                private final LineCol lineCol;\n\n                public Break(LineCol lineCol) {\n                        this.lineCol = lineCol;\n                }\n\n                @Override\n                public LineCol line_col() {\n                        return lineCol;\n                }\n\n                @Override\n                public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                        // do nothing\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Definition.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\n/**\n * definition\n */\npublic interface Definition extends Statement {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/DuplicateVariableNameException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.SyntaxException;\n\n/**\n * duplicate variable name\n */\npublic class DuplicateVariableNameException extends SyntaxException {\n        public DuplicateVariableNameException(String lineMsg, String name, LineCol lineCol) {\n                super(lineMsg, \"duplicate name \" + name, lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Expression.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\n/**\n * expression\n */\npublic interface Expression extends Statement {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Literal.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\n\n/**\n * literal \"string\", 'string', 1, 2.3, true/false/yes/no\n */\npublic abstract class Literal implements Expression {\n        public static final int NUMBER = 0;\n        public static final int STRING = 1;\n        public static final int BOOL = 2;\n        public static final int REGEX = 3;\n\n        private int type;\n        private String literal;\n\n        private final LineCol lineCol;\n\n        public Literal(int type, String literal, LineCol lineCol) {\n                this.type = type;\n                this.literal = literal;\n                this.lineCol = lineCol;\n        }\n\n        public int type() {\n                return type;\n        }\n\n        public String literal() {\n                return literal;\n        }\n\n        @Override\n        public String toString() {\n                return literal;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                Literal literal1 = (Literal) o;\n\n                return type == literal1.type && !(literal != null ? !literal.equals(literal1.literal) : literal1.literal != null);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = type;\n                result = 31 * result + (literal != null ? literal.hashCode() : 0);\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Operation.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport java.util.List;\n\n/**\n * operation + - * /\n */\npublic interface Operation extends Expression {\n        /**\n         * the operator string\n         *\n         * @return operator\n         */\n        String operator();\n\n        /**\n         * expressions to the operator\n         *\n         * @return an immutable list containing expressions\n         */\n        List<Expression> expressions();\n\n        /**\n         * the index of expression to invoke this operation on\n         *\n         * @return index of expression\n         */\n        int invokeOn();\n\n        /**\n         * the operator is an unary operator\n         *\n         * @return true/false\n         */\n        boolean isUnary();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Pre.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\n/**\n * pre\n */\npublic interface Pre extends Statement {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/Statement.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\nimport lt.lang.function.Function2;\n\nimport java.io.Serializable;\n\n/**\n * statement\n */\npublic interface Statement extends Serializable {\n        LineCol line_col();\n\n        /**\n         * travel through the ast\n         *\n         * @param f   a function takes current statement and a context object\n         * @param t   the context object\n         * @param <T> context type\n         * @throws Exception any exception\n         */\n        <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/UnexpectedNewLayerException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.SyntaxException;\n\n/**\n * unexpected new layer. which means there's an unexpected ElementStartNode\n */\npublic class UnexpectedNewLayerException extends SyntaxException {\n        public UnexpectedNewLayerException(String lineMsg, LineCol lineCol) {\n                super(lineMsg, \"unexpected new layer\", lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/UnknownTokenException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.SyntaxException;\n\n/**\n * unknown token\n */\npublic class UnknownTokenException extends SyntaxException {\n        public UnknownTokenException(String lineMsg, String token, LineCol lineCol) {\n                super(lineMsg, \"unknown token \" + token, lineCol);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/AnnotationDef.java",
    "content": "package lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * annotation type def\n */\npublic class AnnotationDef implements Statement {\n        public final String name;\n        public final Set<AST.Anno> annos;\n        public final List<Statement> stmts;\n        private final LineCol lineCol;\n\n        public AnnotationDef(String name, Set<AST.Anno> annos, List<Statement> stmts, LineCol lineCol) {\n                this.name = name;\n                this.annos = annos;\n                this.stmts = stmts;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(annos, f, t);\n                CompileUtil.visitStmt(stmts, f, t);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                AnnotationDef that = (AnnotationDef) o;\n\n                if (!name.equals(that.name)) return false;\n                if (!annos.equals(that.annos)) return false;\n                //\n                return stmts.equals(that.stmts);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + annos.hashCode();\n                result = 31 * result + stmts.hashCode();\n                return result;\n        }\n\n        @Override\n        public String toString() {\n                return \"((\" + annos + \") annotation \" + name + \"( \" + stmts + \" ))\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/ClassDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function1;\nimport lt.lang.function.Function2;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * class definition\n */\npublic class ClassDef implements Definition {\n        public final String name;\n        public final List<AST.Access> generics;\n        public final Set<Modifier> modifiers;\n        public final List<VariableDef> params;\n        public final AST.Invocation superWithInvocation;\n        public final List<AST.Access> superWithoutInvocation;\n        public final Set<AST.Anno> annos;\n        public final List<Statement> statements;\n\n        private final LineCol lineCol;\n\n        public ClassDef(String name, List<AST.Access> generics, Set<Modifier> modifiers, List<VariableDef> params, AST.Invocation superWithInvocation, List<AST.Access> superWithoutInvocation, Set<AST.Anno> annos, List<Statement> statements, LineCol lineCol) {\n                this.name = name;\n                this.generics = generics;\n                this.lineCol = lineCol;\n                this.modifiers = new HashSet<Modifier>(modifiers);\n                this.params = params;\n                this.superWithInvocation = superWithInvocation;\n                this.superWithoutInvocation = superWithoutInvocation;\n                this.annos = new HashSet<AST.Anno>(annos);\n                this.statements = statements;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"(\");\n                for (AST.Anno anno : annos) {\n                        sb.append(anno).append(\" \");\n                }\n                for (Modifier m : modifiers) {\n                        sb.append(m).append(\" \");\n                }\n                sb.append(\"class \").append(name);\n                if (!generics.isEmpty()) {\n                        sb.append(\"<:\").append(generics).append(\":>\");\n                }\n                sb.append(\"(\");\n                boolean isFirst = true;\n                for (VariableDef v : params) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(v);\n                }\n                sb.append(\")\");\n                if (superWithInvocation != null || !superWithoutInvocation.isEmpty()) {\n                        sb.append(\" : \");\n                }\n\n                isFirst = true;\n                if (superWithInvocation != null) {\n                        sb.append(superWithInvocation);\n                        isFirst = false;\n                }\n                for (AST.Access a : superWithoutInvocation) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(a);\n                }\n\n                sb.append(\" \").append(statements).append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                ClassDef classDef = (ClassDef) o;\n\n                if (!name.equals(classDef.name)) return false;\n                if (!generics.equals(classDef.generics)) return false;\n                if (!modifiers.equals(classDef.modifiers)) return false;\n                if (!params.equals(classDef.params)) return false;\n                if (superWithInvocation != null ? !superWithInvocation.equals(classDef.superWithInvocation) : classDef.superWithInvocation != null)\n                        return false;\n                if (!superWithoutInvocation.equals(classDef.superWithoutInvocation)) return false;\n                if (!annos.equals(classDef.annos)) return false;\n                //\n                return statements.equals(classDef.statements);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + generics.hashCode();\n                result = 31 * result + modifiers.hashCode();\n                result = 31 * result + params.hashCode();\n                result = 31 * result + (superWithInvocation != null ? superWithInvocation.hashCode() : 0);\n                result = 31 * result + superWithoutInvocation.hashCode();\n                result = 31 * result + annos.hashCode();\n                result = 31 * result + statements.hashCode();\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(generics, f, t);\n                CompileUtil.visitStmt(modifiers, f, t);\n                CompileUtil.visitStmt(params, f, t);\n                CompileUtil.visitStmt(superWithInvocation, f, t);\n                CompileUtil.visitStmt(superWithoutInvocation, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n                CompileUtil.visitStmt(statements, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/FunDef.java",
    "content": "package lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Definition;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * function definitions.\n */\npublic class FunDef implements Definition {\n        public final String name;\n        public final List<VariableDef> params;\n        public final AST.Access superType;\n        public final Set<AST.Anno> annos;\n        public final List<Statement> statements;\n\n        private final LineCol lineCol;\n\n        public FunDef(String name, List<VariableDef> params, AST.Access superType, Set<AST.Anno> annos, List<Statement> statements, LineCol lineCol) {\n                this.name = name;\n                this.params = params;\n                this.superType = superType;\n                this.annos = annos;\n                this.statements = statements;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(params, f, t);\n                CompileUtil.visitStmt(superType, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n                CompileUtil.visitStmt(statements, f, t);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                FunDef funDef = (FunDef) o;\n\n                if (name != null ? !name.equals(funDef.name) : funDef.name != null) return false;\n                if (params != null ? !params.equals(funDef.params) : funDef.params != null) return false;\n                if (superType != null ? !superType.equals(funDef.superType) : funDef.superType != null) return false;\n                if (annos != null ? !annos.equals(funDef.annos) : funDef.annos != null) return false;\n                //\n                return statements != null ? statements.equals(funDef.statements) : funDef.statements == null;\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name != null ? name.hashCode() : 0;\n                result = 31 * result + (params != null ? params.hashCode() : 0);\n                result = 31 * result + (superType != null ? superType.hashCode() : 0);\n                result = 31 * result + (annos != null ? annos.hashCode() : 0);\n                result = 31 * result + (statements != null ? statements.hashCode() : 0);\n                return result;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"(\");\n                for (AST.Anno anno : annos) {\n                        sb.append(anno).append(\" \");\n                }\n                sb.append(\"fun \").append(name);\n                sb.append(\"(\");\n                boolean isFirst = true;\n                for (VariableDef v : params) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(v);\n                }\n                sb.append(\") : \").append(superType).append(\" \").append(statements).append(\")\");\n                return sb.toString();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/InterfaceDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Definition;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * interface definition\n */\npublic class InterfaceDef implements Definition {\n        public final String name;\n        public final List<AST.Access> generics;\n        public final Set<Modifier> modifiers;\n        public final List<AST.Access> superInterfaces;\n        public final List<Statement> statements;\n        public final Set<AST.Anno> annos;\n\n        private final LineCol lineCol;\n\n        public InterfaceDef(String name, List<AST.Access> generics, Set<Modifier> modifiers, List<AST.Access> superInterfaces, Set<AST.Anno> annos, List<Statement> statements, LineCol lineCol) {\n                this.name = name;\n                this.generics = generics;\n                this.lineCol = lineCol;\n                this.modifiers = new HashSet<Modifier>(modifiers);\n                this.superInterfaces = superInterfaces;\n                this.statements = statements;\n                this.annos = new HashSet<AST.Anno>(annos);\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"(\");\n                for (AST.Anno anno : annos) {\n                        sb.append(anno).append(\" \");\n                }\n                for (Modifier m : modifiers) {\n                        sb.append(m).append(\" \");\n                }\n                sb.append(\"interface \").append(name);\n                if (!generics.isEmpty()) {\n                        sb.append(\"<:\").append(generics).append(\":>\");\n                }\n                if (!superInterfaces.isEmpty()) {\n                        sb.append(\" : \");\n                        boolean isFirst = true;\n                        for (AST.Access access : superInterfaces) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\");\n                                }\n                                sb.append(access);\n                        }\n                }\n                sb.append(\" \").append(statements).append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                InterfaceDef that = (InterfaceDef) o;\n\n                if (!name.equals(that.name)) return false;\n                if (!generics.equals(that.generics)) return false;\n                if (!modifiers.equals(that.modifiers)) return false;\n                if (!superInterfaces.equals(that.superInterfaces)) return false;\n                if (!statements.equals(that.statements)) return false;\n                //\n                return annos.equals(that.annos);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + generics.hashCode();\n                result = 31 * result + modifiers.hashCode();\n                result = 31 * result + superInterfaces.hashCode();\n                result = 31 * result + statements.hashCode();\n                result = 31 * result + annos.hashCode();\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(generics, f, t);\n                CompileUtil.visitStmt(modifiers, f, t);\n                CompileUtil.visitStmt(superInterfaces, f, t);\n                CompileUtil.visitStmt(statements, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/MethodDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Definition;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.util.ArrayList;\nimport java.util.HashSet;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * define a method\n */\npublic class MethodDef implements Definition {\n        public final String name;\n        public final Set<Modifier> modifiers;\n        public final AST.Access returnType;\n        public final List<VariableDef> params;\n        public final Set<AST.Anno> annos;\n        public final List<Statement> body;\n\n        private final LineCol lineCol;\n\n        public MethodDef(String name, Set<Modifier> modifiers, AST.Access returnType, List<VariableDef> params, Set<AST.Anno> annos, List<Statement> body, LineCol lineCol) {\n                this.name = name;\n                this.lineCol = lineCol;\n                this.modifiers = new HashSet<Modifier>(modifiers);\n                this.returnType = returnType;\n                this.params = params;\n                this.annos = new HashSet<AST.Anno>(annos);\n                this.body = new ArrayList<Statement>(body);\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"MethodDef(\");\n                for (AST.Anno anno : annos) {\n                        sb.append(anno).append(\"\");\n                }\n                for (Modifier m : modifiers) {\n                        sb.append(m).append(\" \");\n                }\n                sb.append(name).append(\"(\");\n                boolean isFirst = true;\n                for (VariableDef v : params) {\n                        if (isFirst)\n                                isFirst = false;\n                        else\n                                sb.append(\",\");\n                        sb.append(v);\n                }\n                sb.append(\")\");\n                if (returnType != null)\n                        sb.append(\":\").append(returnType);\n\n                sb.append(body);\n\n                sb.append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                MethodDef methodDef = (MethodDef) o;\n\n                if (!name.equals(methodDef.name)) return false;\n                if (!modifiers.equals(methodDef.modifiers)) return false;\n                if (returnType != null ? !returnType.equals(methodDef.returnType) : methodDef.returnType != null)\n                        return false;\n                if (!params.equals(methodDef.params)) return false;\n                if (!annos.equals(methodDef.annos)) return false;\n                //\n                return body.equals(methodDef.body);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + modifiers.hashCode();\n                result = 31 * result + (returnType != null ? returnType.hashCode() : 0);\n                result = 31 * result + params.hashCode();\n                result = 31 * result + annos.hashCode();\n                result = 31 * result + body.hashCode();\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(modifiers, f, t);\n                CompileUtil.visitStmt(returnType, f, t);\n                CompileUtil.visitStmt(params, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n                CompileUtil.visitStmt(body, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/ObjectDef.java",
    "content": "package lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Definition;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.util.ArrayList;\nimport java.util.List;\nimport java.util.Set;\n\n/**\n * defines an object\n */\npublic class ObjectDef implements Definition {\n        public final String name;\n        public final List<AST.Access> generics;\n        public final AST.Invocation superWithInvocation;\n        public final List<AST.Access> superWithoutInvocation;\n        public final Set<Modifier> modifiers;\n        public final Set<AST.Anno> annos;\n        public final List<Statement> statements;\n\n        private final LineCol lineCol;\n\n        public ObjectDef(String name,\n                         List<AST.Access> generics,\n                         AST.Invocation superWithInvocation,\n                         List<AST.Access> superWithoutInvocation,\n                         Set<Modifier> modifiers,\n                         Set<AST.Anno> annos,\n                         List<Statement> statements,\n                         LineCol lineCol) {\n                this.name = name;\n                this.generics = generics;\n                this.superWithInvocation = superWithInvocation;\n                this.superWithoutInvocation = superWithoutInvocation;\n                this.modifiers = modifiers;\n                this.annos = annos;\n                this.statements = new ArrayList<Statement>(statements);\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(superWithInvocation, f, t);\n                CompileUtil.visitStmt(superWithoutInvocation, f, t);\n                CompileUtil.visitStmt(modifiers, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n                CompileUtil.visitStmt(statements, f, t);\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"object \").append(name);\n                if (!generics.isEmpty()) {\n                        sb.append(\"<:\").append(generics).append(\":>\");\n                }\n                if (superWithInvocation != null || superWithoutInvocation.isEmpty()) {\n                        sb.append(\":\");\n                }\n                if (superWithInvocation != null) {\n                        sb.append(superWithInvocation);\n                        if (!superWithoutInvocation.isEmpty()) {\n                                sb.append(\",\");\n                        }\n                }\n                if (superWithoutInvocation.isEmpty()) {\n                        sb.append(superWithoutInvocation);\n                }\n                sb.append(statements);\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                ObjectDef objectDef = (ObjectDef) o;\n\n                if (!name.equals(objectDef.name)) return false;\n                if (!generics.equals(objectDef.generics)) return false;\n                if (superWithInvocation != null ? !superWithInvocation.equals(objectDef.superWithInvocation) : objectDef.superWithInvocation != null)\n                        return false;\n                if (!superWithoutInvocation.equals(objectDef.superWithoutInvocation)) return false;\n                if (!modifiers.equals(objectDef.modifiers)) return false;\n                if (!annos.equals(objectDef.annos)) return false;\n                //\n                return statements.equals(objectDef.statements);\n\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + generics.hashCode();\n                result = 31 * result + (superWithInvocation != null ? superWithInvocation.hashCode() : 0);\n                result = 31 * result + superWithoutInvocation.hashCode();\n                result = 31 * result + modifiers.hashCode();\n                result = 31 * result + annos.hashCode();\n                result = 31 * result + statements.hashCode();\n                return result;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/def/VariableDef.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.def;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Definition;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.lang.function.Function2;\n\nimport java.util.HashSet;\nimport java.util.Iterator;\nimport java.util.Set;\n\n/**\n * define a variable\n */\npublic class VariableDef implements Definition, Expression {\n        private String name;\n        private AST.Access type;\n        private Expression init;\n        private Set<Modifier> modifiers;\n        private Set<AST.Anno> annos;\n\n        private final LineCol lineCol;\n\n        public VariableDef(String name, Set<Modifier> modifiers, Set<AST.Anno> annos, LineCol lineCol) {\n                // remove var from modifiers\n                Iterator<Modifier> it = modifiers.iterator();\n                while (it.hasNext()) {\n                        Modifier m = it.next();\n                        if (m.modifier.equals(Modifier.Available.VAR)) {\n                                it.remove();\n                                break;\n                        }\n                }\n\n                this.name = name;\n                this.lineCol = lineCol;\n                this.modifiers = new HashSet<Modifier>(modifiers);\n                this.annos = new HashSet<AST.Anno>(annos);\n        }\n\n        public String getName() {\n                return name;\n        }\n\n        public AST.Access getType() {\n                return type;\n        }\n\n        public void setType(AST.Access type) {\n                this.type = type;\n        }\n\n        public Expression getInit() {\n                return init;\n        }\n\n        public void setInit(Expression init) {\n                this.init = init;\n        }\n\n        public Set<Modifier> getModifiers() {\n                return modifiers;\n        }\n\n        public Set<AST.Anno> getAnnos() {\n                return annos;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"VariableDef(\");\n                for (AST.Anno anno : annos) {\n                        sb.append(anno).append(\" \");\n                }\n                for (Modifier m : modifiers) {\n                        sb.append(m).append(\" \");\n                }\n                sb.append(\"(\").append(name).append(\")\");\n                if (type != null) {\n                        sb.append(\" : \").append(type);\n                }\n                if (init != null) {\n                        sb.append(\" = \").append(init);\n                }\n                sb.append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                VariableDef that = (VariableDef) o;\n\n                if (!name.equals(that.name)) return false;\n                if (type != null ? !type.equals(that.type) : that.type != null) return false;\n                if (init != null ? !init.equals(that.init) : that.init != null) return false;\n                if (!modifiers.equals(that.modifiers)) return false;\n                //\n                return annos.equals(that.annos);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = name.hashCode();\n                result = 31 * result + (type != null ? type.hashCode() : 0);\n                result = 31 * result + (init != null ? init.hashCode() : 0);\n                result = 31 * result + modifiers.hashCode();\n                result = 31 * result + annos.hashCode();\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(type, f, t);\n                CompileUtil.visitStmt(init, f, t);\n                CompileUtil.visitStmt(modifiers, f, t);\n                CompileUtil.visitStmt(annos, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/literal/BoolLiteral.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.literal;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Literal;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * bool literal\n */\npublic class BoolLiteral extends Literal {\n        public BoolLiteral(String literal, LineCol lineCol) {\n                super(BOOL, literal, lineCol);\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                // nothing to visit\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/literal/NumberLiteral.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.literal;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Literal;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * number literal\n */\npublic class NumberLiteral extends Literal {\n        public NumberLiteral(String literal, LineCol lineCol) {\n                super(NUMBER, literal, lineCol);\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                // nothing to visit\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/literal/StringLiteral.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.literal;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Literal;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * string literal, \"str\", 'str'\n */\npublic class StringLiteral extends Literal {\n        public StringLiteral(String literal, LineCol lineCol) {\n                super(STRING, literal, lineCol);\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                // nothing to visit\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/operation/OneVariableOperation.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.operation;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Operation;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * one variable operation\n */\npublic class OneVariableOperation implements Operation {\n        private String operator;\n        private List<Expression> expressions;\n        private final LineCol lineCol;\n\n        public OneVariableOperation(String operator, Expression e1, LineCol lineCol) {\n                this.operator = operator;\n                this.lineCol = lineCol;\n                expressions = Collections.singletonList(e1);\n        }\n\n        @Override\n        public String operator() {\n                return operator;\n        }\n\n        @Override\n        public List<Expression> expressions() {\n                return expressions;\n        }\n\n        @Override\n        public int invokeOn() {\n                return 0;\n        }\n\n        @Override\n        public boolean isUnary() {\n                return false;\n        }\n\n        @Override\n        public String toString() {\n                return \"(\" + expressions.get(0) + \" \" + operator + ')';\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                OneVariableOperation that = (OneVariableOperation) o;\n\n                return !(operator != null ? !operator.equals(that.operator) : that.operator != null) && !(expressions != null ? !expressions.equals(that.expressions) : that.expressions != null);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = operator != null ? operator.hashCode() : 0;\n                result = 31 * result + (expressions != null ? expressions.hashCode() : 0);\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(expressions, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/operation/TwoVariableOperation.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.operation;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Operation;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\nimport java.util.Arrays;\nimport java.util.List;\n\n/**\n * two variable operation\n */\npublic class TwoVariableOperation implements Operation {\n        private String operator;\n        private List<Expression> expressions;\n        private final LineCol lineCol;\n\n        public TwoVariableOperation(String operator, Expression e1, Expression e2, LineCol lineCol) {\n                this.operator = operator;\n                this.lineCol = lineCol;\n                expressions = Arrays.asList(e1, e2);\n        }\n\n        @Override\n        public String operator() {\n                return operator;\n        }\n\n        @Override\n        public List<Expression> expressions() {\n                return expressions;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                TwoVariableOperation that = (TwoVariableOperation) o;\n\n                return operator.equals(that.operator) && expressions.equals(that.expressions);\n        }\n\n        @Override\n        public int invokeOn() {\n                return 0;\n        }\n\n        @Override\n        public boolean isUnary() {\n                return false;\n        }\n\n        @Override\n        public String toString() {\n                return \"(\" + expressions.get(0) + \" \" + operator + \" \" + expressions.get(1) + \")\";\n        }\n\n        @Override\n        public int hashCode() {\n                int result = operator != null ? operator.hashCode() : 0;\n                result = 31 * result + (expressions != null ? expressions.hashCode() : 0);\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(expressions, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/operation/UnaryOneVariableOperation.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.operation;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Operation;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n *\n */\npublic class UnaryOneVariableOperation implements Operation {\n        public UnaryOneVariableOperation(String operator, Expression e1, LineCol lineCol) {\n                this.operator = operator;\n                this.lineCol = lineCol;\n                this.expressions = Collections.singletonList(e1);\n        }\n\n        private String operator;\n        private List<Expression> expressions;\n        private final LineCol lineCol;\n\n        @Override\n        public String operator() {\n                return operator;\n        }\n\n        @Override\n        public List<Expression> expressions() {\n                return expressions;\n        }\n\n        @Override\n        public int invokeOn() {\n                return 0;\n        }\n\n        @Override\n        public boolean isUnary() {\n                return true;\n        }\n\n        @Override\n        public String toString() {\n                return \"(\" + operator() + \" \" + expressions().get(0) + \")\";\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                UnaryOneVariableOperation that = (UnaryOneVariableOperation) o;\n\n                return !(operator != null ? !operator.equals(that.operator) : that.operator != null) && !(expressions != null ? !expressions.equals(that.expressions) : that.expressions != null);\n        }\n\n        @Override\n        public int hashCode() {\n                int result = operator != null ? operator.hashCode() : 0;\n                result = 31 * result + (expressions != null ? expressions.hashCode() : 0);\n                return result;\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(expressions, f, t);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/pre/Import.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.pre;\n\nimport lt.compiler.CompileUtil;\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Pre;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * import\n */\npublic class Import implements Pre {\n        public final AST.PackageRef pkg;\n        public final AST.Access access;\n        public final boolean importAll;\n        public final boolean implicit;\n        private final LineCol lineCol;\n\n        public Import(AST.PackageRef pkg, AST.Access access, boolean importAll, boolean implicit, LineCol lineCol) {\n                this.pkg = pkg;\n                this.access = access;\n                this.importAll = importAll;\n                this.implicit = implicit;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"(import \");\n                if (implicit) {\n                        sb.append(\"implicit \");\n                }\n                if (pkg == null) {\n                        if (importAll) {\n                                sb.append(access.toString()).append(\"._\");\n                        } else {\n                                sb.append(access.toString());\n                        }\n                } else {\n                        if (importAll) {\n                                sb.append(pkg.toString()).append(\"._\");\n                        } else {\n                                sb.append(\"(invalid import)\");\n                        }\n                }\n                sb.append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                CompileUtil.visitStmt(pkg, f, t);\n                CompileUtil.visitStmt(access, f, t);\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                Import anImport = (Import) o;\n\n                if (importAll != anImport.importAll) return false;\n                if (implicit != anImport.implicit) return false;\n                if (pkg != null ? !pkg.equals(anImport.pkg) : anImport.pkg != null) return false;\n                //\n                return access != null ? access.equals(anImport.access) : anImport.access == null;\n\n        }\n\n        @Override\n        public int hashCode() {\n                int result = pkg != null ? pkg.hashCode() : 0;\n                result = 31 * result + (access != null ? access.hashCode() : 0);\n                result = 31 * result + (importAll ? 1 : 0);\n                result = 31 * result + (implicit ? 1 : 0);\n                return result;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/pre/Modifier.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.pre;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.Pre;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * modifier\n */\npublic class Modifier implements Pre {\n        public enum Available {\n                PRIVATE, PUBLIC, PROTECTED, PKG, SYNCHRONIZED, VAL,\n                NATIVE, ABSTRACT, TRANSIENT, VOLATILE, STRICTFP, DATA,\n                VAR, DEF, NONNULL, NONEMPTY, IMPLICIT\n        }\n\n        public final Available modifier;\n        private final LineCol lineCol;\n\n        public Modifier(Available modifier, LineCol lineCol) {\n                this.modifier = modifier;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                Modifier modifier1 = (Modifier) o;\n\n                return !(modifier != null ? !modifier.equals(modifier1.modifier) : modifier1.modifier != null);\n        }\n\n        @Override\n        public int hashCode() {\n                return modifier != null ? modifier.hashCode() : 0;\n        }\n\n        @Override\n        public String toString() {\n                return \"(\" + modifier + \")\";\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                // nothing to visit\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/syntactic/pre/PackageDeclare.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.syntactic.pre;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Pre;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function2;\n\n/**\n * declare current package\n */\npublic class PackageDeclare implements Pre {\n        public final AST.PackageRef pkg;\n        private final LineCol lineCol;\n\n        public PackageDeclare(AST.PackageRef pkg, LineCol lineCol) {\n                this.pkg = pkg;\n                this.lineCol = lineCol;\n        }\n\n        @Override\n        public String toString() {\n                return \"(package \" + pkg + \")\";\n        }\n\n        @Override\n        public boolean equals(Object o) {\n                if (this == o) return true;\n                if (o == null || getClass() != o.getClass()) return false;\n\n                PackageDeclare that = (PackageDeclare) o;\n\n                return pkg.equals(that.pkg);\n        }\n\n        @Override\n        public int hashCode() {\n                return pkg.hashCode();\n        }\n\n        @Override\n        public LineCol line_col() {\n                return lineCol;\n        }\n\n        @Override\n        public <T> void foreachInnerStatements(Function2<Boolean, ? super Statement, T> f, T t) throws Exception {\n                // nothing to visit\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/util/BindList.java",
    "content": "package lt.compiler.util;\n\nimport java.util.AbstractList;\nimport java.util.List;\n\n/**\n * bind 2 lists into one\n */\npublic class BindList<E> extends AbstractList<E> {\n        private final List<E> list1;\n        private final List<E> list2;\n\n        public BindList(List<E> list1, List<E> list2) {\n                this.list1 = list1;\n                this.list2 = list2;\n        }\n\n        @Override\n        public E get(int index) {\n                if (index < 0 || index >= list1.size() + list2.size())\n                        throw new IndexOutOfBoundsException(String.valueOf(index));\n                if (index < list1.size()) return list1.get(index);\n                index -= list1.size();\n                return list2.get(index);\n        }\n\n        @Override\n        public E set(int index, E element) {\n                if (index < 0 || index >= list1.size() + list2.size())\n                        throw new IndexOutOfBoundsException(String.valueOf(index));\n                if (index < list1.size()) return list1.set(index, element);\n                index -= list1.size();\n                return list2.set(index, element);\n        }\n\n        @Override\n        public int size() {\n                return list1.size() + list2.size();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/util/Consts.java",
    "content": "package lt.compiler.util;\n\n/**\n * the flags\n */\npublic class Consts {\n        public static final int IS_POINTER_SET = 1; // 0001\n        public static final int IS_POINTER_GET = 2; // 0010\n        public static final int IS_POINTER_NEW = 4; // 0100\n\n        public static final String AST_FIELD = \"_LATTE$AST\";\n        public static final String GENERIC_NAME_SPLIT = \"_$G$_\";\n\n        private Consts() {\n        }\n\n        public static boolean flagMatch(int field, int flag) {\n                return (field & flag) == flag;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/compiler/util/LocalVariables.java",
    "content": "package lt.compiler.util;\n\nimport lt.compiler.CodeInfo;\nimport lt.compiler.LtBug;\nimport lt.compiler.SemanticScope;\nimport lt.compiler.semantic.*;\nimport lt.compiler.semantic.builtin.DoubleTypeDef;\nimport lt.compiler.semantic.builtin.LongTypeDef;\nimport lt.lang.Pointer;\n\nimport java.util.Collection;\nimport java.util.Iterator;\n\n/**\n * utils for local variables\n */\npublic class LocalVariables {\n        private LocalVariables() {\n        }\n\n        private static int _slots(STypeDef type) {\n                if (type.equals(LongTypeDef.get()) || type.equals(DoubleTypeDef.get())) {\n                        return 2;\n                } else {\n                        return 1;\n                }\n        }\n\n        public static int calculateIndexForLocalVariable(LeftValue theVar, SemanticScope scope, boolean isStatic) {\n                InvokableMeta meta = scope.getMeta();\n                Collection<LeftValue> localVariables = scope.getRawLocalVariables().values();\n\n                Iterator<LeftValue> localVarIte = localVariables.iterator();\n                if (!localVarIte.hasNext())\n                        throw new LtBug(\"empty local variables ???\");\n                LeftValue current = localVarIte.next();\n\n                int insIndex;\n                // static methods doesn't contain `this` in slot0\n                // so the iteration goes directly from the first param\n                // else, this is in slot0, so iteration goes from this\n                // then the first param\n                if (isStatic) {\n                        insIndex = 0;\n                } else {\n                        insIndex = 1;\n                }\n                while (theVar != current /* reference eq */) {\n                        // check whether it's captured but not used\n                        // which should be removed\n                        if (current instanceof SParameter) {\n                                SParameter p = (SParameter) current;\n                                if (p.isCapture() && !p.isUsed()) {\n                                        current = localVarIte.next();\n                                        continue;\n                                }\n                        }\n\n                        // the local var should be added\n                        int currentSlot = _slots(current.type());\n                        insIndex += currentSlot;\n\n                        // check whether it's pointer and should not be pointer\n                        // which should be optimized as normal local variable\n                        if (current.type().fullName().equals(Pointer.class.getName()) && !meta.pointerLocalVar.contains(current)) {\n                                assert currentSlot == 1; // pointer is a ref type, should take 1 slot\n                                assert current.type() instanceof PointerType; // pointerType\n                                if (isParameterWrappingPointer(current)) {\n                                        // it will be totally ignored, so index should be subtracted as well\n                                        insIndex -= currentSlot;\n                                } else {\n                                        STypeDef t = ((PointerType) current.type()).getPointingType();\n                                        insIndex += (_slots(t) - 1); // expand the slot size\n                                }\n                        }\n\n                        if (!localVarIte.hasNext())\n                                throw new LtBug(\"empty local variable ???\");\n                        current = localVarIte.next();\n                }\n                return insIndex;\n        }\n\n        public static boolean isParameterWrappingPointer(LeftValue v) {\n                return v instanceof LocalVariable && ((LocalVariable) v).getWrappingParam() != null;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/AnnotationVisitor.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A visitor to visit a Java annotation. The methods of this class must be\n * called in the following order: ( <tt>visit</tt> | <tt>visitEnum</tt> |\n * <tt>visitAnnotation</tt> | <tt>visitArray</tt> )* <tt>visitEnd</tt>.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\npublic abstract class AnnotationVisitor {\n\n    /**\n     * The ASM API version implemented by this visitor. The value of this field\n     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    protected final int api;\n\n    /**\n     * The annotation visitor to which this visitor must delegate method calls.\n     * May be null.\n     */\n    protected AnnotationVisitor av;\n\n    /**\n     * Constructs a new {@link AnnotationVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    public AnnotationVisitor(final int api) {\n        this(api, null);\n    }\n\n    /**\n     * Constructs a new {@link AnnotationVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     * @param av\n     *            the annotation visitor to which this visitor must delegate\n     *            method calls. May be null.\n     */\n    public AnnotationVisitor(final int api, final AnnotationVisitor av) {\n        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {\n            throw new IllegalArgumentException();\n        }\n        this.api = api;\n        this.av = av;\n    }\n\n    /**\n     * Visits a primitive value of the annotation.\n     * \n     * @param name\n     *            the value name.\n     * @param value\n     *            the actual value, whose type must be {@link Byte},\n     *            {@link Boolean}, {@link Character}, {@link Short},\n     *            {@link Integer} , {@link Long}, {@link Float}, {@link Double},\n     *            {@link String} or {@link Type} or OBJECT or ARRAY sort. This\n     *            value can also be an array of byte, boolean, short, char, int,\n     *            long, float or double values (this is equivalent to using\n     *            {@link #visitArray visitArray} and visiting each array element\n     *            in turn, but is more convenient).\n     */\n    public void visit(String name, Object value) {\n        if (av != null) {\n            av.visit(name, value);\n        }\n    }\n\n    /**\n     * Visits an enumeration value of the annotation.\n     * \n     * @param name\n     *            the value name.\n     * @param desc\n     *            the class descriptor of the enumeration class.\n     * @param value\n     *            the actual enumeration value.\n     */\n    public void visitEnum(String name, String desc, String value) {\n        if (av != null) {\n            av.visitEnum(name, desc, value);\n        }\n    }\n\n    /**\n     * Visits a nested annotation value of the annotation.\n     * \n     * @param name\n     *            the value name.\n     * @param desc\n     *            the class descriptor of the nested annotation class.\n     * @return a visitor to visit the actual nested annotation value, or\n     *         <tt>null</tt> if this visitor is not interested in visiting this\n     *         nested annotation. <i>The nested annotation value must be fully\n     *         visited before calling other methods on this annotation\n     *         visitor</i>.\n     */\n    public AnnotationVisitor visitAnnotation(String name, String desc) {\n        if (av != null) {\n            return av.visitAnnotation(name, desc);\n        }\n        return null;\n    }\n\n    /**\n     * Visits an array value of the annotation. Note that arrays of primitive\n     * types (such as byte, boolean, short, char, int, long, float or double)\n     * can be passed as value to {@link #visit visit}. This is what\n     * {@link ClassReader} does.\n     * \n     * @param name\n     *            the value name.\n     * @return a visitor to visit the actual array value elements, or\n     *         <tt>null</tt> if this visitor is not interested in visiting these\n     *         values. The 'name' parameters passed to the methods of this\n     *         visitor are ignored. <i>All the array values must be visited\n     *         before calling other methods on this annotation visitor</i>.\n     */\n    public AnnotationVisitor visitArray(String name) {\n        if (av != null) {\n            return av.visitArray(name);\n        }\n        return null;\n    }\n\n    /**\n     * Visits the end of the annotation.\n     */\n    public void visitEnd() {\n        if (av != null) {\n            av.visitEnd();\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/AnnotationWriter.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * An {@link AnnotationVisitor} that generates annotations in bytecode form.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\nfinal class AnnotationWriter extends AnnotationVisitor {\n\n    /**\n     * The class writer to which this annotation must be added.\n     */\n    private final ClassWriter cw;\n\n    /**\n     * The number of values in this annotation.\n     */\n    private int size;\n\n    /**\n     * <tt>true<tt> if values are named, <tt>false</tt> otherwise. Annotation\n     * writers used for annotation default and annotation arrays use unnamed\n     * values.\n     */\n    private final boolean named;\n\n    /**\n     * The annotation values in bytecode form. This byte vector only contains\n     * the values themselves, i.e. the number of values must be stored as a\n     * unsigned short just before these bytes.\n     */\n    private final ByteVector bv;\n\n    /**\n     * The byte vector to be used to store the number of values of this\n     * annotation. See {@link #bv}.\n     */\n    private final ByteVector parent;\n\n    /**\n     * Where the number of values of this annotation must be stored in\n     * {@link #parent}.\n     */\n    private final int offset;\n\n    /**\n     * Next annotation writer. This field is used to store annotation lists.\n     */\n    AnnotationWriter next;\n\n    /**\n     * Previous annotation writer. This field is used to store annotation lists.\n     */\n    AnnotationWriter prev;\n\n    // ------------------------------------------------------------------------\n    // Constructor\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link AnnotationWriter}.\n     * \n     * @param cw\n     *            the class writer to which this annotation must be added.\n     * @param named\n     *            <tt>true<tt> if values are named, <tt>false</tt> otherwise.\n     * @param bv\n     *            where the annotation values must be stored.\n     * @param parent\n     *            where the number of annotation values must be stored.\n     * @param offset\n     *            where in <tt>parent</tt> the number of annotation values must\n     *            be stored.\n     */\n    AnnotationWriter(final ClassWriter cw, final boolean named,\n            final ByteVector bv, final ByteVector parent, final int offset) {\n        super(Opcodes.ASM5);\n        this.cw = cw;\n        this.named = named;\n        this.bv = bv;\n        this.parent = parent;\n        this.offset = offset;\n    }\n\n    // ------------------------------------------------------------------------\n    // Implementation of the AnnotationVisitor abstract class\n    // ------------------------------------------------------------------------\n\n    @Override\n    public void visit(final String name, final Object value) {\n        ++size;\n        if (named) {\n            bv.putShort(cw.newUTF8(name));\n        }\n        if (value instanceof String) {\n            bv.put12('s', cw.newUTF8((String) value));\n        } else if (value instanceof Byte) {\n            bv.put12('B', cw.newInteger(((Byte) value).byteValue()).index);\n        } else if (value instanceof Boolean) {\n            int v = ((Boolean) value).booleanValue() ? 1 : 0;\n            bv.put12('Z', cw.newInteger(v).index);\n        } else if (value instanceof Character) {\n            bv.put12('C', cw.newInteger(((Character) value).charValue()).index);\n        } else if (value instanceof Short) {\n            bv.put12('S', cw.newInteger(((Short) value).shortValue()).index);\n        } else if (value instanceof Type) {\n            bv.put12('c', cw.newUTF8(((Type) value).getDescriptor()));\n        } else if (value instanceof byte[]) {\n            byte[] v = (byte[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('B', cw.newInteger(v[i]).index);\n            }\n        } else if (value instanceof boolean[]) {\n            boolean[] v = (boolean[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('Z', cw.newInteger(v[i] ? 1 : 0).index);\n            }\n        } else if (value instanceof short[]) {\n            short[] v = (short[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('S', cw.newInteger(v[i]).index);\n            }\n        } else if (value instanceof char[]) {\n            char[] v = (char[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('C', cw.newInteger(v[i]).index);\n            }\n        } else if (value instanceof int[]) {\n            int[] v = (int[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('I', cw.newInteger(v[i]).index);\n            }\n        } else if (value instanceof long[]) {\n            long[] v = (long[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('J', cw.newLong(v[i]).index);\n            }\n        } else if (value instanceof float[]) {\n            float[] v = (float[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('F', cw.newFloat(v[i]).index);\n            }\n        } else if (value instanceof double[]) {\n            double[] v = (double[]) value;\n            bv.put12('[', v.length);\n            for (int i = 0; i < v.length; i++) {\n                bv.put12('D', cw.newDouble(v[i]).index);\n            }\n        } else {\n            Item i = cw.newConstItem(value);\n            bv.put12(\".s.IFJDCS\".charAt(i.type), i.index);\n        }\n    }\n\n    @Override\n    public void visitEnum(final String name, final String desc,\n            final String value) {\n        ++size;\n        if (named) {\n            bv.putShort(cw.newUTF8(name));\n        }\n        bv.put12('e', cw.newUTF8(desc)).putShort(cw.newUTF8(value));\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(final String name,\n            final String desc) {\n        ++size;\n        if (named) {\n            bv.putShort(cw.newUTF8(name));\n        }\n        // write tag and type, and reserve space for values count\n        bv.put12('@', cw.newUTF8(desc)).putShort(0);\n        return new AnnotationWriter(cw, true, bv, bv, bv.length - 2);\n    }\n\n    @Override\n    public AnnotationVisitor visitArray(final String name) {\n        ++size;\n        if (named) {\n            bv.putShort(cw.newUTF8(name));\n        }\n        // write tag, and reserve space for array size\n        bv.put12('[', 0);\n        return new AnnotationWriter(cw, false, bv, bv, bv.length - 2);\n    }\n\n    @Override\n    public void visitEnd() {\n        if (parent != null) {\n            byte[] data = parent.data;\n            data[offset] = (byte) (size >>> 8);\n            data[offset + 1] = (byte) size;\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the size of this annotation writer list.\n     * \n     * @return the size of this annotation writer list.\n     */\n    int getSize() {\n        int size = 0;\n        AnnotationWriter aw = this;\n        while (aw != null) {\n            size += aw.bv.length;\n            aw = aw.next;\n        }\n        return size;\n    }\n\n    /**\n     * Puts the annotations of this annotation writer list into the given byte\n     * vector.\n     * \n     * @param out\n     *            where the annotations must be put.\n     */\n    void put(final ByteVector out) {\n        int n = 0;\n        int size = 2;\n        AnnotationWriter aw = this;\n        AnnotationWriter last = null;\n        while (aw != null) {\n            ++n;\n            size += aw.bv.length;\n            aw.visitEnd(); // in case user forgot to call visitEnd\n            aw.prev = last;\n            last = aw;\n            aw = aw.next;\n        }\n        out.putInt(size);\n        out.putShort(n);\n        aw = last;\n        while (aw != null) {\n            out.putByteArray(aw.bv.data, 0, aw.bv.length);\n            aw = aw.prev;\n        }\n    }\n\n    /**\n     * Puts the given annotation lists into the given byte vector.\n     * \n     * @param panns\n     *            an array of annotation writer lists.\n     * @param off\n     *            index of the first annotation to be written.\n     * @param out\n     *            where the annotations must be put.\n     */\n    static void put(final AnnotationWriter[] panns, final int off,\n            final ByteVector out) {\n        int size = 1 + 2 * (panns.length - off);\n        for (int i = off; i < panns.length; ++i) {\n            size += panns[i] == null ? 0 : panns[i].getSize();\n        }\n        out.putInt(size).putByte(panns.length - off);\n        for (int i = off; i < panns.length; ++i) {\n            AnnotationWriter aw = panns[i];\n            AnnotationWriter last = null;\n            int n = 0;\n            while (aw != null) {\n                ++n;\n                aw.visitEnd(); // in case user forgot to call visitEnd\n                aw.prev = last;\n                last = aw;\n                aw = aw.next;\n            }\n            out.putShort(n);\n            aw = last;\n            while (aw != null) {\n                out.putByteArray(aw.bv.data, 0, aw.bv.length);\n                aw = aw.prev;\n            }\n        }\n    }\n\n    /**\n     * Puts the given type reference and type path into the given bytevector.\n     * LOCAL_VARIABLE and RESOURCE_VARIABLE target types are not supported.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. See {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param out\n     *            where the type reference and type path must be put.\n     */\n    static void putTarget(int typeRef, TypePath typePath, ByteVector out) {\n        switch (typeRef >>> 24) {\n        case 0x00: // CLASS_TYPE_PARAMETER\n        case 0x01: // METHOD_TYPE_PARAMETER\n        case 0x16: // METHOD_FORMAL_PARAMETER\n            out.putShort(typeRef >>> 16);\n            break;\n        case 0x13: // FIELD\n        case 0x14: // METHOD_RETURN\n        case 0x15: // METHOD_RECEIVER\n            out.putByte(typeRef >>> 24);\n            break;\n        case 0x47: // CAST\n        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT\n        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\n        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT\n            out.putInt(typeRef);\n            break;\n        // case 0x10: // CLASS_EXTENDS\n        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND\n        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND\n        // case 0x17: // THROWS\n        // case 0x42: // EXCEPTION_PARAMETER\n        // case 0x43: // INSTANCEOF\n        // case 0x44: // NEW\n        // case 0x45: // CONSTRUCTOR_REFERENCE\n        // case 0x46: // METHOD_REFERENCE\n        default:\n            out.put12(typeRef >>> 24, (typeRef & 0xFFFF00) >> 8);\n            break;\n        }\n        if (typePath == null) {\n            out.putByte(0);\n        } else {\n            int length = typePath.b[typePath.offset] * 2 + 1;\n            out.putByteArray(typePath.b, typePath.offset, length);\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Attribute.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A non standard class, field, method or code attribute.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\npublic class Attribute {\n\n    /**\n     * The type of this attribute.\n     */\n    public final String type;\n\n    /**\n     * The raw value of this attribute, used only for unknown attributes.\n     */\n    byte[] value;\n\n    /**\n     * The next attribute in this attribute list. May be <tt>null</tt>.\n     */\n    Attribute next;\n\n    /**\n     * Constructs a new empty attribute.\n     * \n     * @param type\n     *            the type of the attribute.\n     */\n    protected Attribute(final String type) {\n        this.type = type;\n    }\n\n    /**\n     * Returns <tt>true</tt> if this type of attribute is unknown. The default\n     * implementation of this method always returns <tt>true</tt>.\n     * \n     * @return <tt>true</tt> if this type of attribute is unknown.\n     */\n    public boolean isUnknown() {\n        return true;\n    }\n\n    /**\n     * Returns <tt>true</tt> if this type of attribute is a code attribute.\n     * \n     * @return <tt>true</tt> if this type of attribute is a code attribute.\n     */\n    public boolean isCodeAttribute() {\n        return false;\n    }\n\n    /**\n     * Returns the labels corresponding to this attribute.\n     * \n     * @return the labels corresponding to this attribute, or <tt>null</tt> if\n     *         this attribute is not a code attribute that contains labels.\n     */\n    protected Label[] getLabels() {\n        return null;\n    }\n\n    /**\n     * Reads a {@link #type type} attribute. This method must return a\n     * <i>new</i> {@link Attribute} object, of type {@link #type type},\n     * corresponding to the <tt>len</tt> bytes starting at the given offset, in\n     * the given class reader.\n     * \n     * @param cr\n     *            the class that contains the attribute to be read.\n     * @param off\n     *            index of the first byte of the attribute's content in\n     *            {@link ClassReader#b cr.b}. The 6 attribute header bytes,\n     *            containing the type and the length of the attribute, are not\n     *            taken into account here.\n     * @param len\n     *            the length of the attribute's content.\n     * @param buf\n     *            buffer to be used to call {@link ClassReader#readUTF8\n     *            readUTF8}, {@link ClassReader#readClass(int,char[]) readClass}\n     *            or {@link ClassReader#readConst readConst}.\n     * @param codeOff\n     *            index of the first byte of code's attribute content in\n     *            {@link ClassReader#b cr.b}, or -1 if the attribute to be read\n     *            is not a code attribute. The 6 attribute header bytes,\n     *            containing the type and the length of the attribute, are not\n     *            taken into account here.\n     * @param labels\n     *            the labels of the method's code, or <tt>null</tt> if the\n     *            attribute to be read is not a code attribute.\n     * @return a <i>new</i> {@link Attribute} object corresponding to the given\n     *         bytes.\n     */\n    protected Attribute read(final ClassReader cr, final int off,\n            final int len, final char[] buf, final int codeOff,\n            final Label[] labels) {\n        Attribute attr = new Attribute(type);\n        attr.value = new byte[len];\n        System.arraycopy(cr.b, off, attr.value, 0, len);\n        return attr;\n    }\n\n    /**\n     * Returns the byte array form of this attribute.\n     * \n     * @param cw\n     *            the class to which this attribute must be added. This\n     *            parameter can be used to add to the constant pool of this\n     *            class the items that corresponds to this attribute.\n     * @param code\n     *            the bytecode of the method corresponding to this code\n     *            attribute, or <tt>null</tt> if this attribute is not a code\n     *            attributes.\n     * @param len\n     *            the length of the bytecode of the method corresponding to this\n     *            code attribute, or <tt>null</tt> if this attribute is not a\n     *            code attribute.\n     * @param maxStack\n     *            the maximum stack size of the method corresponding to this\n     *            code attribute, or -1 if this attribute is not a code\n     *            attribute.\n     * @param maxLocals\n     *            the maximum number of local variables of the method\n     *            corresponding to this code attribute, or -1 if this attribute\n     *            is not a code attribute.\n     * @return the byte array form of this attribute.\n     */\n    protected ByteVector write(final ClassWriter cw, final byte[] code,\n            final int len, final int maxStack, final int maxLocals) {\n        ByteVector v = new ByteVector();\n        v.data = value;\n        v.length = value.length;\n        return v;\n    }\n\n    /**\n     * Returns the length of the attribute list that begins with this attribute.\n     * \n     * @return the length of the attribute list that begins with this attribute.\n     */\n    final int getCount() {\n        int count = 0;\n        Attribute attr = this;\n        while (attr != null) {\n            count += 1;\n            attr = attr.next;\n        }\n        return count;\n    }\n\n    /**\n     * Returns the size of all the attributes in this attribute list.\n     * \n     * @param cw\n     *            the class writer to be used to convert the attributes into\n     *            byte arrays, with the {@link #write write} method.\n     * @param code\n     *            the bytecode of the method corresponding to these code\n     *            attributes, or <tt>null</tt> if these attributes are not code\n     *            attributes.\n     * @param len\n     *            the length of the bytecode of the method corresponding to\n     *            these code attributes, or <tt>null</tt> if these attributes\n     *            are not code attributes.\n     * @param maxStack\n     *            the maximum stack size of the method corresponding to these\n     *            code attributes, or -1 if these attributes are not code\n     *            attributes.\n     * @param maxLocals\n     *            the maximum number of local variables of the method\n     *            corresponding to these code attributes, or -1 if these\n     *            attributes are not code attributes.\n     * @return the size of all the attributes in this attribute list. This size\n     *         includes the size of the attribute headers.\n     */\n    final int getSize(final ClassWriter cw, final byte[] code, final int len,\n            final int maxStack, final int maxLocals) {\n        Attribute attr = this;\n        int size = 0;\n        while (attr != null) {\n            cw.newUTF8(attr.type);\n            size += attr.write(cw, code, len, maxStack, maxLocals).length + 6;\n            attr = attr.next;\n        }\n        return size;\n    }\n\n    /**\n     * Writes all the attributes of this attribute list in the given byte\n     * vector.\n     * \n     * @param cw\n     *            the class writer to be used to convert the attributes into\n     *            byte arrays, with the {@link #write write} method.\n     * @param code\n     *            the bytecode of the method corresponding to these code\n     *            attributes, or <tt>null</tt> if these attributes are not code\n     *            attributes.\n     * @param len\n     *            the length of the bytecode of the method corresponding to\n     *            these code attributes, or <tt>null</tt> if these attributes\n     *            are not code attributes.\n     * @param maxStack\n     *            the maximum stack size of the method corresponding to these\n     *            code attributes, or -1 if these attributes are not code\n     *            attributes.\n     * @param maxLocals\n     *            the maximum number of local variables of the method\n     *            corresponding to these code attributes, or -1 if these\n     *            attributes are not code attributes.\n     * @param out\n     *            where the attributes must be written.\n     */\n    final void put(final ClassWriter cw, final byte[] code, final int len,\n            final int maxStack, final int maxLocals, final ByteVector out) {\n        Attribute attr = this;\n        while (attr != null) {\n            ByteVector b = attr.write(cw, code, len, maxStack, maxLocals);\n            out.putShort(cw.newUTF8(attr.type)).putInt(b.length);\n            out.putByteArray(b.data, 0, b.length);\n            attr = attr.next;\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/ByteVector.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A dynamically extensible vector of bytes. This class is roughly equivalent to\n * a DataOutputStream on top of a ByteArrayOutputStream, but is more efficient.\n * \n * @author Eric Bruneton\n */\npublic class ByteVector {\n\n    /**\n     * The content of this vector.\n     */\n    byte[] data;\n\n    /**\n     * Actual number of bytes in this vector.\n     */\n    int length;\n\n    /**\n     * Constructs a new {@link ByteVector ByteVector} with a default initial\n     * size.\n     */\n    public ByteVector() {\n        data = new byte[64];\n    }\n\n    /**\n     * Constructs a new {@link ByteVector ByteVector} with the given initial\n     * size.\n     * \n     * @param initialSize\n     *            the initial size of the byte vector to be constructed.\n     */\n    public ByteVector(final int initialSize) {\n        data = new byte[initialSize];\n    }\n\n    /**\n     * Puts a byte into this byte vector. The byte vector is automatically\n     * enlarged if necessary.\n     * \n     * @param b\n     *            a byte.\n     * @return this byte vector.\n     */\n    public ByteVector putByte(final int b) {\n        int length = this.length;\n        if (length + 1 > data.length) {\n            enlarge(1);\n        }\n        data[length++] = (byte) b;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts two bytes into this byte vector. The byte vector is automatically\n     * enlarged if necessary.\n     * \n     * @param b1\n     *            a byte.\n     * @param b2\n     *            another byte.\n     * @return this byte vector.\n     */\n    ByteVector put11(final int b1, final int b2) {\n        int length = this.length;\n        if (length + 2 > data.length) {\n            enlarge(2);\n        }\n        byte[] data = this.data;\n        data[length++] = (byte) b1;\n        data[length++] = (byte) b2;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts a short into this byte vector. The byte vector is automatically\n     * enlarged if necessary.\n     * \n     * @param s\n     *            a short.\n     * @return this byte vector.\n     */\n    public ByteVector putShort(final int s) {\n        int length = this.length;\n        if (length + 2 > data.length) {\n            enlarge(2);\n        }\n        byte[] data = this.data;\n        data[length++] = (byte) (s >>> 8);\n        data[length++] = (byte) s;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts a byte and a short into this byte vector. The byte vector is\n     * automatically enlarged if necessary.\n     * \n     * @param b\n     *            a byte.\n     * @param s\n     *            a short.\n     * @return this byte vector.\n     */\n    ByteVector put12(final int b, final int s) {\n        int length = this.length;\n        if (length + 3 > data.length) {\n            enlarge(3);\n        }\n        byte[] data = this.data;\n        data[length++] = (byte) b;\n        data[length++] = (byte) (s >>> 8);\n        data[length++] = (byte) s;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts an int into this byte vector. The byte vector is automatically\n     * enlarged if necessary.\n     * \n     * @param i\n     *            an int.\n     * @return this byte vector.\n     */\n    public ByteVector putInt(final int i) {\n        int length = this.length;\n        if (length + 4 > data.length) {\n            enlarge(4);\n        }\n        byte[] data = this.data;\n        data[length++] = (byte) (i >>> 24);\n        data[length++] = (byte) (i >>> 16);\n        data[length++] = (byte) (i >>> 8);\n        data[length++] = (byte) i;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts a long into this byte vector. The byte vector is automatically\n     * enlarged if necessary.\n     * \n     * @param l\n     *            a long.\n     * @return this byte vector.\n     */\n    public ByteVector putLong(final long l) {\n        int length = this.length;\n        if (length + 8 > data.length) {\n            enlarge(8);\n        }\n        byte[] data = this.data;\n        int i = (int) (l >>> 32);\n        data[length++] = (byte) (i >>> 24);\n        data[length++] = (byte) (i >>> 16);\n        data[length++] = (byte) (i >>> 8);\n        data[length++] = (byte) i;\n        i = (int) l;\n        data[length++] = (byte) (i >>> 24);\n        data[length++] = (byte) (i >>> 16);\n        data[length++] = (byte) (i >>> 8);\n        data[length++] = (byte) i;\n        this.length = length;\n        return this;\n    }\n\n    /**\n     * Puts an UTF8 string into this byte vector. The byte vector is\n     * automatically enlarged if necessary.\n     * \n     * @param s\n     *            a String whose UTF8 encoded length must be less than 65536.\n     * @return this byte vector.\n     */\n    public ByteVector putUTF8(final String s) {\n        int charLength = s.length();\n        if (charLength > 65535) {\n            throw new IllegalArgumentException();\n        }\n        int len = length;\n        if (len + 2 + charLength > data.length) {\n            enlarge(2 + charLength);\n        }\n        byte[] data = this.data;\n        // optimistic algorithm: instead of computing the byte length and then\n        // serializing the string (which requires two loops), we assume the byte\n        // length is equal to char length (which is the most frequent case), and\n        // we start serializing the string right away. During the serialization,\n        // if we find that this assumption is wrong, we continue with the\n        // general method.\n        data[len++] = (byte) (charLength >>> 8);\n        data[len++] = (byte) charLength;\n        for (int i = 0; i < charLength; ++i) {\n            char c = s.charAt(i);\n            if (c >= '\\001' && c <= '\\177') {\n                data[len++] = (byte) c;\n            } else {\n                length = len;\n                return encodeUTF8(s, i, 65535);\n            }\n        }\n        length = len;\n        return this;\n    }\n\n    /**\n     * Puts an UTF8 string into this byte vector. The byte vector is\n     * automatically enlarged if necessary. The string length is encoded in two\n     * bytes before the encoded characters, if there is space for that (i.e. if\n     * this.length - i - 2 >= 0).\n     * \n     * @param s\n     *            the String to encode.\n     * @param i\n     *            the index of the first character to encode. The previous\n     *            characters are supposed to have already been encoded, using\n     *            only one byte per character.\n     * @param maxByteLength\n     *            the maximum byte length of the encoded string, including the\n     *            already encoded characters.\n     * @return this byte vector.\n     */\n    ByteVector encodeUTF8(final String s, int i, int maxByteLength) {\n        int charLength = s.length();\n        int byteLength = i;\n        char c;\n        for (int j = i; j < charLength; ++j) {\n            c = s.charAt(j);\n            if (c >= '\\001' && c <= '\\177') {\n                byteLength++;\n            } else if (c > '\\u07FF') {\n                byteLength += 3;\n            } else {\n                byteLength += 2;\n            }\n        }\n        if (byteLength > maxByteLength) {\n            throw new IllegalArgumentException();\n        }\n        int start = length - i - 2;\n        if (start >= 0) {\n          data[start] = (byte) (byteLength >>> 8);\n          data[start + 1] = (byte) byteLength;\n        }\n        if (length + byteLength - i > data.length) {\n            enlarge(byteLength - i);\n        }\n        int len = length;\n        for (int j = i; j < charLength; ++j) {\n            c = s.charAt(j);\n            if (c >= '\\001' && c <= '\\177') {\n                data[len++] = (byte) c;\n            } else if (c > '\\u07FF') {\n                data[len++] = (byte) (0xE0 | c >> 12 & 0xF);\n                data[len++] = (byte) (0x80 | c >> 6 & 0x3F);\n                data[len++] = (byte) (0x80 | c & 0x3F);\n            } else {\n                data[len++] = (byte) (0xC0 | c >> 6 & 0x1F);\n                data[len++] = (byte) (0x80 | c & 0x3F);\n            }\n        }\n        length = len;\n        return this;\n    }\n\n    /**\n     * Puts an array of bytes into this byte vector. The byte vector is\n     * automatically enlarged if necessary.\n     * \n     * @param b\n     *            an array of bytes. May be <tt>null</tt> to put <tt>len</tt>\n     *            null bytes into this byte vector.\n     * @param off\n     *            index of the fist byte of b that must be copied.\n     * @param len\n     *            number of bytes of b that must be copied.\n     * @return this byte vector.\n     */\n    public ByteVector putByteArray(final byte[] b, final int off, final int len) {\n        if (length + len > data.length) {\n            enlarge(len);\n        }\n        if (b != null) {\n            System.arraycopy(b, off, data, length, len);\n        }\n        length += len;\n        return this;\n    }\n\n    /**\n     * Enlarge this byte vector so that it can receive n more bytes.\n     * \n     * @param size\n     *            number of additional bytes that this byte vector should be\n     *            able to receive.\n     */\n    private void enlarge(final int size) {\n        int length1 = 2 * data.length;\n        int length2 = length + size;\n        byte[] newData = new byte[length1 > length2 ? length1 : length2];\n        System.arraycopy(data, 0, newData, 0, length);\n        data = newData;\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/ClassReader.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\nimport java.io.IOException;\nimport java.io.InputStream;\n\n/**\n * A Java class parser to make a {@link ClassVisitor} visit an existing class.\n * This class parses a byte array conforming to the Java class file format and\n * calls the appropriate visit methods of a given class visitor for each field,\n * method and bytecode instruction encountered.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\npublic class ClassReader {\n\n    /**\n     * True to enable signatures support.\n     */\n    static final boolean SIGNATURES = true;\n\n    /**\n     * True to enable annotations support.\n     */\n    static final boolean ANNOTATIONS = true;\n\n    /**\n     * True to enable stack map frames support.\n     */\n    static final boolean FRAMES = true;\n\n    /**\n     * True to enable bytecode writing support.\n     */\n    static final boolean WRITER = true;\n\n    /**\n     * True to enable JSR_W and GOTO_W support.\n     */\n    static final boolean RESIZE = true;\n\n    /**\n     * Flag to skip method code. If this class is set <code>CODE</code>\n     * attribute won't be visited. This can be used, for example, to retrieve\n     * annotations for methods and method parameters.\n     */\n    public static final int SKIP_CODE = 1;\n\n    /**\n     * Flag to skip the debug information in the class. If this flag is set the\n     * debug information of the class is not visited, i.e. the\n     * {@link MethodVisitor#visitLocalVariable visitLocalVariable} and\n     * {@link MethodVisitor#visitLineNumber visitLineNumber} methods will not be\n     * called.\n     */\n    public static final int SKIP_DEBUG = 2;\n\n    /**\n     * Flag to skip the stack map frames in the class. If this flag is set the\n     * stack map frames of the class is not visited, i.e. the\n     * {@link MethodVisitor#visitFrame visitFrame} method will not be called.\n     * This flag is useful when the {@link ClassWriter#COMPUTE_FRAMES} option is\n     * used: it avoids visiting frames that will be ignored and recomputed from\n     * scratch in the class writer.\n     */\n    public static final int SKIP_FRAMES = 4;\n\n    /**\n     * Flag to expand the stack map frames. By default stack map frames are\n     * visited in their original format (i.e. \"expanded\" for classes whose\n     * version is less than V1_6, and \"compressed\" for the other classes). If\n     * this flag is set, stack map frames are always visited in expanded format\n     * (this option adds a decompression/recompression step in ClassReader and\n     * ClassWriter which degrades performances quite a lot).\n     */\n    public static final int EXPAND_FRAMES = 8;\n\n    /**\n     * The class to be parsed. <i>The content of this array must not be\n     * modified. This field is intended for {@link Attribute} sub classes, and\n     * is normally not needed by class generators or adapters.</i>\n     */\n    public final byte[] b;\n\n    /**\n     * The start index of each constant pool item in {@link #b b}, plus one. The\n     * one byte offset skips the constant pool item tag that indicates its type.\n     */\n    private final int[] items;\n\n    /**\n     * The String objects corresponding to the CONSTANT_Utf8 items. This cache\n     * avoids multiple parsing of a given CONSTANT_Utf8 constant pool item,\n     * which GREATLY improves performances (by a factor 2 to 3). This caching\n     * strategy could be extended to all constant pool items, but its benefit\n     * would not be so great for these items (because they are much less\n     * expensive to parse than CONSTANT_Utf8 items).\n     */\n    private final String[] strings;\n\n    /**\n     * Maximum length of the strings contained in the constant pool of the\n     * class.\n     */\n    private final int maxStringLength;\n\n    /**\n     * Start index of the class header information (access, name...) in\n     * {@link #b b}.\n     */\n    public final int header;\n\n    // ------------------------------------------------------------------------\n    // Constructors\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     * \n     * @param b\n     *            the bytecode of the class to be read.\n     */\n    public ClassReader(final byte[] b) {\n        this(b, 0, b.length);\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     * \n     * @param b\n     *            the bytecode of the class to be read.\n     * @param off\n     *            the start offset of the class data.\n     * @param len\n     *            the length of the class data.\n     */\n    public ClassReader(final byte[] b, final int off, final int len) {\n        this.b = b;\n        // checks the class version\n        if (readShort(off + 6) > Opcodes.V1_8) {\n            throw new IllegalArgumentException();\n        }\n        // parses the constant pool\n        items = new int[readUnsignedShort(off + 8)];\n        int n = items.length;\n        strings = new String[n];\n        int max = 0;\n        int index = off + 10;\n        for (int i = 1; i < n; ++i) {\n            items[i] = index + 1;\n            int size;\n            switch (b[index]) {\n            case ClassWriter.FIELD:\n            case ClassWriter.METH:\n            case ClassWriter.IMETH:\n            case ClassWriter.INT:\n            case ClassWriter.FLOAT:\n            case ClassWriter.NAME_TYPE:\n            case ClassWriter.INDY:\n                size = 5;\n                break;\n            case ClassWriter.LONG:\n            case ClassWriter.DOUBLE:\n                size = 9;\n                ++i;\n                break;\n            case ClassWriter.UTF8:\n                size = 3 + readUnsignedShort(index + 1);\n                if (size > max) {\n                    max = size;\n                }\n                break;\n            case ClassWriter.HANDLE:\n                size = 4;\n                break;\n            // case ClassWriter.CLASS:\n            // case ClassWriter.STR:\n            // case ClassWriter.MTYPE\n            default:\n                size = 3;\n                break;\n            }\n            index += size;\n        }\n        maxStringLength = max;\n        // the class header information starts just after the constant pool\n        header = index;\n    }\n\n    /**\n     * Returns the class's access flags (see {@link Opcodes}). This value may\n     * not reflect Deprecated and Synthetic flags when bytecode is before 1.5\n     * and those flags are represented by attributes.\n     * \n     * @return the class access flags\n     * \n     * @see ClassVisitor#visit(int, int, String, String, String, String[])\n     */\n    public int getAccess() {\n        return readUnsignedShort(header);\n    }\n\n    /**\n     * Returns the internal name of the class (see\n     * {@link Type#getInternalName() getInternalName}).\n     * \n     * @return the internal class name\n     * \n     * @see ClassVisitor#visit(int, int, String, String, String, String[])\n     */\n    public String getClassName() {\n        return readClass(header + 2, new char[maxStringLength]);\n    }\n\n    /**\n     * Returns the internal of name of the super class (see\n     * {@link Type#getInternalName() getInternalName}). For interfaces, the\n     * super class is {@link Object}.\n     * \n     * @return the internal name of super class, or <tt>null</tt> for\n     *         {@link Object} class.\n     * \n     * @see ClassVisitor#visit(int, int, String, String, String, String[])\n     */\n    public String getSuperName() {\n        return readClass(header + 4, new char[maxStringLength]);\n    }\n\n    /**\n     * Returns the internal names of the class's interfaces (see\n     * {@link Type#getInternalName() getInternalName}).\n     * \n     * @return the array of internal names for all implemented interfaces or\n     *         <tt>null</tt>.\n     * \n     * @see ClassVisitor#visit(int, int, String, String, String, String[])\n     */\n    public String[] getInterfaces() {\n        int index = header + 6;\n        int n = readUnsignedShort(index);\n        String[] interfaces = new String[n];\n        if (n > 0) {\n            char[] buf = new char[maxStringLength];\n            for (int i = 0; i < n; ++i) {\n                index += 2;\n                interfaces[i] = readClass(index, buf);\n            }\n        }\n        return interfaces;\n    }\n\n    /**\n     * Copies the constant pool data into the given {@link ClassWriter}. Should\n     * be called before the {@link #accept(ClassVisitor,int)} method.\n     * \n     * @param classWriter\n     *            the {@link ClassWriter} to copy constant pool into.\n     */\n    void copyPool(final ClassWriter classWriter) {\n        char[] buf = new char[maxStringLength];\n        int ll = items.length;\n        Item[] items2 = new Item[ll];\n        for (int i = 1; i < ll; i++) {\n            int index = items[i];\n            int tag = b[index - 1];\n            Item item = new Item(i);\n            int nameType;\n            switch (tag) {\n            case ClassWriter.FIELD:\n            case ClassWriter.METH:\n            case ClassWriter.IMETH:\n                nameType = items[readUnsignedShort(index + 2)];\n                item.set(tag, readClass(index, buf), readUTF8(nameType, buf),\n                        readUTF8(nameType + 2, buf));\n                break;\n            case ClassWriter.INT:\n                item.set(readInt(index));\n                break;\n            case ClassWriter.FLOAT:\n                item.set(Float.intBitsToFloat(readInt(index)));\n                break;\n            case ClassWriter.NAME_TYPE:\n                item.set(tag, readUTF8(index, buf), readUTF8(index + 2, buf),\n                        null);\n                break;\n            case ClassWriter.LONG:\n                item.set(readLong(index));\n                ++i;\n                break;\n            case ClassWriter.DOUBLE:\n                item.set(Double.longBitsToDouble(readLong(index)));\n                ++i;\n                break;\n            case ClassWriter.UTF8: {\n                String s = strings[i];\n                if (s == null) {\n                    index = items[i];\n                    s = strings[i] = readUTF(index + 2,\n                            readUnsignedShort(index), buf);\n                }\n                item.set(tag, s, null, null);\n                break;\n            }\n            case ClassWriter.HANDLE: {\n                int fieldOrMethodRef = items[readUnsignedShort(index + 1)];\n                nameType = items[readUnsignedShort(fieldOrMethodRef + 2)];\n                item.set(ClassWriter.HANDLE_BASE + readByte(index),\n                        readClass(fieldOrMethodRef, buf),\n                        readUTF8(nameType, buf), readUTF8(nameType + 2, buf));\n                break;\n            }\n            case ClassWriter.INDY:\n                if (classWriter.bootstrapMethods == null) {\n                    copyBootstrapMethods(classWriter, items2, buf);\n                }\n                nameType = items[readUnsignedShort(index + 2)];\n                item.set(readUTF8(nameType, buf), readUTF8(nameType + 2, buf),\n                        readUnsignedShort(index));\n                break;\n            // case ClassWriter.STR:\n            // case ClassWriter.CLASS:\n            // case ClassWriter.MTYPE\n            default:\n                item.set(tag, readUTF8(index, buf), null, null);\n                break;\n            }\n\n            int index2 = item.hashCode % items2.length;\n            item.next = items2[index2];\n            items2[index2] = item;\n        }\n\n        int off = items[1] - 1;\n        classWriter.pool.putByteArray(b, off, header - off);\n        classWriter.items = items2;\n        classWriter.threshold = (int) (0.75d * ll);\n        classWriter.index = ll;\n    }\n\n    /**\n     * Copies the bootstrap method data into the given {@link ClassWriter}.\n     * Should be called before the {@link #accept(ClassVisitor,int)} method.\n     * \n     * @param classWriter\n     *            the {@link ClassWriter} to copy bootstrap methods into.\n     */\n    private void copyBootstrapMethods(final ClassWriter classWriter,\n            final Item[] items, final char[] c) {\n        // finds the \"BootstrapMethods\" attribute\n        int u = getAttributes();\n        boolean found = false;\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            String attrName = readUTF8(u + 2, c);\n            if (\"BootstrapMethods\".equals(attrName)) {\n                found = true;\n                break;\n            }\n            u += 6 + readInt(u + 4);\n        }\n        if (!found) {\n            return;\n        }\n        // copies the bootstrap methods in the class writer\n        int boostrapMethodCount = readUnsignedShort(u + 8);\n        for (int j = 0, v = u + 10; j < boostrapMethodCount; j++) {\n            int position = v - u - 10;\n            int hashCode = readConst(readUnsignedShort(v), c).hashCode();\n            for (int k = readUnsignedShort(v + 2); k > 0; --k) {\n                hashCode ^= readConst(readUnsignedShort(v + 4), c).hashCode();\n                v += 2;\n            }\n            v += 4;\n            Item item = new Item(j);\n            item.set(position, hashCode & 0x7FFFFFFF);\n            int index = item.hashCode % items.length;\n            item.next = items[index];\n            items[index] = item;\n        }\n        int attrSize = readInt(u + 4);\n        ByteVector bootstrapMethods = new ByteVector(attrSize + 62);\n        bootstrapMethods.putByteArray(b, u + 10, attrSize - 2);\n        classWriter.bootstrapMethodsCount = boostrapMethodCount;\n        classWriter.bootstrapMethods = bootstrapMethods;\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     * \n     * @param is\n     *            an input stream from which to read the class.\n     * @throws IOException\n     *             if a problem occurs during reading.\n     */\n    public ClassReader(final InputStream is) throws IOException {\n        this(readClass(is, false));\n    }\n\n    /**\n     * Constructs a new {@link ClassReader} object.\n     * \n     * @param name\n     *            the binary qualified name of the class to be read.\n     * @throws IOException\n     *             if an exception occurs during reading.\n     */\n    public ClassReader(final String name) throws IOException {\n        this(readClass(\n                ClassLoader.getSystemResourceAsStream(name.replace('.', '/')\n                        + \".class\"), true));\n    }\n\n    /**\n     * Reads the bytecode of a class.\n     * \n     * @param is\n     *            an input stream from which to read the class.\n     * @param close\n     *            true to close the input stream after reading.\n     * @return the bytecode read from the given input stream.\n     * @throws IOException\n     *             if a problem occurs during reading.\n     */\n    private static byte[] readClass(final InputStream is, boolean close)\n            throws IOException {\n        if (is == null) {\n            throw new IOException(\"Class not found\");\n        }\n        try {\n            byte[] b = new byte[is.available()];\n            int len = 0;\n            while (true) {\n                int n = is.read(b, len, b.length - len);\n                if (n == -1) {\n                    if (len < b.length) {\n                        byte[] c = new byte[len];\n                        System.arraycopy(b, 0, c, 0, len);\n                        b = c;\n                    }\n                    return b;\n                }\n                len += n;\n                if (len == b.length) {\n                    int last = is.read();\n                    if (last < 0) {\n                        return b;\n                    }\n                    byte[] c = new byte[b.length + 1000];\n                    System.arraycopy(b, 0, c, 0, len);\n                    c[len++] = (byte) last;\n                    b = c;\n                }\n            }\n        } finally {\n            if (close) {\n                is.close();\n            }\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Public methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Makes the given visitor visit the Java class of this {@link ClassReader}\n     * . This class is the one specified in the constructor (see\n     * {@link #ClassReader(byte[]) ClassReader}).\n     * \n     * @param classVisitor\n     *            the visitor that must visit this class.\n     * @param flags\n     *            option flags that can be used to modify the default behavior\n     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}\n     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.\n     */\n    public void accept(final ClassVisitor classVisitor, final int flags) {\n        accept(classVisitor, new Attribute[0], flags);\n    }\n\n    /**\n     * Makes the given visitor visit the Java class of this {@link ClassReader}.\n     * This class is the one specified in the constructor (see\n     * {@link #ClassReader(byte[]) ClassReader}).\n     * \n     * @param classVisitor\n     *            the visitor that must visit this class.\n     * @param attrs\n     *            prototypes of the attributes that must be parsed during the\n     *            visit of the class. Any attribute whose type is not equal to\n     *            the type of one the prototypes will not be parsed: its byte\n     *            array value will be passed unchanged to the ClassWriter.\n     *            <i>This may corrupt it if this value contains references to\n     *            the constant pool, or has syntactic or semantic links with a\n     *            class element that has been transformed by a class adapter\n     *            between the reader and the writer</i>.\n     * @param flags\n     *            option flags that can be used to modify the default behavior\n     *            of this class. See {@link #SKIP_DEBUG}, {@link #EXPAND_FRAMES}\n     *            , {@link #SKIP_FRAMES}, {@link #SKIP_CODE}.\n     */\n    public void accept(final ClassVisitor classVisitor,\n            final Attribute[] attrs, final int flags) {\n        int u = header; // current offset in the class file\n        char[] c = new char[maxStringLength]; // buffer used to read strings\n\n        Context context = new Context();\n        context.attrs = attrs;\n        context.flags = flags;\n        context.buffer = c;\n\n        // reads the class declaration\n        int access = readUnsignedShort(u);\n        String name = readClass(u + 2, c);\n        String superClass = readClass(u + 4, c);\n        String[] interfaces = new String[readUnsignedShort(u + 6)];\n        u += 8;\n        for (int i = 0; i < interfaces.length; ++i) {\n            interfaces[i] = readClass(u, c);\n            u += 2;\n        }\n\n        // reads the class attributes\n        String signature = null;\n        String sourceFile = null;\n        String sourceDebug = null;\n        String enclosingOwner = null;\n        String enclosingName = null;\n        String enclosingDesc = null;\n        int anns = 0;\n        int ianns = 0;\n        int tanns = 0;\n        int itanns = 0;\n        int innerClasses = 0;\n        Attribute attributes = null;\n\n        u = getAttributes();\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            String attrName = readUTF8(u + 2, c);\n            // tests are sorted in decreasing frequency order\n            // (based on frequencies observed on typical classes)\n            if (\"SourceFile\".equals(attrName)) {\n                sourceFile = readUTF8(u + 8, c);\n            } else if (\"InnerClasses\".equals(attrName)) {\n                innerClasses = u + 8;\n            } else if (\"EnclosingMethod\".equals(attrName)) {\n                enclosingOwner = readClass(u + 8, c);\n                int item = readUnsignedShort(u + 10);\n                if (item != 0) {\n                    enclosingName = readUTF8(items[item], c);\n                    enclosingDesc = readUTF8(items[item] + 2, c);\n                }\n            } else if (SIGNATURES && \"Signature\".equals(attrName)) {\n                signature = readUTF8(u + 8, c);\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleAnnotations\".equals(attrName)) {\n                anns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleTypeAnnotations\".equals(attrName)) {\n                tanns = u + 8;\n            } else if (\"Deprecated\".equals(attrName)) {\n                access |= Opcodes.ACC_DEPRECATED;\n            } else if (\"Synthetic\".equals(attrName)) {\n                access |= Opcodes.ACC_SYNTHETIC\n                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;\n            } else if (\"SourceDebugExtension\".equals(attrName)) {\n                int len = readInt(u + 4);\n                sourceDebug = readUTF(u + 8, len, new char[len]);\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleAnnotations\".equals(attrName)) {\n                ianns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleTypeAnnotations\".equals(attrName)) {\n                itanns = u + 8;\n            } else if (\"BootstrapMethods\".equals(attrName)) {\n                int[] bootstrapMethods = new int[readUnsignedShort(u + 8)];\n                for (int j = 0, v = u + 10; j < bootstrapMethods.length; j++) {\n                    bootstrapMethods[j] = v;\n                    v += 2 + readUnsignedShort(v + 2) << 1;\n                }\n                context.bootstrapMethods = bootstrapMethods;\n            } else {\n                Attribute attr = readAttribute(attrs, attrName, u + 8,\n                        readInt(u + 4), c, -1, null);\n                if (attr != null) {\n                    attr.next = attributes;\n                    attributes = attr;\n                }\n            }\n            u += 6 + readInt(u + 4);\n        }\n\n        // visits the class declaration\n        classVisitor.visit(readInt(items[1] - 7), access, name, signature,\n                superClass, interfaces);\n\n        // visits the source and debug info\n        if ((flags & SKIP_DEBUG) == 0\n                && (sourceFile != null || sourceDebug != null)) {\n            classVisitor.visitSource(sourceFile, sourceDebug);\n        }\n\n        // visits the outer class\n        if (enclosingOwner != null) {\n            classVisitor.visitOuterClass(enclosingOwner, enclosingName,\n                    enclosingDesc);\n        }\n\n        // visits the class annotations and type annotations\n        if (ANNOTATIONS && anns != 0) {\n            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        classVisitor.visitAnnotation(readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && ianns != 0) {\n            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        classVisitor.visitAnnotation(readUTF8(v, c), false));\n            }\n        }\n        if (ANNOTATIONS && tanns != 0) {\n            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        classVisitor.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && itanns != 0) {\n            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        classVisitor.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), false));\n            }\n        }\n\n        // visits the attributes\n        while (attributes != null) {\n            Attribute attr = attributes.next;\n            attributes.next = null;\n            classVisitor.visitAttribute(attributes);\n            attributes = attr;\n        }\n\n        // visits the inner classes\n        if (innerClasses != 0) {\n            int v = innerClasses + 2;\n            for (int i = readUnsignedShort(innerClasses); i > 0; --i) {\n                classVisitor.visitInnerClass(readClass(v, c),\n                        readClass(v + 2, c), readUTF8(v + 4, c),\n                        readUnsignedShort(v + 6));\n                v += 8;\n            }\n        }\n\n        // visits the fields and methods\n        u = header + 10 + 2 * interfaces.length;\n        for (int i = readUnsignedShort(u - 2); i > 0; --i) {\n            u = readField(classVisitor, context, u);\n        }\n        u += 2;\n        for (int i = readUnsignedShort(u - 2); i > 0; --i) {\n            u = readMethod(classVisitor, context, u);\n        }\n\n        // visits the end of the class\n        classVisitor.visitEnd();\n    }\n\n    /**\n     * Reads a field and makes the given visitor visit it.\n     * \n     * @param classVisitor\n     *            the visitor that must visit the field.\n     * @param context\n     *            information about the class being parsed.\n     * @param u\n     *            the start offset of the field in the class file.\n     * @return the offset of the first byte following the field in the class.\n     */\n    private int readField(final ClassVisitor classVisitor,\n            final Context context, int u) {\n        // reads the field declaration\n        char[] c = context.buffer;\n        int access = readUnsignedShort(u);\n        String name = readUTF8(u + 2, c);\n        String desc = readUTF8(u + 4, c);\n        u += 6;\n\n        // reads the field attributes\n        String signature = null;\n        int anns = 0;\n        int ianns = 0;\n        int tanns = 0;\n        int itanns = 0;\n        Object value = null;\n        Attribute attributes = null;\n\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            String attrName = readUTF8(u + 2, c);\n            // tests are sorted in decreasing frequency order\n            // (based on frequencies observed on typical classes)\n            if (\"ConstantValue\".equals(attrName)) {\n                int item = readUnsignedShort(u + 8);\n                value = item == 0 ? null : readConst(item, c);\n            } else if (SIGNATURES && \"Signature\".equals(attrName)) {\n                signature = readUTF8(u + 8, c);\n            } else if (\"Deprecated\".equals(attrName)) {\n                access |= Opcodes.ACC_DEPRECATED;\n            } else if (\"Synthetic\".equals(attrName)) {\n                access |= Opcodes.ACC_SYNTHETIC\n                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleAnnotations\".equals(attrName)) {\n                anns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleTypeAnnotations\".equals(attrName)) {\n                tanns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleAnnotations\".equals(attrName)) {\n                ianns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleTypeAnnotations\".equals(attrName)) {\n                itanns = u + 8;\n            } else {\n                Attribute attr = readAttribute(context.attrs, attrName, u + 8,\n                        readInt(u + 4), c, -1, null);\n                if (attr != null) {\n                    attr.next = attributes;\n                    attributes = attr;\n                }\n            }\n            u += 6 + readInt(u + 4);\n        }\n        u += 2;\n\n        // visits the field declaration\n        FieldVisitor fv = classVisitor.visitField(access, name, desc,\n                signature, value);\n        if (fv == null) {\n            return u;\n        }\n\n        // visits the field annotations and type annotations\n        if (ANNOTATIONS && anns != 0) {\n            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        fv.visitAnnotation(readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && ianns != 0) {\n            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        fv.visitAnnotation(readUTF8(v, c), false));\n            }\n        }\n        if (ANNOTATIONS && tanns != 0) {\n            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        fv.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && itanns != 0) {\n            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        fv.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), false));\n            }\n        }\n\n        // visits the field attributes\n        while (attributes != null) {\n            Attribute attr = attributes.next;\n            attributes.next = null;\n            fv.visitAttribute(attributes);\n            attributes = attr;\n        }\n\n        // visits the end of the field\n        fv.visitEnd();\n\n        return u;\n    }\n\n    /**\n     * Reads a method and makes the given visitor visit it.\n     * \n     * @param classVisitor\n     *            the visitor that must visit the method.\n     * @param context\n     *            information about the class being parsed.\n     * @param u\n     *            the start offset of the method in the class file.\n     * @return the offset of the first byte following the method in the class.\n     */\n    private int readMethod(final ClassVisitor classVisitor,\n            final Context context, int u) {\n        // reads the method declaration\n        char[] c = context.buffer;\n        context.access = readUnsignedShort(u);\n        context.name = readUTF8(u + 2, c);\n        context.desc = readUTF8(u + 4, c);\n        u += 6;\n\n        // reads the method attributes\n        int code = 0;\n        int exception = 0;\n        String[] exceptions = null;\n        String signature = null;\n        int methodParameters = 0;\n        int anns = 0;\n        int ianns = 0;\n        int tanns = 0;\n        int itanns = 0;\n        int dann = 0;\n        int mpanns = 0;\n        int impanns = 0;\n        int firstAttribute = u;\n        Attribute attributes = null;\n\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            String attrName = readUTF8(u + 2, c);\n            // tests are sorted in decreasing frequency order\n            // (based on frequencies observed on typical classes)\n            if (\"Code\".equals(attrName)) {\n                if ((context.flags & SKIP_CODE) == 0) {\n                    code = u + 8;\n                }\n            } else if (\"Exceptions\".equals(attrName)) {\n                exceptions = new String[readUnsignedShort(u + 8)];\n                exception = u + 10;\n                for (int j = 0; j < exceptions.length; ++j) {\n                    exceptions[j] = readClass(exception, c);\n                    exception += 2;\n                }\n            } else if (SIGNATURES && \"Signature\".equals(attrName)) {\n                signature = readUTF8(u + 8, c);\n            } else if (\"Deprecated\".equals(attrName)) {\n                context.access |= Opcodes.ACC_DEPRECATED;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleAnnotations\".equals(attrName)) {\n                anns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleTypeAnnotations\".equals(attrName)) {\n                tanns = u + 8;\n            } else if (ANNOTATIONS && \"AnnotationDefault\".equals(attrName)) {\n                dann = u + 8;\n            } else if (\"Synthetic\".equals(attrName)) {\n                context.access |= Opcodes.ACC_SYNTHETIC\n                        | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleAnnotations\".equals(attrName)) {\n                ianns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleTypeAnnotations\".equals(attrName)) {\n                itanns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleParameterAnnotations\".equals(attrName)) {\n                mpanns = u + 8;\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleParameterAnnotations\".equals(attrName)) {\n                impanns = u + 8;\n            } else if (\"MethodParameters\".equals(attrName)) {\n                methodParameters = u + 8;\n            } else {\n                Attribute attr = readAttribute(context.attrs, attrName, u + 8,\n                        readInt(u + 4), c, -1, null);\n                if (attr != null) {\n                    attr.next = attributes;\n                    attributes = attr;\n                }\n            }\n            u += 6 + readInt(u + 4);\n        }\n        u += 2;\n\n        // visits the method declaration\n        MethodVisitor mv = classVisitor.visitMethod(context.access,\n                context.name, context.desc, signature, exceptions);\n        if (mv == null) {\n            return u;\n        }\n\n        /*\n         * if the returned MethodVisitor is in fact a MethodWriter, it means\n         * there is no method adapter between the reader and the writer. If, in\n         * addition, the writer's constant pool was copied from this reader\n         * (mw.cw.cr == this), and the signature and exceptions of the method\n         * have not been changed, then it is possible to skip all visit events\n         * and just copy the original code of the method to the writer (the\n         * access, name and descriptor can have been changed, this is not\n         * important since they are not copied as is from the reader).\n         */\n        if (WRITER && mv instanceof MethodWriter) {\n            MethodWriter mw = (MethodWriter) mv;\n            if (mw.cw.cr == this && signature == mw.signature) {\n                boolean sameExceptions = false;\n                if (exceptions == null) {\n                    sameExceptions = mw.exceptionCount == 0;\n                } else if (exceptions.length == mw.exceptionCount) {\n                    sameExceptions = true;\n                    for (int j = exceptions.length - 1; j >= 0; --j) {\n                        exception -= 2;\n                        if (mw.exceptions[j] != readUnsignedShort(exception)) {\n                            sameExceptions = false;\n                            break;\n                        }\n                    }\n                }\n                if (sameExceptions) {\n                    /*\n                     * we do not copy directly the code into MethodWriter to\n                     * save a byte array copy operation. The real copy will be\n                     * done in ClassWriter.toByteArray().\n                     */\n                    mw.classReaderOffset = firstAttribute;\n                    mw.classReaderLength = u - firstAttribute;\n                    return u;\n                }\n            }\n        }\n\n        // visit the method parameters\n        if (methodParameters != 0) {\n            for (int i = b[methodParameters] & 0xFF, v = methodParameters + 1; i > 0; --i, v = v + 4) {\n                mv.visitParameter(readUTF8(v, c), readUnsignedShort(v + 2));\n            }\n        }\n\n        // visits the method annotations\n        if (ANNOTATIONS && dann != 0) {\n            AnnotationVisitor dv = mv.visitAnnotationDefault();\n            readAnnotationValue(dann, c, null, dv);\n            if (dv != null) {\n                dv.visitEnd();\n            }\n        }\n        if (ANNOTATIONS && anns != 0) {\n            for (int i = readUnsignedShort(anns), v = anns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        mv.visitAnnotation(readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && ianns != 0) {\n            for (int i = readUnsignedShort(ianns), v = ianns + 2; i > 0; --i) {\n                v = readAnnotationValues(v + 2, c, true,\n                        mv.visitAnnotation(readUTF8(v, c), false));\n            }\n        }\n        if (ANNOTATIONS && tanns != 0) {\n            for (int i = readUnsignedShort(tanns), v = tanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        mv.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), true));\n            }\n        }\n        if (ANNOTATIONS && itanns != 0) {\n            for (int i = readUnsignedShort(itanns), v = itanns + 2; i > 0; --i) {\n                v = readAnnotationTarget(context, v);\n                v = readAnnotationValues(v + 2, c, true,\n                        mv.visitTypeAnnotation(context.typeRef,\n                                context.typePath, readUTF8(v, c), false));\n            }\n        }\n        if (ANNOTATIONS && mpanns != 0) {\n            readParameterAnnotations(mv, context, mpanns, true);\n        }\n        if (ANNOTATIONS && impanns != 0) {\n            readParameterAnnotations(mv, context, impanns, false);\n        }\n\n        // visits the method attributes\n        while (attributes != null) {\n            Attribute attr = attributes.next;\n            attributes.next = null;\n            mv.visitAttribute(attributes);\n            attributes = attr;\n        }\n\n        // visits the method code\n        if (code != 0) {\n            mv.visitCode();\n            readCode(mv, context, code);\n        }\n\n        // visits the end of the method\n        mv.visitEnd();\n\n        return u;\n    }\n\n    /**\n     * Reads the bytecode of a method and makes the given visitor visit it.\n     * \n     * @param mv\n     *            the visitor that must visit the method's code.\n     * @param context\n     *            information about the class being parsed.\n     * @param u\n     *            the start offset of the code attribute in the class file.\n     */\n    private void readCode(final MethodVisitor mv, final Context context, int u) {\n        // reads the header\n        byte[] b = this.b;\n        char[] c = context.buffer;\n        int maxStack = readUnsignedShort(u);\n        int maxLocals = readUnsignedShort(u + 2);\n        int codeLength = readInt(u + 4);\n        u += 8;\n\n        // reads the bytecode to find the labels\n        int codeStart = u;\n        int codeEnd = u + codeLength;\n        Label[] labels = context.labels = new Label[codeLength + 2];\n        readLabel(codeLength + 1, labels);\n        while (u < codeEnd) {\n            int offset = u - codeStart;\n            int opcode = b[u] & 0xFF;\n            switch (ClassWriter.TYPE[opcode]) {\n            case ClassWriter.NOARG_INSN:\n            case ClassWriter.IMPLVAR_INSN:\n                u += 1;\n                break;\n            case ClassWriter.LABEL_INSN:\n                readLabel(offset + readShort(u + 1), labels);\n                u += 3;\n                break;\n            case ClassWriter.LABELW_INSN:\n                readLabel(offset + readInt(u + 1), labels);\n                u += 5;\n                break;\n            case ClassWriter.WIDE_INSN:\n                opcode = b[u + 1] & 0xFF;\n                if (opcode == Opcodes.IINC) {\n                    u += 6;\n                } else {\n                    u += 4;\n                }\n                break;\n            case ClassWriter.TABL_INSN:\n                // skips 0 to 3 padding bytes\n                u = u + 4 - (offset & 3);\n                // reads instruction\n                readLabel(offset + readInt(u), labels);\n                for (int i = readInt(u + 8) - readInt(u + 4) + 1; i > 0; --i) {\n                    readLabel(offset + readInt(u + 12), labels);\n                    u += 4;\n                }\n                u += 12;\n                break;\n            case ClassWriter.LOOK_INSN:\n                // skips 0 to 3 padding bytes\n                u = u + 4 - (offset & 3);\n                // reads instruction\n                readLabel(offset + readInt(u), labels);\n                for (int i = readInt(u + 4); i > 0; --i) {\n                    readLabel(offset + readInt(u + 12), labels);\n                    u += 8;\n                }\n                u += 8;\n                break;\n            case ClassWriter.VAR_INSN:\n            case ClassWriter.SBYTE_INSN:\n            case ClassWriter.LDC_INSN:\n                u += 2;\n                break;\n            case ClassWriter.SHORT_INSN:\n            case ClassWriter.LDCW_INSN:\n            case ClassWriter.FIELDORMETH_INSN:\n            case ClassWriter.TYPE_INSN:\n            case ClassWriter.IINC_INSN:\n                u += 3;\n                break;\n            case ClassWriter.ITFMETH_INSN:\n            case ClassWriter.INDYMETH_INSN:\n                u += 5;\n                break;\n            // case MANA_INSN:\n            default:\n                u += 4;\n                break;\n            }\n        }\n\n        // reads the try catch entries to find the labels, and also visits them\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            Label start = readLabel(readUnsignedShort(u + 2), labels);\n            Label end = readLabel(readUnsignedShort(u + 4), labels);\n            Label handler = readLabel(readUnsignedShort(u + 6), labels);\n            String type = readUTF8(items[readUnsignedShort(u + 8)], c);\n            mv.visitTryCatchBlock(start, end, handler, type);\n            u += 8;\n        }\n        u += 2;\n\n        // reads the code attributes\n        int[] tanns = null; // start index of each visible type annotation\n        int[] itanns = null; // start index of each invisible type annotation\n        int tann = 0; // current index in tanns array\n        int itann = 0; // current index in itanns array\n        int ntoff = -1; // next visible type annotation code offset\n        int nitoff = -1; // next invisible type annotation code offset\n        int varTable = 0;\n        int varTypeTable = 0;\n        boolean zip = true;\n        boolean unzip = (context.flags & EXPAND_FRAMES) != 0;\n        int stackMap = 0;\n        int stackMapSize = 0;\n        int frameCount = 0;\n        Context frame = null;\n        Attribute attributes = null;\n\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            String attrName = readUTF8(u + 2, c);\n            if (\"LocalVariableTable\".equals(attrName)) {\n                if ((context.flags & SKIP_DEBUG) == 0) {\n                    varTable = u + 8;\n                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {\n                        int label = readUnsignedShort(v + 10);\n                        if (labels[label] == null) {\n                            readLabel(label, labels).status |= Label.DEBUG;\n                        }\n                        label += readUnsignedShort(v + 12);\n                        if (labels[label] == null) {\n                            readLabel(label, labels).status |= Label.DEBUG;\n                        }\n                        v += 10;\n                    }\n                }\n            } else if (\"LocalVariableTypeTable\".equals(attrName)) {\n                varTypeTable = u + 8;\n            } else if (\"LineNumberTable\".equals(attrName)) {\n                if ((context.flags & SKIP_DEBUG) == 0) {\n                    for (int j = readUnsignedShort(u + 8), v = u; j > 0; --j) {\n                        int label = readUnsignedShort(v + 10);\n                        if (labels[label] == null) {\n                            readLabel(label, labels).status |= Label.DEBUG;\n                        }\n                        Label l = labels[label];\n                        while (l.line > 0) {\n                            if (l.next == null) {\n                                l.next = new Label();\n                            }\n                            l = l.next;\n                        }\n                        l.line = readUnsignedShort(v + 12);\n                        v += 4;\n                    }\n                }\n            } else if (ANNOTATIONS\n                    && \"RuntimeVisibleTypeAnnotations\".equals(attrName)) {\n                tanns = readTypeAnnotations(mv, context, u + 8, true);\n                ntoff = tanns.length == 0 || readByte(tanns[0]) < 0x43 ? -1\n                        : readUnsignedShort(tanns[0] + 1);\n            } else if (ANNOTATIONS\n                    && \"RuntimeInvisibleTypeAnnotations\".equals(attrName)) {\n                itanns = readTypeAnnotations(mv, context, u + 8, false);\n                nitoff = itanns.length == 0 || readByte(itanns[0]) < 0x43 ? -1\n                        : readUnsignedShort(itanns[0] + 1);\n            } else if (FRAMES && \"StackMapTable\".equals(attrName)) {\n                if ((context.flags & SKIP_FRAMES) == 0) {\n                    stackMap = u + 10;\n                    stackMapSize = readInt(u + 4);\n                    frameCount = readUnsignedShort(u + 8);\n                }\n                /*\n                 * here we do not extract the labels corresponding to the\n                 * attribute content. This would require a full parsing of the\n                 * attribute, which would need to be repeated in the second\n                 * phase (see below). Instead the content of the attribute is\n                 * read one frame at a time (i.e. after a frame has been\n                 * visited, the next frame is read), and the labels it contains\n                 * are also extracted one frame at a time. Thanks to the\n                 * ordering of frames, having only a \"one frame lookahead\" is\n                 * not a problem, i.e. it is not possible to see an offset\n                 * smaller than the offset of the current insn and for which no\n                 * Label exist.\n                 */\n                /*\n                 * This is not true for UNINITIALIZED type offsets. We solve\n                 * this by parsing the stack map table without a full decoding\n                 * (see below).\n                 */\n            } else if (FRAMES && \"StackMap\".equals(attrName)) {\n                if ((context.flags & SKIP_FRAMES) == 0) {\n                    zip = false;\n                    stackMap = u + 10;\n                    stackMapSize = readInt(u + 4);\n                    frameCount = readUnsignedShort(u + 8);\n                }\n                /*\n                 * IMPORTANT! here we assume that the frames are ordered, as in\n                 * the StackMapTable attribute, although this is not guaranteed\n                 * by the attribute format.\n                 */\n            } else {\n                for (int j = 0; j < context.attrs.length; ++j) {\n                    if (context.attrs[j].type.equals(attrName)) {\n                        Attribute attr = context.attrs[j].read(this, u + 8,\n                                readInt(u + 4), c, codeStart - 8, labels);\n                        if (attr != null) {\n                            attr.next = attributes;\n                            attributes = attr;\n                        }\n                    }\n                }\n            }\n            u += 6 + readInt(u + 4);\n        }\n        u += 2;\n\n        // generates the first (implicit) stack map frame\n        if (FRAMES && stackMap != 0) {\n            /*\n             * for the first explicit frame the offset is not offset_delta + 1\n             * but only offset_delta; setting the implicit frame offset to -1\n             * allow the use of the \"offset_delta + 1\" rule in all cases\n             */\n            frame = context;\n            frame.offset = -1;\n            frame.mode = 0;\n            frame.localCount = 0;\n            frame.localDiff = 0;\n            frame.stackCount = 0;\n            frame.local = new Object[maxLocals];\n            frame.stack = new Object[maxStack];\n            if (unzip) {\n                getImplicitFrame(context);\n            }\n            /*\n             * Finds labels for UNINITIALIZED frame types. Instead of decoding\n             * each element of the stack map table, we look for 3 consecutive\n             * bytes that \"look like\" an UNINITIALIZED type (tag 8, offset\n             * within code bounds, NEW instruction at this offset). We may find\n             * false positives (i.e. not real UNINITIALIZED types), but this\n             * should be rare, and the only consequence will be the creation of\n             * an unneeded label. This is better than creating a label for each\n             * NEW instruction, and faster than fully decoding the whole stack\n             * map table.\n             */\n            for (int i = stackMap; i < stackMap + stackMapSize - 2; ++i) {\n                if (b[i] == 8) { // UNINITIALIZED FRAME TYPE\n                    int v = readUnsignedShort(i + 1);\n                    if (v >= 0 && v < codeLength) {\n                        if ((b[codeStart + v] & 0xFF) == Opcodes.NEW) {\n                            readLabel(v, labels);\n                        }\n                    }\n                }\n            }\n        }\n\n        // visits the instructions\n        u = codeStart;\n        while (u < codeEnd) {\n            int offset = u - codeStart;\n\n            // visits the label and line number for this offset, if any\n            Label l = labels[offset];\n            if (l != null) {\n                Label next = l.next;\n                l.next = null;\n                mv.visitLabel(l);\n                if ((context.flags & SKIP_DEBUG) == 0 && l.line > 0) {\n                    mv.visitLineNumber(l.line, l);\n                    while (next != null) {\n                        mv.visitLineNumber(next.line, l);\n                        next = next.next;\n                    }\n                }\n            }\n\n            // visits the frame for this offset, if any\n            while (FRAMES && frame != null\n                    && (frame.offset == offset || frame.offset == -1)) {\n                // if there is a frame for this offset, makes the visitor visit\n                // it, and reads the next frame if there is one.\n                if (frame.offset != -1) {\n                    if (!zip || unzip) {\n                        mv.visitFrame(Opcodes.F_NEW, frame.localCount,\n                                frame.local, frame.stackCount, frame.stack);\n                    } else {\n                        mv.visitFrame(frame.mode, frame.localDiff, frame.local,\n                                frame.stackCount, frame.stack);\n                    }\n                }\n                if (frameCount > 0) {\n                    stackMap = readFrame(stackMap, zip, unzip, frame);\n                    --frameCount;\n                } else {\n                    frame = null;\n                }\n            }\n\n            // visits the instruction at this offset\n            int opcode = b[u] & 0xFF;\n            switch (ClassWriter.TYPE[opcode]) {\n            case ClassWriter.NOARG_INSN:\n                mv.visitInsn(opcode);\n                u += 1;\n                break;\n            case ClassWriter.IMPLVAR_INSN:\n                if (opcode > Opcodes.ISTORE) {\n                    opcode -= 59; // ISTORE_0\n                    mv.visitVarInsn(Opcodes.ISTORE + (opcode >> 2),\n                            opcode & 0x3);\n                } else {\n                    opcode -= 26; // ILOAD_0\n                    mv.visitVarInsn(Opcodes.ILOAD + (opcode >> 2), opcode & 0x3);\n                }\n                u += 1;\n                break;\n            case ClassWriter.LABEL_INSN:\n                mv.visitJumpInsn(opcode, labels[offset + readShort(u + 1)]);\n                u += 3;\n                break;\n            case ClassWriter.LABELW_INSN:\n                mv.visitJumpInsn(opcode - 33, labels[offset + readInt(u + 1)]);\n                u += 5;\n                break;\n            case ClassWriter.WIDE_INSN:\n                opcode = b[u + 1] & 0xFF;\n                if (opcode == Opcodes.IINC) {\n                    mv.visitIincInsn(readUnsignedShort(u + 2), readShort(u + 4));\n                    u += 6;\n                } else {\n                    mv.visitVarInsn(opcode, readUnsignedShort(u + 2));\n                    u += 4;\n                }\n                break;\n            case ClassWriter.TABL_INSN: {\n                // skips 0 to 3 padding bytes\n                u = u + 4 - (offset & 3);\n                // reads instruction\n                int label = offset + readInt(u);\n                int min = readInt(u + 4);\n                int max = readInt(u + 8);\n                Label[] table = new Label[max - min + 1];\n                u += 12;\n                for (int i = 0; i < table.length; ++i) {\n                    table[i] = labels[offset + readInt(u)];\n                    u += 4;\n                }\n                mv.visitTableSwitchInsn(min, max, labels[label], table);\n                break;\n            }\n            case ClassWriter.LOOK_INSN: {\n                // skips 0 to 3 padding bytes\n                u = u + 4 - (offset & 3);\n                // reads instruction\n                int label = offset + readInt(u);\n                int len = readInt(u + 4);\n                int[] keys = new int[len];\n                Label[] values = new Label[len];\n                u += 8;\n                for (int i = 0; i < len; ++i) {\n                    keys[i] = readInt(u);\n                    values[i] = labels[offset + readInt(u + 4)];\n                    u += 8;\n                }\n                mv.visitLookupSwitchInsn(labels[label], keys, values);\n                break;\n            }\n            case ClassWriter.VAR_INSN:\n                mv.visitVarInsn(opcode, b[u + 1] & 0xFF);\n                u += 2;\n                break;\n            case ClassWriter.SBYTE_INSN:\n                mv.visitIntInsn(opcode, b[u + 1]);\n                u += 2;\n                break;\n            case ClassWriter.SHORT_INSN:\n                mv.visitIntInsn(opcode, readShort(u + 1));\n                u += 3;\n                break;\n            case ClassWriter.LDC_INSN:\n                mv.visitLdcInsn(readConst(b[u + 1] & 0xFF, c));\n                u += 2;\n                break;\n            case ClassWriter.LDCW_INSN:\n                mv.visitLdcInsn(readConst(readUnsignedShort(u + 1), c));\n                u += 3;\n                break;\n            case ClassWriter.FIELDORMETH_INSN:\n            case ClassWriter.ITFMETH_INSN: {\n                int cpIndex = items[readUnsignedShort(u + 1)];\n                boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;\n                String iowner = readClass(cpIndex, c);\n                cpIndex = items[readUnsignedShort(cpIndex + 2)];\n                String iname = readUTF8(cpIndex, c);\n                String idesc = readUTF8(cpIndex + 2, c);\n                if (opcode < Opcodes.INVOKEVIRTUAL) {\n                    mv.visitFieldInsn(opcode, iowner, iname, idesc);\n                } else {\n                    mv.visitMethodInsn(opcode, iowner, iname, idesc, itf);\n                }\n                if (opcode == Opcodes.INVOKEINTERFACE) {\n                    u += 5;\n                } else {\n                    u += 3;\n                }\n                break;\n            }\n            case ClassWriter.INDYMETH_INSN: {\n                int cpIndex = items[readUnsignedShort(u + 1)];\n                int bsmIndex = context.bootstrapMethods[readUnsignedShort(cpIndex)];\n                Handle bsm = (Handle) readConst(readUnsignedShort(bsmIndex), c);\n                int bsmArgCount = readUnsignedShort(bsmIndex + 2);\n                Object[] bsmArgs = new Object[bsmArgCount];\n                bsmIndex += 4;\n                for (int i = 0; i < bsmArgCount; i++) {\n                    bsmArgs[i] = readConst(readUnsignedShort(bsmIndex), c);\n                    bsmIndex += 2;\n                }\n                cpIndex = items[readUnsignedShort(cpIndex + 2)];\n                String iname = readUTF8(cpIndex, c);\n                String idesc = readUTF8(cpIndex + 2, c);\n                mv.visitInvokeDynamicInsn(iname, idesc, bsm, bsmArgs);\n                u += 5;\n                break;\n            }\n            case ClassWriter.TYPE_INSN:\n                mv.visitTypeInsn(opcode, readClass(u + 1, c));\n                u += 3;\n                break;\n            case ClassWriter.IINC_INSN:\n                mv.visitIincInsn(b[u + 1] & 0xFF, b[u + 2]);\n                u += 3;\n                break;\n            // case MANA_INSN:\n            default:\n                mv.visitMultiANewArrayInsn(readClass(u + 1, c), b[u + 3] & 0xFF);\n                u += 4;\n                break;\n            }\n\n            // visit the instruction annotations, if any\n            while (tanns != null && tann < tanns.length && ntoff <= offset) {\n                if (ntoff == offset) {\n                    int v = readAnnotationTarget(context, tanns[tann]);\n                    readAnnotationValues(v + 2, c, true,\n                            mv.visitInsnAnnotation(context.typeRef,\n                                    context.typePath, readUTF8(v, c), true));\n                }\n                ntoff = ++tann >= tanns.length || readByte(tanns[tann]) < 0x43 ? -1\n                        : readUnsignedShort(tanns[tann] + 1);\n            }\n            while (itanns != null && itann < itanns.length && nitoff <= offset) {\n                if (nitoff == offset) {\n                    int v = readAnnotationTarget(context, itanns[itann]);\n                    readAnnotationValues(v + 2, c, true,\n                            mv.visitInsnAnnotation(context.typeRef,\n                                    context.typePath, readUTF8(v, c), false));\n                }\n                nitoff = ++itann >= itanns.length\n                        || readByte(itanns[itann]) < 0x43 ? -1\n                        : readUnsignedShort(itanns[itann] + 1);\n            }\n        }\n        if (labels[codeLength] != null) {\n            mv.visitLabel(labels[codeLength]);\n        }\n\n        // visits the local variable tables\n        if ((context.flags & SKIP_DEBUG) == 0 && varTable != 0) {\n            int[] typeTable = null;\n            if (varTypeTable != 0) {\n                u = varTypeTable + 2;\n                typeTable = new int[readUnsignedShort(varTypeTable) * 3];\n                for (int i = typeTable.length; i > 0;) {\n                    typeTable[--i] = u + 6; // signature\n                    typeTable[--i] = readUnsignedShort(u + 8); // index\n                    typeTable[--i] = readUnsignedShort(u); // start\n                    u += 10;\n                }\n            }\n            u = varTable + 2;\n            for (int i = readUnsignedShort(varTable); i > 0; --i) {\n                int start = readUnsignedShort(u);\n                int length = readUnsignedShort(u + 2);\n                int index = readUnsignedShort(u + 8);\n                String vsignature = null;\n                if (typeTable != null) {\n                    for (int j = 0; j < typeTable.length; j += 3) {\n                        if (typeTable[j] == start && typeTable[j + 1] == index) {\n                            vsignature = readUTF8(typeTable[j + 2], c);\n                            break;\n                        }\n                    }\n                }\n                mv.visitLocalVariable(readUTF8(u + 4, c), readUTF8(u + 6, c),\n                        vsignature, labels[start], labels[start + length],\n                        index);\n                u += 10;\n            }\n        }\n\n        // visits the local variables type annotations\n        if (tanns != null) {\n            for (int i = 0; i < tanns.length; ++i) {\n                if ((readByte(tanns[i]) >> 1) == (0x40 >> 1)) {\n                    int v = readAnnotationTarget(context, tanns[i]);\n                    v = readAnnotationValues(v + 2, c, true,\n                            mv.visitLocalVariableAnnotation(context.typeRef,\n                                    context.typePath, context.start,\n                                    context.end, context.index, readUTF8(v, c),\n                                    true));\n                }\n            }\n        }\n        if (itanns != null) {\n            for (int i = 0; i < itanns.length; ++i) {\n                if ((readByte(itanns[i]) >> 1) == (0x40 >> 1)) {\n                    int v = readAnnotationTarget(context, itanns[i]);\n                    v = readAnnotationValues(v + 2, c, true,\n                            mv.visitLocalVariableAnnotation(context.typeRef,\n                                    context.typePath, context.start,\n                                    context.end, context.index, readUTF8(v, c),\n                                    false));\n                }\n            }\n        }\n\n        // visits the code attributes\n        while (attributes != null) {\n            Attribute attr = attributes.next;\n            attributes.next = null;\n            mv.visitAttribute(attributes);\n            attributes = attr;\n        }\n\n        // visits the max stack and max locals values\n        mv.visitMaxs(maxStack, maxLocals);\n    }\n\n    /**\n     * Parses a type annotation table to find the labels, and to visit the try\n     * catch block annotations.\n     * \n     * @param u\n     *            the start offset of a type annotation table.\n     * @param mv\n     *            the method visitor to be used to visit the try catch block\n     *            annotations.\n     * @param context\n     *            information about the class being parsed.\n     * @param visible\n     *            if the type annotation table to parse contains runtime visible\n     *            annotations.\n     * @return the start offset of each type annotation in the parsed table.\n     */\n    private int[] readTypeAnnotations(final MethodVisitor mv,\n            final Context context, int u, boolean visible) {\n        char[] c = context.buffer;\n        int[] offsets = new int[readUnsignedShort(u)];\n        u += 2;\n        for (int i = 0; i < offsets.length; ++i) {\n            offsets[i] = u;\n            int target = readInt(u);\n            switch (target >>> 24) {\n            case 0x00: // CLASS_TYPE_PARAMETER\n            case 0x01: // METHOD_TYPE_PARAMETER\n            case 0x16: // METHOD_FORMAL_PARAMETER\n                u += 2;\n                break;\n            case 0x13: // FIELD\n            case 0x14: // METHOD_RETURN\n            case 0x15: // METHOD_RECEIVER\n                u += 1;\n                break;\n            case 0x40: // LOCAL_VARIABLE\n            case 0x41: // RESOURCE_VARIABLE\n                for (int j = readUnsignedShort(u + 1); j > 0; --j) {\n                    int start = readUnsignedShort(u + 3);\n                    int length = readUnsignedShort(u + 5);\n                    readLabel(start, context.labels);\n                    readLabel(start + length, context.labels);\n                    u += 6;\n                }\n                u += 3;\n                break;\n            case 0x47: // CAST\n            case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n            case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT\n            case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\n            case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT\n                u += 4;\n                break;\n            // case 0x10: // CLASS_EXTENDS\n            // case 0x11: // CLASS_TYPE_PARAMETER_BOUND\n            // case 0x12: // METHOD_TYPE_PARAMETER_BOUND\n            // case 0x17: // THROWS\n            // case 0x42: // EXCEPTION_PARAMETER\n            // case 0x43: // INSTANCEOF\n            // case 0x44: // NEW\n            // case 0x45: // CONSTRUCTOR_REFERENCE\n            // case 0x46: // METHOD_REFERENCE\n            default:\n                u += 3;\n                break;\n            }\n            int pathLength = readByte(u);\n            if ((target >>> 24) == 0x42) {\n                TypePath path = pathLength == 0 ? null : new TypePath(b, u);\n                u += 1 + 2 * pathLength;\n                u = readAnnotationValues(u + 2, c, true,\n                        mv.visitTryCatchAnnotation(target, path,\n                                readUTF8(u, c), visible));\n            } else {\n                u = readAnnotationValues(u + 3 + 2 * pathLength, c, true, null);\n            }\n        }\n        return offsets;\n    }\n\n    /**\n     * Parses the header of a type annotation to extract its target_type and\n     * target_path (the result is stored in the given context), and returns the\n     * start offset of the rest of the type_annotation structure (i.e. the\n     * offset to the type_index field, which is followed by\n     * num_element_value_pairs and then the name,value pairs).\n     * \n     * @param context\n     *            information about the class being parsed. This is where the\n     *            extracted target_type and target_path must be stored.\n     * @param u\n     *            the start offset of a type_annotation structure.\n     * @return the start offset of the rest of the type_annotation structure.\n     */\n    private int readAnnotationTarget(final Context context, int u) {\n        int target = readInt(u);\n        switch (target >>> 24) {\n        case 0x00: // CLASS_TYPE_PARAMETER\n        case 0x01: // METHOD_TYPE_PARAMETER\n        case 0x16: // METHOD_FORMAL_PARAMETER\n            target &= 0xFFFF0000;\n            u += 2;\n            break;\n        case 0x13: // FIELD\n        case 0x14: // METHOD_RETURN\n        case 0x15: // METHOD_RECEIVER\n            target &= 0xFF000000;\n            u += 1;\n            break;\n        case 0x40: // LOCAL_VARIABLE\n        case 0x41: { // RESOURCE_VARIABLE\n            target &= 0xFF000000;\n            int n = readUnsignedShort(u + 1);\n            context.start = new Label[n];\n            context.end = new Label[n];\n            context.index = new int[n];\n            u += 3;\n            for (int i = 0; i < n; ++i) {\n                int start = readUnsignedShort(u);\n                int length = readUnsignedShort(u + 2);\n                context.start[i] = readLabel(start, context.labels);\n                context.end[i] = readLabel(start + length, context.labels);\n                context.index[i] = readUnsignedShort(u + 4);\n                u += 6;\n            }\n            break;\n        }\n        case 0x47: // CAST\n        case 0x48: // CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n        case 0x49: // METHOD_INVOCATION_TYPE_ARGUMENT\n        case 0x4A: // CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\n        case 0x4B: // METHOD_REFERENCE_TYPE_ARGUMENT\n            target &= 0xFF0000FF;\n            u += 4;\n            break;\n        // case 0x10: // CLASS_EXTENDS\n        // case 0x11: // CLASS_TYPE_PARAMETER_BOUND\n        // case 0x12: // METHOD_TYPE_PARAMETER_BOUND\n        // case 0x17: // THROWS\n        // case 0x42: // EXCEPTION_PARAMETER\n        // case 0x43: // INSTANCEOF\n        // case 0x44: // NEW\n        // case 0x45: // CONSTRUCTOR_REFERENCE\n        // case 0x46: // METHOD_REFERENCE\n        default:\n            target &= (target >>> 24) < 0x43 ? 0xFFFFFF00 : 0xFF000000;\n            u += 3;\n            break;\n        }\n        int pathLength = readByte(u);\n        context.typeRef = target;\n        context.typePath = pathLength == 0 ? null : new TypePath(b, u);\n        return u + 1 + 2 * pathLength;\n    }\n\n    /**\n     * Reads parameter annotations and makes the given visitor visit them.\n     * \n     * @param mv\n     *            the visitor that must visit the annotations.\n     * @param context\n     *            information about the class being parsed.\n     * @param v\n     *            start offset in {@link #b b} of the annotations to be read.\n     * @param visible\n     *            <tt>true</tt> if the annotations to be read are visible at\n     *            runtime.\n     */\n    private void readParameterAnnotations(final MethodVisitor mv,\n            final Context context, int v, final boolean visible) {\n        int i;\n        int n = b[v++] & 0xFF;\n        // workaround for a bug in javac (javac compiler generates a parameter\n        // annotation array whose size is equal to the number of parameters in\n        // the Java source file, while it should generate an array whose size is\n        // equal to the number of parameters in the method descriptor - which\n        // includes the synthetic parameters added by the compiler). This work-\n        // around supposes that the synthetic parameters are the first ones.\n        int synthetics = Type.getArgumentTypes(context.desc).length - n;\n        AnnotationVisitor av;\n        for (i = 0; i < synthetics; ++i) {\n            // virtual annotation to detect synthetic parameters in MethodWriter\n            av = mv.visitParameterAnnotation(i, \"Ljava/lang/Synthetic;\", false);\n            if (av != null) {\n                av.visitEnd();\n            }\n        }\n        char[] c = context.buffer;\n        for (; i < n + synthetics; ++i) {\n            int j = readUnsignedShort(v);\n            v += 2;\n            for (; j > 0; --j) {\n                av = mv.visitParameterAnnotation(i, readUTF8(v, c), visible);\n                v = readAnnotationValues(v + 2, c, true, av);\n            }\n        }\n    }\n\n    /**\n     * Reads the values of an annotation and makes the given visitor visit them.\n     * \n     * @param v\n     *            the start offset in {@link #b b} of the values to be read\n     *            (including the unsigned short that gives the number of\n     *            values).\n     * @param buf\n     *            buffer to be used to call {@link #readUTF8 readUTF8},\n     *            {@link #readClass(int,char[]) readClass} or {@link #readConst\n     *            readConst}.\n     * @param named\n     *            if the annotation values are named or not.\n     * @param av\n     *            the visitor that must visit the values.\n     * @return the end offset of the annotation values.\n     */\n    private int readAnnotationValues(int v, final char[] buf,\n            final boolean named, final AnnotationVisitor av) {\n        int i = readUnsignedShort(v);\n        v += 2;\n        if (named) {\n            for (; i > 0; --i) {\n                v = readAnnotationValue(v + 2, buf, readUTF8(v, buf), av);\n            }\n        } else {\n            for (; i > 0; --i) {\n                v = readAnnotationValue(v, buf, null, av);\n            }\n        }\n        if (av != null) {\n            av.visitEnd();\n        }\n        return v;\n    }\n\n    /**\n     * Reads a value of an annotation and makes the given visitor visit it.\n     * \n     * @param v\n     *            the start offset in {@link #b b} of the value to be read\n     *            (<i>not including the value name constant pool index</i>).\n     * @param buf\n     *            buffer to be used to call {@link #readUTF8 readUTF8},\n     *            {@link #readClass(int,char[]) readClass} or {@link #readConst\n     *            readConst}.\n     * @param name\n     *            the name of the value to be read.\n     * @param av\n     *            the visitor that must visit the value.\n     * @return the end offset of the annotation value.\n     */\n    private int readAnnotationValue(int v, final char[] buf, final String name,\n            final AnnotationVisitor av) {\n        int i;\n        if (av == null) {\n            switch (b[v] & 0xFF) {\n            case 'e': // enum_const_value\n                return v + 5;\n            case '@': // annotation_value\n                return readAnnotationValues(v + 3, buf, true, null);\n            case '[': // array_value\n                return readAnnotationValues(v + 1, buf, false, null);\n            default:\n                return v + 3;\n            }\n        }\n        switch (b[v++] & 0xFF) {\n        case 'I': // pointer to CONSTANT_Integer\n        case 'J': // pointer to CONSTANT_Long\n        case 'F': // pointer to CONSTANT_Float\n        case 'D': // pointer to CONSTANT_Double\n            av.visit(name, readConst(readUnsignedShort(v), buf));\n            v += 2;\n            break;\n        case 'B': // pointer to CONSTANT_Byte\n            av.visit(name, (byte) readInt(items[readUnsignedShort(v)]));\n            v += 2;\n            break;\n        case 'Z': // pointer to CONSTANT_Boolean\n            av.visit(name,\n                    readInt(items[readUnsignedShort(v)]) == 0 ? Boolean.FALSE\n                            : Boolean.TRUE);\n            v += 2;\n            break;\n        case 'S': // pointer to CONSTANT_Short\n            av.visit(name, (short) readInt(items[readUnsignedShort(v)]));\n            v += 2;\n            break;\n        case 'C': // pointer to CONSTANT_Char\n            av.visit(name, (char) readInt(items[readUnsignedShort(v)]));\n            v += 2;\n            break;\n        case 's': // pointer to CONSTANT_Utf8\n            av.visit(name, readUTF8(v, buf));\n            v += 2;\n            break;\n        case 'e': // enum_const_value\n            av.visitEnum(name, readUTF8(v, buf), readUTF8(v + 2, buf));\n            v += 4;\n            break;\n        case 'c': // class_info\n            av.visit(name, Type.getType(readUTF8(v, buf)));\n            v += 2;\n            break;\n        case '@': // annotation_value\n            v = readAnnotationValues(v + 2, buf, true,\n                    av.visitAnnotation(name, readUTF8(v, buf)));\n            break;\n        case '[': // array_value\n            int size = readUnsignedShort(v);\n            v += 2;\n            if (size == 0) {\n                return readAnnotationValues(v - 2, buf, false,\n                        av.visitArray(name));\n            }\n            switch (this.b[v++] & 0xFF) {\n            case 'B':\n                byte[] bv = new byte[size];\n                for (i = 0; i < size; i++) {\n                    bv[i] = (byte) readInt(items[readUnsignedShort(v)]);\n                    v += 3;\n                }\n                av.visit(name, bv);\n                --v;\n                break;\n            case 'Z':\n                boolean[] zv = new boolean[size];\n                for (i = 0; i < size; i++) {\n                    zv[i] = readInt(items[readUnsignedShort(v)]) != 0;\n                    v += 3;\n                }\n                av.visit(name, zv);\n                --v;\n                break;\n            case 'S':\n                short[] sv = new short[size];\n                for (i = 0; i < size; i++) {\n                    sv[i] = (short) readInt(items[readUnsignedShort(v)]);\n                    v += 3;\n                }\n                av.visit(name, sv);\n                --v;\n                break;\n            case 'C':\n                char[] cv = new char[size];\n                for (i = 0; i < size; i++) {\n                    cv[i] = (char) readInt(items[readUnsignedShort(v)]);\n                    v += 3;\n                }\n                av.visit(name, cv);\n                --v;\n                break;\n            case 'I':\n                int[] iv = new int[size];\n                for (i = 0; i < size; i++) {\n                    iv[i] = readInt(items[readUnsignedShort(v)]);\n                    v += 3;\n                }\n                av.visit(name, iv);\n                --v;\n                break;\n            case 'J':\n                long[] lv = new long[size];\n                for (i = 0; i < size; i++) {\n                    lv[i] = readLong(items[readUnsignedShort(v)]);\n                    v += 3;\n                }\n                av.visit(name, lv);\n                --v;\n                break;\n            case 'F':\n                float[] fv = new float[size];\n                for (i = 0; i < size; i++) {\n                    fv[i] = Float\n                            .intBitsToFloat(readInt(items[readUnsignedShort(v)]));\n                    v += 3;\n                }\n                av.visit(name, fv);\n                --v;\n                break;\n            case 'D':\n                double[] dv = new double[size];\n                for (i = 0; i < size; i++) {\n                    dv[i] = Double\n                            .longBitsToDouble(readLong(items[readUnsignedShort(v)]));\n                    v += 3;\n                }\n                av.visit(name, dv);\n                --v;\n                break;\n            default:\n                v = readAnnotationValues(v - 3, buf, false, av.visitArray(name));\n            }\n        }\n        return v;\n    }\n\n    /**\n     * Computes the implicit frame of the method currently being parsed (as\n     * defined in the given {@link Context}) and stores it in the given context.\n     * \n     * @param frame\n     *            information about the class being parsed.\n     */\n    private void getImplicitFrame(final Context frame) {\n        String desc = frame.desc;\n        Object[] locals = frame.local;\n        int local = 0;\n        if ((frame.access & Opcodes.ACC_STATIC) == 0) {\n            if (\"<init>\".equals(frame.name)) {\n                locals[local++] = Opcodes.UNINITIALIZED_THIS;\n            } else {\n                locals[local++] = readClass(header + 2, frame.buffer);\n            }\n        }\n        int i = 1;\n        loop: while (true) {\n            int j = i;\n            switch (desc.charAt(i++)) {\n            case 'Z':\n            case 'C':\n            case 'B':\n            case 'S':\n            case 'I':\n                locals[local++] = Opcodes.INTEGER;\n                break;\n            case 'F':\n                locals[local++] = Opcodes.FLOAT;\n                break;\n            case 'J':\n                locals[local++] = Opcodes.LONG;\n                break;\n            case 'D':\n                locals[local++] = Opcodes.DOUBLE;\n                break;\n            case '[':\n                while (desc.charAt(i) == '[') {\n                    ++i;\n                }\n                if (desc.charAt(i) == 'L') {\n                    ++i;\n                    while (desc.charAt(i) != ';') {\n                        ++i;\n                    }\n                }\n                locals[local++] = desc.substring(j, ++i);\n                break;\n            case 'L':\n                while (desc.charAt(i) != ';') {\n                    ++i;\n                }\n                locals[local++] = desc.substring(j + 1, i++);\n                break;\n            default:\n                break loop;\n            }\n        }\n        frame.localCount = local;\n    }\n\n    /**\n     * Reads a stack map frame and stores the result in the given\n     * {@link Context} object.\n     * \n     * @param stackMap\n     *            the start offset of a stack map frame in the class file.\n     * @param zip\n     *            if the stack map frame at stackMap is compressed or not.\n     * @param unzip\n     *            if the stack map frame must be uncompressed.\n     * @param frame\n     *            where the parsed stack map frame must be stored.\n     * @return the offset of the first byte following the parsed frame.\n     */\n    private int readFrame(int stackMap, boolean zip, boolean unzip,\n            Context frame) {\n        char[] c = frame.buffer;\n        Label[] labels = frame.labels;\n        int tag;\n        int delta;\n        if (zip) {\n            tag = b[stackMap++] & 0xFF;\n        } else {\n            tag = MethodWriter.FULL_FRAME;\n            frame.offset = -1;\n        }\n        frame.localDiff = 0;\n        if (tag < MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME) {\n            delta = tag;\n            frame.mode = Opcodes.F_SAME;\n            frame.stackCount = 0;\n        } else if (tag < MethodWriter.RESERVED) {\n            delta = tag - MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME;\n            stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);\n            frame.mode = Opcodes.F_SAME1;\n            frame.stackCount = 1;\n        } else {\n            delta = readUnsignedShort(stackMap);\n            stackMap += 2;\n            if (tag == MethodWriter.SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED) {\n                stackMap = readFrameType(frame.stack, 0, stackMap, c, labels);\n                frame.mode = Opcodes.F_SAME1;\n                frame.stackCount = 1;\n            } else if (tag >= MethodWriter.CHOP_FRAME\n                    && tag < MethodWriter.SAME_FRAME_EXTENDED) {\n                frame.mode = Opcodes.F_CHOP;\n                frame.localDiff = MethodWriter.SAME_FRAME_EXTENDED - tag;\n                frame.localCount -= frame.localDiff;\n                frame.stackCount = 0;\n            } else if (tag == MethodWriter.SAME_FRAME_EXTENDED) {\n                frame.mode = Opcodes.F_SAME;\n                frame.stackCount = 0;\n            } else if (tag < MethodWriter.FULL_FRAME) {\n                int local = unzip ? frame.localCount : 0;\n                for (int i = tag - MethodWriter.SAME_FRAME_EXTENDED; i > 0; i--) {\n                    stackMap = readFrameType(frame.local, local++, stackMap, c,\n                            labels);\n                }\n                frame.mode = Opcodes.F_APPEND;\n                frame.localDiff = tag - MethodWriter.SAME_FRAME_EXTENDED;\n                frame.localCount += frame.localDiff;\n                frame.stackCount = 0;\n            } else { // if (tag == FULL_FRAME) {\n                frame.mode = Opcodes.F_FULL;\n                int n = readUnsignedShort(stackMap);\n                stackMap += 2;\n                frame.localDiff = n;\n                frame.localCount = n;\n                for (int local = 0; n > 0; n--) {\n                    stackMap = readFrameType(frame.local, local++, stackMap, c,\n                            labels);\n                }\n                n = readUnsignedShort(stackMap);\n                stackMap += 2;\n                frame.stackCount = n;\n                for (int stack = 0; n > 0; n--) {\n                    stackMap = readFrameType(frame.stack, stack++, stackMap, c,\n                            labels);\n                }\n            }\n        }\n        frame.offset += delta + 1;\n        readLabel(frame.offset, labels);\n        return stackMap;\n    }\n\n    /**\n     * Reads a stack map frame type and stores it at the given index in the\n     * given array.\n     * \n     * @param frame\n     *            the array where the parsed type must be stored.\n     * @param index\n     *            the index in 'frame' where the parsed type must be stored.\n     * @param v\n     *            the start offset of the stack map frame type to read.\n     * @param buf\n     *            a buffer to read strings.\n     * @param labels\n     *            the labels of the method currently being parsed, indexed by\n     *            their offset. If the parsed type is an Uninitialized type, a\n     *            new label for the corresponding NEW instruction is stored in\n     *            this array if it does not already exist.\n     * @return the offset of the first byte after the parsed type.\n     */\n    private int readFrameType(final Object[] frame, final int index, int v,\n            final char[] buf, final Label[] labels) {\n        int type = b[v++] & 0xFF;\n        switch (type) {\n        case 0:\n            frame[index] = Opcodes.TOP;\n            break;\n        case 1:\n            frame[index] = Opcodes.INTEGER;\n            break;\n        case 2:\n            frame[index] = Opcodes.FLOAT;\n            break;\n        case 3:\n            frame[index] = Opcodes.DOUBLE;\n            break;\n        case 4:\n            frame[index] = Opcodes.LONG;\n            break;\n        case 5:\n            frame[index] = Opcodes.NULL;\n            break;\n        case 6:\n            frame[index] = Opcodes.UNINITIALIZED_THIS;\n            break;\n        case 7: // Object\n            frame[index] = readClass(v, buf);\n            v += 2;\n            break;\n        default: // Uninitialized\n            frame[index] = readLabel(readUnsignedShort(v), labels);\n            v += 2;\n        }\n        return v;\n    }\n\n    /**\n     * Returns the label corresponding to the given offset. The default\n     * implementation of this method creates a label for the given offset if it\n     * has not been already created.\n     * \n     * @param offset\n     *            a bytecode offset in a method.\n     * @param labels\n     *            the already created labels, indexed by their offset. If a\n     *            label already exists for offset this method must not create a\n     *            new one. Otherwise it must store the new label in this array.\n     * @return a non null Label, which must be equal to labels[offset].\n     */\n    protected Label readLabel(int offset, Label[] labels) {\n        if (labels[offset] == null) {\n            labels[offset] = new Label();\n        }\n        return labels[offset];\n    }\n\n    /**\n     * Returns the start index of the attribute_info structure of this class.\n     * \n     * @return the start index of the attribute_info structure of this class.\n     */\n    private int getAttributes() {\n        // skips the header\n        int u = header + 8 + readUnsignedShort(header + 6) * 2;\n        // skips fields and methods\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            for (int j = readUnsignedShort(u + 8); j > 0; --j) {\n                u += 6 + readInt(u + 12);\n            }\n            u += 8;\n        }\n        u += 2;\n        for (int i = readUnsignedShort(u); i > 0; --i) {\n            for (int j = readUnsignedShort(u + 8); j > 0; --j) {\n                u += 6 + readInt(u + 12);\n            }\n            u += 8;\n        }\n        // the attribute_info structure starts just after the methods\n        return u + 2;\n    }\n\n    /**\n     * Reads an attribute in {@link #b b}.\n     * \n     * @param attrs\n     *            prototypes of the attributes that must be parsed during the\n     *            visit of the class. Any attribute whose type is not equal to\n     *            the type of one the prototypes is ignored (i.e. an empty\n     *            {@link Attribute} instance is returned).\n     * @param type\n     *            the type of the attribute.\n     * @param off\n     *            index of the first byte of the attribute's content in\n     *            {@link #b b}. The 6 attribute header bytes, containing the\n     *            type and the length of the attribute, are not taken into\n     *            account here (they have already been read).\n     * @param len\n     *            the length of the attribute's content.\n     * @param buf\n     *            buffer to be used to call {@link #readUTF8 readUTF8},\n     *            {@link #readClass(int,char[]) readClass} or {@link #readConst\n     *            readConst}.\n     * @param codeOff\n     *            index of the first byte of code's attribute content in\n     *            {@link #b b}, or -1 if the attribute to be read is not a code\n     *            attribute. The 6 attribute header bytes, containing the type\n     *            and the length of the attribute, are not taken into account\n     *            here.\n     * @param labels\n     *            the labels of the method's code, or <tt>null</tt> if the\n     *            attribute to be read is not a code attribute.\n     * @return the attribute that has been read, or <tt>null</tt> to skip this\n     *         attribute.\n     */\n    private Attribute readAttribute(final Attribute[] attrs, final String type,\n            final int off, final int len, final char[] buf, final int codeOff,\n            final Label[] labels) {\n        for (int i = 0; i < attrs.length; ++i) {\n            if (attrs[i].type.equals(type)) {\n                return attrs[i].read(this, off, len, buf, codeOff, labels);\n            }\n        }\n        return new Attribute(type).read(this, off, len, null, -1, null);\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: low level parsing\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the number of constant pool items in {@link #b b}.\n     * \n     * @return the number of constant pool items in {@link #b b}.\n     */\n    public int getItemCount() {\n        return items.length;\n    }\n\n    /**\n     * Returns the start index of the constant pool item in {@link #b b}, plus\n     * one. <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param item\n     *            the index a constant pool item.\n     * @return the start index of the constant pool item in {@link #b b}, plus\n     *         one.\n     */\n    public int getItem(final int item) {\n        return items[item];\n    }\n\n    /**\n     * Returns the maximum length of the strings contained in the constant pool\n     * of the class.\n     * \n     * @return the maximum length of the strings contained in the constant pool\n     *         of the class.\n     */\n    public int getMaxStringLength() {\n        return maxStringLength;\n    }\n\n    /**\n     * Reads a byte value in {@link #b b}. <i>This method is intended for\n     * {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of the value to be read in {@link #b b}.\n     * @return the read value.\n     */\n    public int readByte(final int index) {\n        return b[index] & 0xFF;\n    }\n\n    /**\n     * Reads an unsigned short value in {@link #b b}. <i>This method is intended\n     * for {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of the value to be read in {@link #b b}.\n     * @return the read value.\n     */\n    public int readUnsignedShort(final int index) {\n        byte[] b = this.b;\n        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);\n    }\n\n    /**\n     * Reads a signed short value in {@link #b b}. <i>This method is intended\n     * for {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of the value to be read in {@link #b b}.\n     * @return the read value.\n     */\n    public short readShort(final int index) {\n        byte[] b = this.b;\n        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));\n    }\n\n    /**\n     * Reads a signed int value in {@link #b b}. <i>This method is intended for\n     * {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of the value to be read in {@link #b b}.\n     * @return the read value.\n     */\n    public int readInt(final int index) {\n        byte[] b = this.b;\n        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)\n                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);\n    }\n\n    /**\n     * Reads a signed long value in {@link #b b}. <i>This method is intended for\n     * {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of the value to be read in {@link #b b}.\n     * @return the read value.\n     */\n    public long readLong(final int index) {\n        long l1 = readInt(index);\n        long l0 = readInt(index + 4) & 0xFFFFFFFFL;\n        return (l1 << 32) | l0;\n    }\n\n    /**\n     * Reads an UTF8 string constant pool item in {@link #b b}. <i>This method\n     * is intended for {@link Attribute} sub classes, and is normally not needed\n     * by class generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of an unsigned short value in {@link #b b},\n     *            whose value is the index of an UTF8 constant pool item.\n     * @param buf\n     *            buffer to be used to read the item. This buffer must be\n     *            sufficiently large. It is not automatically resized.\n     * @return the String corresponding to the specified UTF8 item.\n     */\n    public String readUTF8(int index, final char[] buf) {\n        int item = readUnsignedShort(index);\n        if (index == 0 || item == 0) {\n            return null;\n        }\n        String s = strings[item];\n        if (s != null) {\n            return s;\n        }\n        index = items[item];\n        return strings[item] = readUTF(index + 2, readUnsignedShort(index), buf);\n    }\n\n    /**\n     * Reads UTF8 string in {@link #b b}.\n     * \n     * @param index\n     *            start offset of the UTF8 string to be read.\n     * @param utfLen\n     *            length of the UTF8 string to be read.\n     * @param buf\n     *            buffer to be used to read the string. This buffer must be\n     *            sufficiently large. It is not automatically resized.\n     * @return the String corresponding to the specified UTF8 string.\n     */\n    private String readUTF(int index, final int utfLen, final char[] buf) {\n        int endIndex = index + utfLen;\n        byte[] b = this.b;\n        int strLen = 0;\n        int c;\n        int st = 0;\n        char cc = 0;\n        while (index < endIndex) {\n            c = b[index++];\n            switch (st) {\n            case 0:\n                c = c & 0xFF;\n                if (c < 0x80) { // 0xxxxxxx\n                    buf[strLen++] = (char) c;\n                } else if (c < 0xE0 && c > 0xBF) { // 110x xxxx 10xx xxxx\n                    cc = (char) (c & 0x1F);\n                    st = 1;\n                } else { // 1110 xxxx 10xx xxxx 10xx xxxx\n                    cc = (char) (c & 0x0F);\n                    st = 2;\n                }\n                break;\n\n            case 1: // byte 2 of 2-byte char or byte 3 of 3-byte char\n                buf[strLen++] = (char) ((cc << 6) | (c & 0x3F));\n                st = 0;\n                break;\n\n            case 2: // byte 2 of 3-byte char\n                cc = (char) ((cc << 6) | (c & 0x3F));\n                st = 1;\n                break;\n            }\n        }\n        return new String(buf, 0, strLen);\n    }\n\n    /**\n     * Reads a class constant pool item in {@link #b b}. <i>This method is\n     * intended for {@link Attribute} sub classes, and is normally not needed by\n     * class generators or adapters.</i>\n     * \n     * @param index\n     *            the start index of an unsigned short value in {@link #b b},\n     *            whose value is the index of a class constant pool item.\n     * @param buf\n     *            buffer to be used to read the item. This buffer must be\n     *            sufficiently large. It is not automatically resized.\n     * @return the String corresponding to the specified class item.\n     */\n    public String readClass(final int index, final char[] buf) {\n        // computes the start index of the CONSTANT_Class item in b\n        // and reads the CONSTANT_Utf8 item designated by\n        // the first two bytes of this CONSTANT_Class item\n        return readUTF8(items[readUnsignedShort(index)], buf);\n    }\n\n    /**\n     * Reads a numeric or string constant pool item in {@link #b b}. <i>This\n     * method is intended for {@link Attribute} sub classes, and is normally not\n     * needed by class generators or adapters.</i>\n     * \n     * @param item\n     *            the index of a constant pool item.\n     * @param buf\n     *            buffer to be used to read the item. This buffer must be\n     *            sufficiently large. It is not automatically resized.\n     * @return the {@link Integer}, {@link Float}, {@link Long}, {@link Double},\n     *         {@link String}, {@link Type} or {@link Handle} corresponding to\n     *         the given constant pool item.\n     */\n    public Object readConst(final int item, final char[] buf) {\n        int index = items[item];\n        switch (b[index - 1]) {\n        case ClassWriter.INT:\n            return readInt(index);\n        case ClassWriter.FLOAT:\n            return Float.intBitsToFloat(readInt(index));\n        case ClassWriter.LONG:\n            return readLong(index);\n        case ClassWriter.DOUBLE:\n            return Double.longBitsToDouble(readLong(index));\n        case ClassWriter.CLASS:\n            return Type.getObjectType(readUTF8(index, buf));\n        case ClassWriter.STR:\n            return readUTF8(index, buf);\n        case ClassWriter.MTYPE:\n            return Type.getMethodType(readUTF8(index, buf));\n        default: // case ClassWriter.HANDLE_BASE + [1..9]:\n            int tag = readByte(index);\n            int[] items = this.items;\n            int cpIndex = items[readUnsignedShort(index + 1)];\n            boolean itf = b[cpIndex - 1] == ClassWriter.IMETH;\n            String owner = readClass(cpIndex, buf);\n            cpIndex = items[readUnsignedShort(cpIndex + 2)];\n            String name = readUTF8(cpIndex, buf);\n            String desc = readUTF8(cpIndex + 2, buf);\n            return new Handle(tag, owner, name, desc, itf);\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/ClassVisitor.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A visitor to visit a Java class. The methods of this class must be called in\n * the following order: <tt>visit</tt> [ <tt>visitSource</tt> ] [\n * <tt>visitOuterClass</tt> ] ( <tt>visitAnnotation</tt> |\n * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* (\n * <tt>visitInnerClass</tt> | <tt>visitField</tt> | <tt>visitMethod</tt> )*\n * <tt>visitEnd</tt>.\n * \n * @author Eric Bruneton\n */\npublic abstract class ClassVisitor {\n\n    /**\n     * The ASM API version implemented by this visitor. The value of this field\n     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    protected final int api;\n\n    /**\n     * The class visitor to which this visitor must delegate method calls. May\n     * be null.\n     */\n    protected ClassVisitor cv;\n\n    /**\n     * Constructs a new {@link ClassVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    public ClassVisitor(final int api) {\n        this(api, null);\n    }\n\n    /**\n     * Constructs a new {@link ClassVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     * @param cv\n     *            the class visitor to which this visitor must delegate method\n     *            calls. May be null.\n     */\n    public ClassVisitor(final int api, final ClassVisitor cv) {\n        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {\n            throw new IllegalArgumentException();\n        }\n        this.api = api;\n        this.cv = cv;\n    }\n\n    /**\n     * Visits the header of the class.\n     * \n     * @param version\n     *            the class version.\n     * @param access\n     *            the class's access flags (see {@link Opcodes}). This parameter\n     *            also indicates if the class is deprecated.\n     * @param name\n     *            the internal name of the class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     * @param signature\n     *            the signature of this class. May be <tt>null</tt> if the class\n     *            is not a generic one, and does not extend or implement generic\n     *            classes or interfaces.\n     * @param superName\n     *            the internal of name of the super class (see\n     *            {@link Type#getInternalName() getInternalName}). For\n     *            interfaces, the super class is {@link Object}. May be\n     *            <tt>null</tt>, but only for the {@link Object} class.\n     * @param interfaces\n     *            the internal names of the class's interfaces (see\n     *            {@link Type#getInternalName() getInternalName}). May be\n     *            <tt>null</tt>.\n     */\n    public void visit(int version, int access, String name, String signature,\n            String superName, String[] interfaces) {\n        if (cv != null) {\n            cv.visit(version, access, name, signature, superName, interfaces);\n        }\n    }\n\n    /**\n     * Visits the source of the class.\n     * \n     * @param source\n     *            the name of the source file from which the class was compiled.\n     *            May be <tt>null</tt>.\n     * @param debug\n     *            additional debug information to compute the correspondance\n     *            between source and compiled elements of the class. May be\n     *            <tt>null</tt>.\n     */\n    public void visitSource(String source, String debug) {\n        if (cv != null) {\n            cv.visitSource(source, debug);\n        }\n    }\n\n    /**\n     * Visits the enclosing class of the class. This method must be called only\n     * if the class has an enclosing class.\n     * \n     * @param owner\n     *            internal name of the enclosing class of the class.\n     * @param name\n     *            the name of the method that contains the class, or\n     *            <tt>null</tt> if the class is not enclosed in a method of its\n     *            enclosing class.\n     * @param desc\n     *            the descriptor of the method that contains the class, or\n     *            <tt>null</tt> if the class is not enclosed in a method of its\n     *            enclosing class.\n     */\n    public void visitOuterClass(String owner, String name, String desc) {\n        if (cv != null) {\n            cv.visitOuterClass(owner, name, desc);\n        }\n    }\n\n    /**\n     * Visits an annotation of the class.\n     * \n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        if (cv != null) {\n            return cv.visitAnnotation(desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits an annotation on a type in the class signature.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#CLASS_TYPE_PARAMETER\n     *            CLASS_TYPE_PARAMETER},\n     *            {@link TypeReference#CLASS_TYPE_PARAMETER_BOUND\n     *            CLASS_TYPE_PARAMETER_BOUND} or\n     *            {@link TypeReference#CLASS_EXTENDS CLASS_EXTENDS}. See\n     *            {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitTypeAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (cv != null) {\n            return cv.visitTypeAnnotation(typeRef, typePath, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a non standard attribute of the class.\n     * \n     * @param attr\n     *            an attribute.\n     */\n    public void visitAttribute(Attribute attr) {\n        if (cv != null) {\n            cv.visitAttribute(attr);\n        }\n    }\n\n    /**\n     * Visits information about an inner class. This inner class is not\n     * necessarily a member of the class being visited.\n     * \n     * @param name\n     *            the internal name of an inner class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     * @param outerName\n     *            the internal name of the class to which the inner class\n     *            belongs (see {@link Type#getInternalName() getInternalName}).\n     *            May be <tt>null</tt> for not member classes.\n     * @param innerName\n     *            the (simple) name of the inner class inside its enclosing\n     *            class. May be <tt>null</tt> for anonymous inner classes.\n     * @param access\n     *            the access flags of the inner class as originally declared in\n     *            the enclosing class.\n     */\n    public void visitInnerClass(String name, String outerName,\n            String innerName, int access) {\n        if (cv != null) {\n            cv.visitInnerClass(name, outerName, innerName, access);\n        }\n    }\n\n    /**\n     * Visits a field of the class.\n     * \n     * @param access\n     *            the field's access flags (see {@link Opcodes}). This parameter\n     *            also indicates if the field is synthetic and/or deprecated.\n     * @param name\n     *            the field's name.\n     * @param desc\n     *            the field's descriptor (see {@link Type Type}).\n     * @param signature\n     *            the field's signature. May be <tt>null</tt> if the field's\n     *            type does not use generic types.\n     * @param value\n     *            the field's initial value. This parameter, which may be\n     *            <tt>null</tt> if the field does not have an initial value,\n     *            must be an {@link Integer}, a {@link Float}, a {@link Long}, a\n     *            {@link Double} or a {@link String} (for <tt>int</tt>,\n     *            <tt>float</tt>, <tt>long</tt> or <tt>String</tt> fields\n     *            respectively). <i>This parameter is only used for static\n     *            fields</i>. Its value is ignored for non static fields, which\n     *            must be initialized through bytecode instructions in\n     *            constructors or methods.\n     * @return a visitor to visit field annotations and attributes, or\n     *         <tt>null</tt> if this class visitor is not interested in visiting\n     *         these annotations and attributes.\n     */\n    public FieldVisitor visitField(int access, String name, String desc,\n            String signature, Object value) {\n        if (cv != null) {\n            return cv.visitField(access, name, desc, signature, value);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a method of the class. This method <i>must</i> return a new\n     * {@link MethodVisitor} instance (or <tt>null</tt>) each time it is called,\n     * i.e., it should not return a previously returned visitor.\n     * \n     * @param access\n     *            the method's access flags (see {@link Opcodes}). This\n     *            parameter also indicates if the method is synthetic and/or\n     *            deprecated.\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor (see {@link Type Type}).\n     * @param signature\n     *            the method's signature. May be <tt>null</tt> if the method\n     *            parameters, return type and exceptions do not use generic\n     *            types.\n     * @param exceptions\n     *            the internal names of the method's exception classes (see\n     *            {@link Type#getInternalName() getInternalName}). May be\n     *            <tt>null</tt>.\n     * @return an object to visit the byte code of the method, or <tt>null</tt>\n     *         if this class visitor is not interested in visiting the code of\n     *         this method.\n     */\n    public MethodVisitor visitMethod(int access, String name, String desc,\n            String signature, String[] exceptions) {\n        if (cv != null) {\n            return cv.visitMethod(access, name, desc, signature, exceptions);\n        }\n        return null;\n    }\n\n    /**\n     * Visits the end of the class. This method, which is the last one to be\n     * called, is used to inform the visitor that all the fields and methods of\n     * the class have been visited.\n     */\n    public void visitEnd() {\n        if (cv != null) {\n            cv.visitEnd();\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/ClassWriter.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A {@link ClassVisitor} that generates classes in bytecode form. More\n * precisely this visitor generates a byte array conforming to the Java class\n * file format. It can be used alone, to generate a Java class \"from scratch\",\n * or with one or more {@link ClassReader ClassReader} and adapter class visitor\n * to generate a modified class from one or more existing Java classes.\n * \n * @author Eric Bruneton\n */\npublic class ClassWriter extends ClassVisitor {\n\n    /**\n     * Flag to automatically compute the maximum stack size and the maximum\n     * number of local variables of methods. If this flag is set, then the\n     * arguments of the {@link MethodVisitor#visitMaxs visitMaxs} method of the\n     * {@link MethodVisitor} returned by the {@link #visitMethod visitMethod}\n     * method will be ignored, and computed automatically from the signature and\n     * the bytecode of each method.\n     * \n     * @see #ClassWriter(int)\n     */\n    public static final int COMPUTE_MAXS = 1;\n\n    /**\n     * Flag to automatically compute the stack map frames of methods from\n     * scratch. If this flag is set, then the calls to the\n     * {@link MethodVisitor#visitFrame} method are ignored, and the stack map\n     * frames are recomputed from the methods bytecode. The arguments of the\n     * {@link MethodVisitor#visitMaxs visitMaxs} method are also ignored and\n     * recomputed from the bytecode. In other words, computeFrames implies\n     * computeMaxs.\n     * \n     * @see #ClassWriter(int)\n     */\n    public static final int COMPUTE_FRAMES = 2;\n\n    /**\n     * Pseudo access flag to distinguish between the synthetic attribute and the\n     * synthetic access flag.\n     */\n    static final int ACC_SYNTHETIC_ATTRIBUTE = 0x40000;\n\n    /**\n     * Factor to convert from ACC_SYNTHETIC_ATTRIBUTE to Opcode.ACC_SYNTHETIC.\n     */\n    static final int TO_ACC_SYNTHETIC = ACC_SYNTHETIC_ATTRIBUTE\n            / Opcodes.ACC_SYNTHETIC;\n\n    /**\n     * The type of instructions without any argument.\n     */\n    static final int NOARG_INSN = 0;\n\n    /**\n     * The type of instructions with an signed byte argument.\n     */\n    static final int SBYTE_INSN = 1;\n\n    /**\n     * The type of instructions with an signed short argument.\n     */\n    static final int SHORT_INSN = 2;\n\n    /**\n     * The type of instructions with a local variable index argument.\n     */\n    static final int VAR_INSN = 3;\n\n    /**\n     * The type of instructions with an implicit local variable index argument.\n     */\n    static final int IMPLVAR_INSN = 4;\n\n    /**\n     * The type of instructions with a type descriptor argument.\n     */\n    static final int TYPE_INSN = 5;\n\n    /**\n     * The type of field and method invocations instructions.\n     */\n    static final int FIELDORMETH_INSN = 6;\n\n    /**\n     * The type of the INVOKEINTERFACE/INVOKEDYNAMIC instruction.\n     */\n    static final int ITFMETH_INSN = 7;\n\n    /**\n     * The type of the INVOKEDYNAMIC instruction.\n     */\n    static final int INDYMETH_INSN = 8;\n\n    /**\n     * The type of instructions with a 2 bytes bytecode offset label.\n     */\n    static final int LABEL_INSN = 9;\n\n    /**\n     * The type of instructions with a 4 bytes bytecode offset label.\n     */\n    static final int LABELW_INSN = 10;\n\n    /**\n     * The type of the LDC instruction.\n     */\n    static final int LDC_INSN = 11;\n\n    /**\n     * The type of the LDC_W and LDC2_W instructions.\n     */\n    static final int LDCW_INSN = 12;\n\n    /**\n     * The type of the IINC instruction.\n     */\n    static final int IINC_INSN = 13;\n\n    /**\n     * The type of the TABLESWITCH instruction.\n     */\n    static final int TABL_INSN = 14;\n\n    /**\n     * The type of the LOOKUPSWITCH instruction.\n     */\n    static final int LOOK_INSN = 15;\n\n    /**\n     * The type of the MULTIANEWARRAY instruction.\n     */\n    static final int MANA_INSN = 16;\n\n    /**\n     * The type of the WIDE instruction.\n     */\n    static final int WIDE_INSN = 17;\n\n    /**\n     * The instruction types of all JVM opcodes.\n     */\n    static final byte[] TYPE;\n\n    /**\n     * The type of CONSTANT_Class constant pool items.\n     */\n    static final int CLASS = 7;\n\n    /**\n     * The type of CONSTANT_Fieldref constant pool items.\n     */\n    static final int FIELD = 9;\n\n    /**\n     * The type of CONSTANT_Methodref constant pool items.\n     */\n    static final int METH = 10;\n\n    /**\n     * The type of CONSTANT_InterfaceMethodref constant pool items.\n     */\n    static final int IMETH = 11;\n\n    /**\n     * The type of CONSTANT_String constant pool items.\n     */\n    static final int STR = 8;\n\n    /**\n     * The type of CONSTANT_Integer constant pool items.\n     */\n    static final int INT = 3;\n\n    /**\n     * The type of CONSTANT_Float constant pool items.\n     */\n    static final int FLOAT = 4;\n\n    /**\n     * The type of CONSTANT_Long constant pool items.\n     */\n    static final int LONG = 5;\n\n    /**\n     * The type of CONSTANT_Double constant pool items.\n     */\n    static final int DOUBLE = 6;\n\n    /**\n     * The type of CONSTANT_NameAndType constant pool items.\n     */\n    static final int NAME_TYPE = 12;\n\n    /**\n     * The type of CONSTANT_Utf8 constant pool items.\n     */\n    static final int UTF8 = 1;\n\n    /**\n     * The type of CONSTANT_MethodType constant pool items.\n     */\n    static final int MTYPE = 16;\n\n    /**\n     * The type of CONSTANT_MethodHandle constant pool items.\n     */\n    static final int HANDLE = 15;\n\n    /**\n     * The type of CONSTANT_InvokeDynamic constant pool items.\n     */\n    static final int INDY = 18;\n\n    /**\n     * The base value for all CONSTANT_MethodHandle constant pool items.\n     * Internally, ASM store the 9 variations of CONSTANT_MethodHandle into 9\n     * different items.\n     */\n    static final int HANDLE_BASE = 20;\n\n    /**\n     * Normal type Item stored in the ClassWriter {@link ClassWriter#typeTable},\n     * instead of the constant pool, in order to avoid clashes with normal\n     * constant pool items in the ClassWriter constant pool's hash table.\n     */\n    static final int TYPE_NORMAL = 30;\n\n    /**\n     * Uninitialized type Item stored in the ClassWriter\n     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to\n     * avoid clashes with normal constant pool items in the ClassWriter constant\n     * pool's hash table.\n     */\n    static final int TYPE_UNINIT = 31;\n\n    /**\n     * Merged type Item stored in the ClassWriter {@link ClassWriter#typeTable},\n     * instead of the constant pool, in order to avoid clashes with normal\n     * constant pool items in the ClassWriter constant pool's hash table.\n     */\n    static final int TYPE_MERGED = 32;\n\n    /**\n     * The type of BootstrapMethods items. These items are stored in a special\n     * class attribute named BootstrapMethods and not in the constant pool.\n     */\n    static final int BSM = 33;\n\n    /**\n     * The class reader from which this class writer was constructed, if any.\n     */\n    ClassReader cr;\n\n    /**\n     * Minor and major version numbers of the class to be generated.\n     */\n    int version;\n\n    /**\n     * Index of the next item to be added in the constant pool.\n     */\n    int index;\n\n    /**\n     * The constant pool of this class.\n     */\n    final ByteVector pool;\n\n    /**\n     * The constant pool's hash table data.\n     */\n    Item[] items;\n\n    /**\n     * The threshold of the constant pool's hash table.\n     */\n    int threshold;\n\n    /**\n     * A reusable key used to look for items in the {@link #items} hash table.\n     */\n    final Item key;\n\n    /**\n     * A reusable key used to look for items in the {@link #items} hash table.\n     */\n    final Item key2;\n\n    /**\n     * A reusable key used to look for items in the {@link #items} hash table.\n     */\n    final Item key3;\n\n    /**\n     * A reusable key used to look for items in the {@link #items} hash table.\n     */\n    final Item key4;\n\n    /**\n     * A type table used to temporarily store internal names that will not\n     * necessarily be stored in the constant pool. This type table is used by\n     * the control flow and data flow analysis algorithm used to compute stack\n     * map frames from scratch. This array associates to each index <tt>i</tt>\n     * the Item whose index is <tt>i</tt>. All Item objects stored in this array\n     * are also stored in the {@link #items} hash table. These two arrays allow\n     * to retrieve an Item from its index or, conversely, to get the index of an\n     * Item from its value. Each Item stores an internal name in its\n     * {@link Item#strVal1} field.\n     */\n    Item[] typeTable;\n\n    /**\n     * Number of elements in the {@link #typeTable} array.\n     */\n    private short typeCount;\n\n    /**\n     * The access flags of this class.\n     */\n    private int access;\n\n    /**\n     * The constant pool item that contains the internal name of this class.\n     */\n    private int name;\n\n    /**\n     * The internal name of this class.\n     */\n    String thisName;\n\n    /**\n     * The constant pool item that contains the signature of this class.\n     */\n    private int signature;\n\n    /**\n     * The constant pool item that contains the internal name of the super class\n     * of this class.\n     */\n    private int superName;\n\n    /**\n     * Number of interfaces implemented or extended by this class or interface.\n     */\n    private int interfaceCount;\n\n    /**\n     * The interfaces implemented or extended by this class or interface. More\n     * precisely, this array contains the indexes of the constant pool items\n     * that contain the internal names of these interfaces.\n     */\n    private int[] interfaces;\n\n    /**\n     * The index of the constant pool item that contains the name of the source\n     * file from which this class was compiled.\n     */\n    private int sourceFile;\n\n    /**\n     * The SourceDebug attribute of this class.\n     */\n    private ByteVector sourceDebug;\n\n    /**\n     * The constant pool item that contains the name of the enclosing class of\n     * this class.\n     */\n    private int enclosingMethodOwner;\n\n    /**\n     * The constant pool item that contains the name and descriptor of the\n     * enclosing method of this class.\n     */\n    private int enclosingMethod;\n\n    /**\n     * The runtime visible annotations of this class.\n     */\n    private AnnotationWriter anns;\n\n    /**\n     * The runtime invisible annotations of this class.\n     */\n    private AnnotationWriter ianns;\n\n    /**\n     * The runtime visible type annotations of this class.\n     */\n    private AnnotationWriter tanns;\n\n    /**\n     * The runtime invisible type annotations of this class.\n     */\n    private AnnotationWriter itanns;\n\n    /**\n     * The non standard attributes of this class.\n     */\n    private Attribute attrs;\n\n    /**\n     * The number of entries in the InnerClasses attribute.\n     */\n    private int innerClassesCount;\n\n    /**\n     * The InnerClasses attribute.\n     */\n    private ByteVector innerClasses;\n\n    /**\n     * The number of entries in the BootstrapMethods attribute.\n     */\n    int bootstrapMethodsCount;\n\n    /**\n     * The BootstrapMethods attribute.\n     */\n    ByteVector bootstrapMethods;\n\n    /**\n     * The fields of this class. These fields are stored in a linked list of\n     * {@link FieldWriter} objects, linked to each other by their\n     * {@link FieldWriter#fv} field. This field stores the first element of this\n     * list.\n     */\n    FieldWriter firstField;\n\n    /**\n     * The fields of this class. These fields are stored in a linked list of\n     * {@link FieldWriter} objects, linked to each other by their\n     * {@link FieldWriter#fv} field. This field stores the last element of this\n     * list.\n     */\n    FieldWriter lastField;\n\n    /**\n     * The methods of this class. These methods are stored in a linked list of\n     * {@link MethodWriter} objects, linked to each other by their\n     * {@link MethodWriter#mv} field. This field stores the first element of\n     * this list.\n     */\n    MethodWriter firstMethod;\n\n    /**\n     * The methods of this class. These methods are stored in a linked list of\n     * {@link MethodWriter} objects, linked to each other by their\n     * {@link MethodWriter#mv} field. This field stores the last element of this\n     * list.\n     */\n    MethodWriter lastMethod;\n\n    /**\n     * <tt>true</tt> if the maximum stack size and number of local variables\n     * must be automatically computed.\n     */\n    private boolean computeMaxs;\n\n    /**\n     * <tt>true</tt> if the stack map frames must be recomputed from scratch.\n     */\n    private boolean computeFrames;\n\n    /**\n     * <tt>true</tt> if the stack map tables of this class are invalid. The\n     * {@link MethodWriter#resizeInstructions} method cannot transform existing\n     * stack map tables, and so produces potentially invalid classes when it is\n     * executed. In this case the class is reread and rewritten with the\n     * {@link #COMPUTE_FRAMES} option (the resizeInstructions method can resize\n     * stack map tables when this option is used).\n     */\n    boolean invalidFrames;\n\n    // ------------------------------------------------------------------------\n    // Static initializer\n    // ------------------------------------------------------------------------\n\n    /**\n     * Computes the instruction types of JVM opcodes.\n     */\n    static {\n        int i;\n        byte[] b = new byte[220];\n        String s = \"AAAAAAAAAAAAAAAABCLMMDDDDDEEEEEEEEEEEEEEEEEEEEAAAAAAAADD\"\n                + \"DDDEEEEEEEEEEEEEEEEEEEEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\"\n                + \"AAAAAAAAAAAAAAAAANAAAAAAAAAAAAAAAAAAAAJJJJJJJJJJJJJJJJDOPAA\"\n                + \"AAAAGGGGGGGHIFBFAAFFAARQJJKKJJJJJJJJJJJJJJJJJJ\";\n        for (i = 0; i < b.length; ++i) {\n            b[i] = (byte) (s.charAt(i) - 'A');\n        }\n        TYPE = b;\n\n        // code to generate the above string\n        //\n        // // SBYTE_INSN instructions\n        // b[Constants.NEWARRAY] = SBYTE_INSN;\n        // b[Constants.BIPUSH] = SBYTE_INSN;\n        //\n        // // SHORT_INSN instructions\n        // b[Constants.SIPUSH] = SHORT_INSN;\n        //\n        // // (IMPL)VAR_INSN instructions\n        // b[Constants.RET] = VAR_INSN;\n        // for (i = Constants.ILOAD; i <= Constants.ALOAD; ++i) {\n        // b[i] = VAR_INSN;\n        // }\n        // for (i = Constants.ISTORE; i <= Constants.ASTORE; ++i) {\n        // b[i] = VAR_INSN;\n        // }\n        // for (i = 26; i <= 45; ++i) { // ILOAD_0 to ALOAD_3\n        // b[i] = IMPLVAR_INSN;\n        // }\n        // for (i = 59; i <= 78; ++i) { // ISTORE_0 to ASTORE_3\n        // b[i] = IMPLVAR_INSN;\n        // }\n        //\n        // // TYPE_INSN instructions\n        // b[Constants.NEW] = TYPE_INSN;\n        // b[Constants.ANEWARRAY] = TYPE_INSN;\n        // b[Constants.CHECKCAST] = TYPE_INSN;\n        // b[Constants.INSTANCEOF] = TYPE_INSN;\n        //\n        // // (Set)FIELDORMETH_INSN instructions\n        // for (i = Constants.GETSTATIC; i <= Constants.INVOKESTATIC; ++i) {\n        // b[i] = FIELDORMETH_INSN;\n        // }\n        // b[Constants.INVOKEINTERFACE] = ITFMETH_INSN;\n        // b[Constants.INVOKEDYNAMIC] = INDYMETH_INSN;\n        //\n        // // LABEL(W)_INSN instructions\n        // for (i = Constants.IFEQ; i <= Constants.JSR; ++i) {\n        // b[i] = LABEL_INSN;\n        // }\n        // b[Constants.IFNULL] = LABEL_INSN;\n        // b[Constants.IFNONNULL] = LABEL_INSN;\n        // b[200] = LABELW_INSN; // GOTO_W\n        // b[201] = LABELW_INSN; // JSR_W\n        // // temporary opcodes used internally by ASM - see Label and\n        // MethodWriter\n        // for (i = 202; i < 220; ++i) {\n        // b[i] = LABEL_INSN;\n        // }\n        //\n        // // LDC(_W) instructions\n        // b[Constants.LDC] = LDC_INSN;\n        // b[19] = LDCW_INSN; // LDC_W\n        // b[20] = LDCW_INSN; // LDC2_W\n        //\n        // // special instructions\n        // b[Constants.IINC] = IINC_INSN;\n        // b[Constants.TABLESWITCH] = TABL_INSN;\n        // b[Constants.LOOKUPSWITCH] = LOOK_INSN;\n        // b[Constants.MULTIANEWARRAY] = MANA_INSN;\n        // b[196] = WIDE_INSN; // WIDE\n        //\n        // for (i = 0; i < b.length; ++i) {\n        // System.err.print((char)('A' + b[i]));\n        // }\n        // System.err.println();\n    }\n\n    // ------------------------------------------------------------------------\n    // Constructor\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link ClassWriter} object.\n     * \n     * @param flags\n     *            option flags that can be used to modify the default behavior\n     *            of this class. See {@link #COMPUTE_MAXS},\n     *            {@link #COMPUTE_FRAMES}.\n     */\n    public ClassWriter(final int flags) {\n        super(Opcodes.ASM5);\n        index = 1;\n        pool = new ByteVector();\n        items = new Item[256];\n        threshold = (int) (0.75d * items.length);\n        key = new Item();\n        key2 = new Item();\n        key3 = new Item();\n        key4 = new Item();\n        this.computeMaxs = (flags & COMPUTE_MAXS) != 0;\n        this.computeFrames = (flags & COMPUTE_FRAMES) != 0;\n    }\n\n    /**\n     * Constructs a new {@link ClassWriter} object and enables optimizations for\n     * \"mostly add\" bytecode transformations. These optimizations are the\n     * following:\n     * \n     * <ul>\n     * <li>The constant pool from the original class is copied as is in the new\n     * class, which saves time. New constant pool entries will be added at the\n     * end if necessary, but unused constant pool entries <i>won't be\n     * removed</i>.</li>\n     * <li>Methods that are not transformed are copied as is in the new class,\n     * directly from the original class bytecode (i.e. without emitting visit\n     * events for all the method instructions), which saves a <i>lot</i> of\n     * time. Untransformed methods are detected by the fact that the\n     * {@link ClassReader} receives {@link MethodVisitor} objects that come from\n     * a {@link ClassWriter} (and not from any other {@link ClassVisitor}\n     * instance).</li>\n     * </ul>\n     * \n     * @param classReader\n     *            the {@link ClassReader} used to read the original class. It\n     *            will be used to copy the entire constant pool from the\n     *            original class and also to copy other fragments of original\n     *            bytecode where applicable.\n     * @param flags\n     *            option flags that can be used to modify the default behavior\n     *            of this class. <i>These option flags do not affect methods\n     *            that are copied as is in the new class. This means that\n     *            neither the maximum stack size nor the stack frames will be\n     *            computed for these methods</i>. See {@link #COMPUTE_MAXS},\n     *            {@link #COMPUTE_FRAMES}.\n     */\n    public ClassWriter(final ClassReader classReader, final int flags) {\n        this(flags);\n        classReader.copyPool(this);\n        this.cr = classReader;\n    }\n\n    // ------------------------------------------------------------------------\n    // Implementation of the ClassVisitor abstract class\n    // ------------------------------------------------------------------------\n\n    @Override\n    public final void visit(final int version, final int access,\n            final String name, final String signature, final String superName,\n            final String[] interfaces) {\n        this.version = version;\n        this.access = access;\n        this.name = newClass(name);\n        thisName = name;\n        if (ClassReader.SIGNATURES && signature != null) {\n            this.signature = newUTF8(signature);\n        }\n        this.superName = superName == null ? 0 : newClass(superName);\n        if (interfaces != null && interfaces.length > 0) {\n            interfaceCount = interfaces.length;\n            this.interfaces = new int[interfaceCount];\n            for (int i = 0; i < interfaceCount; ++i) {\n                this.interfaces[i] = newClass(interfaces[i]);\n            }\n        }\n    }\n\n    @Override\n    public final void visitSource(final String file, final String debug) {\n        if (file != null) {\n            sourceFile = newUTF8(file);\n        }\n        if (debug != null) {\n            sourceDebug = new ByteVector().encodeUTF8(debug, 0,\n                    Integer.MAX_VALUE);\n        }\n    }\n\n    @Override\n    public final void visitOuterClass(final String owner, final String name,\n            final String desc) {\n        enclosingMethodOwner = newClass(owner);\n        if (name != null && desc != null) {\n            enclosingMethod = newNameType(name, desc);\n        }\n    }\n\n    @Override\n    public final AnnotationVisitor visitAnnotation(final String desc,\n            final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write type, and reserve space for values count\n        bv.putShort(newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv, 2);\n        if (visible) {\n            aw.next = anns;\n            anns = aw;\n        } else {\n            aw.next = ianns;\n            ianns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public final AnnotationVisitor visitTypeAnnotation(int typeRef,\n            TypePath typePath, final String desc, final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        AnnotationWriter.putTarget(typeRef, typePath, bv);\n        // write type, and reserve space for values count\n        bv.putShort(newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(this, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = tanns;\n            tanns = aw;\n        } else {\n            aw.next = itanns;\n            itanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public final void visitAttribute(final Attribute attr) {\n        attr.next = attrs;\n        attrs = attr;\n    }\n\n    @Override\n    public final void visitInnerClass(final String name,\n            final String outerName, final String innerName, final int access) {\n        if (innerClasses == null) {\n            innerClasses = new ByteVector();\n        }\n        // Sec. 4.7.6 of the JVMS states \"Every CONSTANT_Class_info entry in the\n        // constant_pool table which represents a class or interface C that is\n        // not a package member must have exactly one corresponding entry in the\n        // classes array\". To avoid duplicates we keep track in the intVal field\n        // of the Item of each CONSTANT_Class_info entry C whether an inner\n        // class entry has already been added for C (this field is unused for\n        // class entries, and changing its value does not change the hashcode\n        // and equality tests). If so we store the index of this inner class\n        // entry (plus one) in intVal. This hack allows duplicate detection in\n        // O(1) time.\n        Item nameItem = newClassItem(name);\n        if (nameItem.intVal == 0) {\n            ++innerClassesCount;\n            innerClasses.putShort(nameItem.index);\n            innerClasses.putShort(outerName == null ? 0 : newClass(outerName));\n            innerClasses.putShort(innerName == null ? 0 : newUTF8(innerName));\n            innerClasses.putShort(access);\n            nameItem.intVal = innerClassesCount;\n        } else {\n            // Compare the inner classes entry nameItem.intVal - 1 with the\n            // arguments of this method and throw an exception if there is a\n            // difference?\n        }\n    }\n\n    @Override\n    public final FieldVisitor visitField(final int access, final String name,\n            final String desc, final String signature, final Object value) {\n        return new FieldWriter(this, access, name, desc, signature, value);\n    }\n\n    @Override\n    public final MethodVisitor visitMethod(final int access, final String name,\n            final String desc, final String signature, final String[] exceptions) {\n        return new MethodWriter(this, access, name, desc, signature,\n                exceptions, computeMaxs, computeFrames);\n    }\n\n    @Override\n    public final void visitEnd() {\n    }\n\n    // ------------------------------------------------------------------------\n    // Other public methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the bytecode of the class that was build with this class writer.\n     * \n     * @return the bytecode of the class that was build with this class writer.\n     */\n    public byte[] toByteArray() {\n        if (index > 0xFFFF) {\n            throw new RuntimeException(\"Class file too large!\");\n        }\n        // computes the real size of the bytecode of this class\n        int size = 24 + 2 * interfaceCount;\n        int nbFields = 0;\n        FieldWriter fb = firstField;\n        while (fb != null) {\n            ++nbFields;\n            size += fb.getSize();\n            fb = (FieldWriter) fb.fv;\n        }\n        int nbMethods = 0;\n        MethodWriter mb = firstMethod;\n        while (mb != null) {\n            ++nbMethods;\n            size += mb.getSize();\n            mb = (MethodWriter) mb.mv;\n        }\n        int attributeCount = 0;\n        if (bootstrapMethods != null) {\n            // we put it as first attribute in order to improve a bit\n            // ClassReader.copyBootstrapMethods\n            ++attributeCount;\n            size += 8 + bootstrapMethods.length;\n            newUTF8(\"BootstrapMethods\");\n        }\n        if (ClassReader.SIGNATURES && signature != 0) {\n            ++attributeCount;\n            size += 8;\n            newUTF8(\"Signature\");\n        }\n        if (sourceFile != 0) {\n            ++attributeCount;\n            size += 8;\n            newUTF8(\"SourceFile\");\n        }\n        if (sourceDebug != null) {\n            ++attributeCount;\n            size += sourceDebug.length + 6;\n            newUTF8(\"SourceDebugExtension\");\n        }\n        if (enclosingMethodOwner != 0) {\n            ++attributeCount;\n            size += 10;\n            newUTF8(\"EnclosingMethod\");\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            ++attributeCount;\n            size += 6;\n            newUTF8(\"Deprecated\");\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                ++attributeCount;\n                size += 6;\n                newUTF8(\"Synthetic\");\n            }\n        }\n        if (innerClasses != null) {\n            ++attributeCount;\n            size += 8 + innerClasses.length;\n            newUTF8(\"InnerClasses\");\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            ++attributeCount;\n            size += 8 + anns.getSize();\n            newUTF8(\"RuntimeVisibleAnnotations\");\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            ++attributeCount;\n            size += 8 + ianns.getSize();\n            newUTF8(\"RuntimeInvisibleAnnotations\");\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            ++attributeCount;\n            size += 8 + tanns.getSize();\n            newUTF8(\"RuntimeVisibleTypeAnnotations\");\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            ++attributeCount;\n            size += 8 + itanns.getSize();\n            newUTF8(\"RuntimeInvisibleTypeAnnotations\");\n        }\n        if (attrs != null) {\n            attributeCount += attrs.getCount();\n            size += attrs.getSize(this, null, 0, -1, -1);\n        }\n        size += pool.length;\n        // allocates a byte vector of this size, in order to avoid unnecessary\n        // arraycopy operations in the ByteVector.enlarge() method\n        ByteVector out = new ByteVector(size);\n        out.putInt(0xCAFEBABE).putInt(version);\n        out.putShort(index).putByteArray(pool.data, 0, pool.length);\n        int mask = Opcodes.ACC_DEPRECATED | ACC_SYNTHETIC_ATTRIBUTE\n                | ((access & ACC_SYNTHETIC_ATTRIBUTE) / TO_ACC_SYNTHETIC);\n        out.putShort(access & ~mask).putShort(name).putShort(superName);\n        out.putShort(interfaceCount);\n        for (int i = 0; i < interfaceCount; ++i) {\n            out.putShort(interfaces[i]);\n        }\n        out.putShort(nbFields);\n        fb = firstField;\n        while (fb != null) {\n            fb.put(out);\n            fb = (FieldWriter) fb.fv;\n        }\n        out.putShort(nbMethods);\n        mb = firstMethod;\n        while (mb != null) {\n            mb.put(out);\n            mb = (MethodWriter) mb.mv;\n        }\n        out.putShort(attributeCount);\n        if (bootstrapMethods != null) {\n            out.putShort(newUTF8(\"BootstrapMethods\"));\n            out.putInt(bootstrapMethods.length + 2).putShort(\n                    bootstrapMethodsCount);\n            out.putByteArray(bootstrapMethods.data, 0, bootstrapMethods.length);\n        }\n        if (ClassReader.SIGNATURES && signature != 0) {\n            out.putShort(newUTF8(\"Signature\")).putInt(2).putShort(signature);\n        }\n        if (sourceFile != 0) {\n            out.putShort(newUTF8(\"SourceFile\")).putInt(2).putShort(sourceFile);\n        }\n        if (sourceDebug != null) {\n            int len = sourceDebug.length;\n            out.putShort(newUTF8(\"SourceDebugExtension\")).putInt(len);\n            out.putByteArray(sourceDebug.data, 0, len);\n        }\n        if (enclosingMethodOwner != 0) {\n            out.putShort(newUTF8(\"EnclosingMethod\")).putInt(4);\n            out.putShort(enclosingMethodOwner).putShort(enclosingMethod);\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            out.putShort(newUTF8(\"Deprecated\")).putInt(0);\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                out.putShort(newUTF8(\"Synthetic\")).putInt(0);\n            }\n        }\n        if (innerClasses != null) {\n            out.putShort(newUTF8(\"InnerClasses\"));\n            out.putInt(innerClasses.length + 2).putShort(innerClassesCount);\n            out.putByteArray(innerClasses.data, 0, innerClasses.length);\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            out.putShort(newUTF8(\"RuntimeVisibleAnnotations\"));\n            anns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            out.putShort(newUTF8(\"RuntimeInvisibleAnnotations\"));\n            ianns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            out.putShort(newUTF8(\"RuntimeVisibleTypeAnnotations\"));\n            tanns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            out.putShort(newUTF8(\"RuntimeInvisibleTypeAnnotations\"));\n            itanns.put(out);\n        }\n        if (attrs != null) {\n            attrs.put(this, null, 0, -1, -1, out);\n        }\n        if (invalidFrames) {\n            anns = null;\n            ianns = null;\n            attrs = null;\n            innerClassesCount = 0;\n            innerClasses = null;\n            bootstrapMethodsCount = 0;\n            bootstrapMethods = null;\n            firstField = null;\n            lastField = null;\n            firstMethod = null;\n            lastMethod = null;\n            computeMaxs = false;\n            computeFrames = true;\n            invalidFrames = false;\n            new ClassReader(out.data).accept(this, ClassReader.SKIP_FRAMES);\n            return toByteArray();\n        }\n        return out.data;\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: constant pool management\n    // ------------------------------------------------------------------------\n\n    /**\n     * Adds a number or string constant to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * \n     * @param cst\n     *            the value of the constant to be added to the constant pool.\n     *            This parameter must be an {@link Integer}, a {@link Float}, a\n     *            {@link Long}, a {@link Double}, a {@link String} or a\n     *            {@link Type}.\n     * @return a new or already existing constant item with the given value.\n     */\n    Item newConstItem(final Object cst) {\n        if (cst instanceof Integer) {\n            int val = ((Integer) cst).intValue();\n            return newInteger(val);\n        } else if (cst instanceof Byte) {\n            int val = ((Byte) cst).intValue();\n            return newInteger(val);\n        } else if (cst instanceof Character) {\n            int val = ((Character) cst).charValue();\n            return newInteger(val);\n        } else if (cst instanceof Short) {\n            int val = ((Short) cst).intValue();\n            return newInteger(val);\n        } else if (cst instanceof Boolean) {\n            int val = ((Boolean) cst).booleanValue() ? 1 : 0;\n            return newInteger(val);\n        } else if (cst instanceof Float) {\n            float val = ((Float) cst).floatValue();\n            return newFloat(val);\n        } else if (cst instanceof Long) {\n            long val = ((Long) cst).longValue();\n            return newLong(val);\n        } else if (cst instanceof Double) {\n            double val = ((Double) cst).doubleValue();\n            return newDouble(val);\n        } else if (cst instanceof String) {\n            return newString((String) cst);\n        } else if (cst instanceof Type) {\n            Type t = (Type) cst;\n            int s = t.getSort();\n            if (s == Type.OBJECT) {\n                return newClassItem(t.getInternalName());\n            } else if (s == Type.METHOD) {\n                return newMethodTypeItem(t.getDescriptor());\n            } else { // s == primitive type or array\n                return newClassItem(t.getDescriptor());\n            }\n        } else if (cst instanceof Handle) {\n            Handle h = (Handle) cst;\n            return newHandleItem(h.tag, h.owner, h.name, h.desc, h.itf);\n        } else {\n            throw new IllegalArgumentException(\"value \" + cst);\n        }\n    }\n\n    /**\n     * Adds a number or string constant to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param cst\n     *            the value of the constant to be added to the constant pool.\n     *            This parameter must be an {@link Integer}, a {@link Float}, a\n     *            {@link Long}, a {@link Double} or a {@link String}.\n     * @return the index of a new or already existing constant item with the\n     *         given value.\n     */\n    public int newConst(final Object cst) {\n        return newConstItem(cst).index;\n    }\n\n    /**\n     * Adds an UTF8 string to the constant pool of the class being build. Does\n     * nothing if the constant pool already contains a similar item. <i>This\n     * method is intended for {@link Attribute} sub classes, and is normally not\n     * needed by class generators or adapters.</i>\n     * \n     * @param value\n     *            the String value.\n     * @return the index of a new or already existing UTF8 item.\n     */\n    public int newUTF8(final String value) {\n        key.set(UTF8, value, null, null);\n        Item result = get(key);\n        if (result == null) {\n            pool.putByte(UTF8).putUTF8(value);\n            result = new Item(index++, key);\n            put(result);\n        }\n        return result.index;\n    }\n\n    /**\n     * Adds a class reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param value\n     *            the internal name of the class.\n     * @return a new or already existing class reference item.\n     */\n    Item newClassItem(final String value) {\n        key2.set(CLASS, value, null, null);\n        Item result = get(key2);\n        if (result == null) {\n            pool.put12(CLASS, newUTF8(value));\n            result = new Item(index++, key2);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a class reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param value\n     *            the internal name of the class.\n     * @return the index of a new or already existing class reference item.\n     */\n    public int newClass(final String value) {\n        return newClassItem(value).index;\n    }\n\n    /**\n     * Adds a method type reference to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param methodDesc\n     *            method descriptor of the method type.\n     * @return a new or already existing method type reference item.\n     */\n    Item newMethodTypeItem(final String methodDesc) {\n        key2.set(MTYPE, methodDesc, null, null);\n        Item result = get(key2);\n        if (result == null) {\n            pool.put12(MTYPE, newUTF8(methodDesc));\n            result = new Item(index++, key2);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a method type reference to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param methodDesc\n     *            method descriptor of the method type.\n     * @return the index of a new or already existing method type reference\n     *         item.\n     */\n    public int newMethodType(final String methodDesc) {\n        return newMethodTypeItem(methodDesc).index;\n    }\n\n    /**\n     * Adds a handle to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item. <i>This method is\n     * intended for {@link Attribute} sub classes, and is normally not needed by\n     * class generators or adapters.</i>\n     * \n     * @param tag\n     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},\n     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},\n     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},\n     *            {@link Opcodes#H_INVOKESTATIC},\n     *            {@link Opcodes#H_INVOKESPECIAL},\n     *            {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *            {@link Opcodes#H_INVOKEINTERFACE}.\n     * @param owner\n     *            the internal name of the field or method owner class.\n     * @param name\n     *            the name of the field or method.\n     * @param desc\n     *            the descriptor of the field or method.\n     * @param itf\n     *            true if the owner is an interface.\n     * @return a new or an already existing method type reference item.\n     */\n    Item newHandleItem(final int tag, final String owner, final String name,\n            final String desc, final boolean itf) {\n        key4.set(HANDLE_BASE + tag, owner, name, desc);\n        Item result = get(key4);\n        if (result == null) {\n            if (tag <= Opcodes.H_PUTSTATIC) {\n                put112(HANDLE, tag, newField(owner, name, desc));\n            } else {\n                put112(HANDLE,\n                        tag,\n                        newMethod(owner, name, desc, itf));\n            }\n            result = new Item(index++, key4);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a handle to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item. <i>This method is\n     * intended for {@link Attribute} sub classes, and is normally not needed by\n     * class generators or adapters.</i>\n     * \n     * @param tag\n     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},\n     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},\n     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},\n     *            {@link Opcodes#H_INVOKESTATIC},\n     *            {@link Opcodes#H_INVOKESPECIAL},\n     *            {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *            {@link Opcodes#H_INVOKEINTERFACE}.\n     * @param owner\n     *            the internal name of the field or method owner class.\n     * @param name\n     *            the name of the field or method.\n     * @param desc\n     *            the descriptor of the field or method.\n     * @return the index of a new or already existing method type reference\n     *         item.\n     *         \n     * @deprecated this method is superseded by\n     *             {@link #newHandle(int, String, String, String, boolean)}.\n     */\n    @Deprecated\n    public int newHandle(final int tag, final String owner, final String name,\n            final String desc) {\n        return newHandle(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);\n    }\n\n    /**\n     * Adds a handle to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item. <i>This method is\n     * intended for {@link Attribute} sub classes, and is normally not needed by\n     * class generators or adapters.</i>\n     * \n     * @param tag\n     *            the kind of this handle. Must be {@link Opcodes#H_GETFIELD},\n     *            {@link Opcodes#H_GETSTATIC}, {@link Opcodes#H_PUTFIELD},\n     *            {@link Opcodes#H_PUTSTATIC}, {@link Opcodes#H_INVOKEVIRTUAL},\n     *            {@link Opcodes#H_INVOKESTATIC},\n     *            {@link Opcodes#H_INVOKESPECIAL},\n     *            {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *            {@link Opcodes#H_INVOKEINTERFACE}.\n     * @param owner\n     *            the internal name of the field or method owner class.\n     * @param name\n     *            the name of the field or method.\n     * @param desc\n     *            the descriptor of the field or method.\n     * @param itf\n     *            true if the owner is an interface.\n     * @return the index of a new or already existing method type reference\n     *         item.\n     */\n    public int newHandle(final int tag, final String owner, final String name,\n            final String desc, final boolean itf) {\n        return newHandleItem(tag, owner, name, desc, itf).index;\n    }\n    \n    /**\n     * Adds an invokedynamic reference to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param name\n     *            name of the invoked method.\n     * @param desc\n     *            descriptor of the invoke method.\n     * @param bsm\n     *            the bootstrap method.\n     * @param bsmArgs\n     *            the bootstrap method constant arguments.\n     * \n     * @return a new or an already existing invokedynamic type reference item.\n     */\n    Item newInvokeDynamicItem(final String name, final String desc,\n            final Handle bsm, final Object... bsmArgs) {\n        // cache for performance\n        ByteVector bootstrapMethods = this.bootstrapMethods;\n        if (bootstrapMethods == null) {\n            bootstrapMethods = this.bootstrapMethods = new ByteVector();\n        }\n\n        int position = bootstrapMethods.length; // record current position\n\n        int hashCode = bsm.hashCode();\n        bootstrapMethods.putShort(newHandle(bsm.tag, bsm.owner, bsm.name,\n                bsm.desc, bsm.isInterface()));\n\n        int argsLength = bsmArgs.length;\n        bootstrapMethods.putShort(argsLength);\n\n        for (int i = 0; i < argsLength; i++) {\n            Object bsmArg = bsmArgs[i];\n            hashCode ^= bsmArg.hashCode();\n            bootstrapMethods.putShort(newConst(bsmArg));\n        }\n\n        byte[] data = bootstrapMethods.data;\n        int length = (1 + 1 + argsLength) << 1; // (bsm + argCount + arguments)\n        hashCode &= 0x7FFFFFFF;\n        Item result = items[hashCode % items.length];\n        loop: while (result != null) {\n            if (result.type != BSM || result.hashCode != hashCode) {\n                result = result.next;\n                continue;\n            }\n\n            // because the data encode the size of the argument\n            // we don't need to test if these size are equals\n            int resultPosition = result.intVal;\n            for (int p = 0; p < length; p++) {\n                if (data[position + p] != data[resultPosition + p]) {\n                    result = result.next;\n                    continue loop;\n                }\n            }\n            break;\n        }\n\n        int bootstrapMethodIndex;\n        if (result != null) {\n            bootstrapMethodIndex = result.index;\n            bootstrapMethods.length = position; // revert to old position\n        } else {\n            bootstrapMethodIndex = bootstrapMethodsCount++;\n            result = new Item(bootstrapMethodIndex);\n            result.set(position, hashCode);\n            put(result);\n        }\n\n        // now, create the InvokeDynamic constant\n        key3.set(name, desc, bootstrapMethodIndex);\n        result = get(key3);\n        if (result == null) {\n            put122(INDY, bootstrapMethodIndex, newNameType(name, desc));\n            result = new Item(index++, key3);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds an invokedynamic reference to the constant pool of the class being\n     * build. Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param name\n     *            name of the invoked method.\n     * @param desc\n     *            descriptor of the invoke method.\n     * @param bsm\n     *            the bootstrap method.\n     * @param bsmArgs\n     *            the bootstrap method constant arguments.\n     * \n     * @return the index of a new or already existing invokedynamic reference\n     *         item.\n     */\n    public int newInvokeDynamic(final String name, final String desc,\n            final Handle bsm, final Object... bsmArgs) {\n        return newInvokeDynamicItem(name, desc, bsm, bsmArgs).index;\n    }\n\n    /**\n     * Adds a field reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * \n     * @param owner\n     *            the internal name of the field's owner class.\n     * @param name\n     *            the field's name.\n     * @param desc\n     *            the field's descriptor.\n     * @return a new or already existing field reference item.\n     */\n    Item newFieldItem(final String owner, final String name, final String desc) {\n        key3.set(FIELD, owner, name, desc);\n        Item result = get(key3);\n        if (result == null) {\n            put122(FIELD, newClass(owner), newNameType(name, desc));\n            result = new Item(index++, key3);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a field reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param owner\n     *            the internal name of the field's owner class.\n     * @param name\n     *            the field's name.\n     * @param desc\n     *            the field's descriptor.\n     * @return the index of a new or already existing field reference item.\n     */\n    public int newField(final String owner, final String name, final String desc) {\n        return newFieldItem(owner, name, desc).index;\n    }\n\n    /**\n     * Adds a method reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * \n     * @param owner\n     *            the internal name of the method's owner class.\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor.\n     * @param itf\n     *            <tt>true</tt> if <tt>owner</tt> is an interface.\n     * @return a new or already existing method reference item.\n     */\n    Item newMethodItem(final String owner, final String name,\n            final String desc, final boolean itf) {\n        int type = itf ? IMETH : METH;\n        key3.set(type, owner, name, desc);\n        Item result = get(key3);\n        if (result == null) {\n            put122(type, newClass(owner), newNameType(name, desc));\n            result = new Item(index++, key3);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a method reference to the constant pool of the class being build.\n     * Does nothing if the constant pool already contains a similar item.\n     * <i>This method is intended for {@link Attribute} sub classes, and is\n     * normally not needed by class generators or adapters.</i>\n     * \n     * @param owner\n     *            the internal name of the method's owner class.\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor.\n     * @param itf\n     *            <tt>true</tt> if <tt>owner</tt> is an interface.\n     * @return the index of a new or already existing method reference item.\n     */\n    public int newMethod(final String owner, final String name,\n            final String desc, final boolean itf) {\n        return newMethodItem(owner, name, desc, itf).index;\n    }\n\n    /**\n     * Adds an integer to the constant pool of the class being build. Does\n     * nothing if the constant pool already contains a similar item.\n     * \n     * @param value\n     *            the int value.\n     * @return a new or already existing int item.\n     */\n    Item newInteger(final int value) {\n        key.set(value);\n        Item result = get(key);\n        if (result == null) {\n            pool.putByte(INT).putInt(value);\n            result = new Item(index++, key);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a float to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item.\n     * \n     * @param value\n     *            the float value.\n     * @return a new or already existing float item.\n     */\n    Item newFloat(final float value) {\n        key.set(value);\n        Item result = get(key);\n        if (result == null) {\n            pool.putByte(FLOAT).putInt(key.intVal);\n            result = new Item(index++, key);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a long to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item.\n     * \n     * @param value\n     *            the long value.\n     * @return a new or already existing long item.\n     */\n    Item newLong(final long value) {\n        key.set(value);\n        Item result = get(key);\n        if (result == null) {\n            pool.putByte(LONG).putLong(value);\n            result = new Item(index, key);\n            index += 2;\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a double to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item.\n     * \n     * @param value\n     *            the double value.\n     * @return a new or already existing double item.\n     */\n    Item newDouble(final double value) {\n        key.set(value);\n        Item result = get(key);\n        if (result == null) {\n            pool.putByte(DOUBLE).putLong(key.longVal);\n            result = new Item(index, key);\n            index += 2;\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a string to the constant pool of the class being build. Does nothing\n     * if the constant pool already contains a similar item.\n     * \n     * @param value\n     *            the String value.\n     * @return a new or already existing string item.\n     */\n    private Item newString(final String value) {\n        key2.set(STR, value, null, null);\n        Item result = get(key2);\n        if (result == null) {\n            pool.put12(STR, newUTF8(value));\n            result = new Item(index++, key2);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds a name and type to the constant pool of the class being build. Does\n     * nothing if the constant pool already contains a similar item. <i>This\n     * method is intended for {@link Attribute} sub classes, and is normally not\n     * needed by class generators or adapters.</i>\n     * \n     * @param name\n     *            a name.\n     * @param desc\n     *            a type descriptor.\n     * @return the index of a new or already existing name and type item.\n     */\n    public int newNameType(final String name, final String desc) {\n        return newNameTypeItem(name, desc).index;\n    }\n\n    /**\n     * Adds a name and type to the constant pool of the class being build. Does\n     * nothing if the constant pool already contains a similar item.\n     * \n     * @param name\n     *            a name.\n     * @param desc\n     *            a type descriptor.\n     * @return a new or already existing name and type item.\n     */\n    Item newNameTypeItem(final String name, final String desc) {\n        key2.set(NAME_TYPE, name, desc, null);\n        Item result = get(key2);\n        if (result == null) {\n            put122(NAME_TYPE, newUTF8(name), newUTF8(desc));\n            result = new Item(index++, key2);\n            put(result);\n        }\n        return result;\n    }\n\n    /**\n     * Adds the given internal name to {@link #typeTable} and returns its index.\n     * Does nothing if the type table already contains this internal name.\n     * \n     * @param type\n     *            the internal name to be added to the type table.\n     * @return the index of this internal name in the type table.\n     */\n    int addType(final String type) {\n        key.set(TYPE_NORMAL, type, null, null);\n        Item result = get(key);\n        if (result == null) {\n            result = addType(key);\n        }\n        return result.index;\n    }\n\n    /**\n     * Adds the given \"uninitialized\" type to {@link #typeTable} and returns its\n     * index. This method is used for UNINITIALIZED types, made of an internal\n     * name and a bytecode offset.\n     * \n     * @param type\n     *            the internal name to be added to the type table.\n     * @param offset\n     *            the bytecode offset of the NEW instruction that created this\n     *            UNINITIALIZED type value.\n     * @return the index of this internal name in the type table.\n     */\n    int addUninitializedType(final String type, final int offset) {\n        key.type = TYPE_UNINIT;\n        key.intVal = offset;\n        key.strVal1 = type;\n        key.hashCode = 0x7FFFFFFF & (TYPE_UNINIT + type.hashCode() + offset);\n        Item result = get(key);\n        if (result == null) {\n            result = addType(key);\n        }\n        return result.index;\n    }\n\n    /**\n     * Adds the given Item to {@link #typeTable}.\n     * \n     * @param item\n     *            the value to be added to the type table.\n     * @return the added Item, which a new Item instance with the same value as\n     *         the given Item.\n     */\n    private Item addType(final Item item) {\n        ++typeCount;\n        Item result = new Item(typeCount, key);\n        put(result);\n        if (typeTable == null) {\n            typeTable = new Item[16];\n        }\n        if (typeCount == typeTable.length) {\n            Item[] newTable = new Item[2 * typeTable.length];\n            System.arraycopy(typeTable, 0, newTable, 0, typeTable.length);\n            typeTable = newTable;\n        }\n        typeTable[typeCount] = result;\n        return result;\n    }\n\n    /**\n     * Returns the index of the common super type of the two given types. This\n     * method calls {@link #getCommonSuperClass} and caches the result in the\n     * {@link #items} hash table to speedup future calls with the same\n     * parameters.\n     * \n     * @param type1\n     *            index of an internal name in {@link #typeTable}.\n     * @param type2\n     *            index of an internal name in {@link #typeTable}.\n     * @return the index of the common super type of the two given types.\n     */\n    int getMergedType(final int type1, final int type2) {\n        key2.type = TYPE_MERGED;\n        key2.longVal = type1 | (((long) type2) << 32);\n        key2.hashCode = 0x7FFFFFFF & (TYPE_MERGED + type1 + type2);\n        Item result = get(key2);\n        if (result == null) {\n            String t = typeTable[type1].strVal1;\n            String u = typeTable[type2].strVal1;\n            key2.intVal = addType(getCommonSuperClass(t, u));\n            result = new Item((short) 0, key2);\n            put(result);\n        }\n        return result.intVal;\n    }\n\n    /**\n     * Returns the common super type of the two given types. The default\n     * implementation of this method <i>loads</i> the two given classes and uses\n     * the java.lang.Class methods to find the common super class. It can be\n     * overridden to compute this common super type in other ways, in particular\n     * without actually loading any class, or to take into account the class\n     * that is currently being generated by this ClassWriter, which can of\n     * course not be loaded since it is under construction.\n     * \n     * @param type1\n     *            the internal name of a class.\n     * @param type2\n     *            the internal name of another class.\n     * @return the internal name of the common super class of the two given\n     *         classes.\n     */\n    protected String getCommonSuperClass(final String type1, final String type2) {\n        Class<?> c, d;\n        ClassLoader classLoader = getClass().getClassLoader();\n        try {\n            c = Class.forName(type1.replace('/', '.'), false, classLoader);\n            d = Class.forName(type2.replace('/', '.'), false, classLoader);\n        } catch (Exception e) {\n            throw new RuntimeException(e.getMessage());\n        }\n        if (c.isAssignableFrom(d)) {\n            return type1;\n        }\n        if (d.isAssignableFrom(c)) {\n            return type2;\n        }\n        if (c.isInterface() || d.isInterface()) {\n            return \"java/lang/Object\";\n        } else {\n            do {\n                c = c.getSuperclass();\n            } while (!c.isAssignableFrom(d));\n            return c.getName().replace('.', '/');\n        }\n    }\n\n    /**\n     * Returns the constant pool's hash table item which is equal to the given\n     * item.\n     * \n     * @param key\n     *            a constant pool item.\n     * @return the constant pool's hash table item which is equal to the given\n     *         item, or <tt>null</tt> if there is no such item.\n     */\n    private Item get(final Item key) {\n        Item i = items[key.hashCode % items.length];\n        while (i != null && (i.type != key.type || !key.isEqualTo(i))) {\n            i = i.next;\n        }\n        return i;\n    }\n\n    /**\n     * Puts the given item in the constant pool's hash table. The hash table\n     * <i>must</i> not already contains this item.\n     * \n     * @param i\n     *            the item to be added to the constant pool's hash table.\n     */\n    private void put(final Item i) {\n        if (index + typeCount > threshold) {\n            int ll = items.length;\n            int nl = ll * 2 + 1;\n            Item[] newItems = new Item[nl];\n            for (int l = ll - 1; l >= 0; --l) {\n                Item j = items[l];\n                while (j != null) {\n                    int index = j.hashCode % newItems.length;\n                    Item k = j.next;\n                    j.next = newItems[index];\n                    newItems[index] = j;\n                    j = k;\n                }\n            }\n            items = newItems;\n            threshold = (int) (nl * 0.75);\n        }\n        int index = i.hashCode % items.length;\n        i.next = items[index];\n        items[index] = i;\n    }\n\n    /**\n     * Puts one byte and two shorts into the constant pool.\n     * \n     * @param b\n     *            a byte.\n     * @param s1\n     *            a short.\n     * @param s2\n     *            another short.\n     */\n    private void put122(final int b, final int s1, final int s2) {\n        pool.put12(b, s1).putShort(s2);\n    }\n\n    /**\n     * Puts two bytes and one short into the constant pool.\n     * \n     * @param b1\n     *            a byte.\n     * @param b2\n     *            another byte.\n     * @param s\n     *            a short.\n     */\n    private void put112(final int b1, final int b2, final int s) {\n        pool.put11(b1, b2).putShort(s);\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Context.java",
    "content": "/***\r\n * ASM: a very small and fast Java bytecode manipulation framework\r\n * Copyright (c) 2000-2011 INRIA, France Telecom\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without\r\n * modification, are permitted provided that the following conditions\r\n * are met:\r\n * 1. Redistributions of source code must retain the above copyright\r\n *    notice, this list of conditions and the following disclaimer.\r\n * 2. Redistributions in binary form must reproduce the above copyright\r\n *    notice, this list of conditions and the following disclaimer in the\r\n *    documentation and/or other materials provided with the distribution.\r\n * 3. Neither the name of the copyright holders nor the names of its\r\n *    contributors may be used to endorse or promote products derived from\r\n *    this software without specific prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\r\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r\n * THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\npackage lt.dependencies.asm;\r\n\r\n/**\r\n * Information about a class being parsed in a {@link ClassReader}.\r\n * \r\n * @author Eric Bruneton\r\n */\r\nclass Context {\r\n\r\n    /**\r\n     * Prototypes of the attributes that must be parsed for this class.\r\n     */\r\n    Attribute[] attrs;\r\n\r\n    /**\r\n     * The {@link ClassReader} option flags for the parsing of this class.\r\n     */\r\n    int flags;\r\n\r\n    /**\r\n     * The buffer used to read strings.\r\n     */\r\n    char[] buffer;\r\n\r\n    /**\r\n     * The start index of each bootstrap method.\r\n     */\r\n    int[] bootstrapMethods;\r\n\r\n    /**\r\n     * The access flags of the method currently being parsed.\r\n     */\r\n    int access;\r\n\r\n    /**\r\n     * The name of the method currently being parsed.\r\n     */\r\n    String name;\r\n\r\n    /**\r\n     * The descriptor of the method currently being parsed.\r\n     */\r\n    String desc;\r\n\r\n    /**\r\n     * The label objects, indexed by bytecode offset, of the method currently\r\n     * being parsed (only bytecode offsets for which a label is needed have a\r\n     * non null associated Label object).\r\n     */\r\n    Label[] labels;\r\n\r\n    /**\r\n     * The target of the type annotation currently being parsed.\r\n     */\r\n    int typeRef;\r\n\r\n    /**\r\n     * The path of the type annotation currently being parsed.\r\n     */\r\n    TypePath typePath;\r\n\r\n    /**\r\n     * The offset of the latest stack map frame that has been parsed.\r\n     */\r\n    int offset;\r\n\r\n    /**\r\n     * The labels corresponding to the start of the local variable ranges in the\r\n     * local variable type annotation currently being parsed.\r\n     */\r\n    Label[] start;\r\n\r\n    /**\r\n     * The labels corresponding to the end of the local variable ranges in the\r\n     * local variable type annotation currently being parsed.\r\n     */\r\n    Label[] end;\r\n\r\n    /**\r\n     * The local variable indices for each local variable range in the local\r\n     * variable type annotation currently being parsed.\r\n     */\r\n    int[] index;\r\n\r\n    /**\r\n     * The encoding of the latest stack map frame that has been parsed.\r\n     */\r\n    int mode;\r\n\r\n    /**\r\n     * The number of locals in the latest stack map frame that has been parsed.\r\n     */\r\n    int localCount;\r\n\r\n    /**\r\n     * The number locals in the latest stack map frame that has been parsed,\r\n     * minus the number of locals in the previous frame.\r\n     */\r\n    int localDiff;\r\n\r\n    /**\r\n     * The local values of the latest stack map frame that has been parsed.\r\n     */\r\n    Object[] local;\r\n\r\n    /**\r\n     * The stack size of the latest stack map frame that has been parsed.\r\n     */\r\n    int stackCount;\r\n\r\n    /**\r\n     * The stack values of the latest stack map frame that has been parsed.\r\n     */\r\n    Object[] stack;\r\n}"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Edge.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * An edge in the control flow graph of a method body. See {@link Label Label}.\n * \n * @author Eric Bruneton\n */\nclass Edge {\n\n    /**\n     * Denotes a normal control flow graph edge.\n     */\n    static final int NORMAL = 0;\n\n    /**\n     * Denotes a control flow graph edge corresponding to an exception handler.\n     * More precisely any {@link Edge} whose {@link #info} is strictly positive\n     * corresponds to an exception handler. The actual value of {@link #info} is\n     * the index, in the {@link ClassWriter} type table, of the exception that\n     * is catched.\n     */\n    static final int EXCEPTION = 0x7FFFFFFF;\n\n    /**\n     * Information about this control flow graph edge. If\n     * {@link ClassWriter#COMPUTE_MAXS} is used this field is the (relative)\n     * stack size in the basic block from which this edge originates. This size\n     * is equal to the stack size at the \"jump\" instruction to which this edge\n     * corresponds, relatively to the stack size at the beginning of the\n     * originating basic block. If {@link ClassWriter#COMPUTE_FRAMES} is used,\n     * this field is the kind of this control flow graph edge (i.e. NORMAL or\n     * EXCEPTION).\n     */\n    int info;\n\n    /**\n     * The successor block of the basic block from which this edge originates.\n     */\n    Label successor;\n\n    /**\n     * The next edge in the list of successors of the originating basic block.\n     * See {@link Label#successors successors}.\n     */\n    Edge next;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/FieldVisitor.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A visitor to visit a Java field. The methods of this class must be called in\n * the following order: ( <tt>visitAnnotation</tt> |\n * <tt>visitTypeAnnotation</tt> | <tt>visitAttribute</tt> )* <tt>visitEnd</tt>.\n * \n * @author Eric Bruneton\n */\npublic abstract class FieldVisitor {\n\n    /**\n     * The ASM API version implemented by this visitor. The value of this field\n     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    protected final int api;\n\n    /**\n     * The field visitor to which this visitor must delegate method calls. May\n     * be null.\n     */\n    protected FieldVisitor fv;\n\n    /**\n     * Constructs a new {@link FieldVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    public FieldVisitor(final int api) {\n        this(api, null);\n    }\n\n    /**\n     * Constructs a new {@link FieldVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     * @param fv\n     *            the field visitor to which this visitor must delegate method\n     *            calls. May be null.\n     */\n    public FieldVisitor(final int api, final FieldVisitor fv) {\n        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {\n            throw new IllegalArgumentException();\n        }\n        this.api = api;\n        this.fv = fv;\n    }\n\n    /**\n     * Visits an annotation of the field.\n     * \n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        if (fv != null) {\n            return fv.visitAnnotation(desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits an annotation on the type of the field.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#FIELD FIELD}. See\n     *            {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitTypeAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (fv != null) {\n            return fv.visitTypeAnnotation(typeRef, typePath, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a non standard attribute of the field.\n     * \n     * @param attr\n     *            an attribute.\n     */\n    public void visitAttribute(Attribute attr) {\n        if (fv != null) {\n            fv.visitAttribute(attr);\n        }\n    }\n\n    /**\n     * Visits the end of the field. This method, which is the last one to be\n     * called, is used to inform the visitor that all the annotations and\n     * attributes of the field have been visited.\n     */\n    public void visitEnd() {\n        if (fv != null) {\n            fv.visitEnd();\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/FieldWriter.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * An {@link FieldVisitor} that generates Java fields in bytecode form.\n * \n * @author Eric Bruneton\n */\nfinal class FieldWriter extends FieldVisitor {\n\n    /**\n     * The class writer to which this field must be added.\n     */\n    private final ClassWriter cw;\n\n    /**\n     * Access flags of this field.\n     */\n    private final int access;\n\n    /**\n     * The index of the constant pool item that contains the name of this\n     * method.\n     */\n    private final int name;\n\n    /**\n     * The index of the constant pool item that contains the descriptor of this\n     * field.\n     */\n    private final int desc;\n\n    /**\n     * The index of the constant pool item that contains the signature of this\n     * field.\n     */\n    private int signature;\n\n    /**\n     * The index of the constant pool item that contains the constant value of\n     * this field.\n     */\n    private int value;\n\n    /**\n     * The runtime visible annotations of this field. May be <tt>null</tt>.\n     */\n    private AnnotationWriter anns;\n\n    /**\n     * The runtime invisible annotations of this field. May be <tt>null</tt>.\n     */\n    private AnnotationWriter ianns;\n\n    /**\n     * The runtime visible type annotations of this field. May be <tt>null</tt>.\n     */\n    private AnnotationWriter tanns;\n\n    /**\n     * The runtime invisible type annotations of this field. May be\n     * <tt>null</tt>.\n     */\n    private AnnotationWriter itanns;\n\n    /**\n     * The non standard attributes of this field. May be <tt>null</tt>.\n     */\n    private Attribute attrs;\n\n    // ------------------------------------------------------------------------\n    // Constructor\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link FieldWriter}.\n     * \n     * @param cw\n     *            the class writer to which this field must be added.\n     * @param access\n     *            the field's access flags (see {@link Opcodes}).\n     * @param name\n     *            the field's name.\n     * @param desc\n     *            the field's descriptor (see {@link Type}).\n     * @param signature\n     *            the field's signature. May be <tt>null</tt>.\n     * @param value\n     *            the field's constant value. May be <tt>null</tt>.\n     */\n    FieldWriter(final ClassWriter cw, final int access, final String name,\n            final String desc, final String signature, final Object value) {\n        super(Opcodes.ASM5);\n        if (cw.firstField == null) {\n            cw.firstField = this;\n        } else {\n            cw.lastField.fv = this;\n        }\n        cw.lastField = this;\n        this.cw = cw;\n        this.access = access;\n        this.name = cw.newUTF8(name);\n        this.desc = cw.newUTF8(desc);\n        if (ClassReader.SIGNATURES && signature != null) {\n            this.signature = cw.newUTF8(signature);\n        }\n        if (value != null) {\n            this.value = cw.newConstItem(value).index;\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Implementation of the FieldVisitor abstract class\n    // ------------------------------------------------------------------------\n\n    @Override\n    public AnnotationVisitor visitAnnotation(final String desc,\n            final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);\n        if (visible) {\n            aw.next = anns;\n            anns = aw;\n        } else {\n            aw.next = ianns;\n            ianns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public AnnotationVisitor visitTypeAnnotation(final int typeRef,\n            final TypePath typePath, final String desc, final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        AnnotationWriter.putTarget(typeRef, typePath, bv);\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = tanns;\n            tanns = aw;\n        } else {\n            aw.next = itanns;\n            itanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public void visitAttribute(final Attribute attr) {\n        attr.next = attrs;\n        attrs = attr;\n    }\n\n    @Override\n    public void visitEnd() {\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the size of this field.\n     * \n     * @return the size of this field.\n     */\n    int getSize() {\n        int size = 8;\n        if (value != 0) {\n            cw.newUTF8(\"ConstantValue\");\n            size += 8;\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                cw.newUTF8(\"Synthetic\");\n                size += 6;\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            cw.newUTF8(\"Deprecated\");\n            size += 6;\n        }\n        if (ClassReader.SIGNATURES && signature != 0) {\n            cw.newUTF8(\"Signature\");\n            size += 8;\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            cw.newUTF8(\"RuntimeVisibleAnnotations\");\n            size += 8 + anns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            cw.newUTF8(\"RuntimeInvisibleAnnotations\");\n            size += 8 + ianns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            cw.newUTF8(\"RuntimeVisibleTypeAnnotations\");\n            size += 8 + tanns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\");\n            size += 8 + itanns.getSize();\n        }\n        if (attrs != null) {\n            size += attrs.getSize(cw, null, 0, -1, -1);\n        }\n        return size;\n    }\n\n    /**\n     * Puts the content of this field into the given byte vector.\n     * \n     * @param out\n     *            where the content of this field must be put.\n     */\n    void put(final ByteVector out) {\n        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;\n        int mask = Opcodes.ACC_DEPRECATED | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE\n                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);\n        out.putShort(access & ~mask).putShort(name).putShort(desc);\n        int attributeCount = 0;\n        if (value != 0) {\n            ++attributeCount;\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                ++attributeCount;\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            ++attributeCount;\n        }\n        if (ClassReader.SIGNATURES && signature != 0) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            ++attributeCount;\n        }\n        if (attrs != null) {\n            attributeCount += attrs.getCount();\n        }\n        out.putShort(attributeCount);\n        if (value != 0) {\n            out.putShort(cw.newUTF8(\"ConstantValue\"));\n            out.putInt(2).putShort(value);\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                out.putShort(cw.newUTF8(\"Synthetic\")).putInt(0);\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            out.putShort(cw.newUTF8(\"Deprecated\")).putInt(0);\n        }\n        if (ClassReader.SIGNATURES && signature != 0) {\n            out.putShort(cw.newUTF8(\"Signature\"));\n            out.putInt(2).putShort(signature);\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeVisibleAnnotations\"));\n            anns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeInvisibleAnnotations\"));\n            ianns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeVisibleTypeAnnotations\"));\n            tanns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\"));\n            itanns.put(out);\n        }\n        if (attrs != null) {\n            attrs.put(cw, null, 0, -1, -1, out);\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Frame.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * Information about the input and output stack map frames of a basic block.\n * \n * @author Eric Bruneton\n */\nfinal class Frame {\n\n    /*\n     * Frames are computed in a two steps process: during the visit of each\n     * instruction, the state of the frame at the end of current basic block is\n     * updated by simulating the action of the instruction on the previous state\n     * of this so called \"output frame\". In visitMaxs, a fix point algorithm is\n     * used to compute the \"input frame\" of each basic block, i.e. the stack map\n     * frame at the beginning of the basic block, starting from the input frame\n     * of the first basic block (which is computed from the method descriptor),\n     * and by using the previously computed output frames to compute the input\n     * state of the other blocks.\n     * \n     * All output and input frames are stored as arrays of integers. Reference\n     * and array types are represented by an index into a type table (which is\n     * not the same as the constant pool of the class, in order to avoid adding\n     * unnecessary constants in the pool - not all computed frames will end up\n     * being stored in the stack map table). This allows very fast type\n     * comparisons.\n     * \n     * Output stack map frames are computed relatively to the input frame of the\n     * basic block, which is not yet known when output frames are computed. It\n     * is therefore necessary to be able to represent abstract types such as\n     * \"the type at position x in the input frame locals\" or \"the type at\n     * position x from the top of the input frame stack\" or even \"the type at\n     * position x in the input frame, with y more (or less) array dimensions\".\n     * This explains the rather complicated type format used in output frames.\n     * \n     * This format is the following: DIM KIND VALUE (4, 4 and 24 bits). DIM is a\n     * signed number of array dimensions (from -8 to 7). KIND is either BASE,\n     * LOCAL or STACK. BASE is used for types that are not relative to the input\n     * frame. LOCAL is used for types that are relative to the input local\n     * variable types. STACK is used for types that are relative to the input\n     * stack types. VALUE depends on KIND. For LOCAL types, it is an index in\n     * the input local variable types. For STACK types, it is a position\n     * relatively to the top of input frame stack. For BASE types, it is either\n     * one of the constants defined below, or for OBJECT and UNINITIALIZED\n     * types, a tag and an index in the type table.\n     * \n     * Output frames can contain types of any kind and with a positive or\n     * negative dimension (and even unassigned types, represented by 0 - which\n     * does not correspond to any valid type value). Input frames can only\n     * contain BASE types of positive or null dimension. In all cases the type\n     * table contains only internal type names (array type descriptors are\n     * forbidden - dimensions must be represented through the DIM field).\n     * \n     * The LONG and DOUBLE types are always represented by using two slots (LONG\n     * + TOP or DOUBLE + TOP), for local variable types as well as in the\n     * operand stack. This is necessary to be able to simulate DUPx_y\n     * instructions, whose effect would be dependent on the actual type values\n     * if types were always represented by a single slot in the stack (and this\n     * is not possible, since actual type values are not always known - cf LOCAL\n     * and STACK type kinds).\n     */\n\n    /**\n     * Mask to get the dimension of a frame type. This dimension is a signed\n     * integer between -8 and 7.\n     */\n    static final int DIM = 0xF0000000;\n\n    /**\n     * Constant to be added to a type to get a type with one more dimension.\n     */\n    static final int ARRAY_OF = 0x10000000;\n\n    /**\n     * Constant to be added to a type to get a type with one less dimension.\n     */\n    static final int ELEMENT_OF = 0xF0000000;\n\n    /**\n     * Mask to get the kind of a frame type.\n     * \n     * @see #BASE\n     * @see #LOCAL\n     * @see #STACK\n     */\n    static final int KIND = 0xF000000;\n\n    /**\n     * Flag used for LOCAL and STACK types. Indicates that if this type happens\n     * to be a long or double type (during the computations of input frames),\n     * then it must be set to TOP because the second word of this value has been\n     * reused to store other data in the basic block. Hence the first word no\n     * longer stores a valid long or double value.\n     */\n    static final int TOP_IF_LONG_OR_DOUBLE = 0x800000;\n\n    /**\n     * Mask to get the value of a frame type.\n     */\n    static final int VALUE = 0x7FFFFF;\n\n    /**\n     * Mask to get the kind of base types.\n     */\n    static final int BASE_KIND = 0xFF00000;\n\n    /**\n     * Mask to get the value of base types.\n     */\n    static final int BASE_VALUE = 0xFFFFF;\n\n    /**\n     * Kind of the types that are not relative to an input stack map frame.\n     */\n    static final int BASE = 0x1000000;\n\n    /**\n     * Base kind of the base reference types. The BASE_VALUE of such types is an\n     * index into the type table.\n     */\n    static final int OBJECT = BASE | 0x700000;\n\n    /**\n     * Base kind of the uninitialized base types. The BASE_VALUE of such types\n     * in an index into the type table (the Item at that index contains both an\n     * instruction offset and an internal class name).\n     */\n    static final int UNINITIALIZED = BASE | 0x800000;\n\n    /**\n     * Kind of the types that are relative to the local variable types of an\n     * input stack map frame. The value of such types is a local variable index.\n     */\n    private static final int LOCAL = 0x2000000;\n\n    /**\n     * Kind of the the types that are relative to the stack of an input stack\n     * map frame. The value of such types is a position relatively to the top of\n     * this stack.\n     */\n    private static final int STACK = 0x3000000;\n\n    /**\n     * The TOP type. This is a BASE type.\n     */\n    static final int TOP = BASE | 0;\n\n    /**\n     * The BOOLEAN type. This is a BASE type mainly used for array types.\n     */\n    static final int BOOLEAN = BASE | 9;\n\n    /**\n     * The BYTE type. This is a BASE type mainly used for array types.\n     */\n    static final int BYTE = BASE | 10;\n\n    /**\n     * The CHAR type. This is a BASE type mainly used for array types.\n     */\n    static final int CHAR = BASE | 11;\n\n    /**\n     * The SHORT type. This is a BASE type mainly used for array types.\n     */\n    static final int SHORT = BASE | 12;\n\n    /**\n     * The INTEGER type. This is a BASE type.\n     */\n    static final int INTEGER = BASE | 1;\n\n    /**\n     * The FLOAT type. This is a BASE type.\n     */\n    static final int FLOAT = BASE | 2;\n\n    /**\n     * The DOUBLE type. This is a BASE type.\n     */\n    static final int DOUBLE = BASE | 3;\n\n    /**\n     * The LONG type. This is a BASE type.\n     */\n    static final int LONG = BASE | 4;\n\n    /**\n     * The NULL type. This is a BASE type.\n     */\n    static final int NULL = BASE | 5;\n\n    /**\n     * The UNINITIALIZED_THIS type. This is a BASE type.\n     */\n    static final int UNINITIALIZED_THIS = BASE | 6;\n\n    /**\n     * The stack size variation corresponding to each JVM instruction. This\n     * stack variation is equal to the size of the values produced by an\n     * instruction, minus the size of the values consumed by this instruction.\n     */\n    static final int[] SIZE;\n\n    /**\n     * Computes the stack size variation corresponding to each JVM instruction.\n     */\n    static {\n        int i;\n        int[] b = new int[202];\n        String s = \"EFFFFFFFFGGFFFGGFFFEEFGFGFEEEEEEEEEEEEEEEEEEEEDEDEDDDDD\"\n                + \"CDCDEEEEEEEEEEEEEEEEEEEEBABABBBBDCFFFGGGEDCDCDCDCDCDCDCDCD\"\n                + \"CDCEEEEDDDDDDDCDCDCEFEFDDEEFFDEDEEEBDDBBDDDDDDCCCCCCCCEFED\"\n                + \"DDCDCDEEEEEEEEEEFEEEEEEDDEEDDEE\";\n        for (i = 0; i < b.length; ++i) {\n            b[i] = s.charAt(i) - 'E';\n        }\n        SIZE = b;\n\n        // code to generate the above string\n        //\n        // int NA = 0; // not applicable (unused opcode or variable size opcode)\n        //\n        // b = new int[] {\n        // 0, //NOP, // visitInsn\n        // 1, //ACONST_NULL, // -\n        // 1, //ICONST_M1, // -\n        // 1, //ICONST_0, // -\n        // 1, //ICONST_1, // -\n        // 1, //ICONST_2, // -\n        // 1, //ICONST_3, // -\n        // 1, //ICONST_4, // -\n        // 1, //ICONST_5, // -\n        // 2, //LCONST_0, // -\n        // 2, //LCONST_1, // -\n        // 1, //FCONST_0, // -\n        // 1, //FCONST_1, // -\n        // 1, //FCONST_2, // -\n        // 2, //DCONST_0, // -\n        // 2, //DCONST_1, // -\n        // 1, //BIPUSH, // visitIntInsn\n        // 1, //SIPUSH, // -\n        // 1, //LDC, // visitLdcInsn\n        // NA, //LDC_W, // -\n        // NA, //LDC2_W, // -\n        // 1, //ILOAD, // visitVarInsn\n        // 2, //LLOAD, // -\n        // 1, //FLOAD, // -\n        // 2, //DLOAD, // -\n        // 1, //ALOAD, // -\n        // NA, //ILOAD_0, // -\n        // NA, //ILOAD_1, // -\n        // NA, //ILOAD_2, // -\n        // NA, //ILOAD_3, // -\n        // NA, //LLOAD_0, // -\n        // NA, //LLOAD_1, // -\n        // NA, //LLOAD_2, // -\n        // NA, //LLOAD_3, // -\n        // NA, //FLOAD_0, // -\n        // NA, //FLOAD_1, // -\n        // NA, //FLOAD_2, // -\n        // NA, //FLOAD_3, // -\n        // NA, //DLOAD_0, // -\n        // NA, //DLOAD_1, // -\n        // NA, //DLOAD_2, // -\n        // NA, //DLOAD_3, // -\n        // NA, //ALOAD_0, // -\n        // NA, //ALOAD_1, // -\n        // NA, //ALOAD_2, // -\n        // NA, //ALOAD_3, // -\n        // -1, //IALOAD, // visitInsn\n        // 0, //LALOAD, // -\n        // -1, //FALOAD, // -\n        // 0, //DALOAD, // -\n        // -1, //AALOAD, // -\n        // -1, //BALOAD, // -\n        // -1, //CALOAD, // -\n        // -1, //SALOAD, // -\n        // -1, //ISTORE, // visitVarInsn\n        // -2, //LSTORE, // -\n        // -1, //FSTORE, // -\n        // -2, //DSTORE, // -\n        // -1, //ASTORE, // -\n        // NA, //ISTORE_0, // -\n        // NA, //ISTORE_1, // -\n        // NA, //ISTORE_2, // -\n        // NA, //ISTORE_3, // -\n        // NA, //LSTORE_0, // -\n        // NA, //LSTORE_1, // -\n        // NA, //LSTORE_2, // -\n        // NA, //LSTORE_3, // -\n        // NA, //FSTORE_0, // -\n        // NA, //FSTORE_1, // -\n        // NA, //FSTORE_2, // -\n        // NA, //FSTORE_3, // -\n        // NA, //DSTORE_0, // -\n        // NA, //DSTORE_1, // -\n        // NA, //DSTORE_2, // -\n        // NA, //DSTORE_3, // -\n        // NA, //ASTORE_0, // -\n        // NA, //ASTORE_1, // -\n        // NA, //ASTORE_2, // -\n        // NA, //ASTORE_3, // -\n        // -3, //IASTORE, // visitInsn\n        // -4, //LASTORE, // -\n        // -3, //FASTORE, // -\n        // -4, //DASTORE, // -\n        // -3, //AASTORE, // -\n        // -3, //BASTORE, // -\n        // -3, //CASTORE, // -\n        // -3, //SASTORE, // -\n        // -1, //POP, // -\n        // -2, //POP2, // -\n        // 1, //DUP, // -\n        // 1, //DUP_X1, // -\n        // 1, //DUP_X2, // -\n        // 2, //DUP2, // -\n        // 2, //DUP2_X1, // -\n        // 2, //DUP2_X2, // -\n        // 0, //SWAP, // -\n        // -1, //IADD, // -\n        // -2, //LADD, // -\n        // -1, //FADD, // -\n        // -2, //DADD, // -\n        // -1, //ISUB, // -\n        // -2, //LSUB, // -\n        // -1, //FSUB, // -\n        // -2, //DSUB, // -\n        // -1, //IMUL, // -\n        // -2, //LMUL, // -\n        // -1, //FMUL, // -\n        // -2, //DMUL, // -\n        // -1, //IDIV, // -\n        // -2, //LDIV, // -\n        // -1, //FDIV, // -\n        // -2, //DDIV, // -\n        // -1, //IREM, // -\n        // -2, //LREM, // -\n        // -1, //FREM, // -\n        // -2, //DREM, // -\n        // 0, //INEG, // -\n        // 0, //LNEG, // -\n        // 0, //FNEG, // -\n        // 0, //DNEG, // -\n        // -1, //ISHL, // -\n        // -1, //LSHL, // -\n        // -1, //ISHR, // -\n        // -1, //LSHR, // -\n        // -1, //IUSHR, // -\n        // -1, //LUSHR, // -\n        // -1, //IAND, // -\n        // -2, //LAND, // -\n        // -1, //IOR, // -\n        // -2, //LOR, // -\n        // -1, //IXOR, // -\n        // -2, //LXOR, // -\n        // 0, //IINC, // visitIincInsn\n        // 1, //I2L, // visitInsn\n        // 0, //I2F, // -\n        // 1, //I2D, // -\n        // -1, //L2I, // -\n        // -1, //L2F, // -\n        // 0, //L2D, // -\n        // 0, //F2I, // -\n        // 1, //F2L, // -\n        // 1, //F2D, // -\n        // -1, //D2I, // -\n        // 0, //D2L, // -\n        // -1, //D2F, // -\n        // 0, //I2B, // -\n        // 0, //I2C, // -\n        // 0, //I2S, // -\n        // -3, //LCMP, // -\n        // -1, //FCMPL, // -\n        // -1, //FCMPG, // -\n        // -3, //DCMPL, // -\n        // -3, //DCMPG, // -\n        // -1, //IFEQ, // visitJumpInsn\n        // -1, //IFNE, // -\n        // -1, //IFLT, // -\n        // -1, //IFGE, // -\n        // -1, //IFGT, // -\n        // -1, //IFLE, // -\n        // -2, //IF_ICMPEQ, // -\n        // -2, //IF_ICMPNE, // -\n        // -2, //IF_ICMPLT, // -\n        // -2, //IF_ICMPGE, // -\n        // -2, //IF_ICMPGT, // -\n        // -2, //IF_ICMPLE, // -\n        // -2, //IF_ACMPEQ, // -\n        // -2, //IF_ACMPNE, // -\n        // 0, //GOTO, // -\n        // 1, //JSR, // -\n        // 0, //RET, // visitVarInsn\n        // -1, //TABLESWITCH, // visiTableSwitchInsn\n        // -1, //LOOKUPSWITCH, // visitLookupSwitch\n        // -1, //IRETURN, // visitInsn\n        // -2, //LRETURN, // -\n        // -1, //FRETURN, // -\n        // -2, //DRETURN, // -\n        // -1, //ARETURN, // -\n        // 0, //RETURN, // -\n        // NA, //GETSTATIC, // visitFieldInsn\n        // NA, //PUTSTATIC, // -\n        // NA, //GETFIELD, // -\n        // NA, //PUTFIELD, // -\n        // NA, //INVOKEVIRTUAL, // visitMethodInsn\n        // NA, //INVOKESPECIAL, // -\n        // NA, //INVOKESTATIC, // -\n        // NA, //INVOKEINTERFACE, // -\n        // NA, //INVOKEDYNAMIC, // visitInvokeDynamicInsn\n        // 1, //NEW, // visitTypeInsn\n        // 0, //NEWARRAY, // visitIntInsn\n        // 0, //ANEWARRAY, // visitTypeInsn\n        // 0, //ARRAYLENGTH, // visitInsn\n        // NA, //ATHROW, // -\n        // 0, //CHECKCAST, // visitTypeInsn\n        // 0, //INSTANCEOF, // -\n        // -1, //MONITORENTER, // visitInsn\n        // -1, //MONITOREXIT, // -\n        // NA, //WIDE, // NOT VISITED\n        // NA, //MULTIANEWARRAY, // visitMultiANewArrayInsn\n        // -1, //IFNULL, // visitJumpInsn\n        // -1, //IFNONNULL, // -\n        // NA, //GOTO_W, // -\n        // NA, //JSR_W, // -\n        // };\n        // for (i = 0; i < b.length; ++i) {\n        // System.err.print((char)('E' + b[i]));\n        // }\n        // System.err.println();\n    }\n\n    /**\n     * The label (i.e. basic block) to which these input and output stack map\n     * frames correspond.\n     */\n    Label owner;\n\n    /**\n     * The input stack map frame locals.\n     */\n    int[] inputLocals;\n\n    /**\n     * The input stack map frame stack.\n     */\n    int[] inputStack;\n\n    /**\n     * The output stack map frame locals.\n     */\n    private int[] outputLocals;\n\n    /**\n     * The output stack map frame stack.\n     */\n    private int[] outputStack;\n\n    /**\n     * Relative size of the output stack. The exact semantics of this field\n     * depends on the algorithm that is used.\n     * \n     * When only the maximum stack size is computed, this field is the size of\n     * the output stack relatively to the top of the input stack.\n     * \n     * When the stack map frames are completely computed, this field is the\n     * actual number of types in {@link #outputStack}.\n     */\n    private int outputStackTop;\n\n    /**\n     * Number of types that are initialized in the basic block.\n     * \n     * @see #initializations\n     */\n    private int initializationCount;\n\n    /**\n     * The types that are initialized in the basic block. A constructor\n     * invocation on an UNINITIALIZED or UNINITIALIZED_THIS type must replace\n     * <i>every occurence</i> of this type in the local variables and in the\n     * operand stack. This cannot be done during the first phase of the\n     * algorithm since, during this phase, the local variables and the operand\n     * stack are not completely computed. It is therefore necessary to store the\n     * types on which constructors are invoked in the basic block, in order to\n     * do this replacement during the second phase of the algorithm, where the\n     * frames are fully computed. Note that this array can contain types that\n     * are relative to input locals or to the input stack (see below for the\n     * description of the algorithm).\n     */\n    private int[] initializations;\n\n    /**\n     * Returns the output frame local variable type at the given index.\n     * \n     * @param local\n     *            the index of the local that must be returned.\n     * @return the output frame local variable type at the given index.\n     */\n    private int get(final int local) {\n        if (outputLocals == null || local >= outputLocals.length) {\n            // this local has never been assigned in this basic block,\n            // so it is still equal to its value in the input frame\n            return LOCAL | local;\n        } else {\n            int type = outputLocals[local];\n            if (type == 0) {\n                // this local has never been assigned in this basic block,\n                // so it is still equal to its value in the input frame\n                type = outputLocals[local] = LOCAL | local;\n            }\n            return type;\n        }\n    }\n\n    /**\n     * Sets the output frame local variable type at the given index.\n     * \n     * @param local\n     *            the index of the local that must be set.\n     * @param type\n     *            the value of the local that must be set.\n     */\n    private void set(final int local, final int type) {\n        // creates and/or resizes the output local variables array if necessary\n        if (outputLocals == null) {\n            outputLocals = new int[10];\n        }\n        int n = outputLocals.length;\n        if (local >= n) {\n            int[] t = new int[Math.max(local + 1, 2 * n)];\n            System.arraycopy(outputLocals, 0, t, 0, n);\n            outputLocals = t;\n        }\n        // sets the local variable\n        outputLocals[local] = type;\n    }\n\n    /**\n     * Pushes a new type onto the output frame stack.\n     * \n     * @param type\n     *            the type that must be pushed.\n     */\n    private void push(final int type) {\n        // creates and/or resizes the output stack array if necessary\n        if (outputStack == null) {\n            outputStack = new int[10];\n        }\n        int n = outputStack.length;\n        if (outputStackTop >= n) {\n            int[] t = new int[Math.max(outputStackTop + 1, 2 * n)];\n            System.arraycopy(outputStack, 0, t, 0, n);\n            outputStack = t;\n        }\n        // pushes the type on the output stack\n        outputStack[outputStackTop++] = type;\n        // updates the maximun height reached by the output stack, if needed\n        int top = owner.inputStackTop + outputStackTop;\n        if (top > owner.outputStackMax) {\n            owner.outputStackMax = top;\n        }\n    }\n\n    /**\n     * Pushes a new type onto the output frame stack.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param desc\n     *            the descriptor of the type to be pushed. Can also be a method\n     *            descriptor (in this case this method pushes its return type\n     *            onto the output frame stack).\n     */\n    private void push(final ClassWriter cw, final String desc) {\n        int type = type(cw, desc);\n        if (type != 0) {\n            push(type);\n            if (type == LONG || type == DOUBLE) {\n                push(TOP);\n            }\n        }\n    }\n\n    /**\n     * Returns the int encoding of the given type.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param desc\n     *            a type descriptor.\n     * @return the int encoding of the given type.\n     */\n    private static int type(final ClassWriter cw, final String desc) {\n        String t;\n        int index = desc.charAt(0) == '(' ? desc.indexOf(')') + 1 : 0;\n        switch (desc.charAt(index)) {\n        case 'V':\n            return 0;\n        case 'Z':\n        case 'C':\n        case 'B':\n        case 'S':\n        case 'I':\n            return INTEGER;\n        case 'F':\n            return FLOAT;\n        case 'J':\n            return LONG;\n        case 'D':\n            return DOUBLE;\n        case 'L':\n            // stores the internal name, not the descriptor!\n            t = desc.substring(index + 1, desc.length() - 1);\n            return OBJECT | cw.addType(t);\n            // case '[':\n        default:\n            // extracts the dimensions and the element type\n            int data;\n            int dims = index + 1;\n            while (desc.charAt(dims) == '[') {\n                ++dims;\n            }\n            switch (desc.charAt(dims)) {\n            case 'Z':\n                data = BOOLEAN;\n                break;\n            case 'C':\n                data = CHAR;\n                break;\n            case 'B':\n                data = BYTE;\n                break;\n            case 'S':\n                data = SHORT;\n                break;\n            case 'I':\n                data = INTEGER;\n                break;\n            case 'F':\n                data = FLOAT;\n                break;\n            case 'J':\n                data = LONG;\n                break;\n            case 'D':\n                data = DOUBLE;\n                break;\n            // case 'L':\n            default:\n                // stores the internal name, not the descriptor\n                t = desc.substring(dims + 1, desc.length() - 1);\n                data = OBJECT | cw.addType(t);\n            }\n            return (dims - index) << 28 | data;\n        }\n    }\n\n    /**\n     * Pops a type from the output frame stack and returns its value.\n     * \n     * @return the type that has been popped from the output frame stack.\n     */\n    private int pop() {\n        if (outputStackTop > 0) {\n            return outputStack[--outputStackTop];\n        } else {\n            // if the output frame stack is empty, pops from the input stack\n            return STACK | -(--owner.inputStackTop);\n        }\n    }\n\n    /**\n     * Pops the given number of types from the output frame stack.\n     * \n     * @param elements\n     *            the number of types that must be popped.\n     */\n    private void pop(final int elements) {\n        if (outputStackTop >= elements) {\n            outputStackTop -= elements;\n        } else {\n            // if the number of elements to be popped is greater than the number\n            // of elements in the output stack, clear it, and pops the remaining\n            // elements from the input stack.\n            owner.inputStackTop -= elements - outputStackTop;\n            outputStackTop = 0;\n        }\n    }\n\n    /**\n     * Pops a type from the output frame stack.\n     * \n     * @param desc\n     *            the descriptor of the type to be popped. Can also be a method\n     *            descriptor (in this case this method pops the types\n     *            corresponding to the method arguments).\n     */\n    private void pop(final String desc) {\n        char c = desc.charAt(0);\n        if (c == '(') {\n            pop((Type.getArgumentsAndReturnSizes(desc) >> 2) - 1);\n        } else if (c == 'J' || c == 'D') {\n            pop(2);\n        } else {\n            pop(1);\n        }\n    }\n\n    /**\n     * Adds a new type to the list of types on which a constructor is invoked in\n     * the basic block.\n     * \n     * @param var\n     *            a type on a which a constructor is invoked.\n     */\n    private void init(final int var) {\n        // creates and/or resizes the initializations array if necessary\n        if (initializations == null) {\n            initializations = new int[2];\n        }\n        int n = initializations.length;\n        if (initializationCount >= n) {\n            int[] t = new int[Math.max(initializationCount + 1, 2 * n)];\n            System.arraycopy(initializations, 0, t, 0, n);\n            initializations = t;\n        }\n        // stores the type to be initialized\n        initializations[initializationCount++] = var;\n    }\n\n    /**\n     * Replaces the given type with the appropriate type if it is one of the\n     * types on which a constructor is invoked in the basic block.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param t\n     *            a type\n     * @return t or, if t is one of the types on which a constructor is invoked\n     *         in the basic block, the type corresponding to this constructor.\n     */\n    private int init(final ClassWriter cw, final int t) {\n        int s;\n        if (t == UNINITIALIZED_THIS) {\n            s = OBJECT | cw.addType(cw.thisName);\n        } else if ((t & (DIM | BASE_KIND)) == UNINITIALIZED) {\n            String type = cw.typeTable[t & BASE_VALUE].strVal1;\n            s = OBJECT | cw.addType(type);\n        } else {\n            return t;\n        }\n        for (int j = 0; j < initializationCount; ++j) {\n            int u = initializations[j];\n            int dim = u & DIM;\n            int kind = u & KIND;\n            if (kind == LOCAL) {\n                u = dim + inputLocals[u & VALUE];\n            } else if (kind == STACK) {\n                u = dim + inputStack[inputStack.length - (u & VALUE)];\n            }\n            if (t == u) {\n                return s;\n            }\n        }\n        return t;\n    }\n\n    /**\n     * Initializes the input frame of the first basic block from the method\n     * descriptor.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param access\n     *            the access flags of the method to which this label belongs.\n     * @param args\n     *            the formal parameter types of this method.\n     * @param maxLocals\n     *            the maximum number of local variables of this method.\n     */\n    void initInputFrame(final ClassWriter cw, final int access,\n            final Type[] args, final int maxLocals) {\n        inputLocals = new int[maxLocals];\n        inputStack = new int[0];\n        int i = 0;\n        if ((access & Opcodes.ACC_STATIC) == 0) {\n            if ((access & MethodWriter.ACC_CONSTRUCTOR) == 0) {\n                inputLocals[i++] = OBJECT | cw.addType(cw.thisName);\n            } else {\n                inputLocals[i++] = UNINITIALIZED_THIS;\n            }\n        }\n        for (int j = 0; j < args.length; ++j) {\n            int t = type(cw, args[j].getDescriptor());\n            inputLocals[i++] = t;\n            if (t == LONG || t == DOUBLE) {\n                inputLocals[i++] = TOP;\n            }\n        }\n        while (i < maxLocals) {\n            inputLocals[i++] = TOP;\n        }\n    }\n\n    /**\n     * Simulates the action of the given instruction on the output stack frame.\n     * \n     * @param opcode\n     *            the opcode of the instruction.\n     * @param arg\n     *            the operand of the instruction, if any.\n     * @param cw\n     *            the class writer to which this label belongs.\n     * @param item\n     *            the operand of the instructions, if any.\n     */\n    void execute(final int opcode, final int arg, final ClassWriter cw,\n            final Item item) {\n        int t1, t2, t3, t4;\n        switch (opcode) {\n        case Opcodes.NOP:\n        case Opcodes.INEG:\n        case Opcodes.LNEG:\n        case Opcodes.FNEG:\n        case Opcodes.DNEG:\n        case Opcodes.I2B:\n        case Opcodes.I2C:\n        case Opcodes.I2S:\n        case Opcodes.GOTO:\n        case Opcodes.RETURN:\n            break;\n        case Opcodes.ACONST_NULL:\n            push(NULL);\n            break;\n        case Opcodes.ICONST_M1:\n        case Opcodes.ICONST_0:\n        case Opcodes.ICONST_1:\n        case Opcodes.ICONST_2:\n        case Opcodes.ICONST_3:\n        case Opcodes.ICONST_4:\n        case Opcodes.ICONST_5:\n        case Opcodes.BIPUSH:\n        case Opcodes.SIPUSH:\n        case Opcodes.ILOAD:\n            push(INTEGER);\n            break;\n        case Opcodes.LCONST_0:\n        case Opcodes.LCONST_1:\n        case Opcodes.LLOAD:\n            push(LONG);\n            push(TOP);\n            break;\n        case Opcodes.FCONST_0:\n        case Opcodes.FCONST_1:\n        case Opcodes.FCONST_2:\n        case Opcodes.FLOAD:\n            push(FLOAT);\n            break;\n        case Opcodes.DCONST_0:\n        case Opcodes.DCONST_1:\n        case Opcodes.DLOAD:\n            push(DOUBLE);\n            push(TOP);\n            break;\n        case Opcodes.LDC:\n            switch (item.type) {\n            case ClassWriter.INT:\n                push(INTEGER);\n                break;\n            case ClassWriter.LONG:\n                push(LONG);\n                push(TOP);\n                break;\n            case ClassWriter.FLOAT:\n                push(FLOAT);\n                break;\n            case ClassWriter.DOUBLE:\n                push(DOUBLE);\n                push(TOP);\n                break;\n            case ClassWriter.CLASS:\n                push(OBJECT | cw.addType(\"java/lang/Class\"));\n                break;\n            case ClassWriter.STR:\n                push(OBJECT | cw.addType(\"java/lang/String\"));\n                break;\n            case ClassWriter.MTYPE:\n                push(OBJECT | cw.addType(\"java/lang/invoke/MethodType\"));\n                break;\n            // case ClassWriter.HANDLE_BASE + [1..9]:\n            default:\n                push(OBJECT | cw.addType(\"java/lang/invoke/MethodHandle\"));\n            }\n            break;\n        case Opcodes.ALOAD:\n            push(get(arg));\n            break;\n        case Opcodes.IALOAD:\n        case Opcodes.BALOAD:\n        case Opcodes.CALOAD:\n        case Opcodes.SALOAD:\n            pop(2);\n            push(INTEGER);\n            break;\n        case Opcodes.LALOAD:\n        case Opcodes.D2L:\n            pop(2);\n            push(LONG);\n            push(TOP);\n            break;\n        case Opcodes.FALOAD:\n            pop(2);\n            push(FLOAT);\n            break;\n        case Opcodes.DALOAD:\n        case Opcodes.L2D:\n            pop(2);\n            push(DOUBLE);\n            push(TOP);\n            break;\n        case Opcodes.AALOAD:\n            pop(1);\n            t1 = pop();\n            push(ELEMENT_OF + t1);\n            break;\n        case Opcodes.ISTORE:\n        case Opcodes.FSTORE:\n        case Opcodes.ASTORE:\n            t1 = pop();\n            set(arg, t1);\n            if (arg > 0) {\n                t2 = get(arg - 1);\n                // if t2 is of kind STACK or LOCAL we cannot know its size!\n                if (t2 == LONG || t2 == DOUBLE) {\n                    set(arg - 1, TOP);\n                } else if ((t2 & KIND) != BASE) {\n                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);\n                }\n            }\n            break;\n        case Opcodes.LSTORE:\n        case Opcodes.DSTORE:\n            pop(1);\n            t1 = pop();\n            set(arg, t1);\n            set(arg + 1, TOP);\n            if (arg > 0) {\n                t2 = get(arg - 1);\n                // if t2 is of kind STACK or LOCAL we cannot know its size!\n                if (t2 == LONG || t2 == DOUBLE) {\n                    set(arg - 1, TOP);\n                } else if ((t2 & KIND) != BASE) {\n                    set(arg - 1, t2 | TOP_IF_LONG_OR_DOUBLE);\n                }\n            }\n            break;\n        case Opcodes.IASTORE:\n        case Opcodes.BASTORE:\n        case Opcodes.CASTORE:\n        case Opcodes.SASTORE:\n        case Opcodes.FASTORE:\n        case Opcodes.AASTORE:\n            pop(3);\n            break;\n        case Opcodes.LASTORE:\n        case Opcodes.DASTORE:\n            pop(4);\n            break;\n        case Opcodes.POP:\n        case Opcodes.IFEQ:\n        case Opcodes.IFNE:\n        case Opcodes.IFLT:\n        case Opcodes.IFGE:\n        case Opcodes.IFGT:\n        case Opcodes.IFLE:\n        case Opcodes.IRETURN:\n        case Opcodes.FRETURN:\n        case Opcodes.ARETURN:\n        case Opcodes.TABLESWITCH:\n        case Opcodes.LOOKUPSWITCH:\n        case Opcodes.ATHROW:\n        case Opcodes.MONITORENTER:\n        case Opcodes.MONITOREXIT:\n        case Opcodes.IFNULL:\n        case Opcodes.IFNONNULL:\n            pop(1);\n            break;\n        case Opcodes.POP2:\n        case Opcodes.IF_ICMPEQ:\n        case Opcodes.IF_ICMPNE:\n        case Opcodes.IF_ICMPLT:\n        case Opcodes.IF_ICMPGE:\n        case Opcodes.IF_ICMPGT:\n        case Opcodes.IF_ICMPLE:\n        case Opcodes.IF_ACMPEQ:\n        case Opcodes.IF_ACMPNE:\n        case Opcodes.LRETURN:\n        case Opcodes.DRETURN:\n            pop(2);\n            break;\n        case Opcodes.DUP:\n            t1 = pop();\n            push(t1);\n            push(t1);\n            break;\n        case Opcodes.DUP_X1:\n            t1 = pop();\n            t2 = pop();\n            push(t1);\n            push(t2);\n            push(t1);\n            break;\n        case Opcodes.DUP_X2:\n            t1 = pop();\n            t2 = pop();\n            t3 = pop();\n            push(t1);\n            push(t3);\n            push(t2);\n            push(t1);\n            break;\n        case Opcodes.DUP2:\n            t1 = pop();\n            t2 = pop();\n            push(t2);\n            push(t1);\n            push(t2);\n            push(t1);\n            break;\n        case Opcodes.DUP2_X1:\n            t1 = pop();\n            t2 = pop();\n            t3 = pop();\n            push(t2);\n            push(t1);\n            push(t3);\n            push(t2);\n            push(t1);\n            break;\n        case Opcodes.DUP2_X2:\n            t1 = pop();\n            t2 = pop();\n            t3 = pop();\n            t4 = pop();\n            push(t2);\n            push(t1);\n            push(t4);\n            push(t3);\n            push(t2);\n            push(t1);\n            break;\n        case Opcodes.SWAP:\n            t1 = pop();\n            t2 = pop();\n            push(t1);\n            push(t2);\n            break;\n        case Opcodes.IADD:\n        case Opcodes.ISUB:\n        case Opcodes.IMUL:\n        case Opcodes.IDIV:\n        case Opcodes.IREM:\n        case Opcodes.IAND:\n        case Opcodes.IOR:\n        case Opcodes.IXOR:\n        case Opcodes.ISHL:\n        case Opcodes.ISHR:\n        case Opcodes.IUSHR:\n        case Opcodes.L2I:\n        case Opcodes.D2I:\n        case Opcodes.FCMPL:\n        case Opcodes.FCMPG:\n            pop(2);\n            push(INTEGER);\n            break;\n        case Opcodes.LADD:\n        case Opcodes.LSUB:\n        case Opcodes.LMUL:\n        case Opcodes.LDIV:\n        case Opcodes.LREM:\n        case Opcodes.LAND:\n        case Opcodes.LOR:\n        case Opcodes.LXOR:\n            pop(4);\n            push(LONG);\n            push(TOP);\n            break;\n        case Opcodes.FADD:\n        case Opcodes.FSUB:\n        case Opcodes.FMUL:\n        case Opcodes.FDIV:\n        case Opcodes.FREM:\n        case Opcodes.L2F:\n        case Opcodes.D2F:\n            pop(2);\n            push(FLOAT);\n            break;\n        case Opcodes.DADD:\n        case Opcodes.DSUB:\n        case Opcodes.DMUL:\n        case Opcodes.DDIV:\n        case Opcodes.DREM:\n            pop(4);\n            push(DOUBLE);\n            push(TOP);\n            break;\n        case Opcodes.LSHL:\n        case Opcodes.LSHR:\n        case Opcodes.LUSHR:\n            pop(3);\n            push(LONG);\n            push(TOP);\n            break;\n        case Opcodes.IINC:\n            set(arg, INTEGER);\n            break;\n        case Opcodes.I2L:\n        case Opcodes.F2L:\n            pop(1);\n            push(LONG);\n            push(TOP);\n            break;\n        case Opcodes.I2F:\n            pop(1);\n            push(FLOAT);\n            break;\n        case Opcodes.I2D:\n        case Opcodes.F2D:\n            pop(1);\n            push(DOUBLE);\n            push(TOP);\n            break;\n        case Opcodes.F2I:\n        case Opcodes.ARRAYLENGTH:\n        case Opcodes.INSTANCEOF:\n            pop(1);\n            push(INTEGER);\n            break;\n        case Opcodes.LCMP:\n        case Opcodes.DCMPL:\n        case Opcodes.DCMPG:\n            pop(4);\n            push(INTEGER);\n            break;\n        case Opcodes.JSR:\n        case Opcodes.RET:\n            throw new RuntimeException(\n                    \"JSR/RET are not supported with computeFrames option\");\n        case Opcodes.GETSTATIC:\n            push(cw, item.strVal3);\n            break;\n        case Opcodes.PUTSTATIC:\n            pop(item.strVal3);\n            break;\n        case Opcodes.GETFIELD:\n            pop(1);\n            push(cw, item.strVal3);\n            break;\n        case Opcodes.PUTFIELD:\n            pop(item.strVal3);\n            pop();\n            break;\n        case Opcodes.INVOKEVIRTUAL:\n        case Opcodes.INVOKESPECIAL:\n        case Opcodes.INVOKESTATIC:\n        case Opcodes.INVOKEINTERFACE:\n            pop(item.strVal3);\n            if (opcode != Opcodes.INVOKESTATIC) {\n                t1 = pop();\n                if (opcode == Opcodes.INVOKESPECIAL\n                        && item.strVal2.charAt(0) == '<') {\n                    init(t1);\n                }\n            }\n            push(cw, item.strVal3);\n            break;\n        case Opcodes.INVOKEDYNAMIC:\n            pop(item.strVal2);\n            push(cw, item.strVal2);\n            break;\n        case Opcodes.NEW:\n            push(UNINITIALIZED | cw.addUninitializedType(item.strVal1, arg));\n            break;\n        case Opcodes.NEWARRAY:\n            pop();\n            switch (arg) {\n            case Opcodes.T_BOOLEAN:\n                push(ARRAY_OF | BOOLEAN);\n                break;\n            case Opcodes.T_CHAR:\n                push(ARRAY_OF | CHAR);\n                break;\n            case Opcodes.T_BYTE:\n                push(ARRAY_OF | BYTE);\n                break;\n            case Opcodes.T_SHORT:\n                push(ARRAY_OF | SHORT);\n                break;\n            case Opcodes.T_INT:\n                push(ARRAY_OF | INTEGER);\n                break;\n            case Opcodes.T_FLOAT:\n                push(ARRAY_OF | FLOAT);\n                break;\n            case Opcodes.T_DOUBLE:\n                push(ARRAY_OF | DOUBLE);\n                break;\n            // case Opcodes.T_LONG:\n            default:\n                push(ARRAY_OF | LONG);\n                break;\n            }\n            break;\n        case Opcodes.ANEWARRAY:\n            String s = item.strVal1;\n            pop();\n            if (s.charAt(0) == '[') {\n                push(cw, '[' + s);\n            } else {\n                push(ARRAY_OF | OBJECT | cw.addType(s));\n            }\n            break;\n        case Opcodes.CHECKCAST:\n            s = item.strVal1;\n            pop();\n            if (s.charAt(0) == '[') {\n                push(cw, s);\n            } else {\n                push(OBJECT | cw.addType(s));\n            }\n            break;\n        // case Opcodes.MULTIANEWARRAY:\n        default:\n            pop(arg);\n            push(cw, item.strVal1);\n            break;\n        }\n    }\n\n    /**\n     * Merges the input frame of the given basic block with the input and output\n     * frames of this basic block. Returns <tt>true</tt> if the input frame of\n     * the given label has been changed by this operation.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param frame\n     *            the basic block whose input frame must be updated.\n     * @param edge\n     *            the kind of the {@link Edge} between this label and 'label'.\n     *            See {@link Edge#info}.\n     * @return <tt>true</tt> if the input frame of the given label has been\n     *         changed by this operation.\n     */\n    boolean merge(final ClassWriter cw, final Frame frame, final int edge) {\n        boolean changed = false;\n        int i, s, dim, kind, t;\n\n        int nLocal = inputLocals.length;\n        int nStack = inputStack.length;\n        if (frame.inputLocals == null) {\n            frame.inputLocals = new int[nLocal];\n            changed = true;\n        }\n\n        for (i = 0; i < nLocal; ++i) {\n            if (outputLocals != null && i < outputLocals.length) {\n                s = outputLocals[i];\n                if (s == 0) {\n                    t = inputLocals[i];\n                } else {\n                    dim = s & DIM;\n                    kind = s & KIND;\n                    if (kind == BASE) {\n                        t = s;\n                    } else {\n                        if (kind == LOCAL) {\n                            t = dim + inputLocals[s & VALUE];\n                        } else {\n                            t = dim + inputStack[nStack - (s & VALUE)];\n                        }\n                        if ((s & TOP_IF_LONG_OR_DOUBLE) != 0\n                                && (t == LONG || t == DOUBLE)) {\n                            t = TOP;\n                        }\n                    }\n                }\n            } else {\n                t = inputLocals[i];\n            }\n            if (initializations != null) {\n                t = init(cw, t);\n            }\n            changed |= merge(cw, t, frame.inputLocals, i);\n        }\n\n        if (edge > 0) {\n            for (i = 0; i < nLocal; ++i) {\n                t = inputLocals[i];\n                changed |= merge(cw, t, frame.inputLocals, i);\n            }\n            if (frame.inputStack == null) {\n                frame.inputStack = new int[1];\n                changed = true;\n            }\n            changed |= merge(cw, edge, frame.inputStack, 0);\n            return changed;\n        }\n\n        int nInputStack = inputStack.length + owner.inputStackTop;\n        if (frame.inputStack == null) {\n            frame.inputStack = new int[nInputStack + outputStackTop];\n            changed = true;\n        }\n\n        for (i = 0; i < nInputStack; ++i) {\n            t = inputStack[i];\n            if (initializations != null) {\n                t = init(cw, t);\n            }\n            changed |= merge(cw, t, frame.inputStack, i);\n        }\n        for (i = 0; i < outputStackTop; ++i) {\n            s = outputStack[i];\n            dim = s & DIM;\n            kind = s & KIND;\n            if (kind == BASE) {\n                t = s;\n            } else {\n                if (kind == LOCAL) {\n                    t = dim + inputLocals[s & VALUE];\n                } else {\n                    t = dim + inputStack[nStack - (s & VALUE)];\n                }\n                if ((s & TOP_IF_LONG_OR_DOUBLE) != 0\n                        && (t == LONG || t == DOUBLE)) {\n                    t = TOP;\n                }\n            }\n            if (initializations != null) {\n                t = init(cw, t);\n            }\n            changed |= merge(cw, t, frame.inputStack, nInputStack + i);\n        }\n        return changed;\n    }\n\n    /**\n     * Merges the type at the given index in the given type array with the given\n     * type. Returns <tt>true</tt> if the type array has been modified by this\n     * operation.\n     * \n     * @param cw\n     *            the ClassWriter to which this label belongs.\n     * @param t\n     *            the type with which the type array element must be merged.\n     * @param types\n     *            an array of types.\n     * @param index\n     *            the index of the type that must be merged in 'types'.\n     * @return <tt>true</tt> if the type array has been modified by this\n     *         operation.\n     */\n    private static boolean merge(final ClassWriter cw, int t,\n            final int[] types, final int index) {\n        int u = types[index];\n        if (u == t) {\n            // if the types are equal, merge(u,t)=u, so there is no change\n            return false;\n        }\n        if ((t & ~DIM) == NULL) {\n            if (u == NULL) {\n                return false;\n            }\n            t = NULL;\n        }\n        if (u == 0) {\n            // if types[index] has never been assigned, merge(u,t)=t\n            types[index] = t;\n            return true;\n        }\n        int v;\n        if ((u & BASE_KIND) == OBJECT || (u & DIM) != 0) {\n            // if u is a reference type of any dimension\n            if (t == NULL) {\n                // if t is the NULL type, merge(u,t)=u, so there is no change\n                return false;\n            } else if ((t & (DIM | BASE_KIND)) == (u & (DIM | BASE_KIND))) {\n                // if t and u have the same dimension and same base kind\n                if ((u & BASE_KIND) == OBJECT) {\n                    // if t is also a reference type, and if u and t have the\n                    // same dimension merge(u,t) = dim(t) | common parent of the\n                    // element types of u and t\n                    v = (t & DIM) | OBJECT\n                            | cw.getMergedType(t & BASE_VALUE, u & BASE_VALUE);\n                } else {\n                    // if u and t are array types, but not with the same element\n                    // type, merge(u,t) = dim(u) - 1 | java/lang/Object\n                    int vdim = ELEMENT_OF + (u & DIM);\n                    v = vdim | OBJECT | cw.addType(\"java/lang/Object\");\n                }\n            } else if ((t & BASE_KIND) == OBJECT || (t & DIM) != 0) {\n                // if t is any other reference or array type, the merged type\n                // is min(udim, tdim) | java/lang/Object, where udim is the\n                // array dimension of u, minus 1 if u is an array type with a\n                // primitive element type (and similarly for tdim).\n                int tdim = (((t & DIM) == 0 || (t & BASE_KIND) == OBJECT) ? 0\n                        : ELEMENT_OF) + (t & DIM);\n                int udim = (((u & DIM) == 0 || (u & BASE_KIND) == OBJECT) ? 0\n                        : ELEMENT_OF) + (u & DIM);\n                v = Math.min(tdim, udim) | OBJECT\n                        | cw.addType(\"java/lang/Object\");\n            } else {\n                // if t is any other type, merge(u,t)=TOP\n                v = TOP;\n            }\n        } else if (u == NULL) {\n            // if u is the NULL type, merge(u,t)=t,\n            // or TOP if t is not a reference type\n            v = (t & BASE_KIND) == OBJECT || (t & DIM) != 0 ? t : TOP;\n        } else {\n            // if u is any other type, merge(u,t)=TOP whatever t\n            v = TOP;\n        }\n        if (u != v) {\n            types[index] = v;\n            return true;\n        }\n        return false;\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Handle.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\n\npackage lt.dependencies.asm;\n\n/**\n * A reference to a field or a method.\n * \n * @author Remi Forax\n * @author Eric Bruneton\n */\npublic final class Handle {\n\n    /**\n     * The kind of field or method designated by this Handle. Should be\n     * {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},\n     * {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},\n     * {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},\n     * {@link Opcodes#H_INVOKESPECIAL}, {@link Opcodes#H_NEWINVOKESPECIAL} or\n     * {@link Opcodes#H_INVOKEINTERFACE}.\n     */\n    final int tag;\n\n    /**\n     * The internal name of the class that owns the field or method designated\n     * by this handle.\n     */\n    final String owner;\n\n    /**\n     * The name of the field or method designated by this handle.\n     */\n    final String name;\n\n    /**\n     * The descriptor of the field or method designated by this handle.\n     */\n    final String desc;\n    \n    \n    /**\n     * Indicate if the owner is an interface or not.\n     */\n    final boolean itf;\n\n    /**\n     * Constructs a new field or method handle.\n     * \n     * @param tag\n     *            the kind of field or method designated by this Handle. Must be\n     *            {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},\n     *            {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},\n     *            {@link Opcodes#H_INVOKEVIRTUAL},\n     *            {@link Opcodes#H_INVOKESTATIC},\n     *            {@link Opcodes#H_INVOKESPECIAL},\n     *            {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *            {@link Opcodes#H_INVOKEINTERFACE}.\n     * @param owner\n     *            the internal name of the class that owns the field or method\n     *            designated by this handle.\n     * @param name\n     *            the name of the field or method designated by this handle.\n     * @param desc\n     *            the descriptor of the field or method designated by this\n     *            handle.\n     *            \n     * @deprecated this constructor has been superseded\n     *             by {@link #Handle(int, String, String, String, boolean)}.\n     */\n    @Deprecated\n    public Handle(int tag, String owner, String name, String desc) {\n        this(tag, owner, name, desc, tag == Opcodes.H_INVOKEINTERFACE);\n    }\n\n    /**\n     * Constructs a new field or method handle.\n     * \n     * @param tag\n     *            the kind of field or method designated by this Handle. Must be\n     *            {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},\n     *            {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},\n     *            {@link Opcodes#H_INVOKEVIRTUAL},\n     *            {@link Opcodes#H_INVOKESTATIC},\n     *            {@link Opcodes#H_INVOKESPECIAL},\n     *            {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *            {@link Opcodes#H_INVOKEINTERFACE}.\n     * @param owner\n     *            the internal name of the class that owns the field or method\n     *            designated by this handle.\n     * @param name\n     *            the name of the field or method designated by this handle.\n     * @param desc\n     *            the descriptor of the field or method designated by this\n     *            handle.\n     * @param itf\n     *            true if the owner is an interface.\n     */\n    public Handle(int tag, String owner, String name, String desc, boolean itf) {\n        this.tag = tag;\n        this.owner = owner;\n        this.name = name;\n        this.desc = desc;\n        this.itf = itf;\n    }\n    \n    /**\n     * Returns the kind of field or method designated by this handle.\n     * \n     * @return {@link Opcodes#H_GETFIELD}, {@link Opcodes#H_GETSTATIC},\n     *         {@link Opcodes#H_PUTFIELD}, {@link Opcodes#H_PUTSTATIC},\n     *         {@link Opcodes#H_INVOKEVIRTUAL}, {@link Opcodes#H_INVOKESTATIC},\n     *         {@link Opcodes#H_INVOKESPECIAL},\n     *         {@link Opcodes#H_NEWINVOKESPECIAL} or\n     *         {@link Opcodes#H_INVOKEINTERFACE}.\n     */\n    public int getTag() {\n        return tag;\n    }\n\n    /**\n     * Returns the internal name of the class that owns the field or method\n     * designated by this handle.\n     * \n     * @return the internal name of the class that owns the field or method\n     *         designated by this handle.\n     */\n    public String getOwner() {\n        return owner;\n    }\n\n    /**\n     * Returns the name of the field or method designated by this handle.\n     * \n     * @return the name of the field or method designated by this handle.\n     */\n    public String getName() {\n        return name;\n    }\n\n    /**\n     * Returns the descriptor of the field or method designated by this handle.\n     * \n     * @return the descriptor of the field or method designated by this handle.\n     */\n    public String getDesc() {\n        return desc;\n    }\n    \n    /**\n     * Returns true if the owner of the field or method designated\n     * by this handle is an interface.\n     * \n     * @return true if the owner of the field or method designated\n     *         by this handle is an interface.\n     */\n    public boolean isInterface() {\n        return itf;\n    }\n\n    @Override\n    public boolean equals(Object obj) {\n        if (obj == this) {\n            return true;\n        }\n        if (!(obj instanceof Handle)) {\n            return false;\n        }\n        Handle h = (Handle) obj;\n        return tag == h.tag && itf == h.itf && owner.equals(h.owner)\n                && name.equals(h.name) && desc.equals(h.desc);\n    }\n\n    @Override\n    public int hashCode() {\n        return tag + (itf? 64: 0) + owner.hashCode() * name.hashCode() * desc.hashCode();\n    }\n\n    /**\n     * Returns the textual representation of this handle. The textual\n     * representation is:\n     * \n     * <pre>\n     * for a reference to a class:\n     * owner '.' name desc ' ' '(' tag ')'\n     * for a reference to an interface:\n     * owner '.' name desc ' ' '(' tag ' ' itf ')'\n     * </pre>\n     * \n     * . As this format is unambiguous, it can be parsed if necessary.\n     */\n    @Override\n    public String toString() {\n        return owner + '.' + name + desc + \" (\" + tag + (itf? \" itf\": \"\") + ')';\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Handler.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * Information about an exception handler block.\n * \n * @author Eric Bruneton\n */\nclass Handler {\n\n    /**\n     * Beginning of the exception handler's scope (inclusive).\n     */\n    Label start;\n\n    /**\n     * End of the exception handler's scope (exclusive).\n     */\n    Label end;\n\n    /**\n     * Beginning of the exception handler's code.\n     */\n    Label handler;\n\n    /**\n     * Internal name of the type of exceptions handled by this handler, or\n     * <tt>null</tt> to catch any exceptions.\n     */\n    String desc;\n\n    /**\n     * Constant pool index of the internal name of the type of exceptions\n     * handled by this handler, or 0 to catch any exceptions.\n     */\n    int type;\n\n    /**\n     * Next exception handler block info.\n     */\n    Handler next;\n\n    /**\n     * Removes the range between start and end from the given exception\n     * handlers.\n     * \n     * @param h\n     *            an exception handler list.\n     * @param start\n     *            the start of the range to be removed.\n     * @param end\n     *            the end of the range to be removed. Maybe null.\n     * @return the exception handler list with the start-end range removed.\n     */\n    static Handler remove(Handler h, Label start, Label end) {\n        if (h == null) {\n            return null;\n        } else {\n            h.next = remove(h.next, start, end);\n        }\n        int hstart = h.start.position;\n        int hend = h.end.position;\n        int s = start.position;\n        int e = end == null ? Integer.MAX_VALUE : end.position;\n        // if [hstart,hend[ and [s,e[ intervals intersect...\n        if (s < hend && e > hstart) {\n            if (s <= hstart) {\n                if (e >= hend) {\n                    // [hstart,hend[ fully included in [s,e[, h removed\n                    h = h.next;\n                } else {\n                    // [hstart,hend[ minus [s,e[ = [e,hend[\n                    h.start = end;\n                }\n            } else if (e >= hend) {\n                // [hstart,hend[ minus [s,e[ = [hstart,s[\n                h.end = start;\n            } else {\n                // [hstart,hend[ minus [s,e[ = [hstart,s[ + [e,hend[\n                Handler g = new Handler();\n                g.start = end;\n                g.end = h.end;\n                g.handler = h.handler;\n                g.desc = h.desc;\n                g.type = h.type;\n                g.next = h.next;\n                h.end = start;\n                h.next = g;\n            }\n        }\n        return h;\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Item.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A constant pool item. Constant pool items can be created with the 'newXXX'\n * methods in the {@link ClassWriter} class.\n * \n * @author Eric Bruneton\n */\nfinal class Item {\n\n    /**\n     * Index of this item in the constant pool.\n     */\n    int index;\n\n    /**\n     * Type of this constant pool item. A single class is used to represent all\n     * constant pool item types, in order to minimize the bytecode size of this\n     * package. The value of this field is one of {@link ClassWriter#INT},\n     * {@link ClassWriter#LONG}, {@link ClassWriter#FLOAT},\n     * {@link ClassWriter#DOUBLE}, {@link ClassWriter#UTF8},\n     * {@link ClassWriter#STR}, {@link ClassWriter#CLASS},\n     * {@link ClassWriter#NAME_TYPE}, {@link ClassWriter#FIELD},\n     * {@link ClassWriter#METH}, {@link ClassWriter#IMETH},\n     * {@link ClassWriter#MTYPE}, {@link ClassWriter#INDY}.\n     * \n     * MethodHandle constant 9 variations are stored using a range of 9 values\n     * from {@link ClassWriter#HANDLE_BASE} + 1 to\n     * {@link ClassWriter#HANDLE_BASE} + 9.\n     * \n     * Special Item types are used for Items that are stored in the ClassWriter\n     * {@link ClassWriter#typeTable}, instead of the constant pool, in order to\n     * avoid clashes with normal constant pool items in the ClassWriter constant\n     * pool's hash table. These special item types are\n     * {@link ClassWriter#TYPE_NORMAL}, {@link ClassWriter#TYPE_UNINIT} and\n     * {@link ClassWriter#TYPE_MERGED}.\n     */\n    int type;\n\n    /**\n     * Value of this item, for an integer item.\n     */\n    int intVal;\n\n    /**\n     * Value of this item, for a long item.\n     */\n    long longVal;\n\n    /**\n     * First part of the value of this item, for items that do not hold a\n     * primitive value.\n     */\n    String strVal1;\n\n    /**\n     * Second part of the value of this item, for items that do not hold a\n     * primitive value.\n     */\n    String strVal2;\n\n    /**\n     * Third part of the value of this item, for items that do not hold a\n     * primitive value.\n     */\n    String strVal3;\n\n    /**\n     * The hash code value of this constant pool item.\n     */\n    int hashCode;\n\n    /**\n     * Link to another constant pool item, used for collision lists in the\n     * constant pool's hash table.\n     */\n    Item next;\n\n    /**\n     * Constructs an uninitialized {@link Item}.\n     */\n    Item() {\n    }\n\n    /**\n     * Constructs an uninitialized {@link Item} for constant pool element at\n     * given position.\n     * \n     * @param index\n     *            index of the item to be constructed.\n     */\n    Item(final int index) {\n        this.index = index;\n    }\n\n    /**\n     * Constructs a copy of the given item.\n     * \n     * @param index\n     *            index of the item to be constructed.\n     * @param i\n     *            the item that must be copied into the item to be constructed.\n     */\n    Item(final int index, final Item i) {\n        this.index = index;\n        type = i.type;\n        intVal = i.intVal;\n        longVal = i.longVal;\n        strVal1 = i.strVal1;\n        strVal2 = i.strVal2;\n        strVal3 = i.strVal3;\n        hashCode = i.hashCode;\n    }\n\n    /**\n     * Sets this item to an integer item.\n     * \n     * @param intVal\n     *            the value of this item.\n     */\n    void set(final int intVal) {\n        this.type = ClassWriter.INT;\n        this.intVal = intVal;\n        this.hashCode = 0x7FFFFFFF & (type + intVal);\n    }\n\n    /**\n     * Sets this item to a long item.\n     * \n     * @param longVal\n     *            the value of this item.\n     */\n    void set(final long longVal) {\n        this.type = ClassWriter.LONG;\n        this.longVal = longVal;\n        this.hashCode = 0x7FFFFFFF & (type + (int) longVal);\n    }\n\n    /**\n     * Sets this item to a float item.\n     * \n     * @param floatVal\n     *            the value of this item.\n     */\n    void set(final float floatVal) {\n        this.type = ClassWriter.FLOAT;\n        this.intVal = Float.floatToRawIntBits(floatVal);\n        this.hashCode = 0x7FFFFFFF & (type + (int) floatVal);\n    }\n\n    /**\n     * Sets this item to a double item.\n     * \n     * @param doubleVal\n     *            the value of this item.\n     */\n    void set(final double doubleVal) {\n        this.type = ClassWriter.DOUBLE;\n        this.longVal = Double.doubleToRawLongBits(doubleVal);\n        this.hashCode = 0x7FFFFFFF & (type + (int) doubleVal);\n    }\n\n    /**\n     * Sets this item to an item that do not hold a primitive value.\n     * \n     * @param type\n     *            the type of this item.\n     * @param strVal1\n     *            first part of the value of this item.\n     * @param strVal2\n     *            second part of the value of this item.\n     * @param strVal3\n     *            third part of the value of this item.\n     */\n    @SuppressWarnings(\"fallthrough\")\n    void set(final int type, final String strVal1, final String strVal2,\n            final String strVal3) {\n        this.type = type;\n        this.strVal1 = strVal1;\n        this.strVal2 = strVal2;\n        this.strVal3 = strVal3;\n        switch (type) {\n        case ClassWriter.CLASS:\n            this.intVal = 0;     // intVal of a class must be zero, see visitInnerClass\n        case ClassWriter.UTF8:\n        case ClassWriter.STR:\n        case ClassWriter.MTYPE:\n        case ClassWriter.TYPE_NORMAL:\n            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode());\n            return;\n        case ClassWriter.NAME_TYPE: {\n            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()\n                    * strVal2.hashCode());\n            return;\n        }\n        // ClassWriter.FIELD:\n        // ClassWriter.METH:\n        // ClassWriter.IMETH:\n        // ClassWriter.HANDLE_BASE + 1..9\n        default:\n            hashCode = 0x7FFFFFFF & (type + strVal1.hashCode()\n                    * strVal2.hashCode() * strVal3.hashCode());\n        }\n    }\n\n    /**\n     * Sets the item to an InvokeDynamic item.\n     * \n     * @param name\n     *            invokedynamic's name.\n     * @param desc\n     *            invokedynamic's desc.\n     * @param bsmIndex\n     *            zero based index into the class attribute BootrapMethods.\n     */\n    void set(String name, String desc, int bsmIndex) {\n        this.type = ClassWriter.INDY;\n        this.longVal = bsmIndex;\n        this.strVal1 = name;\n        this.strVal2 = desc;\n        this.hashCode = 0x7FFFFFFF & (ClassWriter.INDY + bsmIndex\n                * strVal1.hashCode() * strVal2.hashCode());\n    }\n\n    /**\n     * Sets the item to a BootstrapMethod item.\n     * \n     * @param position\n     *            position in byte in the class attribute BootrapMethods.\n     * @param hashCode\n     *            hashcode of the item. This hashcode is processed from the\n     *            hashcode of the bootstrap method and the hashcode of all\n     *            bootstrap arguments.\n     */\n    void set(int position, int hashCode) {\n        this.type = ClassWriter.BSM;\n        this.intVal = position;\n        this.hashCode = hashCode;\n    }\n\n    /**\n     * Indicates if the given item is equal to this one. <i>This method assumes\n     * that the two items have the same {@link #type}</i>.\n     * \n     * @param i\n     *            the item to be compared to this one. Both items must have the\n     *            same {@link #type}.\n     * @return <tt>true</tt> if the given item if equal to this one,\n     *         <tt>false</tt> otherwise.\n     */\n    boolean isEqualTo(final Item i) {\n        switch (type) {\n        case ClassWriter.UTF8:\n        case ClassWriter.STR:\n        case ClassWriter.CLASS:\n        case ClassWriter.MTYPE:\n        case ClassWriter.TYPE_NORMAL:\n            return i.strVal1.equals(strVal1);\n        case ClassWriter.TYPE_MERGED:\n        case ClassWriter.LONG:\n        case ClassWriter.DOUBLE:\n            return i.longVal == longVal;\n        case ClassWriter.INT:\n        case ClassWriter.FLOAT:\n            return i.intVal == intVal;\n        case ClassWriter.TYPE_UNINIT:\n            return i.intVal == intVal && i.strVal1.equals(strVal1);\n        case ClassWriter.NAME_TYPE:\n            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2);\n        case ClassWriter.INDY: {\n            return i.longVal == longVal && i.strVal1.equals(strVal1)\n                    && i.strVal2.equals(strVal2);\n        }\n        // case ClassWriter.FIELD:\n        // case ClassWriter.METH:\n        // case ClassWriter.IMETH:\n        // case ClassWriter.HANDLE_BASE + 1..9\n        default:\n            return i.strVal1.equals(strVal1) && i.strVal2.equals(strVal2)\n                    && i.strVal3.equals(strVal3);\n        }\n    }\n\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Label.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A label represents a position in the bytecode of a method. Labels are used\n * for jump, goto, and switch instructions, and for try catch blocks. A label\n * designates the <i>instruction</i> that is just after. Note however that there\n * can be other elements between a label and the instruction it designates (such\n * as other labels, stack map frames, line numbers, etc.).\n *\n * @author Eric Bruneton\n */\npublic class Label {\n\n    /**\n     * Indicates if this label is only used for debug attributes. Such a label\n     * is not the start of a basic block, the target of a jump instruction, or\n     * an exception handler. It can be safely ignored in control flow graph\n     * analysis algorithms (for optimization purposes).\n     */\n    static final int DEBUG = 1;\n\n    /**\n     * Indicates if the position of this label is known.\n     */\n    static final int RESOLVED = 2;\n\n    /**\n     * Indicates if this label has been updated, after instruction resizing.\n     */\n    static final int RESIZED = 4;\n\n    /**\n     * Indicates if this basic block has been pushed in the basic block stack.\n     * See {@link MethodWriter#visitMaxs visitMaxs}.\n     */\n    static final int PUSHED = 8;\n\n    /**\n     * Indicates if this label is the target of a jump instruction, or the start\n     * of an exception handler.\n     */\n    static final int TARGET = 16;\n\n    /**\n     * Indicates if a stack map frame must be stored for this label.\n     */\n    static final int STORE = 32;\n\n    /**\n     * Indicates if this label corresponds to a reachable basic block.\n     */\n    static final int REACHABLE = 64;\n\n    /**\n     * Indicates if this basic block ends with a JSR instruction.\n     */\n    static final int JSR = 128;\n\n    /**\n     * Indicates if this basic block ends with a RET instruction.\n     */\n    static final int RET = 256;\n\n    /**\n     * Indicates if this basic block is the start of a subroutine.\n     */\n    static final int SUBROUTINE = 512;\n\n    /**\n     * Indicates if this subroutine basic block has been visited by a\n     * visitSubroutine(null, ...) call.\n     */\n    static final int VISITED = 1024;\n\n    /**\n     * Indicates if this subroutine basic block has been visited by a\n     * visitSubroutine(!null, ...) call.\n     */\n    static final int VISITED2 = 2048;\n\n    /**\n     * Field used to associate user information to a label. Warning: this field\n     * is used by the ASM tree package. In order to use it with the ASM tree\n     * package you must override the\n     * <code>org.objectweb.asm.tree.MethodNode#getLabelNode</code> method.\n     */\n    public Object info;\n\n    /**\n     * Flags that indicate the status of this label.\n     *\n     * @see #DEBUG\n     * @see #RESOLVED\n     * @see #RESIZED\n     * @see #PUSHED\n     * @see #TARGET\n     * @see #STORE\n     * @see #REACHABLE\n     * @see #JSR\n     * @see #RET\n     */\n    int status;\n\n    /**\n     * The line number corresponding to this label, if known. If there are\n     * several lines, each line is stored in a separate label, all linked via\n     * their next field (these links are created in ClassReader and removed just\n     * before visitLabel is called, so that this does not impact the rest of the\n     * code).\n     */\n    int line;\n\n    /**\n     * The position of this label in the code, if known.\n     */\n    int position;\n\n    /**\n     * Number of forward references to this label, times two.\n     */\n    private int referenceCount;\n\n    /**\n     * Informations about forward references. Each forward reference is\n     * described by two consecutive integers in this array: the first one is the\n     * position of the first byte of the bytecode instruction that contains the\n     * forward reference, while the second is the position of the first byte of\n     * the forward reference itself. In fact the sign of the first integer\n     * indicates if this reference uses 2 or 4 bytes, and its absolute value\n     * gives the position of the bytecode instruction. This array is also used\n     * as a bitset to store the subroutines to which a basic block belongs. This\n     * information is needed in {@linked MethodWriter#visitMaxs}, after all\n     * forward references have been resolved. Hence the same array can be used\n     * for both purposes without problems.\n     */\n    private int[] srcAndRefPositions;\n\n    // ------------------------------------------------------------------------\n\n    /*\n     * Fields for the control flow and data flow graph analysis algorithms (used\n     * to compute the maximum stack size or the stack map frames). A control\n     * flow graph contains one node per \"basic block\", and one edge per \"jump\"\n     * from one basic block to another. Each node (i.e., each basic block) is\n     * represented by the Label object that corresponds to the first instruction\n     * of this basic block. Each node also stores the list of its successors in\n     * the graph, as a linked list of Edge objects.\n     * \n     * The control flow analysis algorithms used to compute the maximum stack\n     * size or the stack map frames are similar and use two steps. The first\n     * step, during the visit of each instruction, builds information about the\n     * state of the local variables and the operand stack at the end of each\n     * basic block, called the \"output frame\", <i>relatively</i> to the frame\n     * state at the beginning of the basic block, which is called the \"input\n     * frame\", and which is <i>unknown</i> during this step. The second step, in\n     * {@link MethodWriter#visitMaxs}, is a fix point algorithm that computes\n     * information about the input frame of each basic block, from the input\n     * state of the first basic block (known from the method signature), and by\n     * the using the previously computed relative output frames.\n     * \n     * The algorithm used to compute the maximum stack size only computes the\n     * relative output and absolute input stack heights, while the algorithm\n     * used to compute stack map frames computes relative output frames and\n     * absolute input frames.\n     */\n\n    /**\n     * Start of the output stack relatively to the input stack. The exact\n     * semantics of this field depends on the algorithm that is used.\n     *\n     * When only the maximum stack size is computed, this field is the number of\n     * elements in the input stack.\n     *\n     * When the stack map frames are completely computed, this field is the\n     * offset of the first output stack element relatively to the top of the\n     * input stack. This offset is always negative or null. A null offset means\n     * that the output stack must be appended to the input stack. A -n offset\n     * means that the first n output stack elements must replace the top n input\n     * stack elements, and that the other elements must be appended to the input\n     * stack.\n     */\n    int inputStackTop;\n\n    /**\n     * Maximum height reached by the output stack, relatively to the top of the\n     * input stack. This maximum is always positive or null.\n     */\n    int outputStackMax;\n\n    /**\n     * Information about the input and output stack map frames of this basic\n     * block. This field is only used when {@link ClassWriter#COMPUTE_FRAMES}\n     * option is used.\n     */\n    Frame frame;\n\n    /**\n     * The successor of this label, in the order they are visited. This linked\n     * list does not include labels used for debug info only. If\n     * {@link ClassWriter#COMPUTE_FRAMES} option is used then, in addition, it\n     * does not contain successive labels that denote the same bytecode position\n     * (in this case only the first label appears in this list).\n     */\n    Label successor;\n\n    /**\n     * The successors of this node in the control flow graph. These successors\n     * are stored in a linked list of {@link Edge Edge} objects, linked to each\n     * other by their {@link Edge#next} field.\n     */\n    Edge successors;\n\n    /**\n     * The next basic block in the basic block stack. This stack is used in the\n     * main loop of the fix point algorithm used in the second step of the\n     * control flow analysis algorithms. It is also used in\n     * {@link #visitSubroutine} to avoid using a recursive method, and in\n     * ClassReader to temporarily store multiple source lines for a label.\n     *\n     * @see MethodWriter#visitMaxs\n     */\n    Label next;\n\n    // ------------------------------------------------------------------------\n    // Constructor\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new label.\n     */\n    public Label() {\n    }\n\n    // ------------------------------------------------------------------------\n    // Methods to compute offsets and to manage forward references\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the offset corresponding to this label. This offset is computed\n     * from the start of the method's bytecode. <i>This method is intended for\n     * {@link Attribute} sub classes, and is normally not needed by class\n     * generators or adapters.</i>\n     *\n     * @return the offset corresponding to this label.\n     * @throws IllegalStateException\n     *             if this label is not resolved yet.\n     */\n    public int getOffset() {\n        if ((status & RESOLVED) == 0) {\n            throw new IllegalStateException(\n                    \"Label offset position has not been resolved yet\");\n        }\n        return position;\n    }\n\n    /**\n     * Puts a reference to this label in the bytecode of a method. If the\n     * position of the label is known, the offset is computed and written\n     * directly. Otherwise, a null offset is written and a new forward reference\n     * is declared for this label.\n     *\n     * @param owner\n     *            the code writer that calls this method.\n     * @param out\n     *            the bytecode of the method.\n     * @param source\n     *            the position of first byte of the bytecode instruction that\n     *            contains this label.\n     * @param wideOffset\n     *            <tt>true</tt> if the reference must be stored in 4 bytes, or\n     *            <tt>false</tt> if it must be stored with 2 bytes.\n     * @throws IllegalArgumentException\n     *             if this label has not been created by the given code writer.\n     */\n    void put(final MethodWriter owner, final ByteVector out, final int source,\n            final boolean wideOffset) {\n        if ((status & RESOLVED) == 0) {\n            if (wideOffset) {\n                addReference(-1 - source, out.length);\n                out.putInt(-1);\n            } else {\n                addReference(source, out.length);\n                out.putShort(-1);\n            }\n        } else {\n            if (wideOffset) {\n                out.putInt(position - source);\n            } else {\n                out.putShort(position - source);\n            }\n        }\n    }\n\n    /**\n     * Adds a forward reference to this label. This method must be called only\n     * for a true forward reference, i.e. only if this label is not resolved\n     * yet. For backward references, the offset of the reference can be, and\n     * must be, computed and stored directly.\n     *\n     * @param sourcePosition\n     *            the position of the referencing instruction. This position\n     *            will be used to compute the offset of this forward reference.\n     * @param referencePosition\n     *            the position where the offset for this forward reference must\n     *            be stored.\n     */\n    private void addReference(final int sourcePosition,\n            final int referencePosition) {\n        if (srcAndRefPositions == null) {\n            srcAndRefPositions = new int[6];\n        }\n        if (referenceCount >= srcAndRefPositions.length) {\n            int[] a = new int[srcAndRefPositions.length + 6];\n            System.arraycopy(srcAndRefPositions, 0, a, 0,\n                    srcAndRefPositions.length);\n            srcAndRefPositions = a;\n        }\n        srcAndRefPositions[referenceCount++] = sourcePosition;\n        srcAndRefPositions[referenceCount++] = referencePosition;\n    }\n\n    /**\n     * Resolves all forward references to this label. This method must be called\n     * when this label is added to the bytecode of the method, i.e. when its\n     * position becomes known. This method fills in the blanks that where left\n     * in the bytecode by each forward reference previously added to this label.\n     *\n     * @param owner\n     *            the code writer that calls this method.\n     * @param position\n     *            the position of this label in the bytecode.\n     * @param data\n     *            the bytecode of the method.\n     * @return <tt>true</tt> if a blank that was left for this label was to\n     *         small to store the offset. In such a case the corresponding jump\n     *         instruction is replaced with a pseudo instruction (using unused\n     *         opcodes) using an unsigned two bytes offset. These pseudo\n     *         instructions will need to be replaced with true instructions with\n     *         wider offsets (4 bytes instead of 2). This is done in\n     *         {@link MethodWriter#resizeInstructions}.\n     * @throws IllegalArgumentException\n     *             if this label has already been resolved, or if it has not\n     *             been created by the given code writer.\n     */\n    boolean resolve(final MethodWriter owner, final int position,\n            final byte[] data) {\n        boolean needUpdate = false;\n        this.status |= RESOLVED;\n        this.position = position;\n        int i = 0;\n        while (i < referenceCount) {\n            int source = srcAndRefPositions[i++];\n            int reference = srcAndRefPositions[i++];\n            int offset;\n            if (source >= 0) {\n                offset = position - source;\n                if (offset < Short.MIN_VALUE || offset > Short.MAX_VALUE) {\n                    /*\n                     * changes the opcode of the jump instruction, in order to\n                     * be able to find it later (see resizeInstructions in\n                     * MethodWriter). These temporary opcodes are similar to\n                     * jump instruction opcodes, except that the 2 bytes offset\n                     * is unsigned (and can therefore represent values from 0 to\n                     * 65535, which is sufficient since the size of a method is\n                     * limited to 65535 bytes).\n                     */\n                    int opcode = data[reference - 1] & 0xFF;\n                    if (opcode <= Opcodes.JSR) {\n                        // changes IFEQ ... JSR to opcodes 202 to 217\n                        data[reference - 1] = (byte) (opcode + 49);\n                    } else {\n                        // changes IFNULL and IFNONNULL to opcodes 218 and 219\n                        data[reference - 1] = (byte) (opcode + 20);\n                    }\n                    needUpdate = true;\n                }\n                data[reference++] = (byte) (offset >>> 8);\n                data[reference] = (byte) offset;\n            } else {\n                offset = position + source + 1;\n                data[reference++] = (byte) (offset >>> 24);\n                data[reference++] = (byte) (offset >>> 16);\n                data[reference++] = (byte) (offset >>> 8);\n                data[reference] = (byte) offset;\n            }\n        }\n        return needUpdate;\n    }\n\n    /**\n     * Returns the first label of the series to which this label belongs. For an\n     * isolated label or for the first label in a series of successive labels,\n     * this method returns the label itself. For other labels it returns the\n     * first label of the series.\n     *\n     * @return the first label of the series to which this label belongs.\n     */\n    Label getFirst() {\n        return !ClassReader.FRAMES || frame == null ? this : frame.owner;\n    }\n\n    // ------------------------------------------------------------------------\n    // Methods related to subroutines\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns true is this basic block belongs to the given subroutine.\n     *\n     * @param id\n     *            a subroutine id.\n     * @return true is this basic block belongs to the given subroutine.\n     */\n    boolean inSubroutine(final long id) {\n        if ((status & Label.VISITED) != 0) {\n            return (srcAndRefPositions[(int) (id >>> 32)] & (int) id) != 0;\n        }\n        return false;\n    }\n\n    /**\n     * Returns true if this basic block and the given one belong to a common\n     * subroutine.\n     *\n     * @param block\n     *            another basic block.\n     * @return true if this basic block and the given one belong to a common\n     *         subroutine.\n     */\n    boolean inSameSubroutine(final Label block) {\n        if ((status & VISITED) == 0 || (block.status & VISITED) == 0) {\n            return false;\n        }\n        for (int i = 0; i < srcAndRefPositions.length; ++i) {\n            if ((srcAndRefPositions[i] & block.srcAndRefPositions[i]) != 0) {\n                return true;\n            }\n        }\n        return false;\n    }\n\n    /**\n     * Marks this basic block as belonging to the given subroutine.\n     *\n     * @param id\n     *            a subroutine id.\n     * @param nbSubroutines\n     *            the total number of subroutines in the method.\n     */\n    void addToSubroutine(final long id, final int nbSubroutines) {\n        if ((status & VISITED) == 0) {\n            status |= VISITED;\n            srcAndRefPositions = new int[nbSubroutines / 32 + 1];\n        }\n        srcAndRefPositions[(int) (id >>> 32)] |= (int) id;\n    }\n\n    /**\n     * Finds the basic blocks that belong to a given subroutine, and marks these\n     * blocks as belonging to this subroutine. This method follows the control\n     * flow graph to find all the blocks that are reachable from the current\n     * block WITHOUT following any JSR target.\n     *\n     * @param JSR\n     *            a JSR block that jumps to this subroutine. If this JSR is not\n     *            null it is added to the successor of the RET blocks found in\n     *            the subroutine.\n     * @param id\n     *            the id of this subroutine.\n     * @param nbSubroutines\n     *            the total number of subroutines in the method.\n     */\n    void visitSubroutine(final Label JSR, final long id, final int nbSubroutines) {\n        // user managed stack of labels, to avoid using a recursive method\n        // (recursivity can lead to stack overflow with very large methods)\n        Label stack = this;\n        while (stack != null) {\n            // removes a label l from the stack\n            Label l = stack;\n            stack = l.next;\n            l.next = null;\n\n            if (JSR != null) {\n                if ((l.status & VISITED2) != 0) {\n                    continue;\n                }\n                l.status |= VISITED2;\n                // adds JSR to the successors of l, if it is a RET block\n                if ((l.status & RET) != 0) {\n                    if (!l.inSameSubroutine(JSR)) {\n                        Edge e = new Edge();\n                        e.info = l.inputStackTop;\n                        e.successor = JSR.successors.successor;\n                        e.next = l.successors;\n                        l.successors = e;\n                    }\n                }\n            } else {\n                // if the l block already belongs to subroutine 'id', continue\n                if (l.inSubroutine(id)) {\n                    continue;\n                }\n                // marks the l block as belonging to subroutine 'id'\n                l.addToSubroutine(id, nbSubroutines);\n            }\n            // pushes each successor of l on the stack, except JSR targets\n            Edge e = l.successors;\n            while (e != null) {\n                // if the l block is a JSR block, then 'l.successors.next' leads\n                // to the JSR target (see {@link #visitJumpInsn}) and must\n                // therefore not be followed\n                if ((l.status & Label.JSR) == 0 || e != l.successors.next) {\n                    // pushes e.successor on the stack if it not already added\n                    if (e.successor.next == null) {\n                        e.successor.next = stack;\n                        stack = e.successor;\n                    }\n                }\n                e = e.next;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Overriden Object methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns a string representation of this label.\n     *\n     * @return a string representation of this label.\n     */\n    @Override\n    public String toString() {\n        return \"L\" + System.identityHashCode(this);\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/MethodVisitor.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A visitor to visit a Java method. The methods of this class must be called in\n * the following order: ( <tt>visitParameter</tt> )* [\n * <tt>visitAnnotationDefault</tt> ] ( <tt>visitAnnotation</tt> |\n * <tt>visitParameterAnnotation</tt> <tt>visitTypeAnnotation</tt> |\n * <tt>visitAttribute</tt> )* [ <tt>visitCode</tt> ( <tt>visitFrame</tt> |\n * <tt>visit<i>X</i>Insn</tt> | <tt>visitLabel</tt> |\n * <tt>visitInsnAnnotation</tt> | <tt>visitTryCatchBlock</tt> |\n * <tt>visitTryCatchAnnotation</tt> | <tt>visitLocalVariable</tt> |\n * <tt>visitLocalVariableAnnotation</tt> | <tt>visitLineNumber</tt> )*\n * <tt>visitMaxs</tt> ] <tt>visitEnd</tt>. In addition, the\n * <tt>visit<i>X</i>Insn</tt> and <tt>visitLabel</tt> methods must be called in\n * the sequential order of the bytecode instructions of the visited code,\n * <tt>visitInsnAnnotation</tt> must be called <i>after</i> the annotated\n * instruction, <tt>visitTryCatchBlock</tt> must be called <i>before</i> the\n * labels passed as arguments have been visited,\n * <tt>visitTryCatchBlockAnnotation</tt> must be called <i>after</i> the\n * corresponding try catch block has been visited, and the\n * <tt>visitLocalVariable</tt>, <tt>visitLocalVariableAnnotation</tt> and\n * <tt>visitLineNumber</tt> methods must be called <i>after</i> the labels\n * passed as arguments have been visited.\n * \n * @author Eric Bruneton\n */\npublic abstract class MethodVisitor {\n\n    /**\n     * The ASM API version implemented by this visitor. The value of this field\n     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    protected final int api;\n\n    /**\n     * The method visitor to which this visitor must delegate method calls. May\n     * be null.\n     */\n    protected MethodVisitor mv;\n\n    /**\n     * Constructs a new {@link MethodVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    public MethodVisitor(final int api) {\n        this(api, null);\n    }\n\n    /**\n     * Constructs a new {@link MethodVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     * @param mv\n     *            the method visitor to which this visitor must delegate method\n     *            calls. May be null.\n     */\n    public MethodVisitor(final int api, final MethodVisitor mv) {\n        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {\n            throw new IllegalArgumentException();\n        }\n        this.api = api;\n        this.mv = mv;\n    }\n\n    // -------------------------------------------------------------------------\n    // Parameters, annotations and non standard attributes\n    // -------------------------------------------------------------------------\n\n    /**\n     * Visits a parameter of this method.\n     * \n     * @param name\n     *            parameter name or null if none is provided.\n     * @param access\n     *            the parameter's access flags, only <tt>ACC_FINAL</tt>,\n     *            <tt>ACC_SYNTHETIC</tt> or/and <tt>ACC_MANDATED</tt> are\n     *            allowed (see {@link Opcodes}).\n     */\n    public void visitParameter(String name, int access) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (mv != null) {\n            mv.visitParameter(name, access);\n        }\n    }\n\n    /**\n     * Visits the default value of this annotation interface method.\n     * \n     * @return a visitor to the visit the actual default value of this\n     *         annotation interface method, or <tt>null</tt> if this visitor is\n     *         not interested in visiting this default value. The 'name'\n     *         parameters passed to the methods of this annotation visitor are\n     *         ignored. Moreover, exacly one visit method must be called on this\n     *         annotation visitor, followed by visitEnd.\n     */\n    public AnnotationVisitor visitAnnotationDefault() {\n        if (mv != null) {\n            return mv.visitAnnotationDefault();\n        }\n        return null;\n    }\n\n    /**\n     * Visits an annotation of this method.\n     * \n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitAnnotation(String desc, boolean visible) {\n        if (mv != null) {\n            return mv.visitAnnotation(desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits an annotation on a type in the method signature.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#METHOD_TYPE_PARAMETER\n     *            METHOD_TYPE_PARAMETER},\n     *            {@link TypeReference#METHOD_TYPE_PARAMETER_BOUND\n     *            METHOD_TYPE_PARAMETER_BOUND},\n     *            {@link TypeReference#METHOD_RETURN METHOD_RETURN},\n     *            {@link TypeReference#METHOD_RECEIVER METHOD_RECEIVER},\n     *            {@link TypeReference#METHOD_FORMAL_PARAMETER\n     *            METHOD_FORMAL_PARAMETER} or {@link TypeReference#THROWS\n     *            THROWS}. See {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitTypeAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (mv != null) {\n            return mv.visitTypeAnnotation(typeRef, typePath, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits an annotation of a parameter this method.\n     * \n     * @param parameter\n     *            the parameter index.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitParameterAnnotation(int parameter,\n            String desc, boolean visible) {\n        if (mv != null) {\n            return mv.visitParameterAnnotation(parameter, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a non standard attribute of this method.\n     * \n     * @param attr\n     *            an attribute.\n     */\n    public void visitAttribute(Attribute attr) {\n        if (mv != null) {\n            mv.visitAttribute(attr);\n        }\n    }\n\n    /**\n     * Starts the visit of the method's code, if any (i.e. non abstract method).\n     */\n    public void visitCode() {\n        if (mv != null) {\n            mv.visitCode();\n        }\n    }\n\n    /**\n     * Visits the current state of the local variables and operand stack\n     * elements. This method must(*) be called <i>just before</i> any\n     * instruction <b>i</b> that follows an unconditional branch instruction\n     * such as GOTO or THROW, that is the target of a jump instruction, or that\n     * starts an exception handler block. The visited types must describe the\n     * values of the local variables and of the operand stack elements <i>just\n     * before</i> <b>i</b> is executed.<br>\n     * <br>\n     * (*) this is mandatory only for classes whose version is greater than or\n     * equal to {@link Opcodes#V1_6 V1_6}. <br>\n     * <br>\n     * The frames of a method must be given either in expanded form, or in\n     * compressed form (all frames must use the same format, i.e. you must not\n     * mix expanded and compressed frames within a single method):\n     * <ul>\n     * <li>In expanded form, all frames must have the F_NEW type.</li>\n     * <li>In compressed form, frames are basically \"deltas\" from the state of\n     * the previous frame:\n     * <ul>\n     * <li>{@link Opcodes#F_SAME} representing frame with exactly the same\n     * locals as the previous frame and with the empty stack.</li>\n     * <li>{@link Opcodes#F_SAME1} representing frame with exactly the same\n     * locals as the previous frame and with single value on the stack (\n     * <code>nStack</code> is 1 and <code>stack[0]</code> contains value for the\n     * type of the stack item).</li>\n     * <li>{@link Opcodes#F_APPEND} representing frame with current locals are\n     * the same as the locals in the previous frame, except that additional\n     * locals are defined (<code>nLocal</code> is 1, 2 or 3 and\n     * <code>local</code> elements contains values representing added types).</li>\n     * <li>{@link Opcodes#F_CHOP} representing frame with current locals are the\n     * same as the locals in the previous frame, except that the last 1-3 locals\n     * are absent and with the empty stack (<code>nLocals</code> is 1, 2 or 3).</li>\n     * <li>{@link Opcodes#F_FULL} representing complete frame data.</li>\n     * </ul>\n     * </li>\n     * </ul>\n     * <br>\n     * In both cases the first frame, corresponding to the method's parameters\n     * and access flags, is implicit and must not be visited. Also, it is\n     * illegal to visit two or more frames for the same code location (i.e., at\n     * least one instruction must be visited between two calls to visitFrame).\n     * \n     * @param type\n     *            the type of this stack map frame. Must be\n     *            {@link Opcodes#F_NEW} for expanded frames, or\n     *            {@link Opcodes#F_FULL}, {@link Opcodes#F_APPEND},\n     *            {@link Opcodes#F_CHOP}, {@link Opcodes#F_SAME} or\n     *            {@link Opcodes#F_APPEND}, {@link Opcodes#F_SAME1} for\n     *            compressed frames.\n     * @param nLocal\n     *            the number of local variables in the visited frame.\n     * @param local\n     *            the local variable types in this frame. This array must not be\n     *            modified. Primitive types are represented by\n     *            {@link Opcodes#TOP}, {@link Opcodes#INTEGER},\n     *            {@link Opcodes#FLOAT}, {@link Opcodes#LONG},\n     *            {@link Opcodes#DOUBLE},{@link Opcodes#NULL} or\n     *            {@link Opcodes#UNINITIALIZED_THIS} (long and double are\n     *            represented by a single element). Reference types are\n     *            represented by String objects (representing internal names),\n     *            and uninitialized types by Label objects (this label\n     *            designates the NEW instruction that created this uninitialized\n     *            value).\n     * @param nStack\n     *            the number of operand stack elements in the visited frame.\n     * @param stack\n     *            the operand stack types in this frame. This array must not be\n     *            modified. Its content has the same format as the \"local\"\n     *            array.\n     * @throws IllegalStateException\n     *             if a frame is visited just after another one, without any\n     *             instruction between the two (unless this frame is a\n     *             Opcodes#F_SAME frame, in which case it is silently ignored).\n     */\n    public void visitFrame(int type, int nLocal, Object[] local, int nStack,\n            Object[] stack) {\n        if (mv != null) {\n            mv.visitFrame(type, nLocal, local, nStack, stack);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Normal instructions\n    // -------------------------------------------------------------------------\n\n    /**\n     * Visits a zero operand instruction.\n     * \n     * @param opcode\n     *            the opcode of the instruction to be visited. This opcode is\n     *            either NOP, ACONST_NULL, ICONST_M1, ICONST_0, ICONST_1,\n     *            ICONST_2, ICONST_3, ICONST_4, ICONST_5, LCONST_0, LCONST_1,\n     *            FCONST_0, FCONST_1, FCONST_2, DCONST_0, DCONST_1, IALOAD,\n     *            LALOAD, FALOAD, DALOAD, AALOAD, BALOAD, CALOAD, SALOAD,\n     *            IASTORE, LASTORE, FASTORE, DASTORE, AASTORE, BASTORE, CASTORE,\n     *            SASTORE, POP, POP2, DUP, DUP_X1, DUP_X2, DUP2, DUP2_X1,\n     *            DUP2_X2, SWAP, IADD, LADD, FADD, DADD, ISUB, LSUB, FSUB, DSUB,\n     *            IMUL, LMUL, FMUL, DMUL, IDIV, LDIV, FDIV, DDIV, IREM, LREM,\n     *            FREM, DREM, INEG, LNEG, FNEG, DNEG, ISHL, LSHL, ISHR, LSHR,\n     *            IUSHR, LUSHR, IAND, LAND, IOR, LOR, IXOR, LXOR, I2L, I2F, I2D,\n     *            L2I, L2F, L2D, F2I, F2L, F2D, D2I, D2L, D2F, I2B, I2C, I2S,\n     *            LCMP, FCMPL, FCMPG, DCMPL, DCMPG, IRETURN, LRETURN, FRETURN,\n     *            DRETURN, ARETURN, RETURN, ARRAYLENGTH, ATHROW, MONITORENTER,\n     *            or MONITOREXIT.\n     */\n    public void visitInsn(int opcode) {\n        if (mv != null) {\n            mv.visitInsn(opcode);\n        }\n    }\n\n    /**\n     * Visits an instruction with a single int operand.\n     * \n     * @param opcode\n     *            the opcode of the instruction to be visited. This opcode is\n     *            either BIPUSH, SIPUSH or NEWARRAY.\n     * @param operand\n     *            the operand of the instruction to be visited.<br>\n     *            When opcode is BIPUSH, operand value should be between\n     *            Byte.MIN_VALUE and Byte.MAX_VALUE.<br>\n     *            When opcode is SIPUSH, operand value should be between\n     *            Short.MIN_VALUE and Short.MAX_VALUE.<br>\n     *            When opcode is NEWARRAY, operand value should be one of\n     *            {@link Opcodes#T_BOOLEAN}, {@link Opcodes#T_CHAR},\n     *            {@link Opcodes#T_FLOAT}, {@link Opcodes#T_DOUBLE},\n     *            {@link Opcodes#T_BYTE}, {@link Opcodes#T_SHORT},\n     *            {@link Opcodes#T_INT} or {@link Opcodes#T_LONG}.\n     */\n    public void visitIntInsn(int opcode, int operand) {\n        if (mv != null) {\n            mv.visitIntInsn(opcode, operand);\n        }\n    }\n\n    /**\n     * Visits a local variable instruction. A local variable instruction is an\n     * instruction that loads or stores the value of a local variable.\n     * \n     * @param opcode\n     *            the opcode of the local variable instruction to be visited.\n     *            This opcode is either ILOAD, LLOAD, FLOAD, DLOAD, ALOAD,\n     *            ISTORE, LSTORE, FSTORE, DSTORE, ASTORE or RET.\n     * @param var\n     *            the operand of the instruction to be visited. This operand is\n     *            the index of a local variable.\n     */\n    public void visitVarInsn(int opcode, int var) {\n        if (mv != null) {\n            mv.visitVarInsn(opcode, var);\n        }\n    }\n\n    /**\n     * Visits a type instruction. A type instruction is an instruction that\n     * takes the internal name of a class as parameter.\n     * \n     * @param opcode\n     *            the opcode of the type instruction to be visited. This opcode\n     *            is either NEW, ANEWARRAY, CHECKCAST or INSTANCEOF.\n     * @param type\n     *            the operand of the instruction to be visited. This operand\n     *            must be the internal name of an object or array class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     */\n    public void visitTypeInsn(int opcode, String type) {\n        if (mv != null) {\n            mv.visitTypeInsn(opcode, type);\n        }\n    }\n\n    /**\n     * Visits a field instruction. A field instruction is an instruction that\n     * loads or stores the value of a field of an object.\n     * \n     * @param opcode\n     *            the opcode of the type instruction to be visited. This opcode\n     *            is either GETSTATIC, PUTSTATIC, GETFIELD or PUTFIELD.\n     * @param owner\n     *            the internal name of the field's owner class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     * @param name\n     *            the field's name.\n     * @param desc\n     *            the field's descriptor (see {@link Type Type}).\n     */\n    public void visitFieldInsn(int opcode, String owner, String name,\n            String desc) {\n        if (mv != null) {\n            mv.visitFieldInsn(opcode, owner, name, desc);\n        }\n    }\n\n    /**\n     * Visits a method instruction. A method instruction is an instruction that\n     * invokes a method.\n     * \n     * @param opcode\n     *            the opcode of the type instruction to be visited. This opcode\n     *            is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or\n     *            INVOKEINTERFACE.\n     * @param owner\n     *            the internal name of the method's owner class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor (see {@link Type Type}).\n     */\n    @Deprecated\n    public void visitMethodInsn(int opcode, String owner, String name,\n            String desc) {\n        if (api >= Opcodes.ASM5) {\n            boolean itf = opcode == Opcodes.INVOKEINTERFACE;\n            visitMethodInsn(opcode, owner, name, desc, itf);\n            return;\n        }\n        if (mv != null) {\n            mv.visitMethodInsn(opcode, owner, name, desc);\n        }\n    }\n\n    /**\n     * Visits a method instruction. A method instruction is an instruction that\n     * invokes a method.\n     * \n     * @param opcode\n     *            the opcode of the type instruction to be visited. This opcode\n     *            is either INVOKEVIRTUAL, INVOKESPECIAL, INVOKESTATIC or\n     *            INVOKEINTERFACE.\n     * @param owner\n     *            the internal name of the method's owner class (see\n     *            {@link Type#getInternalName() getInternalName}).\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor (see {@link Type Type}).\n     * @param itf\n     *            if the method's owner class is an interface.\n     */\n    public void visitMethodInsn(int opcode, String owner, String name,\n            String desc, boolean itf) {\n        if (api < Opcodes.ASM5) {\n            if (itf != (opcode == Opcodes.INVOKEINTERFACE)) {\n                throw new IllegalArgumentException(\n                        \"INVOKESPECIAL/STATIC on interfaces require ASM 5\");\n            }\n            visitMethodInsn(opcode, owner, name, desc);\n            return;\n        }\n        if (mv != null) {\n            mv.visitMethodInsn(opcode, owner, name, desc, itf);\n        }\n    }\n\n    /**\n     * Visits an invokedynamic instruction.\n     * \n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor (see {@link Type Type}).\n     * @param bsm\n     *            the bootstrap method.\n     * @param bsmArgs\n     *            the bootstrap method constant arguments. Each argument must be\n     *            an {@link Integer}, {@link Float}, {@link Long},\n     *            {@link Double}, {@link String}, {@link Type} or {@link Handle}\n     *            value. This method is allowed to modify the content of the\n     *            array so a caller should expect that this array may change.\n     */\n    public void visitInvokeDynamicInsn(String name, String desc, Handle bsm,\n            Object... bsmArgs) {\n        if (mv != null) {\n            mv.visitInvokeDynamicInsn(name, desc, bsm, bsmArgs);\n        }\n    }\n\n    /**\n     * Visits a jump instruction. A jump instruction is an instruction that may\n     * jump to another instruction.\n     * \n     * @param opcode\n     *            the opcode of the type instruction to be visited. This opcode\n     *            is either IFEQ, IFNE, IFLT, IFGE, IFGT, IFLE, IF_ICMPEQ,\n     *            IF_ICMPNE, IF_ICMPLT, IF_ICMPGE, IF_ICMPGT, IF_ICMPLE,\n     *            IF_ACMPEQ, IF_ACMPNE, GOTO, JSR, IFNULL or IFNONNULL.\n     * @param label\n     *            the operand of the instruction to be visited. This operand is\n     *            a label that designates the instruction to which the jump\n     *            instruction may jump.\n     */\n    public void visitJumpInsn(int opcode, Label label) {\n        if (mv != null) {\n            mv.visitJumpInsn(opcode, label);\n        }\n    }\n\n    /**\n     * Visits a label. A label designates the instruction that will be visited\n     * just after it.\n     * \n     * @param label\n     *            a {@link Label Label} object.\n     */\n    public void visitLabel(Label label) {\n        if (mv != null) {\n            mv.visitLabel(label);\n        }\n    }\n\n    // -------------------------------------------------------------------------\n    // Special instructions\n    // -------------------------------------------------------------------------\n\n    /**\n     * Visits a LDC instruction. Note that new constant types may be added in\n     * future versions of the Java Virtual Machine. To easily detect new\n     * constant types, implementations of this method should check for\n     * unexpected constant types, like this:\n     * \n     * <pre>\n     * if (cst instanceof Integer) {\n     *     // ...\n     * } else if (cst instanceof Float) {\n     *     // ...\n     * } else if (cst instanceof Long) {\n     *     // ...\n     * } else if (cst instanceof Double) {\n     *     // ...\n     * } else if (cst instanceof String) {\n     *     // ...\n     * } else if (cst instanceof Type) {\n     *     int sort = ((Type) cst).getSort();\n     *     if (sort == Type.OBJECT) {\n     *         // ...\n     *     } else if (sort == Type.ARRAY) {\n     *         // ...\n     *     } else if (sort == Type.METHOD) {\n     *         // ...\n     *     } else {\n     *         // throw an exception\n     *     }\n     * } else if (cst instanceof Handle) {\n     *     // ...\n     * } else {\n     *     // throw an exception\n     * }\n     * </pre>\n     * \n     * @param cst\n     *            the constant to be loaded on the stack. This parameter must be\n     *            a non null {@link Integer}, a {@link Float}, a {@link Long}, a\n     *            {@link Double}, a {@link String}, a {@link Type} of OBJECT or\n     *            ARRAY sort for <tt>.class</tt> constants, for classes whose\n     *            version is 49.0, a {@link Type} of METHOD sort or a\n     *            {@link Handle} for MethodType and MethodHandle constants, for\n     *            classes whose version is 51.0.\n     */\n    public void visitLdcInsn(Object cst) {\n        if (mv != null) {\n            mv.visitLdcInsn(cst);\n        }\n    }\n\n    /**\n     * Visits an IINC instruction.\n     * \n     * @param var\n     *            index of the local variable to be incremented.\n     * @param increment\n     *            amount to increment the local variable by.\n     */\n    public void visitIincInsn(int var, int increment) {\n        if (mv != null) {\n            mv.visitIincInsn(var, increment);\n        }\n    }\n\n    /**\n     * Visits a TABLESWITCH instruction.\n     * \n     * @param min\n     *            the minimum key value.\n     * @param max\n     *            the maximum key value.\n     * @param dflt\n     *            beginning of the default handler block.\n     * @param labels\n     *            beginnings of the handler blocks. <tt>labels[i]</tt> is the\n     *            beginning of the handler block for the <tt>min + i</tt> key.\n     */\n    public void visitTableSwitchInsn(int min, int max, Label dflt,\n            Label... labels) {\n        if (mv != null) {\n            mv.visitTableSwitchInsn(min, max, dflt, labels);\n        }\n    }\n\n    /**\n     * Visits a LOOKUPSWITCH instruction.\n     * \n     * @param dflt\n     *            beginning of the default handler block.\n     * @param keys\n     *            the values of the keys.\n     * @param labels\n     *            beginnings of the handler blocks. <tt>labels[i]</tt> is the\n     *            beginning of the handler block for the <tt>keys[i]</tt> key.\n     */\n    public void visitLookupSwitchInsn(Label dflt, int[] keys, Label[] labels) {\n        if (mv != null) {\n            mv.visitLookupSwitchInsn(dflt, keys, labels);\n        }\n    }\n\n    /**\n     * Visits a MULTIANEWARRAY instruction.\n     * \n     * @param desc\n     *            an array type descriptor (see {@link Type Type}).\n     * @param dims\n     *            number of dimensions of the array to allocate.\n     */\n    public void visitMultiANewArrayInsn(String desc, int dims) {\n        if (mv != null) {\n            mv.visitMultiANewArrayInsn(desc, dims);\n        }\n    }\n\n    /**\n     * Visits an annotation on an instruction. This method must be called just\n     * <i>after</i> the annotated instruction. It can be called several times\n     * for the same instruction.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#INSTANCEOF INSTANCEOF},\n     *            {@link TypeReference#NEW NEW},\n     *            {@link TypeReference#CONSTRUCTOR_REFERENCE\n     *            CONSTRUCTOR_REFERENCE}, {@link TypeReference#METHOD_REFERENCE\n     *            METHOD_REFERENCE}, {@link TypeReference#CAST CAST},\n     *            {@link TypeReference#CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\n     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},\n     *            {@link TypeReference#METHOD_INVOCATION_TYPE_ARGUMENT\n     *            METHOD_INVOCATION_TYPE_ARGUMENT},\n     *            {@link TypeReference#CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\n     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or\n     *            {@link TypeReference#METHOD_REFERENCE_TYPE_ARGUMENT\n     *            METHOD_REFERENCE_TYPE_ARGUMENT}. See {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitInsnAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (mv != null) {\n            return mv.visitInsnAnnotation(typeRef, typePath, desc, visible);\n        }\n        return null;\n    }\n\n    // -------------------------------------------------------------------------\n    // Exceptions table entries, debug information, max stack and max locals\n    // -------------------------------------------------------------------------\n\n    /**\n     * Visits a try catch block.\n     * \n     * @param start\n     *            beginning of the exception handler's scope (inclusive).\n     * @param end\n     *            end of the exception handler's scope (exclusive).\n     * @param handler\n     *            beginning of the exception handler's code.\n     * @param type\n     *            internal name of the type of exceptions handled by the\n     *            handler, or <tt>null</tt> to catch any exceptions (for\n     *            \"finally\" blocks).\n     * @throws IllegalArgumentException\n     *             if one of the labels has already been visited by this visitor\n     *             (by the {@link #visitLabel visitLabel} method).\n     */\n    public void visitTryCatchBlock(Label start, Label end, Label handler,\n            String type) {\n        if (mv != null) {\n            mv.visitTryCatchBlock(start, end, handler, type);\n        }\n    }\n\n    /**\n     * Visits an annotation on an exception handler type. This method must be\n     * called <i>after</i> the {@link #visitTryCatchBlock} for the annotated\n     * exception handler. It can be called several times for the same exception\n     * handler.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#EXCEPTION_PARAMETER\n     *            EXCEPTION_PARAMETER}. See {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (mv != null) {\n            return mv.visitTryCatchAnnotation(typeRef, typePath, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a local variable declaration.\n     * \n     * @param name\n     *            the name of a local variable.\n     * @param desc\n     *            the type descriptor of this local variable.\n     * @param signature\n     *            the type signature of this local variable. May be\n     *            <tt>null</tt> if the local variable type does not use generic\n     *            types.\n     * @param start\n     *            the first instruction corresponding to the scope of this local\n     *            variable (inclusive).\n     * @param end\n     *            the last instruction corresponding to the scope of this local\n     *            variable (exclusive).\n     * @param index\n     *            the local variable's index.\n     * @throws IllegalArgumentException\n     *             if one of the labels has not already been visited by this\n     *             visitor (by the {@link #visitLabel visitLabel} method).\n     */\n    public void visitLocalVariable(String name, String desc, String signature,\n            Label start, Label end, int index) {\n        if (mv != null) {\n            mv.visitLocalVariable(name, desc, signature, start, end, index);\n        }\n    }\n\n    /**\n     * Visits an annotation on a local variable type.\n     * \n     * @param typeRef\n     *            a reference to the annotated type. The sort of this type\n     *            reference must be {@link TypeReference#LOCAL_VARIABLE\n     *            LOCAL_VARIABLE} or {@link TypeReference#RESOURCE_VARIABLE\n     *            RESOURCE_VARIABLE}. See {@link TypeReference}.\n     * @param typePath\n     *            the path to the annotated type argument, wildcard bound, array\n     *            element type, or static inner type within 'typeRef'. May be\n     *            <tt>null</tt> if the annotation targets 'typeRef' as a whole.\n     * @param start\n     *            the fist instructions corresponding to the continuous ranges\n     *            that make the scope of this local variable (inclusive).\n     * @param end\n     *            the last instructions corresponding to the continuous ranges\n     *            that make the scope of this local variable (exclusive). This\n     *            array must have the same size as the 'start' array.\n     * @param index\n     *            the local variable's index in each range. This array must have\n     *            the same size as the 'start' array.\n     * @param desc\n     *            the class descriptor of the annotation class.\n     * @param visible\n     *            <tt>true</tt> if the annotation is visible at runtime.\n     * @return a visitor to visit the annotation values, or <tt>null</tt> if\n     *         this visitor is not interested in visiting this annotation.\n     */\n    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,\n            TypePath typePath, Label[] start, Label[] end, int[] index,\n            String desc, boolean visible) {\n        if (api < Opcodes.ASM5) {\n            throw new RuntimeException();\n        }\n        if (mv != null) {\n            return mv.visitLocalVariableAnnotation(typeRef, typePath, start,\n                    end, index, desc, visible);\n        }\n        return null;\n    }\n\n    /**\n     * Visits a line number declaration.\n     * \n     * @param line\n     *            a line number. This number refers to the source file from\n     *            which the class was compiled.\n     * @param start\n     *            the first instruction corresponding to this line number.\n     * @throws IllegalArgumentException\n     *             if <tt>start</tt> has not already been visited by this\n     *             visitor (by the {@link #visitLabel visitLabel} method).\n     */\n    public void visitLineNumber(int line, Label start) {\n        if (mv != null) {\n            mv.visitLineNumber(line, start);\n        }\n    }\n\n    /**\n     * Visits the maximum stack size and the maximum number of local variables\n     * of the method.\n     * \n     * @param maxStack\n     *            maximum stack size of the method.\n     * @param maxLocals\n     *            maximum number of local variables for the method.\n     */\n    public void visitMaxs(int maxStack, int maxLocals) {\n        if (mv != null) {\n            mv.visitMaxs(maxStack, maxLocals);\n        }\n    }\n\n    /**\n     * Visits the end of the method. This method, which is the last one to be\n     * called, is used to inform the visitor that all the annotations and\n     * attributes of the method have been visited.\n     */\n    public void visitEnd() {\n        if (mv != null) {\n            mv.visitEnd();\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/MethodWriter.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * A {@link MethodVisitor} that generates methods in bytecode form. Each visit\n * method of this class appends the bytecode corresponding to the visited\n * instruction to a byte vector, in the order these methods are called.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\nclass MethodWriter extends MethodVisitor {\n\n    /**\n     * Pseudo access flag used to denote constructors.\n     */\n    static final int ACC_CONSTRUCTOR = 0x80000;\n\n    /**\n     * Frame has exactly the same locals as the previous stack map frame and\n     * number of stack items is zero.\n     */\n    static final int SAME_FRAME = 0; // to 63 (0-3f)\n\n    /**\n     * Frame has exactly the same locals as the previous stack map frame and\n     * number of stack items is 1\n     */\n    static final int SAME_LOCALS_1_STACK_ITEM_FRAME = 64; // to 127 (40-7f)\n\n    /**\n     * Reserved for future use\n     */\n    static final int RESERVED = 128;\n\n    /**\n     * Frame has exactly the same locals as the previous stack map frame and\n     * number of stack items is 1. Offset is bigger then 63;\n     */\n    static final int SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED = 247; // f7\n\n    /**\n     * Frame where current locals are the same as the locals in the previous\n     * frame, except that the k last locals are absent. The value of k is given\n     * by the formula 251-frame_type.\n     */\n    static final int CHOP_FRAME = 248; // to 250 (f8-fA)\n\n    /**\n     * Frame has exactly the same locals as the previous stack map frame and\n     * number of stack items is zero. Offset is bigger then 63;\n     */\n    static final int SAME_FRAME_EXTENDED = 251; // fb\n\n    /**\n     * Frame where current locals are the same as the locals in the previous\n     * frame, except that k additional locals are defined. The value of k is\n     * given by the formula frame_type-251.\n     */\n    static final int APPEND_FRAME = 252; // to 254 // fc-fe\n\n    /**\n     * Full frame\n     */\n    static final int FULL_FRAME = 255; // ff\n\n    /**\n     * Indicates that the stack map frames must be recomputed from scratch. In\n     * this case the maximum stack size and number of local variables is also\n     * recomputed from scratch.\n     * \n     * @see #compute\n     */\n    private static final int FRAMES = 0;\n\n    /**\n     * Indicates that the maximum stack size and number of local variables must\n     * be automatically computed.\n     * \n     * @see #compute\n     */\n    private static final int MAXS = 1;\n\n    /**\n     * Indicates that nothing must be automatically computed.\n     * \n     * @see #compute\n     */\n    private static final int NOTHING = 2;\n\n    /**\n     * The class writer to which this method must be added.\n     */\n    final ClassWriter cw;\n\n    /**\n     * Access flags of this method.\n     */\n    private int access;\n\n    /**\n     * The index of the constant pool item that contains the name of this\n     * method.\n     */\n    private final int name;\n\n    /**\n     * The index of the constant pool item that contains the descriptor of this\n     * method.\n     */\n    private final int desc;\n\n    /**\n     * The descriptor of this method.\n     */\n    private final String descriptor;\n\n    /**\n     * The signature of this method.\n     */\n    String signature;\n\n    /**\n     * If not zero, indicates that the code of this method must be copied from\n     * the ClassReader associated to this writer in <code>cw.cr</code>. More\n     * precisely, this field gives the index of the first byte to copied from\n     * <code>cw.cr.b</code>.\n     */\n    int classReaderOffset;\n\n    /**\n     * If not zero, indicates that the code of this method must be copied from\n     * the ClassReader associated to this writer in <code>cw.cr</code>. More\n     * precisely, this field gives the number of bytes to copied from\n     * <code>cw.cr.b</code>.\n     */\n    int classReaderLength;\n\n    /**\n     * Number of exceptions that can be thrown by this method.\n     */\n    int exceptionCount;\n\n    /**\n     * The exceptions that can be thrown by this method. More precisely, this\n     * array contains the indexes of the constant pool items that contain the\n     * internal names of these exception classes.\n     */\n    int[] exceptions;\n\n    /**\n     * The annotation default attribute of this method. May be <tt>null</tt>.\n     */\n    private ByteVector annd;\n\n    /**\n     * The runtime visible annotations of this method. May be <tt>null</tt>.\n     */\n    private AnnotationWriter anns;\n\n    /**\n     * The runtime invisible annotations of this method. May be <tt>null</tt>.\n     */\n    private AnnotationWriter ianns;\n\n    /**\n     * The runtime visible type annotations of this method. May be <tt>null</tt>\n     * .\n     */\n    private AnnotationWriter tanns;\n\n    /**\n     * The runtime invisible type annotations of this method. May be\n     * <tt>null</tt>.\n     */\n    private AnnotationWriter itanns;\n\n    /**\n     * The runtime visible parameter annotations of this method. May be\n     * <tt>null</tt>.\n     */\n    private AnnotationWriter[] panns;\n\n    /**\n     * The runtime invisible parameter annotations of this method. May be\n     * <tt>null</tt>.\n     */\n    private AnnotationWriter[] ipanns;\n\n    /**\n     * The number of synthetic parameters of this method.\n     */\n    private int synthetics;\n\n    /**\n     * The non standard attributes of the method.\n     */\n    private Attribute attrs;\n\n    /**\n     * The bytecode of this method.\n     */\n    private ByteVector code = new ByteVector();\n\n    /**\n     * Maximum stack size of this method.\n     */\n    private int maxStack;\n\n    /**\n     * Maximum number of local variables for this method.\n     */\n    private int maxLocals;\n\n    /**\n     * Number of local variables in the current stack map frame.\n     */\n    private int currentLocals;\n\n    /**\n     * Number of stack map frames in the StackMapTable attribute.\n     */\n    private int frameCount;\n\n    /**\n     * The StackMapTable attribute.\n     */\n    private ByteVector stackMap;\n\n    /**\n     * The offset of the last frame that was written in the StackMapTable\n     * attribute.\n     */\n    private int previousFrameOffset;\n\n    /**\n     * The last frame that was written in the StackMapTable attribute.\n     * \n     * @see #frame\n     */\n    private int[] previousFrame;\n\n    /**\n     * The current stack map frame. The first element contains the offset of the\n     * instruction to which the frame corresponds, the second element is the\n     * number of locals and the third one is the number of stack elements. The\n     * local variables start at index 3 and are followed by the operand stack\n     * values. In summary frame[0] = offset, frame[1] = nLocal, frame[2] =\n     * nStack, frame[3] = nLocal. All types are encoded as integers, with the\n     * same format as the one used in {@link Label}, but limited to BASE types.\n     */\n    private int[] frame;\n\n    /**\n     * Number of elements in the exception handler list.\n     */\n    private int handlerCount;\n\n    /**\n     * The first element in the exception handler list.\n     */\n    private Handler firstHandler;\n\n    /**\n     * The last element in the exception handler list.\n     */\n    private Handler lastHandler;\n\n    /**\n     * Number of entries in the MethodParameters attribute.\n     */\n    private int methodParametersCount;\n\n    /**\n     * The MethodParameters attribute.\n     */\n    private ByteVector methodParameters;\n\n    /**\n     * Number of entries in the LocalVariableTable attribute.\n     */\n    private int localVarCount;\n\n    /**\n     * The LocalVariableTable attribute.\n     */\n    private ByteVector localVar;\n\n    /**\n     * Number of entries in the LocalVariableTypeTable attribute.\n     */\n    private int localVarTypeCount;\n\n    /**\n     * The LocalVariableTypeTable attribute.\n     */\n    private ByteVector localVarType;\n\n    /**\n     * Number of entries in the LineNumberTable attribute.\n     */\n    private int lineNumberCount;\n\n    /**\n     * The LineNumberTable attribute.\n     */\n    private ByteVector lineNumber;\n\n    /**\n     * The start offset of the last visited instruction.\n     */\n    private int lastCodeOffset;\n\n    /**\n     * The runtime visible type annotations of the code. May be <tt>null</tt>.\n     */\n    private AnnotationWriter ctanns;\n\n    /**\n     * The runtime invisible type annotations of the code. May be <tt>null</tt>.\n     */\n    private AnnotationWriter ictanns;\n\n    /**\n     * The non standard attributes of the method's code.\n     */\n    private Attribute cattrs;\n\n    /**\n     * Indicates if some jump instructions are too small and need to be resized.\n     */\n    private boolean resize;\n\n    /**\n     * The number of subroutines in this method.\n     */\n    private int subroutines;\n\n    // ------------------------------------------------------------------------\n\n    /*\n     * Fields for the control flow graph analysis algorithm (used to compute the\n     * maximum stack size). A control flow graph contains one node per \"basic\n     * block\", and one edge per \"jump\" from one basic block to another. Each\n     * node (i.e., each basic block) is represented by the Label object that\n     * corresponds to the first instruction of this basic block. Each node also\n     * stores the list of its successors in the graph, as a linked list of Edge\n     * objects.\n     */\n\n    /**\n     * Indicates what must be automatically computed.\n     * \n     * @see #FRAMES\n     * @see #MAXS\n     * @see #NOTHING\n     */\n    private final int compute;\n\n    /**\n     * A list of labels. This list is the list of basic blocks in the method,\n     * i.e. a list of Label objects linked to each other by their\n     * {@link Label#successor} field, in the order they are visited by\n     * {@link MethodVisitor#visitLabel}, and starting with the first basic\n     * block.\n     */\n    private Label labels;\n\n    /**\n     * The previous basic block.\n     */\n    private Label previousBlock;\n\n    /**\n     * The current basic block.\n     */\n    private Label currentBlock;\n\n    /**\n     * The (relative) stack size after the last visited instruction. This size\n     * is relative to the beginning of the current basic block, i.e., the true\n     * stack size after the last visited instruction is equal to the\n     * {@link Label#inputStackTop beginStackSize} of the current basic block\n     * plus <tt>stackSize</tt>.\n     */\n    private int stackSize;\n\n    /**\n     * The (relative) maximum stack size after the last visited instruction.\n     * This size is relative to the beginning of the current basic block, i.e.,\n     * the true maximum stack size after the last visited instruction is equal\n     * to the {@link Label#inputStackTop beginStackSize} of the current basic\n     * block plus <tt>stackSize</tt>.\n     */\n    private int maxStackSize;\n\n    // ------------------------------------------------------------------------\n    // Constructor\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a new {@link MethodWriter}.\n     * \n     * @param cw\n     *            the class writer in which the method must be added.\n     * @param access\n     *            the method's access flags (see {@link Opcodes}).\n     * @param name\n     *            the method's name.\n     * @param desc\n     *            the method's descriptor (see {@link Type}).\n     * @param signature\n     *            the method's signature. May be <tt>null</tt>.\n     * @param exceptions\n     *            the internal names of the method's exceptions. May be\n     *            <tt>null</tt>.\n     * @param computeMaxs\n     *            <tt>true</tt> if the maximum stack size and number of local\n     *            variables must be automatically computed.\n     * @param computeFrames\n     *            <tt>true</tt> if the stack map tables must be recomputed from\n     *            scratch.\n     */\n    MethodWriter(final ClassWriter cw, final int access, final String name,\n            final String desc, final String signature,\n            final String[] exceptions, final boolean computeMaxs,\n            final boolean computeFrames) {\n        super(Opcodes.ASM5);\n        if (cw.firstMethod == null) {\n            cw.firstMethod = this;\n        } else {\n            cw.lastMethod.mv = this;\n        }\n        cw.lastMethod = this;\n        this.cw = cw;\n        this.access = access;\n        if (\"<init>\".equals(name)) {\n            this.access |= ACC_CONSTRUCTOR;\n        }\n        this.name = cw.newUTF8(name);\n        this.desc = cw.newUTF8(desc);\n        this.descriptor = desc;\n        if (ClassReader.SIGNATURES) {\n            this.signature = signature;\n        }\n        if (exceptions != null && exceptions.length > 0) {\n            exceptionCount = exceptions.length;\n            this.exceptions = new int[exceptionCount];\n            for (int i = 0; i < exceptionCount; ++i) {\n                this.exceptions[i] = cw.newClass(exceptions[i]);\n            }\n        }\n        this.compute = computeFrames ? FRAMES : (computeMaxs ? MAXS : NOTHING);\n        if (computeMaxs || computeFrames) {\n            // updates maxLocals\n            int size = Type.getArgumentsAndReturnSizes(descriptor) >> 2;\n            if ((access & Opcodes.ACC_STATIC) != 0) {\n                --size;\n            }\n            maxLocals = size;\n            currentLocals = size;\n            // creates and visits the label for the first basic block\n            labels = new Label();\n            labels.status |= Label.PUSHED;\n            visitLabel(labels);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Implementation of the MethodVisitor abstract class\n    // ------------------------------------------------------------------------\n\n    @Override\n    public void visitParameter(String name, int access) {\n        if (methodParameters == null) {\n            methodParameters = new ByteVector();\n        }\n        ++methodParametersCount;\n        methodParameters.putShort((name == null) ? 0 : cw.newUTF8(name))\n                .putShort(access);\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotationDefault() {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        annd = new ByteVector();\n        return new AnnotationWriter(cw, false, annd, null, 0);\n    }\n\n    @Override\n    public AnnotationVisitor visitAnnotation(final String desc,\n            final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);\n        if (visible) {\n            aw.next = anns;\n            anns = aw;\n        } else {\n            aw.next = ianns;\n            ianns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public AnnotationVisitor visitTypeAnnotation(final int typeRef,\n            final TypePath typePath, final String desc, final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        AnnotationWriter.putTarget(typeRef, typePath, bv);\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = tanns;\n            tanns = aw;\n        } else {\n            aw.next = itanns;\n            itanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public AnnotationVisitor visitParameterAnnotation(final int parameter,\n            final String desc, final boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        if (\"Ljava/lang/Synthetic;\".equals(desc)) {\n            // workaround for a bug in javac with synthetic parameters\n            // see ClassReader.readParameterAnnotations\n            synthetics = Math.max(synthetics, parameter + 1);\n            return new AnnotationWriter(cw, false, bv, null, 0);\n        }\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv, 2);\n        if (visible) {\n            if (panns == null) {\n                panns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];\n            }\n            aw.next = panns[parameter];\n            panns[parameter] = aw;\n        } else {\n            if (ipanns == null) {\n                ipanns = new AnnotationWriter[Type.getArgumentTypes(descriptor).length];\n            }\n            aw.next = ipanns[parameter];\n            ipanns[parameter] = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public void visitAttribute(final Attribute attr) {\n        if (attr.isCodeAttribute()) {\n            attr.next = cattrs;\n            cattrs = attr;\n        } else {\n            attr.next = attrs;\n            attrs = attr;\n        }\n    }\n\n    @Override\n    public void visitCode() {\n    }\n\n    @Override\n    public void visitFrame(final int type, final int nLocal,\n            final Object[] local, final int nStack, final Object[] stack) {\n        if (!ClassReader.FRAMES || compute == FRAMES) {\n            return;\n        }\n\n        if (type == Opcodes.F_NEW) {\n            if (previousFrame == null) {\n                visitImplicitFirstFrame();\n            }\n            currentLocals = nLocal;\n            int frameIndex = startFrame(code.length, nLocal, nStack);\n            for (int i = 0; i < nLocal; ++i) {\n                if (local[i] instanceof String) {\n                    frame[frameIndex++] = Frame.OBJECT\n                            | cw.addType((String) local[i]);\n                } else if (local[i] instanceof Integer) {\n                    frame[frameIndex++] = ((Integer) local[i]).intValue();\n                } else {\n                    frame[frameIndex++] = Frame.UNINITIALIZED\n                            | cw.addUninitializedType(\"\",\n                                    ((Label) local[i]).position);\n                }\n            }\n            for (int i = 0; i < nStack; ++i) {\n                if (stack[i] instanceof String) {\n                    frame[frameIndex++] = Frame.OBJECT\n                            | cw.addType((String) stack[i]);\n                } else if (stack[i] instanceof Integer) {\n                    frame[frameIndex++] = ((Integer) stack[i]).intValue();\n                } else {\n                    frame[frameIndex++] = Frame.UNINITIALIZED\n                            | cw.addUninitializedType(\"\",\n                                    ((Label) stack[i]).position);\n                }\n            }\n            endFrame();\n        } else {\n            int delta;\n            if (stackMap == null) {\n                stackMap = new ByteVector();\n                delta = code.length;\n            } else {\n                delta = code.length - previousFrameOffset - 1;\n                if (delta < 0) {\n                    if (type == Opcodes.F_SAME) {\n                        return;\n                    } else {\n                        throw new IllegalStateException();\n                    }\n                }\n            }\n\n            switch (type) {\n            case Opcodes.F_FULL:\n                currentLocals = nLocal;\n                stackMap.putByte(FULL_FRAME).putShort(delta).putShort(nLocal);\n                for (int i = 0; i < nLocal; ++i) {\n                    writeFrameType(local[i]);\n                }\n                stackMap.putShort(nStack);\n                for (int i = 0; i < nStack; ++i) {\n                    writeFrameType(stack[i]);\n                }\n                break;\n            case Opcodes.F_APPEND:\n                currentLocals += nLocal;\n                stackMap.putByte(SAME_FRAME_EXTENDED + nLocal).putShort(delta);\n                for (int i = 0; i < nLocal; ++i) {\n                    writeFrameType(local[i]);\n                }\n                break;\n            case Opcodes.F_CHOP:\n                currentLocals -= nLocal;\n                stackMap.putByte(SAME_FRAME_EXTENDED - nLocal).putShort(delta);\n                break;\n            case Opcodes.F_SAME:\n                if (delta < 64) {\n                    stackMap.putByte(delta);\n                } else {\n                    stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);\n                }\n                break;\n            case Opcodes.F_SAME1:\n                if (delta < 64) {\n                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);\n                } else {\n                    stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED)\n                            .putShort(delta);\n                }\n                writeFrameType(stack[0]);\n                break;\n            }\n\n            previousFrameOffset = code.length;\n            ++frameCount;\n        }\n\n        maxStack = Math.max(maxStack, nStack);\n        maxLocals = Math.max(maxLocals, currentLocals);\n    }\n\n    @Override\n    public void visitInsn(final int opcode) {\n        lastCodeOffset = code.length;\n        // adds the instruction to the bytecode of the method\n        code.putByte(opcode);\n        // update currentBlock\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, 0, null, null);\n            } else {\n                // updates current and max stack sizes\n                int size = stackSize + Frame.SIZE[opcode];\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n            // if opcode == ATHROW or xRETURN, ends current block (no successor)\n            if ((opcode >= Opcodes.IRETURN && opcode <= Opcodes.RETURN)\n                    || opcode == Opcodes.ATHROW) {\n                noSuccessor();\n            }\n        }\n    }\n\n    @Override\n    public void visitIntInsn(final int opcode, final int operand) {\n        lastCodeOffset = code.length;\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, operand, null, null);\n            } else if (opcode != Opcodes.NEWARRAY) {\n                // updates current and max stack sizes only for NEWARRAY\n                // (stack size variation = 0 for BIPUSH or SIPUSH)\n                int size = stackSize + 1;\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        if (opcode == Opcodes.SIPUSH) {\n            code.put12(opcode, operand);\n        } else { // BIPUSH or NEWARRAY\n            code.put11(opcode, operand);\n        }\n    }\n\n    @Override\n    public void visitVarInsn(final int opcode, final int var) {\n        lastCodeOffset = code.length;\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, var, null, null);\n            } else {\n                // updates current and max stack sizes\n                if (opcode == Opcodes.RET) {\n                    // no stack change, but end of current block (no successor)\n                    currentBlock.status |= Label.RET;\n                    // save 'stackSize' here for future use\n                    // (see {@link #findSubroutineSuccessors})\n                    currentBlock.inputStackTop = stackSize;\n                    noSuccessor();\n                } else { // xLOAD or xSTORE\n                    int size = stackSize + Frame.SIZE[opcode];\n                    if (size > maxStackSize) {\n                        maxStackSize = size;\n                    }\n                    stackSize = size;\n                }\n            }\n        }\n        if (compute != NOTHING) {\n            // updates max locals\n            int n;\n            if (opcode == Opcodes.LLOAD || opcode == Opcodes.DLOAD\n                    || opcode == Opcodes.LSTORE || opcode == Opcodes.DSTORE) {\n                n = var + 2;\n            } else {\n                n = var + 1;\n            }\n            if (n > maxLocals) {\n                maxLocals = n;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        if (var < 4 && opcode != Opcodes.RET) {\n            int opt;\n            if (opcode < Opcodes.ISTORE) {\n                /* ILOAD_0 */\n                opt = 26 + ((opcode - Opcodes.ILOAD) << 2) + var;\n            } else {\n                /* ISTORE_0 */\n                opt = 59 + ((opcode - Opcodes.ISTORE) << 2) + var;\n            }\n            code.putByte(opt);\n        } else if (var >= 256) {\n            code.putByte(196 /* WIDE */).put12(opcode, var);\n        } else {\n            code.put11(opcode, var);\n        }\n        if (opcode >= Opcodes.ISTORE && compute == FRAMES && handlerCount > 0) {\n            visitLabel(new Label());\n        }\n    }\n\n    @Override\n    public void visitTypeInsn(final int opcode, final String type) {\n        lastCodeOffset = code.length;\n        Item i = cw.newClassItem(type);\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, code.length, cw, i);\n            } else if (opcode == Opcodes.NEW) {\n                // updates current and max stack sizes only if opcode == NEW\n                // (no stack change for ANEWARRAY, CHECKCAST, INSTANCEOF)\n                int size = stackSize + 1;\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        code.put12(opcode, i.index);\n    }\n\n    @Override\n    public void visitFieldInsn(final int opcode, final String owner,\n            final String name, final String desc) {\n        lastCodeOffset = code.length;\n        Item i = cw.newFieldItem(owner, name, desc);\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, 0, cw, i);\n            } else {\n                int size;\n                // computes the stack size variation\n                char c = desc.charAt(0);\n                switch (opcode) {\n                case Opcodes.GETSTATIC:\n                    size = stackSize + (c == 'D' || c == 'J' ? 2 : 1);\n                    break;\n                case Opcodes.PUTSTATIC:\n                    size = stackSize + (c == 'D' || c == 'J' ? -2 : -1);\n                    break;\n                case Opcodes.GETFIELD:\n                    size = stackSize + (c == 'D' || c == 'J' ? 1 : 0);\n                    break;\n                // case Constants.PUTFIELD:\n                default:\n                    size = stackSize + (c == 'D' || c == 'J' ? -3 : -2);\n                    break;\n                }\n                // updates current and max stack sizes\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        code.put12(opcode, i.index);\n    }\n\n    @Override\n    public void visitMethodInsn(final int opcode, final String owner,\n            final String name, final String desc, final boolean itf) {\n        lastCodeOffset = code.length;\n        Item i = cw.newMethodItem(owner, name, desc, itf);\n        int argSize = i.intVal;\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, 0, cw, i);\n            } else {\n                /*\n                 * computes the stack size variation. In order not to recompute\n                 * several times this variation for the same Item, we use the\n                 * intVal field of this item to store this variation, once it\n                 * has been computed. More precisely this intVal field stores\n                 * the sizes of the arguments and of the return value\n                 * corresponding to desc.\n                 */\n                if (argSize == 0) {\n                    // the above sizes have not been computed yet,\n                    // so we compute them...\n                    argSize = Type.getArgumentsAndReturnSizes(desc);\n                    // ... and we save them in order\n                    // not to recompute them in the future\n                    i.intVal = argSize;\n                }\n                int size;\n                if (opcode == Opcodes.INVOKESTATIC) {\n                    size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;\n                } else {\n                    size = stackSize - (argSize >> 2) + (argSize & 0x03);\n                }\n                // updates current and max stack sizes\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        if (opcode == Opcodes.INVOKEINTERFACE) {\n            if (argSize == 0) {\n                argSize = Type.getArgumentsAndReturnSizes(desc);\n                i.intVal = argSize;\n            }\n            code.put12(Opcodes.INVOKEINTERFACE, i.index).put11(argSize >> 2, 0);\n        } else {\n            code.put12(opcode, i.index);\n        }\n    }\n\n    @Override\n    public void visitInvokeDynamicInsn(final String name, final String desc,\n            final Handle bsm, final Object... bsmArgs) {\n        lastCodeOffset = code.length;\n        Item i = cw.newInvokeDynamicItem(name, desc, bsm, bsmArgs);\n        int argSize = i.intVal;\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(Opcodes.INVOKEDYNAMIC, 0, cw, i);\n            } else {\n                /*\n                 * computes the stack size variation. In order not to recompute\n                 * several times this variation for the same Item, we use the\n                 * intVal field of this item to store this variation, once it\n                 * has been computed. More precisely this intVal field stores\n                 * the sizes of the arguments and of the return value\n                 * corresponding to desc.\n                 */\n                if (argSize == 0) {\n                    // the above sizes have not been computed yet,\n                    // so we compute them...\n                    argSize = Type.getArgumentsAndReturnSizes(desc);\n                    // ... and we save them in order\n                    // not to recompute them in the future\n                    i.intVal = argSize;\n                }\n                int size = stackSize - (argSize >> 2) + (argSize & 0x03) + 1;\n\n                // updates current and max stack sizes\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        code.put12(Opcodes.INVOKEDYNAMIC, i.index);\n        code.putShort(0);\n    }\n\n    @Override\n    public void visitJumpInsn(final int opcode, final Label label) {\n        lastCodeOffset = code.length;\n        Label nextInsn = null;\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(opcode, 0, null, null);\n                // 'label' is the target of a jump instruction\n                label.getFirst().status |= Label.TARGET;\n                // adds 'label' as a successor of this basic block\n                addSuccessor(Edge.NORMAL, label);\n                if (opcode != Opcodes.GOTO) {\n                    // creates a Label for the next basic block\n                    nextInsn = new Label();\n                }\n            } else {\n                if (opcode == Opcodes.JSR) {\n                    if ((label.status & Label.SUBROUTINE) == 0) {\n                        label.status |= Label.SUBROUTINE;\n                        ++subroutines;\n                    }\n                    currentBlock.status |= Label.JSR;\n                    addSuccessor(stackSize + 1, label);\n                    // creates a Label for the next basic block\n                    nextInsn = new Label();\n                    /*\n                     * note that, by construction in this method, a JSR block\n                     * has at least two successors in the control flow graph:\n                     * the first one leads the next instruction after the JSR,\n                     * while the second one leads to the JSR target.\n                     */\n                } else {\n                    // updates current stack size (max stack size unchanged\n                    // because stack size variation always negative in this\n                    // case)\n                    stackSize += Frame.SIZE[opcode];\n                    addSuccessor(stackSize, label);\n                }\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        if ((label.status & Label.RESOLVED) != 0\n                && label.position - code.length < Short.MIN_VALUE) {\n            /*\n             * case of a backward jump with an offset < -32768. In this case we\n             * automatically replace GOTO with GOTO_W, JSR with JSR_W and IFxxx\n             * <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is the\n             * \"opposite\" opcode of IFxxx (i.e., IFNE for IFEQ) and where <l'>\n             * designates the instruction just after the GOTO_W.\n             */\n            if (opcode == Opcodes.GOTO) {\n                code.putByte(200); // GOTO_W\n            } else if (opcode == Opcodes.JSR) {\n                code.putByte(201); // JSR_W\n            } else {\n                // if the IF instruction is transformed into IFNOT GOTO_W the\n                // next instruction becomes the target of the IFNOT instruction\n                if (nextInsn != null) {\n                    nextInsn.status |= Label.TARGET;\n                }\n                code.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1\n                        : opcode ^ 1);\n                code.putShort(8); // jump offset\n                code.putByte(200); // GOTO_W\n            }\n            label.put(this, code, code.length - 1, true);\n        } else {\n            /*\n             * case of a backward jump with an offset >= -32768, or of a forward\n             * jump with, of course, an unknown offset. In these cases we store\n             * the offset in 2 bytes (which will be increased in\n             * resizeInstructions, if needed).\n             */\n            code.putByte(opcode);\n            label.put(this, code, code.length - 1, false);\n        }\n        if (currentBlock != null) {\n            if (nextInsn != null) {\n                // if the jump instruction is not a GOTO, the next instruction\n                // is also a successor of this instruction. Calling visitLabel\n                // adds the label of this next instruction as a successor of the\n                // current block, and starts a new basic block\n                visitLabel(nextInsn);\n            }\n            if (opcode == Opcodes.GOTO) {\n                noSuccessor();\n            }\n        }\n    }\n\n    @Override\n    public void visitLabel(final Label label) {\n        // resolves previous forward references to label, if any\n        resize |= label.resolve(this, code.length, code.data);\n        // updates currentBlock\n        if ((label.status & Label.DEBUG) != 0) {\n            return;\n        }\n        if (compute == FRAMES) {\n            if (currentBlock != null) {\n                if (label.position == currentBlock.position) {\n                    // successive labels, do not start a new basic block\n                    currentBlock.status |= (label.status & Label.TARGET);\n                    label.frame = currentBlock.frame;\n                    return;\n                }\n                // ends current block (with one new successor)\n                addSuccessor(Edge.NORMAL, label);\n            }\n            // begins a new current block\n            currentBlock = label;\n            if (label.frame == null) {\n                label.frame = new Frame();\n                label.frame.owner = label;\n            }\n            // updates the basic block list\n            if (previousBlock != null) {\n                if (label.position == previousBlock.position) {\n                    previousBlock.status |= (label.status & Label.TARGET);\n                    label.frame = previousBlock.frame;\n                    currentBlock = previousBlock;\n                    return;\n                }\n                previousBlock.successor = label;\n            }\n            previousBlock = label;\n        } else if (compute == MAXS) {\n            if (currentBlock != null) {\n                // ends current block (with one new successor)\n                currentBlock.outputStackMax = maxStackSize;\n                addSuccessor(stackSize, label);\n            }\n            // begins a new current block\n            currentBlock = label;\n            // resets the relative current and max stack sizes\n            stackSize = 0;\n            maxStackSize = 0;\n            // updates the basic block list\n            if (previousBlock != null) {\n                previousBlock.successor = label;\n            }\n            previousBlock = label;\n        }\n    }\n\n    @Override\n    public void visitLdcInsn(final Object cst) {\n        lastCodeOffset = code.length;\n        Item i = cw.newConstItem(cst);\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(Opcodes.LDC, 0, cw, i);\n            } else {\n                int size;\n                // computes the stack size variation\n                if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {\n                    size = stackSize + 2;\n                } else {\n                    size = stackSize + 1;\n                }\n                // updates current and max stack sizes\n                if (size > maxStackSize) {\n                    maxStackSize = size;\n                }\n                stackSize = size;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        int index = i.index;\n        if (i.type == ClassWriter.LONG || i.type == ClassWriter.DOUBLE) {\n            code.put12(20 /* LDC2_W */, index);\n        } else if (index >= 256) {\n            code.put12(19 /* LDC_W */, index);\n        } else {\n            code.put11(Opcodes.LDC, index);\n        }\n    }\n\n    @Override\n    public void visitIincInsn(final int var, final int increment) {\n        lastCodeOffset = code.length;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(Opcodes.IINC, var, null, null);\n            }\n        }\n        if (compute != NOTHING) {\n            // updates max locals\n            int n = var + 1;\n            if (n > maxLocals) {\n                maxLocals = n;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        if ((var > 255) || (increment > 127) || (increment < -128)) {\n            code.putByte(196 /* WIDE */).put12(Opcodes.IINC, var)\n                    .putShort(increment);\n        } else {\n            code.putByte(Opcodes.IINC).put11(var, increment);\n        }\n    }\n\n    @Override\n    public void visitTableSwitchInsn(final int min, final int max,\n            final Label dflt, final Label... labels) {\n        lastCodeOffset = code.length;\n        // adds the instruction to the bytecode of the method\n        int source = code.length;\n        code.putByte(Opcodes.TABLESWITCH);\n        code.putByteArray(null, 0, (4 - code.length % 4) % 4);\n        dflt.put(this, code, source, true);\n        code.putInt(min).putInt(max);\n        for (int i = 0; i < labels.length; ++i) {\n            labels[i].put(this, code, source, true);\n        }\n        // updates currentBlock\n        visitSwitchInsn(dflt, labels);\n    }\n\n    @Override\n    public void visitLookupSwitchInsn(final Label dflt, final int[] keys,\n            final Label[] labels) {\n        lastCodeOffset = code.length;\n        // adds the instruction to the bytecode of the method\n        int source = code.length;\n        code.putByte(Opcodes.LOOKUPSWITCH);\n        code.putByteArray(null, 0, (4 - code.length % 4) % 4);\n        dflt.put(this, code, source, true);\n        code.putInt(labels.length);\n        for (int i = 0; i < labels.length; ++i) {\n            code.putInt(keys[i]);\n            labels[i].put(this, code, source, true);\n        }\n        // updates currentBlock\n        visitSwitchInsn(dflt, labels);\n    }\n\n    private void visitSwitchInsn(final Label dflt, final Label[] labels) {\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(Opcodes.LOOKUPSWITCH, 0, null, null);\n                // adds current block successors\n                addSuccessor(Edge.NORMAL, dflt);\n                dflt.getFirst().status |= Label.TARGET;\n                for (int i = 0; i < labels.length; ++i) {\n                    addSuccessor(Edge.NORMAL, labels[i]);\n                    labels[i].getFirst().status |= Label.TARGET;\n                }\n            } else {\n                // updates current stack size (max stack size unchanged)\n                --stackSize;\n                // adds current block successors\n                addSuccessor(stackSize, dflt);\n                for (int i = 0; i < labels.length; ++i) {\n                    addSuccessor(stackSize, labels[i]);\n                }\n            }\n            // ends current block\n            noSuccessor();\n        }\n    }\n\n    @Override\n    public void visitMultiANewArrayInsn(final String desc, final int dims) {\n        lastCodeOffset = code.length;\n        Item i = cw.newClassItem(desc);\n        // Label currentBlock = this.currentBlock;\n        if (currentBlock != null) {\n            if (compute == FRAMES) {\n                currentBlock.frame.execute(Opcodes.MULTIANEWARRAY, dims, cw, i);\n            } else {\n                // updates current stack size (max stack size unchanged because\n                // stack size variation always negative or null)\n                stackSize += 1 - dims;\n            }\n        }\n        // adds the instruction to the bytecode of the method\n        code.put12(Opcodes.MULTIANEWARRAY, i.index).putByte(dims);\n    }\n\n    @Override\n    public AnnotationVisitor visitInsnAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        typeRef = (typeRef & 0xFF0000FF) | (lastCodeOffset << 8);\n        AnnotationWriter.putTarget(typeRef, typePath, bv);\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = ctanns;\n            ctanns = aw;\n        } else {\n            aw.next = ictanns;\n            ictanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public void visitTryCatchBlock(final Label start, final Label end,\n            final Label handler, final String type) {\n        ++handlerCount;\n        Handler h = new Handler();\n        h.start = start;\n        h.end = end;\n        h.handler = handler;\n        h.desc = type;\n        h.type = type != null ? cw.newClass(type) : 0;\n        if (lastHandler == null) {\n            firstHandler = h;\n        } else {\n            lastHandler.next = h;\n        }\n        lastHandler = h;\n    }\n\n    @Override\n    public AnnotationVisitor visitTryCatchAnnotation(int typeRef,\n            TypePath typePath, String desc, boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        AnnotationWriter.putTarget(typeRef, typePath, bv);\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = ctanns;\n            ctanns = aw;\n        } else {\n            aw.next = ictanns;\n            ictanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public void visitLocalVariable(final String name, final String desc,\n            final String signature, final Label start, final Label end,\n            final int index) {\n        if (signature != null) {\n            if (localVarType == null) {\n                localVarType = new ByteVector();\n            }\n            ++localVarTypeCount;\n            localVarType.putShort(start.position)\n                    .putShort(end.position - start.position)\n                    .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(signature))\n                    .putShort(index);\n        }\n        if (localVar == null) {\n            localVar = new ByteVector();\n        }\n        ++localVarCount;\n        localVar.putShort(start.position)\n                .putShort(end.position - start.position)\n                .putShort(cw.newUTF8(name)).putShort(cw.newUTF8(desc))\n                .putShort(index);\n        if (compute != NOTHING) {\n            // updates max locals\n            char c = desc.charAt(0);\n            int n = index + (c == 'J' || c == 'D' ? 2 : 1);\n            if (n > maxLocals) {\n                maxLocals = n;\n            }\n        }\n    }\n\n    @Override\n    public AnnotationVisitor visitLocalVariableAnnotation(int typeRef,\n            TypePath typePath, Label[] start, Label[] end, int[] index,\n            String desc, boolean visible) {\n        if (!ClassReader.ANNOTATIONS) {\n            return null;\n        }\n        ByteVector bv = new ByteVector();\n        // write target_type and target_info\n        bv.putByte(typeRef >>> 24).putShort(start.length);\n        for (int i = 0; i < start.length; ++i) {\n            bv.putShort(start[i].position)\n                    .putShort(end[i].position - start[i].position)\n                    .putShort(index[i]);\n        }\n        if (typePath == null) {\n            bv.putByte(0);\n        } else {\n            int length = typePath.b[typePath.offset] * 2 + 1;\n            bv.putByteArray(typePath.b, typePath.offset, length);\n        }\n        // write type, and reserve space for values count\n        bv.putShort(cw.newUTF8(desc)).putShort(0);\n        AnnotationWriter aw = new AnnotationWriter(cw, true, bv, bv,\n                bv.length - 2);\n        if (visible) {\n            aw.next = ctanns;\n            ctanns = aw;\n        } else {\n            aw.next = ictanns;\n            ictanns = aw;\n        }\n        return aw;\n    }\n\n    @Override\n    public void visitLineNumber(final int line, final Label start) {\n        if (lineNumber == null) {\n            lineNumber = new ByteVector();\n        }\n        ++lineNumberCount;\n        lineNumber.putShort(start.position);\n        lineNumber.putShort(line);\n    }\n\n    @Override\n    public void visitMaxs(final int maxStack, final int maxLocals) {\n        if (resize) {\n            // replaces the temporary jump opcodes introduced by Label.resolve.\n            if (ClassReader.RESIZE) {\n                resizeInstructions();\n            } else {\n                throw new RuntimeException(\"Method code too large!\");\n            }\n        }\n        if (ClassReader.FRAMES && compute == FRAMES) {\n            // completes the control flow graph with exception handler blocks\n            Handler handler = firstHandler;\n            while (handler != null) {\n                Label l = handler.start.getFirst();\n                Label h = handler.handler.getFirst();\n                Label e = handler.end.getFirst();\n                // computes the kind of the edges to 'h'\n                String t = handler.desc == null ? \"java/lang/Throwable\"\n                        : handler.desc;\n                int kind = Frame.OBJECT | cw.addType(t);\n                // h is an exception handler\n                h.status |= Label.TARGET;\n                // adds 'h' as a successor of labels between 'start' and 'end'\n                while (l != e) {\n                    // creates an edge to 'h'\n                    Edge b = new Edge();\n                    b.info = kind;\n                    b.successor = h;\n                    // adds it to the successors of 'l'\n                    b.next = l.successors;\n                    l.successors = b;\n                    // goes to the next label\n                    l = l.successor;\n                }\n                handler = handler.next;\n            }\n\n            // creates and visits the first (implicit) frame\n            Frame f = labels.frame;\n            Type[] args = Type.getArgumentTypes(descriptor);\n            f.initInputFrame(cw, access, args, this.maxLocals);\n            visitFrame(f);\n\n            /*\n             * fix point algorithm: mark the first basic block as 'changed'\n             * (i.e. put it in the 'changed' list) and, while there are changed\n             * basic blocks, choose one, mark it as unchanged, and update its\n             * successors (which can be changed in the process).\n             */\n            int max = 0;\n            Label changed = labels;\n            while (changed != null) {\n                // removes a basic block from the list of changed basic blocks\n                Label l = changed;\n                changed = changed.next;\n                l.next = null;\n                f = l.frame;\n                // a reachable jump target must be stored in the stack map\n                if ((l.status & Label.TARGET) != 0) {\n                    l.status |= Label.STORE;\n                }\n                // all visited labels are reachable, by definition\n                l.status |= Label.REACHABLE;\n                // updates the (absolute) maximum stack size\n                int blockMax = f.inputStack.length + l.outputStackMax;\n                if (blockMax > max) {\n                    max = blockMax;\n                }\n                // updates the successors of the current basic block\n                Edge e = l.successors;\n                while (e != null) {\n                    Label n = e.successor.getFirst();\n                    boolean change = f.merge(cw, n.frame, e.info);\n                    if (change && n.next == null) {\n                        // if n has changed and is not already in the 'changed'\n                        // list, adds it to this list\n                        n.next = changed;\n                        changed = n;\n                    }\n                    e = e.next;\n                }\n            }\n\n            // visits all the frames that must be stored in the stack map\n            Label l = labels;\n            while (l != null) {\n                f = l.frame;\n                if ((l.status & Label.STORE) != 0) {\n                    visitFrame(f);\n                }\n                if ((l.status & Label.REACHABLE) == 0) {\n                    // finds start and end of dead basic block\n                    Label k = l.successor;\n                    int start = l.position;\n                    int end = (k == null ? code.length : k.position) - 1;\n                    // if non empty basic block\n                    if (end >= start) {\n                        max = Math.max(max, 1);\n                        // replaces instructions with NOP ... NOP ATHROW\n                        for (int i = start; i < end; ++i) {\n                            code.data[i] = Opcodes.NOP;\n                        }\n                        code.data[end] = (byte) Opcodes.ATHROW;\n                        // emits a frame for this unreachable block\n                        int frameIndex = startFrame(start, 0, 1);\n                        frame[frameIndex] = Frame.OBJECT\n                                | cw.addType(\"java/lang/Throwable\");\n                        endFrame();\n                        // removes the start-end range from the exception\n                        // handlers\n                        firstHandler = Handler.remove(firstHandler, l, k);\n                    }\n                }\n                l = l.successor;\n            }\n\n            handler = firstHandler;\n            handlerCount = 0;\n            while (handler != null) {\n                handlerCount += 1;\n                handler = handler.next;\n            }\n\n            this.maxStack = max;\n        } else if (compute == MAXS) {\n            // completes the control flow graph with exception handler blocks\n            Handler handler = firstHandler;\n            while (handler != null) {\n                Label l = handler.start;\n                Label h = handler.handler;\n                Label e = handler.end;\n                // adds 'h' as a successor of labels between 'start' and 'end'\n                while (l != e) {\n                    // creates an edge to 'h'\n                    Edge b = new Edge();\n                    b.info = Edge.EXCEPTION;\n                    b.successor = h;\n                    // adds it to the successors of 'l'\n                    if ((l.status & Label.JSR) == 0) {\n                        b.next = l.successors;\n                        l.successors = b;\n                    } else {\n                        // if l is a JSR block, adds b after the first two edges\n                        // to preserve the hypothesis about JSR block successors\n                        // order (see {@link #visitJumpInsn})\n                        b.next = l.successors.next.next;\n                        l.successors.next.next = b;\n                    }\n                    // goes to the next label\n                    l = l.successor;\n                }\n                handler = handler.next;\n            }\n\n            if (subroutines > 0) {\n                // completes the control flow graph with the RET successors\n                /*\n                 * first step: finds the subroutines. This step determines, for\n                 * each basic block, to which subroutine(s) it belongs.\n                 */\n                // finds the basic blocks that belong to the \"main\" subroutine\n                int id = 0;\n                labels.visitSubroutine(null, 1, subroutines);\n                // finds the basic blocks that belong to the real subroutines\n                Label l = labels;\n                while (l != null) {\n                    if ((l.status & Label.JSR) != 0) {\n                        // the subroutine is defined by l's TARGET, not by l\n                        Label subroutine = l.successors.next.successor;\n                        // if this subroutine has not been visited yet...\n                        if ((subroutine.status & Label.VISITED) == 0) {\n                            // ...assigns it a new id and finds its basic blocks\n                            id += 1;\n                            subroutine.visitSubroutine(null, (id / 32L) << 32\n                                    | (1L << (id % 32)), subroutines);\n                        }\n                    }\n                    l = l.successor;\n                }\n                // second step: finds the successors of RET blocks\n                l = labels;\n                while (l != null) {\n                    if ((l.status & Label.JSR) != 0) {\n                        Label L = labels;\n                        while (L != null) {\n                            L.status &= ~Label.VISITED2;\n                            L = L.successor;\n                        }\n                        // the subroutine is defined by l's TARGET, not by l\n                        Label subroutine = l.successors.next.successor;\n                        subroutine.visitSubroutine(l, 0, subroutines);\n                    }\n                    l = l.successor;\n                }\n            }\n\n            /*\n             * control flow analysis algorithm: while the block stack is not\n             * empty, pop a block from this stack, update the max stack size,\n             * compute the true (non relative) begin stack size of the\n             * successors of this block, and push these successors onto the\n             * stack (unless they have already been pushed onto the stack).\n             * Note: by hypothesis, the {@link Label#inputStackTop} of the\n             * blocks in the block stack are the true (non relative) beginning\n             * stack sizes of these blocks.\n             */\n            int max = 0;\n            Label stack = labels;\n            while (stack != null) {\n                // pops a block from the stack\n                Label l = stack;\n                stack = stack.next;\n                // computes the true (non relative) max stack size of this block\n                int start = l.inputStackTop;\n                int blockMax = start + l.outputStackMax;\n                // updates the global max stack size\n                if (blockMax > max) {\n                    max = blockMax;\n                }\n                // analyzes the successors of the block\n                Edge b = l.successors;\n                if ((l.status & Label.JSR) != 0) {\n                    // ignores the first edge of JSR blocks (virtual successor)\n                    b = b.next;\n                }\n                while (b != null) {\n                    l = b.successor;\n                    // if this successor has not already been pushed...\n                    if ((l.status & Label.PUSHED) == 0) {\n                        // computes its true beginning stack size...\n                        l.inputStackTop = b.info == Edge.EXCEPTION ? 1 : start\n                                + b.info;\n                        // ...and pushes it onto the stack\n                        l.status |= Label.PUSHED;\n                        l.next = stack;\n                        stack = l;\n                    }\n                    b = b.next;\n                }\n            }\n            this.maxStack = Math.max(maxStack, max);\n        } else {\n            this.maxStack = maxStack;\n            this.maxLocals = maxLocals;\n        }\n    }\n\n    @Override\n    public void visitEnd() {\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: control flow analysis algorithm\n    // ------------------------------------------------------------------------\n\n    /**\n     * Adds a successor to the {@link #currentBlock currentBlock} block.\n     * \n     * @param info\n     *            information about the control flow edge to be added.\n     * @param successor\n     *            the successor block to be added to the current block.\n     */\n    private void addSuccessor(final int info, final Label successor) {\n        // creates and initializes an Edge object...\n        Edge b = new Edge();\n        b.info = info;\n        b.successor = successor;\n        // ...and adds it to the successor list of the currentBlock block\n        b.next = currentBlock.successors;\n        currentBlock.successors = b;\n    }\n\n    /**\n     * Ends the current basic block. This method must be used in the case where\n     * the current basic block does not have any successor.\n     */\n    private void noSuccessor() {\n        if (compute == FRAMES) {\n            Label l = new Label();\n            l.frame = new Frame();\n            l.frame.owner = l;\n            l.resolve(this, code.length, code.data);\n            previousBlock.successor = l;\n            previousBlock = l;\n        } else {\n            currentBlock.outputStackMax = maxStackSize;\n        }\n        currentBlock = null;\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: stack map frames\n    // ------------------------------------------------------------------------\n\n    /**\n     * Visits a frame that has been computed from scratch.\n     * \n     * @param f\n     *            the frame that must be visited.\n     */\n    private void visitFrame(final Frame f) {\n        int i, t;\n        int nTop = 0;\n        int nLocal = 0;\n        int nStack = 0;\n        int[] locals = f.inputLocals;\n        int[] stacks = f.inputStack;\n        // computes the number of locals (ignores TOP types that are just after\n        // a LONG or a DOUBLE, and all trailing TOP types)\n        for (i = 0; i < locals.length; ++i) {\n            t = locals[i];\n            if (t == Frame.TOP) {\n                ++nTop;\n            } else {\n                nLocal += nTop + 1;\n                nTop = 0;\n            }\n            if (t == Frame.LONG || t == Frame.DOUBLE) {\n                ++i;\n            }\n        }\n        // computes the stack size (ignores TOP types that are just after\n        // a LONG or a DOUBLE)\n        for (i = 0; i < stacks.length; ++i) {\n            t = stacks[i];\n            ++nStack;\n            if (t == Frame.LONG || t == Frame.DOUBLE) {\n                ++i;\n            }\n        }\n        // visits the frame and its content\n        int frameIndex = startFrame(f.owner.position, nLocal, nStack);\n        for (i = 0; nLocal > 0; ++i, --nLocal) {\n            t = locals[i];\n            frame[frameIndex++] = t;\n            if (t == Frame.LONG || t == Frame.DOUBLE) {\n                ++i;\n            }\n        }\n        for (i = 0; i < stacks.length; ++i) {\n            t = stacks[i];\n            frame[frameIndex++] = t;\n            if (t == Frame.LONG || t == Frame.DOUBLE) {\n                ++i;\n            }\n        }\n        endFrame();\n    }\n\n    /**\n     * Visit the implicit first frame of this method.\n     */\n    private void visitImplicitFirstFrame() {\n        // There can be at most descriptor.length() + 1 locals\n        int frameIndex = startFrame(0, descriptor.length() + 1, 0);\n        if ((access & Opcodes.ACC_STATIC) == 0) {\n            if ((access & ACC_CONSTRUCTOR) == 0) {\n                frame[frameIndex++] = Frame.OBJECT | cw.addType(cw.thisName);\n            } else {\n                frame[frameIndex++] = 6; // Opcodes.UNINITIALIZED_THIS;\n            }\n        }\n        int i = 1;\n        loop: while (true) {\n            int j = i;\n            switch (descriptor.charAt(i++)) {\n            case 'Z':\n            case 'C':\n            case 'B':\n            case 'S':\n            case 'I':\n                frame[frameIndex++] = 1; // Opcodes.INTEGER;\n                break;\n            case 'F':\n                frame[frameIndex++] = 2; // Opcodes.FLOAT;\n                break;\n            case 'J':\n                frame[frameIndex++] = 4; // Opcodes.LONG;\n                break;\n            case 'D':\n                frame[frameIndex++] = 3; // Opcodes.DOUBLE;\n                break;\n            case '[':\n                while (descriptor.charAt(i) == '[') {\n                    ++i;\n                }\n                if (descriptor.charAt(i) == 'L') {\n                    ++i;\n                    while (descriptor.charAt(i) != ';') {\n                        ++i;\n                    }\n                }\n                frame[frameIndex++] = Frame.OBJECT\n                        | cw.addType(descriptor.substring(j, ++i));\n                break;\n            case 'L':\n                while (descriptor.charAt(i) != ';') {\n                    ++i;\n                }\n                frame[frameIndex++] = Frame.OBJECT\n                        | cw.addType(descriptor.substring(j + 1, i++));\n                break;\n            default:\n                break loop;\n            }\n        }\n        frame[1] = frameIndex - 3;\n        endFrame();\n    }\n\n    /**\n     * Starts the visit of a stack map frame.\n     * \n     * @param offset\n     *            the offset of the instruction to which the frame corresponds.\n     * @param nLocal\n     *            the number of local variables in the frame.\n     * @param nStack\n     *            the number of stack elements in the frame.\n     * @return the index of the next element to be written in this frame.\n     */\n    private int startFrame(final int offset, final int nLocal, final int nStack) {\n        int n = 3 + nLocal + nStack;\n        if (frame == null || frame.length < n) {\n            frame = new int[n];\n        }\n        frame[0] = offset;\n        frame[1] = nLocal;\n        frame[2] = nStack;\n        return 3;\n    }\n\n    /**\n     * Checks if the visit of the current frame {@link #frame} is finished, and\n     * if yes, write it in the StackMapTable attribute.\n     */\n    private void endFrame() {\n        if (previousFrame != null) { // do not write the first frame\n            if (stackMap == null) {\n                stackMap = new ByteVector();\n            }\n            writeFrame();\n            ++frameCount;\n        }\n        previousFrame = frame;\n        frame = null;\n    }\n\n    /**\n     * Compress and writes the current frame {@link #frame} in the StackMapTable\n     * attribute.\n     */\n    private void writeFrame() {\n        int clocalsSize = frame[1];\n        int cstackSize = frame[2];\n        if ((cw.version & 0xFFFF) < Opcodes.V1_6) {\n            stackMap.putShort(frame[0]).putShort(clocalsSize);\n            writeFrameTypes(3, 3 + clocalsSize);\n            stackMap.putShort(cstackSize);\n            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);\n            return;\n        }\n        int localsSize = previousFrame[1];\n        int type = FULL_FRAME;\n        int k = 0;\n        int delta;\n        if (frameCount == 0) {\n            delta = frame[0];\n        } else {\n            delta = frame[0] - previousFrame[0] - 1;\n        }\n        if (cstackSize == 0) {\n            k = clocalsSize - localsSize;\n            switch (k) {\n            case -3:\n            case -2:\n            case -1:\n                type = CHOP_FRAME;\n                localsSize = clocalsSize;\n                break;\n            case 0:\n                type = delta < 64 ? SAME_FRAME : SAME_FRAME_EXTENDED;\n                break;\n            case 1:\n            case 2:\n            case 3:\n                type = APPEND_FRAME;\n                break;\n            }\n        } else if (clocalsSize == localsSize && cstackSize == 1) {\n            type = delta < 63 ? SAME_LOCALS_1_STACK_ITEM_FRAME\n                    : SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED;\n        }\n        if (type != FULL_FRAME) {\n            // verify if locals are the same\n            int l = 3;\n            for (int j = 0; j < localsSize; j++) {\n                if (frame[l] != previousFrame[l]) {\n                    type = FULL_FRAME;\n                    break;\n                }\n                l++;\n            }\n        }\n        switch (type) {\n        case SAME_FRAME:\n            stackMap.putByte(delta);\n            break;\n        case SAME_LOCALS_1_STACK_ITEM_FRAME:\n            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME + delta);\n            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);\n            break;\n        case SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED:\n            stackMap.putByte(SAME_LOCALS_1_STACK_ITEM_FRAME_EXTENDED).putShort(\n                    delta);\n            writeFrameTypes(3 + clocalsSize, 4 + clocalsSize);\n            break;\n        case SAME_FRAME_EXTENDED:\n            stackMap.putByte(SAME_FRAME_EXTENDED).putShort(delta);\n            break;\n        case CHOP_FRAME:\n            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);\n            break;\n        case APPEND_FRAME:\n            stackMap.putByte(SAME_FRAME_EXTENDED + k).putShort(delta);\n            writeFrameTypes(3 + localsSize, 3 + clocalsSize);\n            break;\n        // case FULL_FRAME:\n        default:\n            stackMap.putByte(FULL_FRAME).putShort(delta).putShort(clocalsSize);\n            writeFrameTypes(3, 3 + clocalsSize);\n            stackMap.putShort(cstackSize);\n            writeFrameTypes(3 + clocalsSize, 3 + clocalsSize + cstackSize);\n        }\n    }\n\n    /**\n     * Writes some types of the current frame {@link #frame} into the\n     * StackMapTableAttribute. This method converts types from the format used\n     * in {@link Label} to the format used in StackMapTable attributes. In\n     * particular, it converts type table indexes to constant pool indexes.\n     * \n     * @param start\n     *            index of the first type in {@link #frame} to write.\n     * @param end\n     *            index of last type in {@link #frame} to write (exclusive).\n     */\n    private void writeFrameTypes(final int start, final int end) {\n        for (int i = start; i < end; ++i) {\n            int t = frame[i];\n            int d = t & Frame.DIM;\n            if (d == 0) {\n                int v = t & Frame.BASE_VALUE;\n                switch (t & Frame.BASE_KIND) {\n                case Frame.OBJECT:\n                    stackMap.putByte(7).putShort(\n                            cw.newClass(cw.typeTable[v].strVal1));\n                    break;\n                case Frame.UNINITIALIZED:\n                    stackMap.putByte(8).putShort(cw.typeTable[v].intVal);\n                    break;\n                default:\n                    stackMap.putByte(v);\n                }\n            } else {\n                StringBuilder sb = new StringBuilder();\n                d >>= 28;\n                while (d-- > 0) {\n                    sb.append('[');\n                }\n                if ((t & Frame.BASE_KIND) == Frame.OBJECT) {\n                    sb.append('L');\n                    sb.append(cw.typeTable[t & Frame.BASE_VALUE].strVal1);\n                    sb.append(';');\n                } else {\n                    switch (t & 0xF) {\n                    case 1:\n                        sb.append('I');\n                        break;\n                    case 2:\n                        sb.append('F');\n                        break;\n                    case 3:\n                        sb.append('D');\n                        break;\n                    case 9:\n                        sb.append('Z');\n                        break;\n                    case 10:\n                        sb.append('B');\n                        break;\n                    case 11:\n                        sb.append('C');\n                        break;\n                    case 12:\n                        sb.append('S');\n                        break;\n                    default:\n                        sb.append('J');\n                    }\n                }\n                stackMap.putByte(7).putShort(cw.newClass(sb.toString()));\n            }\n        }\n    }\n\n    private void writeFrameType(final Object type) {\n        if (type instanceof String) {\n            stackMap.putByte(7).putShort(cw.newClass((String) type));\n        } else if (type instanceof Integer) {\n            stackMap.putByte(((Integer) type).intValue());\n        } else {\n            stackMap.putByte(8).putShort(((Label) type).position);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: dump bytecode array\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the size of the bytecode of this method.\n     * \n     * @return the size of the bytecode of this method.\n     */\n    final int getSize() {\n        if (classReaderOffset != 0) {\n            return 6 + classReaderLength;\n        }\n        int size = 8;\n        if (code.length > 0) {\n            if (code.length > 65535) {\n                throw new RuntimeException(\"Method code too large!\");\n            }\n            cw.newUTF8(\"Code\");\n            size += 18 + code.length + 8 * handlerCount;\n            if (localVar != null) {\n                cw.newUTF8(\"LocalVariableTable\");\n                size += 8 + localVar.length;\n            }\n            if (localVarType != null) {\n                cw.newUTF8(\"LocalVariableTypeTable\");\n                size += 8 + localVarType.length;\n            }\n            if (lineNumber != null) {\n                cw.newUTF8(\"LineNumberTable\");\n                size += 8 + lineNumber.length;\n            }\n            if (stackMap != null) {\n                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;\n                cw.newUTF8(zip ? \"StackMapTable\" : \"StackMap\");\n                size += 8 + stackMap.length;\n            }\n            if (ClassReader.ANNOTATIONS && ctanns != null) {\n                cw.newUTF8(\"RuntimeVisibleTypeAnnotations\");\n                size += 8 + ctanns.getSize();\n            }\n            if (ClassReader.ANNOTATIONS && ictanns != null) {\n                cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\");\n                size += 8 + ictanns.getSize();\n            }\n            if (cattrs != null) {\n                size += cattrs.getSize(cw, code.data, code.length, maxStack,\n                        maxLocals);\n            }\n        }\n        if (exceptionCount > 0) {\n            cw.newUTF8(\"Exceptions\");\n            size += 8 + 2 * exceptionCount;\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                cw.newUTF8(\"Synthetic\");\n                size += 6;\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            cw.newUTF8(\"Deprecated\");\n            size += 6;\n        }\n        if (ClassReader.SIGNATURES && signature != null) {\n            cw.newUTF8(\"Signature\");\n            cw.newUTF8(signature);\n            size += 8;\n        }\n        if (methodParameters != null) {\n            cw.newUTF8(\"MethodParameters\");\n            size += 7 + methodParameters.length;\n        }\n        if (ClassReader.ANNOTATIONS && annd != null) {\n            cw.newUTF8(\"AnnotationDefault\");\n            size += 6 + annd.length;\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            cw.newUTF8(\"RuntimeVisibleAnnotations\");\n            size += 8 + anns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            cw.newUTF8(\"RuntimeInvisibleAnnotations\");\n            size += 8 + ianns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            cw.newUTF8(\"RuntimeVisibleTypeAnnotations\");\n            size += 8 + tanns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\");\n            size += 8 + itanns.getSize();\n        }\n        if (ClassReader.ANNOTATIONS && panns != null) {\n            cw.newUTF8(\"RuntimeVisibleParameterAnnotations\");\n            size += 7 + 2 * (panns.length - synthetics);\n            for (int i = panns.length - 1; i >= synthetics; --i) {\n                size += panns[i] == null ? 0 : panns[i].getSize();\n            }\n        }\n        if (ClassReader.ANNOTATIONS && ipanns != null) {\n            cw.newUTF8(\"RuntimeInvisibleParameterAnnotations\");\n            size += 7 + 2 * (ipanns.length - synthetics);\n            for (int i = ipanns.length - 1; i >= synthetics; --i) {\n                size += ipanns[i] == null ? 0 : ipanns[i].getSize();\n            }\n        }\n        if (attrs != null) {\n            size += attrs.getSize(cw, null, 0, -1, -1);\n        }\n        return size;\n    }\n\n    /**\n     * Puts the bytecode of this method in the given byte vector.\n     * \n     * @param out\n     *            the byte vector into which the bytecode of this method must be\n     *            copied.\n     */\n    final void put(final ByteVector out) {\n        final int FACTOR = ClassWriter.TO_ACC_SYNTHETIC;\n        int mask = ACC_CONSTRUCTOR | Opcodes.ACC_DEPRECATED\n                | ClassWriter.ACC_SYNTHETIC_ATTRIBUTE\n                | ((access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) / FACTOR);\n        out.putShort(access & ~mask).putShort(name).putShort(desc);\n        if (classReaderOffset != 0) {\n            out.putByteArray(cw.cr.b, classReaderOffset, classReaderLength);\n            return;\n        }\n        int attributeCount = 0;\n        if (code.length > 0) {\n            ++attributeCount;\n        }\n        if (exceptionCount > 0) {\n            ++attributeCount;\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                ++attributeCount;\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            ++attributeCount;\n        }\n        if (ClassReader.SIGNATURES && signature != null) {\n            ++attributeCount;\n        }\n        if (methodParameters != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && annd != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && panns != null) {\n            ++attributeCount;\n        }\n        if (ClassReader.ANNOTATIONS && ipanns != null) {\n            ++attributeCount;\n        }\n        if (attrs != null) {\n            attributeCount += attrs.getCount();\n        }\n        out.putShort(attributeCount);\n        if (code.length > 0) {\n            int size = 12 + code.length + 8 * handlerCount;\n            if (localVar != null) {\n                size += 8 + localVar.length;\n            }\n            if (localVarType != null) {\n                size += 8 + localVarType.length;\n            }\n            if (lineNumber != null) {\n                size += 8 + lineNumber.length;\n            }\n            if (stackMap != null) {\n                size += 8 + stackMap.length;\n            }\n            if (ClassReader.ANNOTATIONS && ctanns != null) {\n                size += 8 + ctanns.getSize();\n            }\n            if (ClassReader.ANNOTATIONS && ictanns != null) {\n                size += 8 + ictanns.getSize();\n            }\n            if (cattrs != null) {\n                size += cattrs.getSize(cw, code.data, code.length, maxStack,\n                        maxLocals);\n            }\n            out.putShort(cw.newUTF8(\"Code\")).putInt(size);\n            out.putShort(maxStack).putShort(maxLocals);\n            out.putInt(code.length).putByteArray(code.data, 0, code.length);\n            out.putShort(handlerCount);\n            if (handlerCount > 0) {\n                Handler h = firstHandler;\n                while (h != null) {\n                    out.putShort(h.start.position).putShort(h.end.position)\n                            .putShort(h.handler.position).putShort(h.type);\n                    h = h.next;\n                }\n            }\n            attributeCount = 0;\n            if (localVar != null) {\n                ++attributeCount;\n            }\n            if (localVarType != null) {\n                ++attributeCount;\n            }\n            if (lineNumber != null) {\n                ++attributeCount;\n            }\n            if (stackMap != null) {\n                ++attributeCount;\n            }\n            if (ClassReader.ANNOTATIONS && ctanns != null) {\n                ++attributeCount;\n            }\n            if (ClassReader.ANNOTATIONS && ictanns != null) {\n                ++attributeCount;\n            }\n            if (cattrs != null) {\n                attributeCount += cattrs.getCount();\n            }\n            out.putShort(attributeCount);\n            if (localVar != null) {\n                out.putShort(cw.newUTF8(\"LocalVariableTable\"));\n                out.putInt(localVar.length + 2).putShort(localVarCount);\n                out.putByteArray(localVar.data, 0, localVar.length);\n            }\n            if (localVarType != null) {\n                out.putShort(cw.newUTF8(\"LocalVariableTypeTable\"));\n                out.putInt(localVarType.length + 2).putShort(localVarTypeCount);\n                out.putByteArray(localVarType.data, 0, localVarType.length);\n            }\n            if (lineNumber != null) {\n                out.putShort(cw.newUTF8(\"LineNumberTable\"));\n                out.putInt(lineNumber.length + 2).putShort(lineNumberCount);\n                out.putByteArray(lineNumber.data, 0, lineNumber.length);\n            }\n            if (stackMap != null) {\n                boolean zip = (cw.version & 0xFFFF) >= Opcodes.V1_6;\n                out.putShort(cw.newUTF8(zip ? \"StackMapTable\" : \"StackMap\"));\n                out.putInt(stackMap.length + 2).putShort(frameCount);\n                out.putByteArray(stackMap.data, 0, stackMap.length);\n            }\n            if (ClassReader.ANNOTATIONS && ctanns != null) {\n                out.putShort(cw.newUTF8(\"RuntimeVisibleTypeAnnotations\"));\n                ctanns.put(out);\n            }\n            if (ClassReader.ANNOTATIONS && ictanns != null) {\n                out.putShort(cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\"));\n                ictanns.put(out);\n            }\n            if (cattrs != null) {\n                cattrs.put(cw, code.data, code.length, maxLocals, maxStack, out);\n            }\n        }\n        if (exceptionCount > 0) {\n            out.putShort(cw.newUTF8(\"Exceptions\")).putInt(\n                    2 * exceptionCount + 2);\n            out.putShort(exceptionCount);\n            for (int i = 0; i < exceptionCount; ++i) {\n                out.putShort(exceptions[i]);\n            }\n        }\n        if ((access & Opcodes.ACC_SYNTHETIC) != 0) {\n            if ((cw.version & 0xFFFF) < Opcodes.V1_5\n                    || (access & ClassWriter.ACC_SYNTHETIC_ATTRIBUTE) != 0) {\n                out.putShort(cw.newUTF8(\"Synthetic\")).putInt(0);\n            }\n        }\n        if ((access & Opcodes.ACC_DEPRECATED) != 0) {\n            out.putShort(cw.newUTF8(\"Deprecated\")).putInt(0);\n        }\n        if (ClassReader.SIGNATURES && signature != null) {\n            out.putShort(cw.newUTF8(\"Signature\")).putInt(2)\n                    .putShort(cw.newUTF8(signature));\n        }\n        if (methodParameters != null) {\n            out.putShort(cw.newUTF8(\"MethodParameters\"));\n            out.putInt(methodParameters.length + 1).putByte(\n                    methodParametersCount);\n            out.putByteArray(methodParameters.data, 0, methodParameters.length);\n        }\n        if (ClassReader.ANNOTATIONS && annd != null) {\n            out.putShort(cw.newUTF8(\"AnnotationDefault\"));\n            out.putInt(annd.length);\n            out.putByteArray(annd.data, 0, annd.length);\n        }\n        if (ClassReader.ANNOTATIONS && anns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeVisibleAnnotations\"));\n            anns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && ianns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeInvisibleAnnotations\"));\n            ianns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && tanns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeVisibleTypeAnnotations\"));\n            tanns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && itanns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeInvisibleTypeAnnotations\"));\n            itanns.put(out);\n        }\n        if (ClassReader.ANNOTATIONS && panns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeVisibleParameterAnnotations\"));\n            AnnotationWriter.put(panns, synthetics, out);\n        }\n        if (ClassReader.ANNOTATIONS && ipanns != null) {\n            out.putShort(cw.newUTF8(\"RuntimeInvisibleParameterAnnotations\"));\n            AnnotationWriter.put(ipanns, synthetics, out);\n        }\n        if (attrs != null) {\n            attrs.put(cw, null, 0, -1, -1, out);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods: instruction resizing (used to handle GOTO_W and JSR_W)\n    // ------------------------------------------------------------------------\n\n    /**\n     * Resizes and replaces the temporary instructions inserted by\n     * {@link Label#resolve} for wide forward jumps, while keeping jump offsets\n     * and instruction addresses consistent. This may require to resize other\n     * existing instructions, or even to introduce new instructions: for\n     * example, increasing the size of an instruction by 2 at the middle of a\n     * method can increases the offset of an IFEQ instruction from 32766 to\n     * 32768, in which case IFEQ 32766 must be replaced with IFNEQ 8 GOTO_W\n     * 32765. This, in turn, may require to increase the size of another jump\n     * instruction, and so on... All these operations are handled automatically\n     * by this method.\n     * <p>\n     * <i>This method must be called after all the method that is being built\n     * has been visited</i>. In particular, the {@link Label Label} objects used\n     * to construct the method are no longer valid after this method has been\n     * called.\n     */\n    private void resizeInstructions() {\n        byte[] b = code.data; // bytecode of the method\n        int u, v, label; // indexes in b\n        int i, j; // loop indexes\n        /*\n         * 1st step: As explained above, resizing an instruction may require to\n         * resize another one, which may require to resize yet another one, and\n         * so on. The first step of the algorithm consists in finding all the\n         * instructions that need to be resized, without modifying the code.\n         * This is done by the following \"fix point\" algorithm:\n         * \n         * Parse the code to find the jump instructions whose offset will need\n         * more than 2 bytes to be stored (the future offset is computed from\n         * the current offset and from the number of bytes that will be inserted\n         * or removed between the source and target instructions). For each such\n         * instruction, adds an entry in (a copy of) the indexes and sizes\n         * arrays (if this has not already been done in a previous iteration!).\n         * \n         * If at least one entry has been added during the previous step, go\n         * back to the beginning, otherwise stop.\n         * \n         * In fact the real algorithm is complicated by the fact that the size\n         * of TABLESWITCH and LOOKUPSWITCH instructions depends on their\n         * position in the bytecode (because of padding). In order to ensure the\n         * convergence of the algorithm, the number of bytes to be added or\n         * removed from these instructions is over estimated during the previous\n         * loop, and computed exactly only after the loop is finished (this\n         * requires another pass to parse the bytecode of the method).\n         */\n        int[] allIndexes = new int[0]; // copy of indexes\n        int[] allSizes = new int[0]; // copy of sizes\n        boolean[] resize; // instructions to be resized\n        int newOffset; // future offset of a jump instruction\n\n        resize = new boolean[code.length];\n\n        // 3 = loop again, 2 = loop ended, 1 = last pass, 0 = done\n        int state = 3;\n        do {\n            if (state == 3) {\n                state = 2;\n            }\n            u = 0;\n            while (u < b.length) {\n                int opcode = b[u] & 0xFF; // opcode of current instruction\n                int insert = 0; // bytes to be added after this instruction\n\n                switch (ClassWriter.TYPE[opcode]) {\n                case ClassWriter.NOARG_INSN:\n                case ClassWriter.IMPLVAR_INSN:\n                    u += 1;\n                    break;\n                case ClassWriter.LABEL_INSN:\n                    if (opcode > 201) {\n                        // converts temporary opcodes 202 to 217, 218 and\n                        // 219 to IFEQ ... JSR (inclusive), IFNULL and\n                        // IFNONNULL\n                        opcode = opcode < 218 ? opcode - 49 : opcode - 20;\n                        label = u + readUnsignedShort(b, u + 1);\n                    } else {\n                        label = u + readShort(b, u + 1);\n                    }\n                    newOffset = getNewOffset(allIndexes, allSizes, u, label);\n                    if (newOffset < Short.MIN_VALUE\n                            || newOffset > Short.MAX_VALUE) {\n                        if (!resize[u]) {\n                            if (opcode == Opcodes.GOTO || opcode == Opcodes.JSR) {\n                                // two additional bytes will be required to\n                                // replace this GOTO or JSR instruction with\n                                // a GOTO_W or a JSR_W\n                                insert = 2;\n                            } else {\n                                // five additional bytes will be required to\n                                // replace this IFxxx <l> instruction with\n                                // IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx\n                                // is the \"opposite\" opcode of IFxxx (i.e.,\n                                // IFNE for IFEQ) and where <l'> designates\n                                // the instruction just after the GOTO_W.\n                                insert = 5;\n                            }\n                            resize[u] = true;\n                        }\n                    }\n                    u += 3;\n                    break;\n                case ClassWriter.LABELW_INSN:\n                    u += 5;\n                    break;\n                case ClassWriter.TABL_INSN:\n                    if (state == 1) {\n                        // true number of bytes to be added (or removed)\n                        // from this instruction = (future number of padding\n                        // bytes - current number of padding byte) -\n                        // previously over estimated variation =\n                        // = ((3 - newOffset%4) - (3 - u%4)) - u%4\n                        // = (-newOffset%4 + u%4) - u%4\n                        // = -(newOffset & 3)\n                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);\n                        insert = -(newOffset & 3);\n                    } else if (!resize[u]) {\n                        // over estimation of the number of bytes to be\n                        // added to this instruction = 3 - current number\n                        // of padding bytes = 3 - (3 - u%4) = u%4 = u & 3\n                        insert = u & 3;\n                        resize[u] = true;\n                    }\n                    // skips instruction\n                    u = u + 4 - (u & 3);\n                    u += 4 * (readInt(b, u + 8) - readInt(b, u + 4) + 1) + 12;\n                    break;\n                case ClassWriter.LOOK_INSN:\n                    if (state == 1) {\n                        // like TABL_INSN\n                        newOffset = getNewOffset(allIndexes, allSizes, 0, u);\n                        insert = -(newOffset & 3);\n                    } else if (!resize[u]) {\n                        // like TABL_INSN\n                        insert = u & 3;\n                        resize[u] = true;\n                    }\n                    // skips instruction\n                    u = u + 4 - (u & 3);\n                    u += 8 * readInt(b, u + 4) + 8;\n                    break;\n                case ClassWriter.WIDE_INSN:\n                    opcode = b[u + 1] & 0xFF;\n                    if (opcode == Opcodes.IINC) {\n                        u += 6;\n                    } else {\n                        u += 4;\n                    }\n                    break;\n                case ClassWriter.VAR_INSN:\n                case ClassWriter.SBYTE_INSN:\n                case ClassWriter.LDC_INSN:\n                    u += 2;\n                    break;\n                case ClassWriter.SHORT_INSN:\n                case ClassWriter.LDCW_INSN:\n                case ClassWriter.FIELDORMETH_INSN:\n                case ClassWriter.TYPE_INSN:\n                case ClassWriter.IINC_INSN:\n                    u += 3;\n                    break;\n                case ClassWriter.ITFMETH_INSN:\n                case ClassWriter.INDYMETH_INSN:\n                    u += 5;\n                    break;\n                // case ClassWriter.MANA_INSN:\n                default:\n                    u += 4;\n                    break;\n                }\n                if (insert != 0) {\n                    // adds a new (u, insert) entry in the allIndexes and\n                    // allSizes arrays\n                    int[] newIndexes = new int[allIndexes.length + 1];\n                    int[] newSizes = new int[allSizes.length + 1];\n                    System.arraycopy(allIndexes, 0, newIndexes, 0,\n                            allIndexes.length);\n                    System.arraycopy(allSizes, 0, newSizes, 0, allSizes.length);\n                    newIndexes[allIndexes.length] = u;\n                    newSizes[allSizes.length] = insert;\n                    allIndexes = newIndexes;\n                    allSizes = newSizes;\n                    if (insert > 0) {\n                        state = 3;\n                    }\n                }\n            }\n            if (state < 3) {\n                --state;\n            }\n        } while (state != 0);\n\n        // 2nd step:\n        // copies the bytecode of the method into a new bytevector, updates the\n        // offsets, and inserts (or removes) bytes as requested.\n\n        ByteVector newCode = new ByteVector(code.length);\n\n        u = 0;\n        while (u < code.length) {\n            int opcode = b[u] & 0xFF;\n            switch (ClassWriter.TYPE[opcode]) {\n            case ClassWriter.NOARG_INSN:\n            case ClassWriter.IMPLVAR_INSN:\n                newCode.putByte(opcode);\n                u += 1;\n                break;\n            case ClassWriter.LABEL_INSN:\n                if (opcode > 201) {\n                    // changes temporary opcodes 202 to 217 (inclusive), 218\n                    // and 219 to IFEQ ... JSR (inclusive), IFNULL and\n                    // IFNONNULL\n                    opcode = opcode < 218 ? opcode - 49 : opcode - 20;\n                    label = u + readUnsignedShort(b, u + 1);\n                } else {\n                    label = u + readShort(b, u + 1);\n                }\n                newOffset = getNewOffset(allIndexes, allSizes, u, label);\n                if (resize[u]) {\n                    // replaces GOTO with GOTO_W, JSR with JSR_W and IFxxx\n                    // <l> with IFNOTxxx <l'> GOTO_W <l>, where IFNOTxxx is\n                    // the \"opposite\" opcode of IFxxx (i.e., IFNE for IFEQ)\n                    // and where <l'> designates the instruction just after\n                    // the GOTO_W.\n                    if (opcode == Opcodes.GOTO) {\n                        newCode.putByte(200); // GOTO_W\n                    } else if (opcode == Opcodes.JSR) {\n                        newCode.putByte(201); // JSR_W\n                    } else {\n                        newCode.putByte(opcode <= 166 ? ((opcode + 1) ^ 1) - 1\n                                : opcode ^ 1);\n                        newCode.putShort(8); // jump offset\n                        newCode.putByte(200); // GOTO_W\n                        // newOffset now computed from start of GOTO_W\n                        newOffset -= 3;\n                    }\n                    newCode.putInt(newOffset);\n                } else {\n                    newCode.putByte(opcode);\n                    newCode.putShort(newOffset);\n                }\n                u += 3;\n                break;\n            case ClassWriter.LABELW_INSN:\n                label = u + readInt(b, u + 1);\n                newOffset = getNewOffset(allIndexes, allSizes, u, label);\n                newCode.putByte(opcode);\n                newCode.putInt(newOffset);\n                u += 5;\n                break;\n            case ClassWriter.TABL_INSN:\n                // skips 0 to 3 padding bytes\n                v = u;\n                u = u + 4 - (v & 3);\n                // reads and copies instruction\n                newCode.putByte(Opcodes.TABLESWITCH);\n                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);\n                label = v + readInt(b, u);\n                u += 4;\n                newOffset = getNewOffset(allIndexes, allSizes, v, label);\n                newCode.putInt(newOffset);\n                j = readInt(b, u);\n                u += 4;\n                newCode.putInt(j);\n                j = readInt(b, u) - j + 1;\n                u += 4;\n                newCode.putInt(readInt(b, u - 4));\n                for (; j > 0; --j) {\n                    label = v + readInt(b, u);\n                    u += 4;\n                    newOffset = getNewOffset(allIndexes, allSizes, v, label);\n                    newCode.putInt(newOffset);\n                }\n                break;\n            case ClassWriter.LOOK_INSN:\n                // skips 0 to 3 padding bytes\n                v = u;\n                u = u + 4 - (v & 3);\n                // reads and copies instruction\n                newCode.putByte(Opcodes.LOOKUPSWITCH);\n                newCode.putByteArray(null, 0, (4 - newCode.length % 4) % 4);\n                label = v + readInt(b, u);\n                u += 4;\n                newOffset = getNewOffset(allIndexes, allSizes, v, label);\n                newCode.putInt(newOffset);\n                j = readInt(b, u);\n                u += 4;\n                newCode.putInt(j);\n                for (; j > 0; --j) {\n                    newCode.putInt(readInt(b, u));\n                    u += 4;\n                    label = v + readInt(b, u);\n                    u += 4;\n                    newOffset = getNewOffset(allIndexes, allSizes, v, label);\n                    newCode.putInt(newOffset);\n                }\n                break;\n            case ClassWriter.WIDE_INSN:\n                opcode = b[u + 1] & 0xFF;\n                if (opcode == Opcodes.IINC) {\n                    newCode.putByteArray(b, u, 6);\n                    u += 6;\n                } else {\n                    newCode.putByteArray(b, u, 4);\n                    u += 4;\n                }\n                break;\n            case ClassWriter.VAR_INSN:\n            case ClassWriter.SBYTE_INSN:\n            case ClassWriter.LDC_INSN:\n                newCode.putByteArray(b, u, 2);\n                u += 2;\n                break;\n            case ClassWriter.SHORT_INSN:\n            case ClassWriter.LDCW_INSN:\n            case ClassWriter.FIELDORMETH_INSN:\n            case ClassWriter.TYPE_INSN:\n            case ClassWriter.IINC_INSN:\n                newCode.putByteArray(b, u, 3);\n                u += 3;\n                break;\n            case ClassWriter.ITFMETH_INSN:\n            case ClassWriter.INDYMETH_INSN:\n                newCode.putByteArray(b, u, 5);\n                u += 5;\n                break;\n            // case MANA_INSN:\n            default:\n                newCode.putByteArray(b, u, 4);\n                u += 4;\n                break;\n            }\n        }\n\n        // updates the stack map frame labels\n        if (compute == FRAMES) {\n            Label l = labels;\n            while (l != null) {\n                /*\n                 * Detects the labels that are just after an IF instruction that\n                 * has been resized with the IFNOT GOTO_W pattern. These labels\n                 * are now the target of a jump instruction (the IFNOT\n                 * instruction). Note that we need the original label position\n                 * here. getNewOffset must therefore never have been called for\n                 * this label.\n                 */\n                u = l.position - 3;\n                if (u >= 0 && resize[u]) {\n                    l.status |= Label.TARGET;\n                }\n                getNewOffset(allIndexes, allSizes, l);\n                l = l.successor;\n            }\n            // Update the offsets in the uninitialized types\n            if (cw.typeTable != null) {\n                for (i = 0; i < cw.typeTable.length; ++i) {\n                    Item item = cw.typeTable[i];\n                    if (item != null && item.type == ClassWriter.TYPE_UNINIT) {\n                        item.intVal = getNewOffset(allIndexes, allSizes, 0,\n                                item.intVal);\n                    }\n                }\n            }\n            // The stack map frames are not serialized yet, so we don't need\n            // to update them. They will be serialized in visitMaxs.\n        } else if (frameCount > 0) {\n            /*\n             * Resizing an existing stack map frame table is really hard. Not\n             * only the table must be parsed to update the offets, but new\n             * frames may be needed for jump instructions that were inserted by\n             * this method. And updating the offsets or inserting frames can\n             * change the format of the following frames, in case of packed\n             * frames. In practice the whole table must be recomputed. For this\n             * the frames are marked as potentially invalid. This will cause the\n             * whole class to be reread and rewritten with the COMPUTE_FRAMES\n             * option (see the ClassWriter.toByteArray method). This is not very\n             * efficient but is much easier and requires much less code than any\n             * other method I can think of.\n             */\n            cw.invalidFrames = true;\n        }\n        // updates the exception handler block labels\n        Handler h = firstHandler;\n        while (h != null) {\n            getNewOffset(allIndexes, allSizes, h.start);\n            getNewOffset(allIndexes, allSizes, h.end);\n            getNewOffset(allIndexes, allSizes, h.handler);\n            h = h.next;\n        }\n        // updates the instructions addresses in the\n        // local var and line number tables\n        for (i = 0; i < 2; ++i) {\n            ByteVector bv = i == 0 ? localVar : localVarType;\n            if (bv != null) {\n                b = bv.data;\n                u = 0;\n                while (u < bv.length) {\n                    label = readUnsignedShort(b, u);\n                    newOffset = getNewOffset(allIndexes, allSizes, 0, label);\n                    writeShort(b, u, newOffset);\n                    label += readUnsignedShort(b, u + 2);\n                    newOffset = getNewOffset(allIndexes, allSizes, 0, label)\n                            - newOffset;\n                    writeShort(b, u + 2, newOffset);\n                    u += 10;\n                }\n            }\n        }\n        if (lineNumber != null) {\n            b = lineNumber.data;\n            u = 0;\n            while (u < lineNumber.length) {\n                writeShort(\n                        b,\n                        u,\n                        getNewOffset(allIndexes, allSizes, 0,\n                                readUnsignedShort(b, u)));\n                u += 4;\n            }\n        }\n        // updates the labels of the other attributes\n        Attribute attr = cattrs;\n        while (attr != null) {\n            Label[] labels = attr.getLabels();\n            if (labels != null) {\n                for (i = labels.length - 1; i >= 0; --i) {\n                    getNewOffset(allIndexes, allSizes, labels[i]);\n                }\n            }\n            attr = attr.next;\n        }\n\n        // replaces old bytecodes with new ones\n        code = newCode;\n    }\n\n    /**\n     * Reads an unsigned short value in the given byte array.\n     * \n     * @param b\n     *            a byte array.\n     * @param index\n     *            the start index of the value to be read.\n     * @return the read value.\n     */\n    static int readUnsignedShort(final byte[] b, final int index) {\n        return ((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF);\n    }\n\n    /**\n     * Reads a signed short value in the given byte array.\n     * \n     * @param b\n     *            a byte array.\n     * @param index\n     *            the start index of the value to be read.\n     * @return the read value.\n     */\n    static short readShort(final byte[] b, final int index) {\n        return (short) (((b[index] & 0xFF) << 8) | (b[index + 1] & 0xFF));\n    }\n\n    /**\n     * Reads a signed int value in the given byte array.\n     * \n     * @param b\n     *            a byte array.\n     * @param index\n     *            the start index of the value to be read.\n     * @return the read value.\n     */\n    static int readInt(final byte[] b, final int index) {\n        return ((b[index] & 0xFF) << 24) | ((b[index + 1] & 0xFF) << 16)\n                | ((b[index + 2] & 0xFF) << 8) | (b[index + 3] & 0xFF);\n    }\n\n    /**\n     * Writes a short value in the given byte array.\n     * \n     * @param b\n     *            a byte array.\n     * @param index\n     *            where the first byte of the short value must be written.\n     * @param s\n     *            the value to be written in the given byte array.\n     */\n    static void writeShort(final byte[] b, final int index, final int s) {\n        b[index] = (byte) (s >>> 8);\n        b[index + 1] = (byte) s;\n    }\n\n    /**\n     * Computes the future value of a bytecode offset.\n     * <p>\n     * Note: it is possible to have several entries for the same instruction in\n     * the <tt>indexes</tt> and <tt>sizes</tt>: two entries (index=a,size=b) and\n     * (index=a,size=b') are equivalent to a single entry (index=a,size=b+b').\n     * \n     * @param indexes\n     *            current positions of the instructions to be resized. Each\n     *            instruction must be designated by the index of its <i>last</i>\n     *            byte, plus one (or, in other words, by the index of the\n     *            <i>first</i> byte of the <i>next</i> instruction).\n     * @param sizes\n     *            the number of bytes to be <i>added</i> to the above\n     *            instructions. More precisely, for each i < <tt>len</tt>,\n     *            <tt>sizes</tt>[i] bytes will be added at the end of the\n     *            instruction designated by <tt>indexes</tt>[i] or, if\n     *            <tt>sizes</tt>[i] is negative, the <i>last</i> |\n     *            <tt>sizes[i]</tt>| bytes of the instruction will be removed\n     *            (the instruction size <i>must not</i> become negative or\n     *            null).\n     * @param begin\n     *            index of the first byte of the source instruction.\n     * @param end\n     *            index of the first byte of the target instruction.\n     * @return the future value of the given bytecode offset.\n     */\n    static int getNewOffset(final int[] indexes, final int[] sizes,\n            final int begin, final int end) {\n        int offset = end - begin;\n        for (int i = 0; i < indexes.length; ++i) {\n            if (begin < indexes[i] && indexes[i] <= end) {\n                // forward jump\n                offset += sizes[i];\n            } else if (end < indexes[i] && indexes[i] <= begin) {\n                // backward jump\n                offset -= sizes[i];\n            }\n        }\n        return offset;\n    }\n\n    /**\n     * Updates the offset of the given label.\n     * \n     * @param indexes\n     *            current positions of the instructions to be resized. Each\n     *            instruction must be designated by the index of its <i>last</i>\n     *            byte, plus one (or, in other words, by the index of the\n     *            <i>first</i> byte of the <i>next</i> instruction).\n     * @param sizes\n     *            the number of bytes to be <i>added</i> to the above\n     *            instructions. More precisely, for each i < <tt>len</tt>,\n     *            <tt>sizes</tt>[i] bytes will be added at the end of the\n     *            instruction designated by <tt>indexes</tt>[i] or, if\n     *            <tt>sizes</tt>[i] is negative, the <i>last</i> |\n     *            <tt>sizes[i]</tt>| bytes of the instruction will be removed\n     *            (the instruction size <i>must not</i> become negative or\n     *            null).\n     * @param label\n     *            the label whose offset must be updated.\n     */\n    static void getNewOffset(final int[] indexes, final int[] sizes,\n            final Label label) {\n        if ((label.status & Label.RESIZED) == 0) {\n            label.position = getNewOffset(indexes, sizes, 0, label.position);\n            label.status |= Label.RESIZED;\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Opcodes.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\n/**\n * Defines the JVM opcodes, access flags and array type codes. This interface\n * does not define all the JVM opcodes because some opcodes are automatically\n * handled. For example, the xLOAD and xSTORE opcodes are automatically replaced\n * by xLOAD_n and xSTORE_n opcodes when possible. The xLOAD_n and xSTORE_n\n * opcodes are therefore not defined in this interface. Likewise for LDC,\n * automatically replaced by LDC_W or LDC2_W when necessary, WIDE, GOTO_W and\n * JSR_W.\n * \n * @author Eric Bruneton\n * @author Eugene Kuleshov\n */\npublic interface Opcodes {\n\n    // ASM API versions\n\n    int ASM4 = 4 << 16 | 0 << 8 | 0;\n    int ASM5 = 5 << 16 | 0 << 8 | 0;\n\n    // versions\n\n    int V1_1 = 3 << 16 | 45;\n    int V1_2 = 0 << 16 | 46;\n    int V1_3 = 0 << 16 | 47;\n    int V1_4 = 0 << 16 | 48;\n    int V1_5 = 0 << 16 | 49;\n    int V1_6 = 0 << 16 | 50;\n    int V1_7 = 0 << 16 | 51;\n    int V1_8 = 0 << 16 | 52;\n\n    // access flags\n\n    int ACC_PUBLIC = 0x0001; // class, field, method\n    int ACC_PRIVATE = 0x0002; // class, field, method\n    int ACC_PROTECTED = 0x0004; // class, field, method\n    int ACC_STATIC = 0x0008; // field, method\n    int ACC_FINAL = 0x0010; // class, field, method, parameter\n    int ACC_SUPER = 0x0020; // class\n    int ACC_SYNCHRONIZED = 0x0020; // method\n    int ACC_VOLATILE = 0x0040; // field\n    int ACC_BRIDGE = 0x0040; // method\n    int ACC_VARARGS = 0x0080; // method\n    int ACC_TRANSIENT = 0x0080; // field\n    int ACC_NATIVE = 0x0100; // method\n    int ACC_INTERFACE = 0x0200; // class\n    int ACC_ABSTRACT = 0x0400; // class, method\n    int ACC_STRICT = 0x0800; // method\n    int ACC_SYNTHETIC = 0x1000; // class, field, method, parameter\n    int ACC_ANNOTATION = 0x2000; // class\n    int ACC_ENUM = 0x4000; // class(?) field inner\n    int ACC_MANDATED = 0x8000; // parameter\n\n    // ASM specific pseudo access flags\n\n    int ACC_DEPRECATED = 0x20000; // class, field, method\n\n    // types for NEWARRAY\n\n    int T_BOOLEAN = 4;\n    int T_CHAR = 5;\n    int T_FLOAT = 6;\n    int T_DOUBLE = 7;\n    int T_BYTE = 8;\n    int T_SHORT = 9;\n    int T_INT = 10;\n    int T_LONG = 11;\n\n    // tags for Handle\n\n    int H_GETFIELD = 1;\n    int H_GETSTATIC = 2;\n    int H_PUTFIELD = 3;\n    int H_PUTSTATIC = 4;\n    int H_INVOKEVIRTUAL = 5;\n    int H_INVOKESTATIC = 6;\n    int H_INVOKESPECIAL = 7;\n    int H_NEWINVOKESPECIAL = 8;\n    int H_INVOKEINTERFACE = 9;\n\n    // stack map frame types\n\n    /**\n     * Represents an expanded frame. See {@link ClassReader#EXPAND_FRAMES}.\n     */\n    int F_NEW = -1;\n\n    /**\n     * Represents a compressed frame with complete frame data.\n     */\n    int F_FULL = 0;\n\n    /**\n     * Represents a compressed frame where locals are the same as the locals in\n     * the previous frame, except that additional 1-3 locals are defined, and\n     * with an empty stack.\n     */\n    int F_APPEND = 1;\n\n    /**\n     * Represents a compressed frame where locals are the same as the locals in\n     * the previous frame, except that the last 1-3 locals are absent and with\n     * an empty stack.\n     */\n    int F_CHOP = 2;\n\n    /**\n     * Represents a compressed frame with exactly the same locals as the\n     * previous frame and with an empty stack.\n     */\n    int F_SAME = 3;\n\n    /**\n     * Represents a compressed frame with exactly the same locals as the\n     * previous frame and with a single value on the stack.\n     */\n    int F_SAME1 = 4;\n\n    // Do not try to change the following code to use auto-boxing,\n    // these values are compared by reference and not by value\n    // The constructor of Integer was deprecated in 9\n    // but we are stuck with it by backward compatibility\n    @SuppressWarnings(\"deprecation\") Integer TOP = new Integer(0);\n    @SuppressWarnings(\"deprecation\") Integer INTEGER = new Integer(1);\n    @SuppressWarnings(\"deprecation\") Integer FLOAT = new Integer(2);\n    @SuppressWarnings(\"deprecation\") Integer DOUBLE = new Integer(3);\n    @SuppressWarnings(\"deprecation\") Integer LONG = new Integer(4);\n    @SuppressWarnings(\"deprecation\") Integer NULL = new Integer(5);\n    @SuppressWarnings(\"deprecation\") Integer UNINITIALIZED_THIS = new Integer(6);\n\n    // opcodes // visit method (- = idem)\n\n    int NOP = 0; // visitInsn\n    int ACONST_NULL = 1; // -\n    int ICONST_M1 = 2; // -\n    int ICONST_0 = 3; // -\n    int ICONST_1 = 4; // -\n    int ICONST_2 = 5; // -\n    int ICONST_3 = 6; // -\n    int ICONST_4 = 7; // -\n    int ICONST_5 = 8; // -\n    int LCONST_0 = 9; // -\n    int LCONST_1 = 10; // -\n    int FCONST_0 = 11; // -\n    int FCONST_1 = 12; // -\n    int FCONST_2 = 13; // -\n    int DCONST_0 = 14; // -\n    int DCONST_1 = 15; // -\n    int BIPUSH = 16; // visitIntInsn\n    int SIPUSH = 17; // -\n    int LDC = 18; // visitLdcInsn\n    // int LDC_W = 19; // -\n    // int LDC2_W = 20; // -\n    int ILOAD = 21; // visitVarInsn\n    int LLOAD = 22; // -\n    int FLOAD = 23; // -\n    int DLOAD = 24; // -\n    int ALOAD = 25; // -\n    // int ILOAD_0 = 26; // -\n    // int ILOAD_1 = 27; // -\n    // int ILOAD_2 = 28; // -\n    // int ILOAD_3 = 29; // -\n    // int LLOAD_0 = 30; // -\n    // int LLOAD_1 = 31; // -\n    // int LLOAD_2 = 32; // -\n    // int LLOAD_3 = 33; // -\n    // int FLOAD_0 = 34; // -\n    // int FLOAD_1 = 35; // -\n    // int FLOAD_2 = 36; // -\n    // int FLOAD_3 = 37; // -\n    // int DLOAD_0 = 38; // -\n    // int DLOAD_1 = 39; // -\n    // int DLOAD_2 = 40; // -\n    // int DLOAD_3 = 41; // -\n    // int ALOAD_0 = 42; // -\n    // int ALOAD_1 = 43; // -\n    // int ALOAD_2 = 44; // -\n    // int ALOAD_3 = 45; // -\n    int IALOAD = 46; // visitInsn\n    int LALOAD = 47; // -\n    int FALOAD = 48; // -\n    int DALOAD = 49; // -\n    int AALOAD = 50; // -\n    int BALOAD = 51; // -\n    int CALOAD = 52; // -\n    int SALOAD = 53; // -\n    int ISTORE = 54; // visitVarInsn\n    int LSTORE = 55; // -\n    int FSTORE = 56; // -\n    int DSTORE = 57; // -\n    int ASTORE = 58; // -\n    // int ISTORE_0 = 59; // -\n    // int ISTORE_1 = 60; // -\n    // int ISTORE_2 = 61; // -\n    // int ISTORE_3 = 62; // -\n    // int LSTORE_0 = 63; // -\n    // int LSTORE_1 = 64; // -\n    // int LSTORE_2 = 65; // -\n    // int LSTORE_3 = 66; // -\n    // int FSTORE_0 = 67; // -\n    // int FSTORE_1 = 68; // -\n    // int FSTORE_2 = 69; // -\n    // int FSTORE_3 = 70; // -\n    // int DSTORE_0 = 71; // -\n    // int DSTORE_1 = 72; // -\n    // int DSTORE_2 = 73; // -\n    // int DSTORE_3 = 74; // -\n    // int ASTORE_0 = 75; // -\n    // int ASTORE_1 = 76; // -\n    // int ASTORE_2 = 77; // -\n    // int ASTORE_3 = 78; // -\n    int IASTORE = 79; // visitInsn\n    int LASTORE = 80; // -\n    int FASTORE = 81; // -\n    int DASTORE = 82; // -\n    int AASTORE = 83; // -\n    int BASTORE = 84; // -\n    int CASTORE = 85; // -\n    int SASTORE = 86; // -\n    int POP = 87; // -\n    int POP2 = 88; // -\n    int DUP = 89; // -\n    int DUP_X1 = 90; // -\n    int DUP_X2 = 91; // -\n    int DUP2 = 92; // -\n    int DUP2_X1 = 93; // -\n    int DUP2_X2 = 94; // -\n    int SWAP = 95; // -\n    int IADD = 96; // -\n    int LADD = 97; // -\n    int FADD = 98; // -\n    int DADD = 99; // -\n    int ISUB = 100; // -\n    int LSUB = 101; // -\n    int FSUB = 102; // -\n    int DSUB = 103; // -\n    int IMUL = 104; // -\n    int LMUL = 105; // -\n    int FMUL = 106; // -\n    int DMUL = 107; // -\n    int IDIV = 108; // -\n    int LDIV = 109; // -\n    int FDIV = 110; // -\n    int DDIV = 111; // -\n    int IREM = 112; // -\n    int LREM = 113; // -\n    int FREM = 114; // -\n    int DREM = 115; // -\n    int INEG = 116; // -\n    int LNEG = 117; // -\n    int FNEG = 118; // -\n    int DNEG = 119; // -\n    int ISHL = 120; // -\n    int LSHL = 121; // -\n    int ISHR = 122; // -\n    int LSHR = 123; // -\n    int IUSHR = 124; // -\n    int LUSHR = 125; // -\n    int IAND = 126; // -\n    int LAND = 127; // -\n    int IOR = 128; // -\n    int LOR = 129; // -\n    int IXOR = 130; // -\n    int LXOR = 131; // -\n    int IINC = 132; // visitIincInsn\n    int I2L = 133; // visitInsn\n    int I2F = 134; // -\n    int I2D = 135; // -\n    int L2I = 136; // -\n    int L2F = 137; // -\n    int L2D = 138; // -\n    int F2I = 139; // -\n    int F2L = 140; // -\n    int F2D = 141; // -\n    int D2I = 142; // -\n    int D2L = 143; // -\n    int D2F = 144; // -\n    int I2B = 145; // -\n    int I2C = 146; // -\n    int I2S = 147; // -\n    int LCMP = 148; // -\n    int FCMPL = 149; // -\n    int FCMPG = 150; // -\n    int DCMPL = 151; // -\n    int DCMPG = 152; // -\n    int IFEQ = 153; // visitJumpInsn\n    int IFNE = 154; // -\n    int IFLT = 155; // -\n    int IFGE = 156; // -\n    int IFGT = 157; // -\n    int IFLE = 158; // -\n    int IF_ICMPEQ = 159; // -\n    int IF_ICMPNE = 160; // -\n    int IF_ICMPLT = 161; // -\n    int IF_ICMPGE = 162; // -\n    int IF_ICMPGT = 163; // -\n    int IF_ICMPLE = 164; // -\n    int IF_ACMPEQ = 165; // -\n    int IF_ACMPNE = 166; // -\n    int GOTO = 167; // -\n    int JSR = 168; // -\n    int RET = 169; // visitVarInsn\n    int TABLESWITCH = 170; // visiTableSwitchInsn\n    int LOOKUPSWITCH = 171; // visitLookupSwitch\n    int IRETURN = 172; // visitInsn\n    int LRETURN = 173; // -\n    int FRETURN = 174; // -\n    int DRETURN = 175; // -\n    int ARETURN = 176; // -\n    int RETURN = 177; // -\n    int GETSTATIC = 178; // visitFieldInsn\n    int PUTSTATIC = 179; // -\n    int GETFIELD = 180; // -\n    int PUTFIELD = 181; // -\n    int INVOKEVIRTUAL = 182; // visitMethodInsn\n    int INVOKESPECIAL = 183; // -\n    int INVOKESTATIC = 184; // -\n    int INVOKEINTERFACE = 185; // -\n    int INVOKEDYNAMIC = 186; // visitInvokeDynamicInsn\n    int NEW = 187; // visitTypeInsn\n    int NEWARRAY = 188; // visitIntInsn\n    int ANEWARRAY = 189; // visitTypeInsn\n    int ARRAYLENGTH = 190; // visitInsn\n    int ATHROW = 191; // -\n    int CHECKCAST = 192; // visitTypeInsn\n    int INSTANCEOF = 193; // -\n    int MONITORENTER = 194; // visitInsn\n    int MONITOREXIT = 195; // -\n    // int WIDE = 196; // NOT VISITED\n    int MULTIANEWARRAY = 197; // visitMultiANewArrayInsn\n    int IFNULL = 198; // visitJumpInsn\n    int IFNONNULL = 199; // -\n    // int GOTO_W = 200; // -\n    // int JSR_W = 201; // -\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/Type.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm;\n\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Method;\n\n/**\n * A Java field or method type. This class can be used to make it easier to\n * manipulate type and method descriptors.\n * \n * @author Eric Bruneton\n * @author Chris Nokleberg\n */\npublic class Type {\n\n    /**\n     * The sort of the <tt>void</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int VOID = 0;\n\n    /**\n     * The sort of the <tt>boolean</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int BOOLEAN = 1;\n\n    /**\n     * The sort of the <tt>char</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int CHAR = 2;\n\n    /**\n     * The sort of the <tt>byte</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int BYTE = 3;\n\n    /**\n     * The sort of the <tt>short</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int SHORT = 4;\n\n    /**\n     * The sort of the <tt>int</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int INT = 5;\n\n    /**\n     * The sort of the <tt>float</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int FLOAT = 6;\n\n    /**\n     * The sort of the <tt>long</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int LONG = 7;\n\n    /**\n     * The sort of the <tt>double</tt> type. See {@link #getSort getSort}.\n     */\n    public static final int DOUBLE = 8;\n\n    /**\n     * The sort of array reference types. See {@link #getSort getSort}.\n     */\n    public static final int ARRAY = 9;\n\n    /**\n     * The sort of object reference types. See {@link #getSort getSort}.\n     */\n    public static final int OBJECT = 10;\n\n    /**\n     * The sort of method types. See {@link #getSort getSort}.\n     */\n    public static final int METHOD = 11;\n\n    /**\n     * The <tt>void</tt> type.\n     */\n    public static final Type VOID_TYPE = new Type(VOID, null, ('V' << 24)\n            | (5 << 16) | (0 << 8) | 0, 1);\n\n    /**\n     * The <tt>boolean</tt> type.\n     */\n    public static final Type BOOLEAN_TYPE = new Type(BOOLEAN, null, ('Z' << 24)\n            | (0 << 16) | (5 << 8) | 1, 1);\n\n    /**\n     * The <tt>char</tt> type.\n     */\n    public static final Type CHAR_TYPE = new Type(CHAR, null, ('C' << 24)\n            | (0 << 16) | (6 << 8) | 1, 1);\n\n    /**\n     * The <tt>byte</tt> type.\n     */\n    public static final Type BYTE_TYPE = new Type(BYTE, null, ('B' << 24)\n            | (0 << 16) | (5 << 8) | 1, 1);\n\n    /**\n     * The <tt>short</tt> type.\n     */\n    public static final Type SHORT_TYPE = new Type(SHORT, null, ('S' << 24)\n            | (0 << 16) | (7 << 8) | 1, 1);\n\n    /**\n     * The <tt>int</tt> type.\n     */\n    public static final Type INT_TYPE = new Type(INT, null, ('I' << 24)\n            | (0 << 16) | (0 << 8) | 1, 1);\n\n    /**\n     * The <tt>float</tt> type.\n     */\n    public static final Type FLOAT_TYPE = new Type(FLOAT, null, ('F' << 24)\n            | (2 << 16) | (2 << 8) | 1, 1);\n\n    /**\n     * The <tt>long</tt> type.\n     */\n    public static final Type LONG_TYPE = new Type(LONG, null, ('J' << 24)\n            | (1 << 16) | (1 << 8) | 2, 1);\n\n    /**\n     * The <tt>double</tt> type.\n     */\n    public static final Type DOUBLE_TYPE = new Type(DOUBLE, null, ('D' << 24)\n            | (3 << 16) | (3 << 8) | 2, 1);\n\n    // ------------------------------------------------------------------------\n    // Fields\n    // ------------------------------------------------------------------------\n\n    /**\n     * The sort of this Java type.\n     */\n    private final int sort;\n\n    /**\n     * A buffer containing the internal name of this Java type. This field is\n     * only used for reference types.\n     */\n    private final char[] buf;\n\n    /**\n     * The offset of the internal name of this Java type in {@link #buf buf} or,\n     * for primitive types, the size, descriptor and getOpcode offsets for this\n     * type (byte 0 contains the size, byte 1 the descriptor, byte 2 the offset\n     * for IALOAD or IASTORE, byte 3 the offset for all other instructions).\n     */\n    private final int off;\n\n    /**\n     * The length of the internal name of this Java type.\n     */\n    private final int len;\n\n    // ------------------------------------------------------------------------\n    // Constructors\n    // ------------------------------------------------------------------------\n\n    /**\n     * Constructs a reference type.\n     * \n     * @param sort\n     *            the sort of the reference type to be constructed.\n     * @param buf\n     *            a buffer containing the descriptor of the previous type.\n     * @param off\n     *            the offset of this descriptor in the previous buffer.\n     * @param len\n     *            the length of this descriptor.\n     */\n    private Type(final int sort, final char[] buf, final int off, final int len) {\n        this.sort = sort;\n        this.buf = buf;\n        this.off = off;\n        this.len = len;\n    }\n\n    /**\n     * Returns the Java type corresponding to the given type descriptor.\n     * \n     * @param typeDescriptor\n     *            a field or method type descriptor.\n     * @return the Java type corresponding to the given type descriptor.\n     */\n    public static Type getType(final String typeDescriptor) {\n        return getType(typeDescriptor.toCharArray(), 0);\n    }\n\n    /**\n     * Returns the Java type corresponding to the given internal name.\n     * \n     * @param internalName\n     *            an internal name.\n     * @return the Java type corresponding to the given internal name.\n     */\n    public static Type getObjectType(final String internalName) {\n        char[] buf = internalName.toCharArray();\n        return new Type(buf[0] == '[' ? ARRAY : OBJECT, buf, 0, buf.length);\n    }\n\n    /**\n     * Returns the Java type corresponding to the given method descriptor.\n     * Equivalent to <code>Type.getType(methodDescriptor)</code>.\n     * \n     * @param methodDescriptor\n     *            a method descriptor.\n     * @return the Java type corresponding to the given method descriptor.\n     */\n    public static Type getMethodType(final String methodDescriptor) {\n        return getType(methodDescriptor.toCharArray(), 0);\n    }\n\n    /**\n     * Returns the Java method type corresponding to the given argument and\n     * return types.\n     * \n     * @param returnType\n     *            the return type of the method.\n     * @param argumentTypes\n     *            the argument types of the method.\n     * @return the Java type corresponding to the given argument and return\n     *         types.\n     */\n    public static Type getMethodType(final Type returnType,\n            final Type... argumentTypes) {\n        return getType(getMethodDescriptor(returnType, argumentTypes));\n    }\n\n    /**\n     * Returns the Java type corresponding to the given class.\n     * \n     * @param c\n     *            a class.\n     * @return the Java type corresponding to the given class.\n     */\n    public static Type getType(final Class<?> c) {\n        if (c.isPrimitive()) {\n            if (c == Integer.TYPE) {\n                return INT_TYPE;\n            } else if (c == Void.TYPE) {\n                return VOID_TYPE;\n            } else if (c == Boolean.TYPE) {\n                return BOOLEAN_TYPE;\n            } else if (c == Byte.TYPE) {\n                return BYTE_TYPE;\n            } else if (c == Character.TYPE) {\n                return CHAR_TYPE;\n            } else if (c == Short.TYPE) {\n                return SHORT_TYPE;\n            } else if (c == Double.TYPE) {\n                return DOUBLE_TYPE;\n            } else if (c == Float.TYPE) {\n                return FLOAT_TYPE;\n            } else /* if (c == Long.TYPE) */{\n                return LONG_TYPE;\n            }\n        } else {\n            return getType(getDescriptor(c));\n        }\n    }\n\n    /**\n     * Returns the Java method type corresponding to the given constructor.\n     * \n     * @param c\n     *            a {@link Constructor Constructor} object.\n     * @return the Java method type corresponding to the given constructor.\n     */\n    public static Type getType(final Constructor<?> c) {\n        return getType(getConstructorDescriptor(c));\n    }\n\n    /**\n     * Returns the Java method type corresponding to the given method.\n     * \n     * @param m\n     *            a {@link Method Method} object.\n     * @return the Java method type corresponding to the given method.\n     */\n    public static Type getType(final Method m) {\n        return getType(getMethodDescriptor(m));\n    }\n\n    /**\n     * Returns the Java types corresponding to the argument types of the given\n     * method descriptor.\n     * \n     * @param methodDescriptor\n     *            a method descriptor.\n     * @return the Java types corresponding to the argument types of the given\n     *         method descriptor.\n     */\n    public static Type[] getArgumentTypes(final String methodDescriptor) {\n        char[] buf = methodDescriptor.toCharArray();\n        int off = 1;\n        int size = 0;\n        while (true) {\n            char car = buf[off++];\n            if (car == ')') {\n                break;\n            } else if (car == 'L') {\n                while (buf[off++] != ';') {\n                }\n                ++size;\n            } else if (car != '[') {\n                ++size;\n            }\n        }\n        Type[] args = new Type[size];\n        off = 1;\n        size = 0;\n        while (buf[off] != ')') {\n            args[size] = getType(buf, off);\n            off += args[size].len + (args[size].sort == OBJECT ? 2 : 0);\n            size += 1;\n        }\n        return args;\n    }\n\n    /**\n     * Returns the Java types corresponding to the argument types of the given\n     * method.\n     * \n     * @param method\n     *            a method.\n     * @return the Java types corresponding to the argument types of the given\n     *         method.\n     */\n    public static Type[] getArgumentTypes(final Method method) {\n        Class<?>[] classes = method.getParameterTypes();\n        Type[] types = new Type[classes.length];\n        for (int i = classes.length - 1; i >= 0; --i) {\n            types[i] = getType(classes[i]);\n        }\n        return types;\n    }\n\n    /**\n     * Returns the Java type corresponding to the return type of the given\n     * method descriptor.\n     * \n     * @param methodDescriptor\n     *            a method descriptor.\n     * @return the Java type corresponding to the return type of the given\n     *         method descriptor.\n     */\n    public static Type getReturnType(final String methodDescriptor) {\n        char[] buf = methodDescriptor.toCharArray();\n        int off = 1;\n        while (true) {\n            char car = buf[off++];\n            if (car == ')') {\n                return getType(buf, off);\n            } else if (car == 'L') {\n                while (buf[off++] != ';') {\n                }\n            }\n        }\n    }\n\n    /**\n     * Returns the Java type corresponding to the return type of the given\n     * method.\n     * \n     * @param method\n     *            a method.\n     * @return the Java type corresponding to the return type of the given\n     *         method.\n     */\n    public static Type getReturnType(final Method method) {\n        return getType(method.getReturnType());\n    }\n\n    /**\n     * Computes the size of the arguments and of the return value of a method.\n     * \n     * @param desc\n     *            the descriptor of a method.\n     * @return the size of the arguments of the method (plus one for the\n     *         implicit this argument), argSize, and the size of its return\n     *         value, retSize, packed into a single int i =\n     *         <tt>(argSize &lt;&lt; 2) | retSize</tt> (argSize is therefore equal to\n     *         <tt>i &gt;&gt; 2</tt>, and retSize to <tt>i &amp; 0x03</tt>).\n     */\n    public static int getArgumentsAndReturnSizes(final String desc) {\n        int n = 1;\n        int c = 1;\n        while (true) {\n            char car = desc.charAt(c++);\n            if (car == ')') {\n                car = desc.charAt(c);\n                return n << 2\n                        | (car == 'V' ? 0 : (car == 'D' || car == 'J' ? 2 : 1));\n            } else if (car == 'L') {\n                while (desc.charAt(c++) != ';') {\n                }\n                n += 1;\n            } else if (car == '[') {\n                while ((car = desc.charAt(c)) == '[') {\n                    ++c;\n                }\n                if (car == 'D' || car == 'J') {\n                    n -= 1;\n                }\n            } else if (car == 'D' || car == 'J') {\n                n += 2;\n            } else {\n                n += 1;\n            }\n        }\n    }\n\n    /**\n     * Returns the Java type corresponding to the given type descriptor. For\n     * method descriptors, buf is supposed to contain nothing more than the\n     * descriptor itself.\n     * \n     * @param buf\n     *            a buffer containing a type descriptor.\n     * @param off\n     *            the offset of this descriptor in the previous buffer.\n     * @return the Java type corresponding to the given type descriptor.\n     */\n    private static Type getType(final char[] buf, final int off) {\n        int len;\n        switch (buf[off]) {\n        case 'V':\n            return VOID_TYPE;\n        case 'Z':\n            return BOOLEAN_TYPE;\n        case 'C':\n            return CHAR_TYPE;\n        case 'B':\n            return BYTE_TYPE;\n        case 'S':\n            return SHORT_TYPE;\n        case 'I':\n            return INT_TYPE;\n        case 'F':\n            return FLOAT_TYPE;\n        case 'J':\n            return LONG_TYPE;\n        case 'D':\n            return DOUBLE_TYPE;\n        case '[':\n            len = 1;\n            while (buf[off + len] == '[') {\n                ++len;\n            }\n            if (buf[off + len] == 'L') {\n                ++len;\n                while (buf[off + len] != ';') {\n                    ++len;\n                }\n            }\n            return new Type(ARRAY, buf, off, len + 1);\n        case 'L':\n            len = 1;\n            while (buf[off + len] != ';') {\n                ++len;\n            }\n            return new Type(OBJECT, buf, off + 1, len - 1);\n            // case '(':\n        default:\n            return new Type(METHOD, buf, off, buf.length - off);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Accessors\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the sort of this Java type.\n     * \n     * @return {@link #VOID VOID}, {@link #BOOLEAN BOOLEAN}, {@link #CHAR CHAR},\n     *         {@link #BYTE BYTE}, {@link #SHORT SHORT}, {@link #INT INT},\n     *         {@link #FLOAT FLOAT}, {@link #LONG LONG}, {@link #DOUBLE DOUBLE},\n     *         {@link #ARRAY ARRAY}, {@link #OBJECT OBJECT} or {@link #METHOD\n     *         METHOD}.\n     */\n    public int getSort() {\n        return sort;\n    }\n\n    /**\n     * Returns the number of dimensions of this array type. This method should\n     * only be used for an array type.\n     * \n     * @return the number of dimensions of this array type.\n     */\n    public int getDimensions() {\n        int i = 1;\n        while (buf[off + i] == '[') {\n            ++i;\n        }\n        return i;\n    }\n\n    /**\n     * Returns the type of the elements of this array type. This method should\n     * only be used for an array type.\n     * \n     * @return Returns the type of the elements of this array type.\n     */\n    public Type getElementType() {\n        return getType(buf, off + getDimensions());\n    }\n\n    /**\n     * Returns the binary name of the class corresponding to this type. This\n     * method must not be used on method types.\n     * \n     * @return the binary name of the class corresponding to this type.\n     */\n    public String getClassName() {\n        switch (sort) {\n        case VOID:\n            return \"void\";\n        case BOOLEAN:\n            return \"boolean\";\n        case CHAR:\n            return \"char\";\n        case BYTE:\n            return \"byte\";\n        case SHORT:\n            return \"short\";\n        case INT:\n            return \"int\";\n        case FLOAT:\n            return \"float\";\n        case LONG:\n            return \"long\";\n        case DOUBLE:\n            return \"double\";\n        case ARRAY:\n            StringBuilder sb = new StringBuilder(getElementType().getClassName());\n            for (int i = getDimensions(); i > 0; --i) {\n                sb.append(\"[]\");\n            }\n            return sb.toString();\n        case OBJECT:\n            return new String(buf, off, len).replace('/', '.');\n        default:\n            return null;\n        }\n    }\n\n    /**\n     * Returns the internal name of the class corresponding to this object or\n     * array type. The internal name of a class is its fully qualified name (as\n     * returned by Class.getName(), where '.' are replaced by '/'. This method\n     * should only be used for an object or array type.\n     * \n     * @return the internal name of the class corresponding to this object type.\n     */\n    public String getInternalName() {\n        return new String(buf, off, len);\n    }\n\n    /**\n     * Returns the argument types of methods of this type. This method should\n     * only be used for method types.\n     * \n     * @return the argument types of methods of this type.\n     */\n    public Type[] getArgumentTypes() {\n        return getArgumentTypes(getDescriptor());\n    }\n\n    /**\n     * Returns the return type of methods of this type. This method should only\n     * be used for method types.\n     * \n     * @return the return type of methods of this type.\n     */\n    public Type getReturnType() {\n        return getReturnType(getDescriptor());\n    }\n\n    /**\n     * Returns the size of the arguments and of the return value of methods of\n     * this type. This method should only be used for method types.\n     * \n     * @return the size of the arguments (plus one for the implicit this\n     *         argument), argSize, and the size of the return value, retSize,\n     *         packed into a single\n     *         int i = <tt>(argSize &lt;&lt; 2) | retSize</tt>\n     *         (argSize is therefore equal to <tt>i &gt;&gt; 2</tt>,\n     *         and retSize to <tt>i &amp; 0x03</tt>).\n     */\n    public int getArgumentsAndReturnSizes() {\n        return getArgumentsAndReturnSizes(getDescriptor());\n    }\n\n    // ------------------------------------------------------------------------\n    // Conversion to type descriptors\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the descriptor corresponding to this Java type.\n     * \n     * @return the descriptor corresponding to this Java type.\n     */\n    public String getDescriptor() {\n        StringBuilder buf = new StringBuilder();\n        getDescriptor(buf);\n        return buf.toString();\n    }\n\n    /**\n     * Returns the descriptor corresponding to the given argument and return\n     * types.\n     * \n     * @param returnType\n     *            the return type of the method.\n     * @param argumentTypes\n     *            the argument types of the method.\n     * @return the descriptor corresponding to the given argument and return\n     *         types.\n     */\n    public static String getMethodDescriptor(final Type returnType,\n            final Type... argumentTypes) {\n        StringBuilder buf = new StringBuilder();\n        buf.append('(');\n        for (int i = 0; i < argumentTypes.length; ++i) {\n            argumentTypes[i].getDescriptor(buf);\n        }\n        buf.append(')');\n        returnType.getDescriptor(buf);\n        return buf.toString();\n    }\n\n    /**\n     * Appends the descriptor corresponding to this Java type to the given\n     * string buffer.\n     * \n     * @param buf\n     *            the string buffer to which the descriptor must be appended.\n     */\n    private void getDescriptor(final StringBuilder buf) {\n        if (this.buf == null) {\n            // descriptor is in byte 3 of 'off' for primitive types (buf ==\n            // null)\n            buf.append((char) ((off & 0xFF000000) >>> 24));\n        } else if (sort == OBJECT) {\n            buf.append('L');\n            buf.append(this.buf, off, len);\n            buf.append(';');\n        } else { // sort == ARRAY || sort == METHOD\n            buf.append(this.buf, off, len);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Direct conversion from classes to type descriptors,\n    // without intermediate Type objects\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the internal name of the given class. The internal name of a\n     * class is its fully qualified name, as returned by Class.getName(), where\n     * '.' are replaced by '/'.\n     * \n     * @param c\n     *            an object or array class.\n     * @return the internal name of the given class.\n     */\n    public static String getInternalName(final Class<?> c) {\n        return c.getName().replace('.', '/');\n    }\n\n    /**\n     * Returns the descriptor corresponding to the given Java type.\n     * \n     * @param c\n     *            an object class, a primitive class or an array class.\n     * @return the descriptor corresponding to the given class.\n     */\n    public static String getDescriptor(final Class<?> c) {\n        StringBuilder buf = new StringBuilder();\n        getDescriptor(buf, c);\n        return buf.toString();\n    }\n\n    /**\n     * Returns the descriptor corresponding to the given constructor.\n     * \n     * @param c\n     *            a {@link Constructor Constructor} object.\n     * @return the descriptor of the given constructor.\n     */\n    public static String getConstructorDescriptor(final Constructor<?> c) {\n        Class<?>[] parameters = c.getParameterTypes();\n        StringBuilder buf = new StringBuilder();\n        buf.append('(');\n        for (int i = 0; i < parameters.length; ++i) {\n            getDescriptor(buf, parameters[i]);\n        }\n        return buf.append(\")V\").toString();\n    }\n\n    /**\n     * Returns the descriptor corresponding to the given method.\n     * \n     * @param m\n     *            a {@link Method Method} object.\n     * @return the descriptor of the given method.\n     */\n    public static String getMethodDescriptor(final Method m) {\n        Class<?>[] parameters = m.getParameterTypes();\n        StringBuilder buf = new StringBuilder();\n        buf.append('(');\n        for (int i = 0; i < parameters.length; ++i) {\n            getDescriptor(buf, parameters[i]);\n        }\n        buf.append(')');\n        getDescriptor(buf, m.getReturnType());\n        return buf.toString();\n    }\n\n    /**\n     * Appends the descriptor of the given class to the given string buffer.\n     * \n     * @param buf\n     *            the string buffer to which the descriptor must be appended.\n     * @param c\n     *            the class whose descriptor must be computed.\n     */\n    private static void getDescriptor(final StringBuilder buf, final Class<?> c) {\n        Class<?> d = c;\n        while (true) {\n            if (d.isPrimitive()) {\n                char car;\n                if (d == Integer.TYPE) {\n                    car = 'I';\n                } else if (d == Void.TYPE) {\n                    car = 'V';\n                } else if (d == Boolean.TYPE) {\n                    car = 'Z';\n                } else if (d == Byte.TYPE) {\n                    car = 'B';\n                } else if (d == Character.TYPE) {\n                    car = 'C';\n                } else if (d == Short.TYPE) {\n                    car = 'S';\n                } else if (d == Double.TYPE) {\n                    car = 'D';\n                } else if (d == Float.TYPE) {\n                    car = 'F';\n                } else /* if (d == Long.TYPE) */{\n                    car = 'J';\n                }\n                buf.append(car);\n                return;\n            } else if (d.isArray()) {\n                buf.append('[');\n                d = d.getComponentType();\n            } else {\n                buf.append('L');\n                String name = d.getName();\n                int len = name.length();\n                for (int i = 0; i < len; ++i) {\n                    char car = name.charAt(i);\n                    buf.append(car == '.' ? '/' : car);\n                }\n                buf.append(';');\n                return;\n            }\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Corresponding size and opcodes\n    // ------------------------------------------------------------------------\n\n    /**\n     * Returns the size of values of this type. This method must not be used for\n     * method types.\n     * \n     * @return the size of values of this type, i.e., 2 for <tt>long</tt> and\n     *         <tt>double</tt>, 0 for <tt>void</tt> and 1 otherwise.\n     */\n    public int getSize() {\n        // the size is in byte 0 of 'off' for primitive types (buf == null)\n        return buf == null ? (off & 0xFF) : 1;\n    }\n\n    /**\n     * Returns a JVM instruction opcode adapted to this Java type. This method\n     * must not be used for method types.\n     * \n     * @param opcode\n     *            a JVM instruction opcode. This opcode must be one of ILOAD,\n     *            ISTORE, IALOAD, IASTORE, IADD, ISUB, IMUL, IDIV, IREM, INEG,\n     *            ISHL, ISHR, IUSHR, IAND, IOR, IXOR and IRETURN.\n     * @return an opcode that is similar to the given opcode, but adapted to\n     *         this Java type. For example, if this type is <tt>float</tt> and\n     *         <tt>opcode</tt> is IRETURN, this method returns FRETURN.\n     */\n    public int getOpcode(final int opcode) {\n        if (opcode == Opcodes.IALOAD || opcode == Opcodes.IASTORE) {\n            // the offset for IALOAD or IASTORE is in byte 1 of 'off' for\n            // primitive types (buf == null)\n            return opcode + (buf == null ? (off & 0xFF00) >> 8 : 4);\n        } else {\n            // the offset for other instructions is in byte 2 of 'off' for\n            // primitive types (buf == null)\n            return opcode + (buf == null ? (off & 0xFF0000) >> 16 : 4);\n        }\n    }\n\n    // ------------------------------------------------------------------------\n    // Equals, hashCode and toString\n    // ------------------------------------------------------------------------\n\n    /**\n     * Tests if the given object is equal to this type.\n     * \n     * @param o\n     *            the object to be compared to this type.\n     * @return <tt>true</tt> if the given object is equal to this type.\n     */\n    @Override\n    public boolean equals(final Object o) {\n        if (this == o) {\n            return true;\n        }\n        if (!(o instanceof Type)) {\n            return false;\n        }\n        Type t = (Type) o;\n        if (sort != t.sort) {\n            return false;\n        }\n        if (sort >= ARRAY) {\n            if (len != t.len) {\n                return false;\n            }\n            for (int i = off, j = t.off, end = i + len; i < end; i++, j++) {\n                if (buf[i] != t.buf[j]) {\n                    return false;\n                }\n            }\n        }\n        return true;\n    }\n\n    /**\n     * Returns a hash code value for this type.\n     * \n     * @return a hash code value for this type.\n     */\n    @Override\n    public int hashCode() {\n        int hc = 13 * sort;\n        if (sort >= ARRAY) {\n            for (int i = off, end = i + len; i < end; i++) {\n                hc = 17 * (hc + buf[i]);\n            }\n        }\n        return hc;\n    }\n\n    /**\n     * Returns a string representation of this type.\n     * \n     * @return the descriptor of this type.\n     */\n    @Override\n    public String toString() {\n        return getDescriptor();\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/TypePath.java",
    "content": "/***\r\n * ASM: a very small and fast Java bytecode manipulation framework\r\n * Copyright (c) 2000-2013 INRIA, France Telecom\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without\r\n * modification, are permitted provided that the following conditions\r\n * are met:\r\n * 1. Redistributions of source code must retain the above copyright\r\n *    notice, this list of conditions and the following disclaimer.\r\n * 2. Redistributions in binary form must reproduce the above copyright\r\n *    notice, this list of conditions and the following disclaimer in the\r\n *    documentation and/or other materials provided with the distribution.\r\n * 3. Neither the name of the copyright holders nor the names of its\r\n *    contributors may be used to endorse or promote products derived from\r\n *    this software without specific prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\r\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r\n * THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\npackage lt.dependencies.asm;\r\n\r\n/**\r\n * The path to a type argument, wildcard bound, array element type, or static\r\n * inner type within an enclosing type.\r\n * \r\n * @author Eric Bruneton\r\n */\r\npublic class TypePath {\r\n\r\n    /**\r\n     * A type path step that steps into the element type of an array type. See\r\n     * {@link #getStep getStep}.\r\n     */\r\n    public final static int ARRAY_ELEMENT = 0;\r\n\r\n    /**\r\n     * A type path step that steps into the nested type of a class type. See\r\n     * {@link #getStep getStep}.\r\n     */\r\n    public final static int INNER_TYPE = 1;\r\n\r\n    /**\r\n     * A type path step that steps into the bound of a wildcard type. See\r\n     * {@link #getStep getStep}.\r\n     */\r\n    public final static int WILDCARD_BOUND = 2;\r\n\r\n    /**\r\n     * A type path step that steps into a type argument of a generic type. See\r\n     * {@link #getStep getStep}.\r\n     */\r\n    public final static int TYPE_ARGUMENT = 3;\r\n\r\n    /**\r\n     * The byte array where the path is stored, in Java class file format.\r\n     */\r\n    byte[] b;\r\n\r\n    /**\r\n     * The offset of the first byte of the type path in 'b'.\r\n     */\r\n    int offset;\r\n\r\n    /**\r\n     * Creates a new type path.\r\n     * \r\n     * @param b\r\n     *            the byte array containing the type path in Java class file\r\n     *            format.\r\n     * @param offset\r\n     *            the offset of the first byte of the type path in 'b'.\r\n     */\r\n    TypePath(byte[] b, int offset) {\r\n        this.b = b;\r\n        this.offset = offset;\r\n    }\r\n\r\n    /**\r\n     * Returns the length of this path.\r\n     * \r\n     * @return the length of this path.\r\n     */\r\n    public int getLength() {\r\n        return b[offset];\r\n    }\r\n\r\n    /**\r\n     * Returns the value of the given step of this path.\r\n     * \r\n     * @param index\r\n     *            an index between 0 and {@link #getLength()}, exclusive.\r\n     * @return {@link #ARRAY_ELEMENT ARRAY_ELEMENT}, {@link #INNER_TYPE\r\n     *         INNER_TYPE}, {@link #WILDCARD_BOUND WILDCARD_BOUND}, or\r\n     *         {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.\r\n     */\r\n    public int getStep(int index) {\r\n        return b[offset + 2 * index + 1];\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the type argument that the given step is stepping\r\n     * into. This method should only be used for steps whose value is\r\n     * {@link #TYPE_ARGUMENT TYPE_ARGUMENT}.\r\n     * \r\n     * @param index\r\n     *            an index between 0 and {@link #getLength()}, exclusive.\r\n     * @return the index of the type argument that the given step is stepping\r\n     *         into.\r\n     */\r\n    public int getStepArgument(int index) {\r\n        return b[offset + 2 * index + 2];\r\n    }\r\n\r\n    /**\r\n     * Converts a type path in string form, in the format used by\r\n     * {@link #toString()}, into a TypePath object.\r\n     * \r\n     * @param typePath\r\n     *            a type path in string form, in the format used by\r\n     *            {@link #toString()}. May be null or empty.\r\n     * @return the corresponding TypePath object, or null if the path is empty.\r\n     */\r\n    public static TypePath fromString(final String typePath) {\r\n        if (typePath == null || typePath.length() == 0) {\r\n            return null;\r\n        }\r\n        int n = typePath.length();\r\n        ByteVector out = new ByteVector(n);\r\n        out.putByte(0);\r\n        for (int i = 0; i < n;) {\r\n            char c = typePath.charAt(i++);\r\n            if (c == '[') {\r\n                out.put11(ARRAY_ELEMENT, 0);\r\n            } else if (c == '.') {\r\n                out.put11(INNER_TYPE, 0);\r\n            } else if (c == '*') {\r\n                out.put11(WILDCARD_BOUND, 0);\r\n            } else if (c >= '0' && c <= '9') {\r\n                int typeArg = c - '0';\r\n                while (i < n && (c = typePath.charAt(i)) >= '0' && c <= '9') {\r\n                    typeArg = typeArg * 10 + c - '0';\r\n                    i += 1;\r\n                }\r\n                if (i < n && typePath.charAt(i) == ';') {\r\n                    i += 1;\r\n                }\r\n                out.put11(TYPE_ARGUMENT, typeArg);\r\n            }\r\n        }\r\n        out.data[0] = (byte) (out.length / 2);\r\n        return new TypePath(out.data, 0);\r\n    }\r\n\r\n    /**\r\n     * Returns a string representation of this type path. {@link #ARRAY_ELEMENT\r\n     * ARRAY_ELEMENT} steps are represented with '[', {@link #INNER_TYPE\r\n     * INNER_TYPE} steps with '.', {@link #WILDCARD_BOUND WILDCARD_BOUND} steps\r\n     * with '*' and {@link #TYPE_ARGUMENT TYPE_ARGUMENT} steps with their type\r\n     * argument index in decimal form followed by ';'.\r\n     */\r\n    @Override\r\n    public String toString() {\r\n        int length = getLength();\r\n        StringBuilder result = new StringBuilder(length * 2);\r\n        for (int i = 0; i < length; ++i) {\r\n            switch (getStep(i)) {\r\n            case ARRAY_ELEMENT:\r\n                result.append('[');\r\n                break;\r\n            case INNER_TYPE:\r\n                result.append('.');\r\n                break;\r\n            case WILDCARD_BOUND:\r\n                result.append('*');\r\n                break;\r\n            case TYPE_ARGUMENT:\r\n                result.append(getStepArgument(i)).append(';');\r\n                break;\r\n            default:\r\n                result.append('_');\r\n            }\r\n        }\r\n        return result.toString();\r\n    }\r\n}\r\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/TypeReference.java",
    "content": "/***\r\n * ASM: a very small and fast Java bytecode manipulation framework\r\n * Copyright (c) 2000-2013 INRIA, France Telecom\r\n * All rights reserved.\r\n *\r\n * Redistribution and use in source and binary forms, with or without\r\n * modification, are permitted provided that the following conditions\r\n * are met:\r\n * 1. Redistributions of source code must retain the above copyright\r\n *    notice, this list of conditions and the following disclaimer.\r\n * 2. Redistributions in binary form must reproduce the above copyright\r\n *    notice, this list of conditions and the following disclaimer in the\r\n *    documentation and/or other materials provided with the distribution.\r\n * 3. Neither the name of the copyright holders nor the names of its\r\n *    contributors may be used to endorse or promote products derived from\r\n *    this software without specific prior written permission.\r\n *\r\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\r\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\r\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\r\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\r\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\r\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\r\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\r\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\r\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\r\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\r\n * THE POSSIBILITY OF SUCH DAMAGE.\r\n */\r\n\r\npackage lt.dependencies.asm;\r\n\r\n/**\r\n * A reference to a type appearing in a class, field or method declaration, or\r\n * on an instruction. Such a reference designates the part of the class where\r\n * the referenced type is appearing (e.g. an 'extends', 'implements' or 'throws'\r\n * clause, a 'new' instruction, a 'catch' clause, a type cast, a local variable\r\n * declaration, etc).\r\n * \r\n * @author Eric Bruneton\r\n */\r\npublic class TypeReference {\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * class. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CLASS_TYPE_PARAMETER = 0x00;\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_TYPE_PARAMETER = 0x01;\r\n\r\n    /**\r\n     * The sort of type references that target the super class of a class or one\r\n     * of the interfaces it implements. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CLASS_EXTENDS = 0x10;\r\n\r\n    /**\r\n     * The sort of type references that target a bound of a type parameter of a\r\n     * generic class. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CLASS_TYPE_PARAMETER_BOUND = 0x11;\r\n\r\n    /**\r\n     * The sort of type references that target a bound of a type parameter of a\r\n     * generic method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_TYPE_PARAMETER_BOUND = 0x12;\r\n\r\n    /**\r\n     * The sort of type references that target the type of a field. See\r\n     * {@link #getSort getSort}.\r\n     */\r\n    public final static int FIELD = 0x13;\r\n\r\n    /**\r\n     * The sort of type references that target the return type of a method. See\r\n     * {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_RETURN = 0x14;\r\n\r\n    /**\r\n     * The sort of type references that target the receiver type of a method.\r\n     * See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_RECEIVER = 0x15;\r\n\r\n    /**\r\n     * The sort of type references that target the type of a formal parameter of\r\n     * a method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_FORMAL_PARAMETER = 0x16;\r\n\r\n    /**\r\n     * The sort of type references that target the type of an exception declared\r\n     * in the throws clause of a method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int THROWS = 0x17;\r\n\r\n    /**\r\n     * The sort of type references that target the type of a local variable in a\r\n     * method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int LOCAL_VARIABLE = 0x40;\r\n\r\n    /**\r\n     * The sort of type references that target the type of a resource variable\r\n     * in a method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int RESOURCE_VARIABLE = 0x41;\r\n\r\n    /**\r\n     * The sort of type references that target the type of the exception of a\r\n     * 'catch' clause in a method. See {@link #getSort getSort}.\r\n     */\r\n    public final static int EXCEPTION_PARAMETER = 0x42;\r\n\r\n    /**\r\n     * The sort of type references that target the type declared in an\r\n     * 'instanceof' instruction. See {@link #getSort getSort}.\r\n     */\r\n    public final static int INSTANCEOF = 0x43;\r\n\r\n    /**\r\n     * The sort of type references that target the type of the object created by\r\n     * a 'new' instruction. See {@link #getSort getSort}.\r\n     */\r\n    public final static int NEW = 0x44;\r\n\r\n    /**\r\n     * The sort of type references that target the receiver type of a\r\n     * constructor reference. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CONSTRUCTOR_REFERENCE = 0x45;\r\n\r\n    /**\r\n     * The sort of type references that target the receiver type of a method\r\n     * reference. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_REFERENCE = 0x46;\r\n\r\n    /**\r\n     * The sort of type references that target the type declared in an explicit\r\n     * or implicit cast instruction. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CAST = 0x47;\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * constructor in a constructor call. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT = 0x48;\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * method in a method call. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_INVOCATION_TYPE_ARGUMENT = 0x49;\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * constructor in a constructor reference. See {@link #getSort getSort}.\r\n     */\r\n    public final static int CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT = 0x4A;\r\n\r\n    /**\r\n     * The sort of type references that target a type parameter of a generic\r\n     * method in a method reference. See {@link #getSort getSort}.\r\n     */\r\n    public final static int METHOD_REFERENCE_TYPE_ARGUMENT = 0x4B;\r\n\r\n    /**\r\n     * The type reference value in Java class file format.\r\n     */\r\n    private int value;\r\n\r\n    /**\r\n     * Creates a new TypeReference.\r\n     * \r\n     * @param typeRef\r\n     *            the int encoded value of the type reference, as received in a\r\n     *            visit method related to type annotations, like\r\n     *            visitTypeAnnotation.\r\n     */\r\n    public TypeReference(int typeRef) {\r\n        this.value = typeRef;\r\n    }\r\n\r\n    /**\r\n     * Returns a type reference of the given sort.\r\n     * \r\n     * @param sort\r\n     *            {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},\r\n     *            {@link #METHOD_RECEIVER METHOD_RECEIVER},\r\n     *            {@link #LOCAL_VARIABLE LOCAL_VARIABLE},\r\n     *            {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},\r\n     *            {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},\r\n     *            {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE}, or\r\n     *            {@link #METHOD_REFERENCE METHOD_REFERENCE}.\r\n     * @return a type reference of the given sort.\r\n     */\r\n    public static TypeReference newTypeReference(int sort) {\r\n        return new TypeReference(sort << 24);\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to a type parameter of a generic class or method.\r\n     * \r\n     * @param sort\r\n     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or\r\n     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.\r\n     * @param paramIndex\r\n     *            the type parameter index.\r\n     * @return a reference to the given generic class or method type parameter.\r\n     */\r\n    public static TypeReference newTypeParameterReference(int sort,\r\n            int paramIndex) {\r\n        return new TypeReference((sort << 24) | (paramIndex << 16));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to a type parameter bound of a generic class or\r\n     * method.\r\n     * \r\n     * @param sort\r\n     *            {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER} or\r\n     *            {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER}.\r\n     * @param paramIndex\r\n     *            the type parameter index.\r\n     * @param boundIndex\r\n     *            the type bound index within the above type parameters.\r\n     * @return a reference to the given generic class or method type parameter\r\n     *         bound.\r\n     */\r\n    public static TypeReference newTypeParameterBoundReference(int sort,\r\n            int paramIndex, int boundIndex) {\r\n        return new TypeReference((sort << 24) | (paramIndex << 16)\r\n                | (boundIndex << 8));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to the super class or to an interface of the\r\n     * 'implements' clause of a class.\r\n     * \r\n     * @param itfIndex\r\n     *            the index of an interface in the 'implements' clause of a\r\n     *            class, or -1 to reference the super class of the class.\r\n     * @return a reference to the given super type of a class.\r\n     */\r\n    public static TypeReference newSuperTypeReference(int itfIndex) {\r\n        itfIndex &= 0xFFFF;\r\n        return new TypeReference((CLASS_EXTENDS << 24) | (itfIndex << 8));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to the type of a formal parameter of a method.\r\n     * \r\n     * @param paramIndex\r\n     *            the formal parameter index.\r\n     * \r\n     * @return a reference to the type of the given method formal parameter.\r\n     */\r\n    public static TypeReference newFormalParameterReference(int paramIndex) {\r\n        return new TypeReference((METHOD_FORMAL_PARAMETER << 24)\r\n                | (paramIndex << 16));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to the type of an exception, in a 'throws' clause of\r\n     * a method.\r\n     * \r\n     * @param exceptionIndex\r\n     *            the index of an exception in a 'throws' clause of a method.\r\n     * \r\n     * @return a reference to the type of the given exception.\r\n     */\r\n    public static TypeReference newExceptionReference(int exceptionIndex) {\r\n        return new TypeReference((THROWS << 24) | (exceptionIndex << 8));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to the type of the exception declared in a 'catch'\r\n     * clause of a method.\r\n     * \r\n     * @param tryCatchBlockIndex\r\n     *            the index of a try catch block (using the order in which they\r\n     *            are visited with visitTryCatchBlock).\r\n     * \r\n     * @return a reference to the type of the given exception.\r\n     */\r\n    public static TypeReference newTryCatchReference(int tryCatchBlockIndex) {\r\n        return new TypeReference((EXCEPTION_PARAMETER << 24)\r\n                | (tryCatchBlockIndex << 8));\r\n    }\r\n\r\n    /**\r\n     * Returns a reference to the type of a type argument in a constructor or\r\n     * method call or reference.\r\n     * \r\n     * @param sort\r\n     *            {@link #CAST CAST},\r\n     *            {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\r\n     *            CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},\r\n     *            {@link #METHOD_INVOCATION_TYPE_ARGUMENT\r\n     *            METHOD_INVOCATION_TYPE_ARGUMENT},\r\n     *            {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\r\n     *            CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or\r\n     *            {@link #METHOD_REFERENCE_TYPE_ARGUMENT\r\n     *            METHOD_REFERENCE_TYPE_ARGUMENT}.\r\n     * @param argIndex\r\n     *            the type argument index.\r\n     * \r\n     * @return a reference to the type of the given type argument.\r\n     */\r\n    public static TypeReference newTypeArgumentReference(int sort, int argIndex) {\r\n        return new TypeReference((sort << 24) | argIndex);\r\n    }\r\n\r\n    /**\r\n     * Returns the sort of this type reference.\r\n     * \r\n     * @return {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},\r\n     *         {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},\r\n     *         {@link #CLASS_EXTENDS CLASS_EXTENDS},\r\n     *         {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND},\r\n     *         {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND},\r\n     *         {@link #FIELD FIELD}, {@link #METHOD_RETURN METHOD_RETURN},\r\n     *         {@link #METHOD_RECEIVER METHOD_RECEIVER},\r\n     *         {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER},\r\n     *         {@link #THROWS THROWS}, {@link #LOCAL_VARIABLE LOCAL_VARIABLE},\r\n     *         {@link #RESOURCE_VARIABLE RESOURCE_VARIABLE},\r\n     *         {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER},\r\n     *         {@link #INSTANCEOF INSTANCEOF}, {@link #NEW NEW},\r\n     *         {@link #CONSTRUCTOR_REFERENCE CONSTRUCTOR_REFERENCE},\r\n     *         {@link #METHOD_REFERENCE METHOD_REFERENCE}, {@link #CAST CAST},\r\n     *         {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\r\n     *         CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},\r\n     *         {@link #METHOD_INVOCATION_TYPE_ARGUMENT\r\n     *         METHOD_INVOCATION_TYPE_ARGUMENT},\r\n     *         {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\r\n     *         CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or\r\n     *         {@link #METHOD_REFERENCE_TYPE_ARGUMENT\r\n     *         METHOD_REFERENCE_TYPE_ARGUMENT}.\r\n     */\r\n    public int getSort() {\r\n        return value >>> 24;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the type parameter referenced by this type\r\n     * reference. This method must only be used for type references whose sort\r\n     * is {@link #CLASS_TYPE_PARAMETER CLASS_TYPE_PARAMETER},\r\n     * {@link #METHOD_TYPE_PARAMETER METHOD_TYPE_PARAMETER},\r\n     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or\r\n     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.\r\n     * \r\n     * @return a type parameter index.\r\n     */\r\n    public int getTypeParameterIndex() {\r\n        return (value & 0x00FF0000) >> 16;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the type parameter bound, within the type parameter\r\n     * {@link #getTypeParameterIndex}, referenced by this type reference. This\r\n     * method must only be used for type references whose sort is\r\n     * {@link #CLASS_TYPE_PARAMETER_BOUND CLASS_TYPE_PARAMETER_BOUND} or\r\n     * {@link #METHOD_TYPE_PARAMETER_BOUND METHOD_TYPE_PARAMETER_BOUND}.\r\n     * \r\n     * @return a type parameter bound index.\r\n     */\r\n    public int getTypeParameterBoundIndex() {\r\n        return (value & 0x0000FF00) >> 8;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the \"super type\" of a class that is referenced by\r\n     * this type reference. This method must only be used for type references\r\n     * whose sort is {@link #CLASS_EXTENDS CLASS_EXTENDS}.\r\n     * \r\n     * @return the index of an interface in the 'implements' clause of a class,\r\n     *         or -1 if this type reference references the type of the super\r\n     *         class.\r\n     */\r\n    public int getSuperTypeIndex() {\r\n        return (short) ((value & 0x00FFFF00) >> 8);\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the formal parameter whose type is referenced by\r\n     * this type reference. This method must only be used for type references\r\n     * whose sort is {@link #METHOD_FORMAL_PARAMETER METHOD_FORMAL_PARAMETER}.\r\n     * \r\n     * @return a formal parameter index.\r\n     */\r\n    public int getFormalParameterIndex() {\r\n        return (value & 0x00FF0000) >> 16;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the exception, in a 'throws' clause of a method,\r\n     * whose type is referenced by this type reference. This method must only be\r\n     * used for type references whose sort is {@link #THROWS THROWS}.\r\n     * \r\n     * @return the index of an exception in the 'throws' clause of a method.\r\n     */\r\n    public int getExceptionIndex() {\r\n        return (value & 0x00FFFF00) >> 8;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the try catch block (using the order in which they\r\n     * are visited with visitTryCatchBlock), whose 'catch' type is referenced by\r\n     * this type reference. This method must only be used for type references\r\n     * whose sort is {@link #EXCEPTION_PARAMETER EXCEPTION_PARAMETER} .\r\n     * \r\n     * @return the index of an exception in the 'throws' clause of a method.\r\n     */\r\n    public int getTryCatchBlockIndex() {\r\n        return (value & 0x00FFFF00) >> 8;\r\n    }\r\n\r\n    /**\r\n     * Returns the index of the type argument referenced by this type reference.\r\n     * This method must only be used for type references whose sort is\r\n     * {@link #CAST CAST}, {@link #CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT\r\n     * CONSTRUCTOR_INVOCATION_TYPE_ARGUMENT},\r\n     * {@link #METHOD_INVOCATION_TYPE_ARGUMENT METHOD_INVOCATION_TYPE_ARGUMENT},\r\n     * {@link #CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT\r\n     * CONSTRUCTOR_REFERENCE_TYPE_ARGUMENT}, or\r\n     * {@link #METHOD_REFERENCE_TYPE_ARGUMENT METHOD_REFERENCE_TYPE_ARGUMENT}.\r\n     * \r\n     * @return a type parameter index.\r\n     */\r\n    public int getTypeArgumentIndex() {\r\n        return value & 0xFF;\r\n    }\r\n\r\n    /**\r\n     * Returns the int encoded value of this type reference, suitable for use in\r\n     * visit methods related to type annotations, like visitTypeAnnotation.\r\n     * \r\n     * @return the int encoded value of this type reference.\r\n     */\r\n    public int getValue() {\r\n        return value;\r\n    }\r\n}\r\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/package.html",
    "content": "<html>\n<!--\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n-->\n<body>\nProvides a small and fast bytecode manipulation framework.\n\n<p>\nThe <a href=\"http://www.objectweb.org/asm\">ASM</a> framework is organized\naround the {@link org.objectweb.asm.ClassVisitor ClassVisitor},\n{@link org.objectweb.asm.FieldVisitor FieldVisitor},\n{@link org.objectweb.asm.MethodVisitor MethodVisitor} and\n{@link org.objectweb.asm.AnnotationVisitor AnnotationVisitor} abstract classes,\nwhich allow one to visit the fields, methods and annotations of a class,\nincluding the bytecode instructions of each method.\n\n<p>\nIn addition to these main abstract classes, ASM provides a {@link\norg.objectweb.asm.ClassReader ClassReader} class, that can parse an\nexisting class and make a given visitor visit it. ASM also provides\na {@link org.objectweb.asm.ClassWriter ClassWriter} class, which is\na visitor that generates Java class files.\n\n<p>\nIn order to generate a class from scratch, only the {@link\norg.objectweb.asm.ClassWriter ClassWriter} class is necessary. Indeed,\nin order to generate a class, one must just call its visit<i>Xxx</i>\nmethods with the appropriate arguments to generate the desired fields\nand methods. See the \"helloworld\" example in the ASM distribution for\nmore details about class generation.\n\n<p>\nIn order to modify existing classes, one must use a {@link\norg.objectweb.asm.ClassReader ClassReader} class to analyze\nthe original class, a class modifier, and a {@link org.objectweb.asm.ClassWriter\nClassWriter} to construct the modified class. The class modifier\nis just a {@link org.objectweb.asm.ClassVisitor ClassVisitor}\nthat delegates most of the work to another {@link org.objectweb.asm.ClassVisitor\nClassVisitor}, but that sometimes changes some parameter values,\nor call additional methods, in order to implement the desired\nmodification process. In order to make it easier to implement such\nclass modifiers, the {@link org.objectweb.asm.ClassVisitor\nClassVisitor} and {@link org.objectweb.asm.MethodVisitor MethodVisitor}\nclasses delegate by default all the method calls they receive to an\noptional visitor. See the \"adapt\" example in the ASM\ndistribution for more details about class modification.\n\n<p>\nThe size of the core ASM library, <tt>asm.jar</tt>, is only 45KB, which is much\nsmaller than the size of the\n<a href=\"http://jakarta.apache.org/bcel\">BCEL</a> library (504KB), and than the\nsize of the\n<a href=\"http://serp.sourceforge.net\">SERP</a> library (150KB). ASM is also\nmuch faster than these tools. Indeed the overhead of a load time class\ntransformation process is of the order of 60% with ASM, 700% or more with BCEL,\nand 1100% or more with SERP (see the <tt>test/perf</tt> directory in the ASM\ndistribution)!\n\n@since ASM 1.3\n</body>\n</html>\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/signature/SignatureReader.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm.signature;\n\nimport lt.dependencies.asm.MethodVisitor;\nimport lt.dependencies.asm.ClassVisitor;\n\n/**\n * A type signature parser to make a signature visitor visit an existing\n * signature.\n * \n * @author Thomas Hallgren\n * @author Eric Bruneton\n */\npublic class SignatureReader {\n\n    /**\n     * The signature to be read.\n     */\n    private final String signature;\n\n    /**\n     * Constructs a {@link SignatureReader} for the given signature.\n     * \n     * @param signature\n     *            A <i>ClassSignature</i>, <i>MethodTypeSignature</i>, or\n     *            <i>FieldTypeSignature</i>.\n     */\n    public SignatureReader(final String signature) {\n        this.signature = signature;\n    }\n\n    /**\n     * Makes the given visitor visit the signature of this\n     * {@link SignatureReader}. This signature is the one specified in the\n     * constructor (see {@link #SignatureReader(String) SignatureReader}). This\n     * method is intended to be called on a {@link SignatureReader} that was\n     * created using a <i>ClassSignature</i> (such as the <code>signature</code>\n     * parameter of the {@link ClassVisitor#visit\n     * ClassVisitor.visit} method) or a <i>MethodTypeSignature</i> (such as the\n     * <code>signature</code> parameter of the\n     * {@link ClassVisitor#visitMethod\n     * ClassVisitor.visitMethod} method).\n     * \n     * @param v\n     *            the visitor that must visit this signature.\n     */\n    public void accept(final SignatureVisitor v) {\n        String signature = this.signature;\n        int len = signature.length();\n        int pos;\n        char c;\n\n        if (signature.charAt(0) == '<') {\n            pos = 2;\n            do {\n                int end = signature.indexOf(':', pos);\n                v.visitFormalTypeParameter(signature.substring(pos - 1, end));\n                pos = end + 1;\n\n                c = signature.charAt(pos);\n                if (c == 'L' || c == '[' || c == 'T') {\n                    pos = parseType(signature, pos, v.visitClassBound());\n                }\n\n                while ((c = signature.charAt(pos++)) == ':') {\n                    pos = parseType(signature, pos, v.visitInterfaceBound());\n                }\n            } while (c != '>');\n        } else {\n            pos = 0;\n        }\n\n        if (signature.charAt(pos) == '(') {\n            pos++;\n            while (signature.charAt(pos) != ')') {\n                pos = parseType(signature, pos, v.visitParameterType());\n            }\n            pos = parseType(signature, pos + 1, v.visitReturnType());\n            while (pos < len) {\n                pos = parseType(signature, pos + 1, v.visitExceptionType());\n            }\n        } else {\n            pos = parseType(signature, pos, v.visitSuperclass());\n            while (pos < len) {\n                pos = parseType(signature, pos, v.visitInterface());\n            }\n        }\n    }\n\n    /**\n     * Makes the given visitor visit the signature of this\n     * {@link SignatureReader}. This signature is the one specified in the\n     * constructor (see {@link #SignatureReader(String) SignatureReader}). This\n     * method is intended to be called on a {@link SignatureReader} that was\n     * created using a <i>FieldTypeSignature</i>, such as the\n     * <code>signature</code> parameter of the\n     * {@link ClassVisitor#visitField ClassVisitor.visitField}\n     * or {@link MethodVisitor#visitLocalVariable\n     * MethodVisitor.visitLocalVariable} methods.\n     * \n     * @param v\n     *            the visitor that must visit this signature.\n     */\n    public void acceptType(final SignatureVisitor v) {\n        parseType(this.signature, 0, v);\n    }\n\n    /**\n     * Parses a field type signature and makes the given visitor visit it.\n     * \n     * @param signature\n     *            a string containing the signature that must be parsed.\n     * @param pos\n     *            index of the first character of the signature to parsed.\n     * @param v\n     *            the visitor that must visit this signature.\n     * @return the index of the first character after the parsed signature.\n     */\n    private static int parseType(final String signature, int pos,\n            final SignatureVisitor v) {\n        char c;\n        int start, end;\n        boolean visited, inner;\n        String name;\n\n        switch (c = signature.charAt(pos++)) {\n        case 'Z':\n        case 'C':\n        case 'B':\n        case 'S':\n        case 'I':\n        case 'F':\n        case 'J':\n        case 'D':\n        case 'V':\n            v.visitBaseType(c);\n            return pos;\n\n        case '[':\n            return parseType(signature, pos, v.visitArrayType());\n\n        case 'T':\n            end = signature.indexOf(';', pos);\n            v.visitTypeVariable(signature.substring(pos, end));\n            return end + 1;\n\n        default: // case 'L':\n            start = pos;\n            visited = false;\n            inner = false;\n            for (;;) {\n                switch (c = signature.charAt(pos++)) {\n                case '.':\n                case ';':\n                    if (!visited) {\n                        name = signature.substring(start, pos - 1);\n                        if (inner) {\n                            v.visitInnerClassType(name);\n                        } else {\n                            v.visitClassType(name);\n                        }\n                    }\n                    if (c == ';') {\n                        v.visitEnd();\n                        return pos;\n                    }\n                    start = pos;\n                    visited = false;\n                    inner = true;\n                    break;\n\n                case '<':\n                    name = signature.substring(start, pos - 1);\n                    if (inner) {\n                        v.visitInnerClassType(name);\n                    } else {\n                        v.visitClassType(name);\n                    }\n                    visited = true;\n                    top: for (;;) {\n                        switch (c = signature.charAt(pos)) {\n                        case '>':\n                            break top;\n                        case '*':\n                            ++pos;\n                            v.visitTypeArgument();\n                            break;\n                        case '+':\n                        case '-':\n                            pos = parseType(signature, pos + 1,\n                                    v.visitTypeArgument(c));\n                            break;\n                        default:\n                            pos = parseType(signature, pos,\n                                    v.visitTypeArgument('='));\n                            break;\n                        }\n                    }\n                }\n            }\n        }\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/signature/SignatureVisitor.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm.signature;\n\nimport lt.dependencies.asm.Opcodes;\n\n/**\n * A visitor to visit a generic signature. The methods of this interface must be\n * called in one of the three following orders (the last one is the only valid\n * order for a {@link SignatureVisitor} that is returned by a method of this\n * interface):\n * <ul>\n * <li><i>ClassSignature</i> = ( <tt>visitFormalTypeParameter</tt>\n * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (\n * <tt>visitSuperclass</tt> <tt>visitInterface</tt>* )</li>\n * <li><i>MethodSignature</i> = ( <tt>visitFormalTypeParameter</tt>\n * <tt>visitClassBound</tt>? <tt>visitInterfaceBound</tt>* )* (\n * <tt>visitParameterType</tt>* <tt>visitReturnType</tt>\n * <tt>visitExceptionType</tt>* )</li>\n * <li><i>TypeSignature</i> = <tt>visitBaseType</tt> |\n * <tt>visitTypeVariable</tt> | <tt>visitArrayType</tt> | (\n * <tt>visitClassType</tt> <tt>visitTypeArgument</tt>* (\n * <tt>visitInnerClassType</tt> <tt>visitTypeArgument</tt>* )* <tt>visitEnd</tt>\n * ) )</li>\n * </ul>\n * \n * @author Thomas Hallgren\n * @author Eric Bruneton\n */\npublic abstract class SignatureVisitor {\n\n    /**\n     * Wildcard for an \"extends\" type argument.\n     */\n    public final static char EXTENDS = '+';\n\n    /**\n     * Wildcard for a \"super\" type argument.\n     */\n    public final static char SUPER = '-';\n\n    /**\n     * Wildcard for a normal type argument.\n     */\n    public final static char INSTANCEOF = '=';\n\n    /**\n     * The ASM API version implemented by this visitor. The value of this field\n     * must be one of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    protected final int api;\n\n    /**\n     * Constructs a new {@link SignatureVisitor}.\n     * \n     * @param api\n     *            the ASM API version implemented by this visitor. Must be one\n     *            of {@link Opcodes#ASM4} or {@link Opcodes#ASM5}.\n     */\n    public SignatureVisitor(final int api) {\n        if (api != Opcodes.ASM4 && api != Opcodes.ASM5) {\n            throw new IllegalArgumentException();\n        }\n        this.api = api;\n    }\n\n    /**\n     * Visits a formal type parameter.\n     * \n     * @param name\n     *            the name of the formal parameter.\n     */\n    public void visitFormalTypeParameter(String name) {\n    }\n\n    /**\n     * Visits the class bound of the last visited formal type parameter.\n     * \n     * @return a non null visitor to visit the signature of the class bound.\n     */\n    public SignatureVisitor visitClassBound() {\n        return this;\n    }\n\n    /**\n     * Visits an interface bound of the last visited formal type parameter.\n     * \n     * @return a non null visitor to visit the signature of the interface bound.\n     */\n    public SignatureVisitor visitInterfaceBound() {\n        return this;\n    }\n\n    /**\n     * Visits the type of the super class.\n     * \n     * @return a non null visitor to visit the signature of the super class\n     *         type.\n     */\n    public SignatureVisitor visitSuperclass() {\n        return this;\n    }\n\n    /**\n     * Visits the type of an interface implemented by the class.\n     * \n     * @return a non null visitor to visit the signature of the interface type.\n     */\n    public SignatureVisitor visitInterface() {\n        return this;\n    }\n\n    /**\n     * Visits the type of a method parameter.\n     * \n     * @return a non null visitor to visit the signature of the parameter type.\n     */\n    public SignatureVisitor visitParameterType() {\n        return this;\n    }\n\n    /**\n     * Visits the return type of the method.\n     * \n     * @return a non null visitor to visit the signature of the return type.\n     */\n    public SignatureVisitor visitReturnType() {\n        return this;\n    }\n\n    /**\n     * Visits the type of a method exception.\n     * \n     * @return a non null visitor to visit the signature of the exception type.\n     */\n    public SignatureVisitor visitExceptionType() {\n        return this;\n    }\n\n    /**\n     * Visits a signature corresponding to a primitive type.\n     * \n     * @param descriptor\n     *            the descriptor of the primitive type, or 'V' for <tt>void</tt>\n     *            .\n     */\n    public void visitBaseType(char descriptor) {\n    }\n\n    /**\n     * Visits a signature corresponding to a type variable.\n     * \n     * @param name\n     *            the name of the type variable.\n     */\n    public void visitTypeVariable(String name) {\n    }\n\n    /**\n     * Visits a signature corresponding to an array type.\n     * \n     * @return a non null visitor to visit the signature of the array element\n     *         type.\n     */\n    public SignatureVisitor visitArrayType() {\n        return this;\n    }\n\n    /**\n     * Starts the visit of a signature corresponding to a class or interface\n     * type.\n     * \n     * @param name\n     *            the internal name of the class or interface.\n     */\n    public void visitClassType(String name) {\n    }\n\n    /**\n     * Visits an inner class.\n     * \n     * @param name\n     *            the local name of the inner class in its enclosing class.\n     */\n    public void visitInnerClassType(String name) {\n    }\n\n    /**\n     * Visits an unbounded type argument of the last visited class or inner\n     * class type.\n     */\n    public void visitTypeArgument() {\n    }\n\n    /**\n     * Visits a type argument of the last visited class or inner class type.\n     * \n     * @param wildcard\n     *            '+', '-' or '='.\n     * @return a non null visitor to visit the signature of the type argument.\n     */\n    public SignatureVisitor visitTypeArgument(char wildcard) {\n        return this;\n    }\n\n    /**\n     * Ends the visit of a signature corresponding to a class or interface type.\n     */\n    public void visitEnd() {\n    }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/signature/SignatureWriter.java",
    "content": "/***\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n */\npackage lt.dependencies.asm.signature;\n\nimport lt.dependencies.asm.Opcodes;\n\n/**\n * A signature visitor that generates signatures in string format.\n * \n * @author Thomas Hallgren\n * @author Eric Bruneton\n */\npublic class SignatureWriter extends SignatureVisitor {\n\n    /**\n     * Builder used to construct the signature.\n     */\n    private final StringBuilder buf = new StringBuilder();\n\n    /**\n     * Indicates if the signature contains formal type parameters.\n     */\n    private boolean hasFormals;\n\n    /**\n     * Indicates if the signature contains method parameter types.\n     */\n    private boolean hasParameters;\n\n    /**\n     * Stack used to keep track of class types that have arguments. Each element\n     * of this stack is a boolean encoded in one bit. The top of the stack is\n     * the lowest order bit. Pushing false = *2, pushing true = *2+1, popping =\n     * /2.\n     */\n    private int argumentStack;\n\n    /**\n     * Constructs a new {@link SignatureWriter} object.\n     */\n    public SignatureWriter() {\n        super(Opcodes.ASM5);\n    }\n\n    // ------------------------------------------------------------------------\n    // Implementation of the SignatureVisitor interface\n    // ------------------------------------------------------------------------\n\n    @Override\n    public void visitFormalTypeParameter(final String name) {\n        if (!hasFormals) {\n            hasFormals = true;\n            buf.append('<');\n        }\n        buf.append(name);\n        buf.append(':');\n    }\n\n    @Override\n    public SignatureVisitor visitClassBound() {\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitInterfaceBound() {\n        buf.append(':');\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitSuperclass() {\n        endFormals();\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitInterface() {\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitParameterType() {\n        endFormals();\n        if (!hasParameters) {\n            hasParameters = true;\n            buf.append('(');\n        }\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitReturnType() {\n        endFormals();\n        if (!hasParameters) {\n            buf.append('(');\n        }\n        buf.append(')');\n        return this;\n    }\n\n    @Override\n    public SignatureVisitor visitExceptionType() {\n        buf.append('^');\n        return this;\n    }\n\n    @Override\n    public void visitBaseType(final char descriptor) {\n        buf.append(descriptor);\n    }\n\n    @Override\n    public void visitTypeVariable(final String name) {\n        buf.append('T');\n        buf.append(name);\n        buf.append(';');\n    }\n\n    @Override\n    public SignatureVisitor visitArrayType() {\n        buf.append('[');\n        return this;\n    }\n\n    @Override\n    public void visitClassType(final String name) {\n        buf.append('L');\n        buf.append(name);\n        argumentStack *= 2;\n    }\n\n    @Override\n    public void visitInnerClassType(final String name) {\n        endArguments();\n        buf.append('.');\n        buf.append(name);\n        argumentStack *= 2;\n    }\n\n    @Override\n    public void visitTypeArgument() {\n        if (argumentStack % 2 == 0) {\n            ++argumentStack;\n            buf.append('<');\n        }\n        buf.append('*');\n    }\n\n    @Override\n    public SignatureVisitor visitTypeArgument(final char wildcard) {\n        if (argumentStack % 2 == 0) {\n            ++argumentStack;\n            buf.append('<');\n        }\n        if (wildcard != '=') {\n            buf.append(wildcard);\n        }\n        return this;\n    }\n\n    @Override\n    public void visitEnd() {\n        endArguments();\n        buf.append(';');\n    }\n\n    /**\n     * Returns the signature that was built by this signature writer.\n     * \n     * @return the signature that was built by this signature writer.\n     */\n    @Override\n    public String toString() {\n        return buf.toString();\n    }\n\n    // ------------------------------------------------------------------------\n    // Utility methods\n    // ------------------------------------------------------------------------\n\n    /**\n     * Ends the formal type parameters section of the signature.\n     */\n    private void endFormals() {\n        if (hasFormals) {\n            hasFormals = false;\n            buf.append('>');\n        }\n    }\n\n    /**\n     * Ends the type arguments of a class or inner class type.\n     */\n    private void endArguments() {\n        if (argumentStack % 2 != 0) {\n            buf.append('>');\n        }\n        argumentStack /= 2;\n    }\n}"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/asm/signature/package.html",
    "content": "<html>\n<!--\n * ASM: a very small and fast Java bytecode manipulation framework\n * Copyright (c) 2000-2011 INRIA, France Telecom\n * All rights reserved.\n *\n * Redistribution and use in source and binary forms, with or without\n * modification, are permitted provided that the following conditions\n * are met:\n * 1. Redistributions of source code must retain the above copyright\n *    notice, this list of conditions and the following disclaimer.\n * 2. Redistributions in binary form must reproduce the above copyright\n *    notice, this list of conditions and the following disclaimer in the\n *    documentation and/or other materials provided with the distribution.\n * 3. Neither the name of the copyright holders nor the names of its\n *    contributors may be used to endorse or promote products derived from\n *    this software without specific prior written permission.\n *\n * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS \"AS IS\"\n * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE\n * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE\n * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE\n * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR\n * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF\n * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS\n * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN\n * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)\n * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF\n * THE POSSIBILITY OF SUCH DAMAGE.\n-->\n<body>\nProvides support for type signatures.\n\n@since ASM 2.0\n</body>\n</html>\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/dependencies/package-info.java",
    "content": "/**\n * Latte lang 's repackaging of all depended libraries<br>\n * the repackaging avoids any potential conflicts with dependencies\n * at the application level or from third-party libraries and frameworks.<br>\n * <br>\n * <code>Latte lang</code> repackages the following libraries :<br>\n * <ul>\n * <li><a href=\"http://asm.ow2.org\">org.objectweb.asm 5.1</a> as {@link lt.dependencies.asm}</li>\n * </ul>\n */\npackage lt.dependencies;\n\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/generator/AbstractSourceGenerator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.generator;\n\nimport lt.compiler.*;\nimport lt.compiler.syntactic.Statement;\nimport lt.generator.SourceGenerator;\n\nimport java.util.List;\n\n/**\n * the generator that save all init params to fields.\n */\npublic abstract class AbstractSourceGenerator implements SourceGenerator {\n        protected List<Statement> ast;\n        protected SemanticProcessor processor;\n        protected SemanticScope scope;\n        protected LineCol lineCol;\n        protected ErrorManager err;\n\n        @Override\n        public void init(List<Statement> ast, SemanticProcessor processor, SemanticScope scope, LineCol lineCol, ErrorManager err) throws SyntaxException {\n                this.ast = ast;\n                this.processor = processor;\n                this.scope = scope;\n                this.lineCol = lineCol;\n                this.err = err;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/generator/SourceGenerator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.generator;\n\nimport lt.compiler.*;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\n\nimport java.util.List;\n\n/**\n * a generator that generates source code.\n */\npublic interface SourceGenerator {\n        int EXPRESSION = 1;\n        int SERIALIZE = 2;\n        int VALUE = 3;\n\n        /**\n         * initiate the generator. This method would be invoked after the generator is constructed.\n         *\n         * @param ast       AST\n         * @param processor semantic processor\n         * @param scope     semantic scope\n         * @param lineCol   lineCol\n         * @param err       Error manager\n         * @throws SyntaxException compiling error\n         */\n        void init(List<Statement> ast, SemanticProcessor processor, SemanticScope scope, LineCol lineCol, ErrorManager err) throws SyntaxException;\n\n        /**\n         * generate an object. if the result type is {@link #EXPRESSION}, then the object <b>must</b> be an {@link Expression}.<br>\n         * if the result type is {@link #SERIALIZE}, then the object <b>must</b> be a {@link java.io.Serializable} object.<br>\n         * if the result type is {@link #VALUE}, then the object <b>must</b> be a {@link lt.compiler.semantic.Value} object.\n         *\n         * @return the transformed state\n         * @throws SyntaxException exception\n         */\n        Object generate() throws SyntaxException;\n\n        /**\n         * @return {@link #EXPRESSION} or {@link #SERIALIZE} or {@link #VALUE}\n         */\n        int resultType();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/FunctionalAbstractClass.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * mark the type as <tt>FunctionalAbstractClass</tt>.\n * a <tt>functional abstract class</tt> has exactly one abstract method,\n * and must have a public constructor with no parameters<br>\n * <pre>\n * ; C1 is a functional abstract class\n * class C1\n *     abs method()=...\n *\n * ; C2 is not a functional abstract class, because it doesn't have public zero-parameter constructor\n * class C2(param)\n *     abs method()=...\n *\n * ; C3 is not a functional abstract class, because it has more than one unimplemented method\n * class C3:java::util::List\n * </pre>\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface FunctionalAbstractClass {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/FunctionalInterface.java",
    "content": "package lt.lang;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * functional interface<br>\n * same meaning as jdk 1.7 FunctionalInterface\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface FunctionalInterface {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/GenericTemplate.java",
    "content": "package lt.lang;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * marks that a type is Latte generic template\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface GenericTemplate {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/Pointer.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * the pointer object.\n * use p[] to access/modify the contained value.\n *\n * @param <T> the contained object type\n */\n@SuppressWarnings(\"unused\")\npublic class Pointer<T> {\n        private T item;\n        private final boolean nonnull;\n        private final boolean nonempty;\n\n        public Pointer(boolean nonnull, boolean nonempty) {\n                this.nonnull = nonnull;\n                this.nonempty = nonempty;\n        }\n\n        /**\n         * retrieve the contained object (or null)\n         *\n         * @return the contained object\n         */\n        public T get() {\n                return item;\n        }\n\n        /**\n         * cast type and set the contained object and return the pointer itself.\n         *\n         * @param item input object (or null)\n         * @return input object\n         * @throws Throwable exception when trying to cast the object\n         */\n        public Pointer set(T item) throws Throwable {\n                if (nonempty) {\n                        if (!LtRuntime.castToBool(item)) throw new IllegalArgumentException();\n                }\n                if (nonnull) {\n                        if (item == null) throw new NullPointerException();\n                        if (item instanceof Unit) throw new IllegalArgumentException();\n                }\n                this.item = item;\n                return this;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/Unit.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang;\n\nimport lt.runtime.LatteObject;\n\n/**\n * the unit object\n */\n@LatteObject\npublic class Unit {\n        public static final Unit singletonInstance = new Unit();\n\n        private Unit() {\n        }\n\n        public static Unit get() {\n                return singletonInstance;\n        }\n\n        @Override\n        public String toString() {\n                return \"Unit\";\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/ast.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang;\n\nimport lt.compiler.*;\nimport lt.compiler.syntactic.Statement;\nimport lt.generator.SourceGenerator;\n\nimport java.util.List;\n\n/**\n * serialize the expression as output\n */\npublic class ast implements SourceGenerator {\n        private List<Statement> ast;\n\n        @Override\n        public void init(List<Statement> ast, SemanticProcessor processor, SemanticScope scope, LineCol lineCol, ErrorManager err) {\n                this.ast = ast;\n        }\n\n        @Override\n        public Object generate() throws SyntaxException {\n                return ast;\n        }\n\n        @Override\n        public int resultType() {\n                return SERIALIZE;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport java.io.Serializable;\n\n/**\n * function\n */\npublic interface Function extends Serializable {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function0.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 0 args\n */\n@FunctionalInterface\npublic interface Function0<R> extends Function {\n        R apply() throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function1.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 1 arg\n */\n@FunctionalInterface\npublic interface Function1<R, A> extends Function {\n        R apply(A a) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function10.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 10 args\n */\n@FunctionalInterface\npublic interface Function10<R, A, B, C, D, E, F, G, H, I, J> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function11.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 11 args\n */\n@FunctionalInterface\npublic interface Function11<R, A, B, C, D, E, F, G, H, I, J, K> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function12.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 12 args\n */\n@FunctionalInterface\npublic interface Function12<R, A, B, C, D, E, F, G, H, I, J, K, L> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function13.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 13 args\n */\n@FunctionalInterface\npublic interface Function13<R, A, B, C, D, E, F, G, H, I, J, K, L, M> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l, M m) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function14.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 14 args\n */\n@FunctionalInterface\npublic interface Function14<R, A, B, C, D, E, F, G, H, I, J, K, L, M, N> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l, M m, N n) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function15.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 15 args\n */\n@FunctionalInterface\npublic interface Function15<R, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l, M m, N n, O o) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function16.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 16 args\n */\n@FunctionalInterface\npublic interface Function16<R, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l, M m, N n, O o,\n                P p) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function17.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 17 args\n */\n@FunctionalInterface\npublic interface Function17<R, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i, J j,\n                K k, L l, M m, N n, O o,\n                P p, Q q) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function18.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 18 args\n */\n@FunctionalInterface\npublic interface Function18<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function19.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 19 args\n */\n@FunctionalInterface\npublic interface Function19<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function2.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 2 args\n */\n@FunctionalInterface\npublic interface Function2<R, A, B> extends Function {\n        R apply(A a, B b) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function20.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 20 args\n */\n@FunctionalInterface\npublic interface Function20<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function21.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 21 args\n */\n@FunctionalInterface\npublic interface Function21<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function22.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 22 args\n */\n@FunctionalInterface\npublic interface Function22<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u, V v) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function23.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 23 args\n */\n@FunctionalInterface\npublic interface Function23<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u, V v, W w) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function24.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 24 args\n */\n@FunctionalInterface\npublic interface Function24<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u, V v, W w, X x) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function25.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 25 args\n */\n@FunctionalInterface\npublic interface Function25<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u, V v, W w, X x, Y y) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function26.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 26 args\n */\n@FunctionalInterface\npublic interface Function26<Res, A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z> extends Function {\n        Res apply(A a, B b, C c, D d, E e,\n                  F f, G g, H h, I i, J j,\n                  K k, L l, M m, N n, O o,\n                  P p, Q q, R r, S s, T t,\n                  U u, V v, W w, X x, Y y,\n                  Z z) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function3.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 3 args\n */\n@FunctionalInterface\npublic interface Function3<R, A, B, C> extends Function {\n        R apply(A a, B b, C c) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function4.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 4 args\n */\n@FunctionalInterface\npublic interface Function4<R, A, B, C, D> extends Function {\n        R apply(A a, B b, C c, D d) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function5.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 5 args\n */\n@FunctionalInterface\npublic interface Function5<R, A, B, C, D, E> extends Function {\n        R apply(A a, B b, C c, D d, E e) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function6.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 6 args\n */\n@FunctionalInterface\npublic interface Function6<R, A, B, C, D, E, F> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function7.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 7 args\n */\n@FunctionalInterface\npublic interface Function7<R, A, B, C, D, E, F, G> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function8.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 8 args\n */\n@FunctionalInterface\npublic interface Function8<R, A, B, C, D, E, F, G, H> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/function/Function9.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang.function;\n\nimport lt.lang.FunctionalInterface;\n\n/**\n * function with 9 args\n */\n@FunctionalInterface\npublic interface Function9<R, A, B, C, D, E, F, G, H, I> extends Function {\n        R apply(A a, B b, C c, D d, E e,\n                F f, G g, H h, I i) throws Exception;\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/CollectionImplicit.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.Implicit;\nimport lt.runtime.LatteObject;\nimport lt.lang.implicit.collection.*;\n\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * implicit casts on collections\n */\n@LatteObject\n@Implicit\npublic class CollectionImplicit {\n        public static final CollectionImplicit singletonInstance = new CollectionImplicit();\n\n        private CollectionImplicit() {\n        }\n\n        @Implicit\n        public <E> RichList<E> cast(List<E> list) {\n                return new RichList<E>(list);\n        }\n\n        @Implicit\n        public <E> RichSet<E> cast(Set<E> set) {\n                return new RichSet<E>(set);\n        }\n\n        @Implicit\n        public <K, V> RichMap cast(Map<K, V> map) {\n                return new RichMap<K, V>(map);\n        }\n\n        @Implicit\n        public <T> RichIterable<T> cast(Iterable<T> i) {\n                return new RichIterable<T>(i);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/ObjectImplicit.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.Implicit;\nimport lt.runtime.LatteObject;\n\n/**\n * implicit casts for object\n */\n@Implicit\n@LatteObject\npublic class ObjectImplicit {\n        public static final ObjectImplicit singletonInstance = new ObjectImplicit();\n\n        private ObjectImplicit() {\n        }\n\n        @Implicit\n        public final RichObject cast(Object s) {\n                return new RichObject(s);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/PrimitivesImplicit.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.Implicit;\nimport lt.runtime.LatteObject;\n\n/**\n * implicit casts for primitives\n */\n@Implicit\n@LatteObject\npublic class PrimitivesImplicit {\n        public static final PrimitivesImplicit singletonInstance = new PrimitivesImplicit();\n\n        private PrimitivesImplicit() {\n        }\n\n        @Implicit\n        public final RichBool cast(Boolean b) {\n                return new RichBool(b);\n        }\n\n        @Implicit\n        public final RichByte cast(Byte b) {\n                return new RichByte(b);\n        }\n\n        @Implicit\n        public final RichChar cast(Character c) {\n                return new RichChar(c);\n        }\n\n        @Implicit\n        public final RichDouble cast(Double d) {\n                return new RichDouble(d);\n        }\n\n        @Implicit\n        public final RichFloat cast(Float f) {\n                return new RichFloat(f);\n        }\n\n        @Implicit\n        public final RichInt cast(Integer i) {\n                return new RichInt(i);\n        }\n\n        @Implicit\n        public final RichLong cast(Long l) {\n                return new RichLong(l);\n        }\n\n        @Implicit\n        public final RichShort cast(Short s) {\n                return new RichShort(s);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichBool.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Bool\n */\npublic class RichBool {\n        private Boolean b;\n\n        public RichBool(Boolean b) {\n                this.b = b;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !b;\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public boolean and(Boolean b) {\n                return this.b & b;\n        }\n\n        public boolean and(Object o) throws Throwable {\n                return this.b & LtRuntime.castToBool(o);\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public boolean or(Boolean b) {\n                return this.b | b;\n        }\n\n        public boolean or(Object o) throws Throwable {\n                return this.b | LtRuntime.castToBool(o);\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        // none\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        // none\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public boolean xor(Boolean b) throws Throwable {\n                return this.b ^ b;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichByte.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Byte\n */\npublic class RichByte {\n        private Byte b;\n\n        public RichByte(Byte b) {\n                this.b = b;\n        }\n\n        public int not() {\n                return ~b;\n        }\n\n        public int negate() {\n                return -b;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(b);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public int add(Integer i) {\n                return this.b + i;\n        }\n\n        public int add(Byte b) {\n                return this.b + b;\n        }\n\n        public int add(Short s) {\n                return b + s;\n        }\n\n        public int add(Character c) {\n                return b + c;\n        }\n\n        public long add(Long l) {\n                return b + l;\n        }\n\n        public float add(Float f) {\n                return b + f;\n        }\n\n        public double add(Double d) {\n                return b + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public int and(Integer i) {\n                return this.b & i;\n        }\n\n        public int and(Byte b) {\n                return this.b & b;\n        }\n\n        public int and(Short s) {\n                return b & s;\n        }\n\n        public int and(Character c) {\n                return b & c;\n        }\n\n        public long and(Long l) {\n                return b & l;\n        }\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.b) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public int or(Integer i) {\n                return this.b | i;\n        }\n\n        public int or(Byte b) {\n                return this.b | b;\n        }\n\n        public int or(Short s) {\n                return b | s;\n        }\n\n        public int or(Character c) {\n                return b | c;\n        }\n\n        public long or(Long l) {\n                return b | l;\n        }\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.b) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public int divide(Integer i) {\n                return this.b / i;\n        }\n\n        public int divide(Byte b) {\n                return this.b / b;\n        }\n\n        public int divide(Short s) {\n                return b / s;\n        }\n\n        public int divide(Character c) {\n                return b / c;\n        }\n\n        public long divide(Long l) {\n                return b / l;\n        }\n\n        public float divide(Float f) {\n                return b / f;\n        }\n\n        public double divide(Double d) {\n                return b / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return this.b >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return this.b >= b;\n        }\n\n        public boolean ge(Short s) {\n                return b >= s;\n        }\n\n        public boolean ge(Character c) {\n                return b >= c;\n        }\n\n        public boolean ge(Long l) {\n                return b >= l;\n        }\n\n        public boolean ge(Float f) {\n                return b >= f;\n        }\n\n        public boolean ge(Double d) {\n                return b >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return this.b > i;\n        }\n\n        public boolean gt(Byte b) {\n                return this.b > b;\n        }\n\n        public boolean gt(Short s) {\n                return b > s;\n        }\n\n        public boolean gt(Character c) {\n                return b > c;\n        }\n\n        public boolean gt(Long l) {\n                return b > l;\n        }\n\n        public boolean gt(Float f) {\n                return b > f;\n        }\n\n        public boolean gt(Double d) {\n                return b > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return this.b <= i;\n        }\n\n        public boolean le(Byte b) {\n                return this.b <= b;\n        }\n\n        public boolean le(Short s) {\n                return b <= s;\n        }\n\n        public boolean le(Character c) {\n                return b <= c;\n        }\n\n        public boolean le(Long l) {\n                return b <= l;\n        }\n\n        public boolean le(Float f) {\n                return b <= f;\n        }\n\n        public boolean le(Double d) {\n                return b <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return this.b < i;\n        }\n\n        public boolean lt(Byte b) {\n                return this.b < b;\n        }\n\n        public boolean lt(Short s) {\n                return b < s;\n        }\n\n        public boolean lt(Character c) {\n                return b < c;\n        }\n\n        public boolean lt(Long l) {\n                return b < l;\n        }\n\n        public boolean lt(Float f) {\n                return b < f;\n        }\n\n        public boolean lt(Double d) {\n                return b < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public int multiply(Integer i) {\n                return this.b * i;\n        }\n\n        public int multiply(Byte b) {\n                return this.b * b;\n        }\n\n        public int multiply(Short s) {\n                return b * s;\n        }\n\n        public int multiply(Character c) {\n                return b * c;\n        }\n\n        public long multiply(Long l) {\n                return b * l;\n        }\n\n        public float multiply(Float f) {\n                return b * f;\n        }\n\n        public double multiply(Double d) {\n                return b * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        public int remainder(Integer i) {\n                return this.b % i;\n        }\n\n        public int remainder(Byte b) {\n                return this.b % b;\n        }\n\n        public int remainder(Short s) {\n                return b % s;\n        }\n\n        public int remainder(Character c) {\n                return b % c;\n        }\n\n        public long remainder(Long l) {\n                return b % l;\n        }\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        public int shiftLeft(Integer i) {\n                return this.b << i;\n        }\n\n        public int shiftLeft(Byte b) {\n                return this.b << b;\n        }\n\n        public int shiftLeft(Short s) {\n                return b << s;\n        }\n\n        public int shiftLeft(Character c) {\n                return b << c;\n        }\n\n        public int shiftLeft(Long l) {\n                return b << l;\n        }\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        public int shiftRight(Integer i) {\n                return this.b >> i;\n        }\n\n        public int shiftRight(Byte b) {\n                return this.b >> b;\n        }\n\n        public int shiftRight(Short s) {\n                return b >> s;\n        }\n\n        public int shiftRight(Character c) {\n                return b >> c;\n        }\n\n        public int shiftRight(Long l) {\n                return b >> l;\n        }\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public int subtract(Integer i) {\n                return this.b - i;\n        }\n\n        public int subtract(Byte b) {\n                return this.b - b;\n        }\n\n        public int subtract(Short s) {\n                return b - s;\n        }\n\n        public int subtract(Character c) {\n                return b - c;\n        }\n\n        public long subtract(Long l) {\n                return b - l;\n        }\n\n        public float subtract(Float f) {\n                return b - f;\n        }\n\n        public double subtract(Double d) {\n                return b - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        public int unsignedShiftRight(Integer i) {\n                return this.b >>> i;\n        }\n\n        public int unsignedShiftRight(Byte b) {\n                return this.b >>> b;\n        }\n\n        public int unsignedShiftRight(Short s) {\n                return b >>> s;\n        }\n\n        public int unsignedShiftRight(Character c) {\n                return b >>> c;\n        }\n\n        public int unsignedShiftRight(Long l) {\n                return b >>> l;\n        }\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public int xor(Integer i) {\n                return this.b ^ i;\n        }\n\n        public int xor(Byte b) {\n                return this.b ^ b;\n        }\n\n        public int xor(Short s) {\n                return b ^ s;\n        }\n\n        public int xor(Character c) {\n                return b ^ c;\n        }\n\n        public long xor(Long l) {\n                return b ^ l;\n        }\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.b) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(b, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(b, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(b, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(b, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(this.b, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(b, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(b, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichChar.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\nimport java.util.regex.Pattern;\n\n/**\n * rich Character\n */\npublic class RichChar {\n        private Character c;\n\n        public RichChar(Character c) {\n                this.c = c;\n        }\n\n        public Pattern r() {\n                return Pattern.compile(c.toString());\n        }\n\n        public Pattern r(int flags) {\n                return Pattern.compile(c.toString(), flags);\n        }\n\n        public int not() {\n                return ~c;\n        }\n\n        public int negate() {\n                return -c;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(c);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public int add(Integer i) {\n                return this.c + i;\n        }\n\n        public int add(Byte b) {\n                return c + b;\n        }\n\n        public int add(Short s) {\n                return c + s;\n        }\n\n        public int add(Character c) {\n                return this.c + c;\n        }\n\n        public long add(Long l) {\n                return c + l;\n        }\n\n        public float add(Float f) {\n                return c + f;\n        }\n\n        public double add(Double d) {\n                return c + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public int and(Integer i) {\n                return this.c & i;\n        }\n\n        public int and(Byte b) {\n                return c & b;\n        }\n\n        public int and(Short s) {\n                return c & s;\n        }\n\n        public int and(Character c) {\n                return this.c & c;\n        }\n\n        public long and(Long l) {\n                return c & l;\n        }\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(c) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public int or(Integer i) {\n                return this.c | i;\n        }\n\n        public int or(Byte b) {\n                return c | b;\n        }\n\n        public int or(Short s) {\n                return c | s;\n        }\n\n        public int or(Character c) {\n                return this.c | c;\n        }\n\n        public long or(Long l) {\n                return c | l;\n        }\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(c) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public int divide(Integer i) {\n                return this.c / i;\n        }\n\n        public int divide(Byte b) {\n                return c / b;\n        }\n\n        public int divide(Short s) {\n                return c / s;\n        }\n\n        public int divide(Character c) {\n                return this.c / c;\n        }\n\n        public long divide(Long l) {\n                return c / l;\n        }\n\n        public float divide(Float f) {\n                return c / f;\n        }\n\n        public double divide(Double d) {\n                return c / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return this.c >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return c >= b;\n        }\n\n        public boolean ge(Short s) {\n                return c >= s;\n        }\n\n        public boolean ge(Character c) {\n                return this.c >= c;\n        }\n\n        public boolean ge(Long l) {\n                return c >= l;\n        }\n\n        public boolean ge(Float f) {\n                return c >= f;\n        }\n\n        public boolean ge(Double d) {\n                return c >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return this.c > i;\n        }\n\n        public boolean gt(Byte b) {\n                return c > b;\n        }\n\n        public boolean gt(Short s) {\n                return c > s;\n        }\n\n        public boolean gt(Character c) {\n                return this.c > c;\n        }\n\n        public boolean gt(Long l) {\n                return c > l;\n        }\n\n        public boolean gt(Float f) {\n                return c > f;\n        }\n\n        public boolean gt(Double d) {\n                return c > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return this.c <= i;\n        }\n\n        public boolean le(Byte b) {\n                return c <= b;\n        }\n\n        public boolean le(Short s) {\n                return c <= s;\n        }\n\n        public boolean le(Character c) {\n                return this.c <= c;\n        }\n\n        public boolean le(Long l) {\n                return c <= l;\n        }\n\n        public boolean le(Float f) {\n                return c <= f;\n        }\n\n        public boolean le(Double d) {\n                return c <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return this.c < i;\n        }\n\n        public boolean lt(Byte b) {\n                return c < b;\n        }\n\n        public boolean lt(Short s) {\n                return c < s;\n        }\n\n        public boolean lt(Character c) {\n                return this.c < c;\n        }\n\n        public boolean lt(Long l) {\n                return c < l;\n        }\n\n        public boolean lt(Float f) {\n                return c < f;\n        }\n\n        public boolean lt(Double d) {\n                return c < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public int multiply(Integer i) {\n                return this.c * i;\n        }\n\n        public int multiply(Byte b) {\n                return c * b;\n        }\n\n        public int multiply(Short s) {\n                return c * s;\n        }\n\n        public int multiply(Character c) {\n                return this.c * c;\n        }\n\n        public long multiply(Long l) {\n                return c * l;\n        }\n\n        public float multiply(Float f) {\n                return c * f;\n        }\n\n        public double multiply(Double d) {\n                return c * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        public int remainder(Integer i) {\n                return this.c % i;\n        }\n\n        public int remainder(Byte b) {\n                return c % b;\n        }\n\n        public int remainder(Short s) {\n                return c % s;\n        }\n\n        public int remainder(Character c) {\n                return this.c % c;\n        }\n\n        public long remainder(Long l) {\n                return c % l;\n        }\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        public int shiftLeft(Integer i) {\n                return this.c << i;\n        }\n\n        public int shiftLeft(Byte b) {\n                return c << b;\n        }\n\n        public int shiftLeft(Short s) {\n                return c << s;\n        }\n\n        public int shiftLeft(Character c) {\n                return this.c << c;\n        }\n\n        public int shiftLeft(Long l) {\n                return c << l;\n        }\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        public int shiftRight(Integer i) {\n                return this.c >> i;\n        }\n\n        public int shiftRight(Byte b) {\n                return c >> b;\n        }\n\n        public int shiftRight(Short s) {\n                return c >> s;\n        }\n\n        public int shiftRight(Character c) {\n                return this.c >> c;\n        }\n\n        public int shiftRight(Long l) {\n                return c >> l;\n        }\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public int subtract(Integer i) {\n                return this.c - i;\n        }\n\n        public int subtract(Byte b) {\n                return c - b;\n        }\n\n        public int subtract(Short s) {\n                return c - s;\n        }\n\n        public int subtract(Character c) {\n                return this.c - c;\n        }\n\n        public long subtract(Long l) {\n                return c - l;\n        }\n\n        public float subtract(Float f) {\n                return c - f;\n        }\n\n        public double subtract(Double d) {\n                return c - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        public int unsignedShiftRight(Integer i) {\n                return this.c >>> i;\n        }\n\n        public int unsignedShiftRight(Byte b) {\n                return c >>> b;\n        }\n\n        public int unsignedShiftRight(Short s) {\n                return c >>> s;\n        }\n\n        public int unsignedShiftRight(Character c) {\n                return this.c >>> c;\n        }\n\n        public int unsignedShiftRight(Long l) {\n                return c >>> l;\n        }\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public int xor(Integer i) {\n                return this.c ^ i;\n        }\n\n        public int xor(Byte b) {\n                return c ^ b;\n        }\n\n        public int xor(Short s) {\n                return c ^ s;\n        }\n\n        public int xor(Character c) {\n                return this.c ^ c;\n        }\n\n        public long xor(Long l) {\n                return c ^ l;\n        }\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(c) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(c, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(c, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(c, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(c, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(c, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(c, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(this.c, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichDouble.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Double\n */\npublic class RichDouble {\n        private Double d;\n\n        public RichDouble(Double d) {\n                this.d = d;\n        }\n\n        public double negate() {\n                return -d;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(d);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public double add(Integer i) {\n                return d + i;\n        }\n\n        public double add(Byte b) {\n                return d + b;\n        }\n\n        public double add(Short s) {\n                return d + s;\n        }\n\n        public double add(Character c) {\n                return d + c;\n        }\n\n        public double add(Long l) {\n                return d + l;\n        }\n\n        public double add(Float f) {\n                return d + f;\n        }\n\n        public double add(Double d) {\n                return this.d + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(d) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(d) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public double divide(Integer i) {\n                return d / i;\n        }\n\n        public double divide(Byte b) {\n                return d / b;\n        }\n\n        public double divide(Short s) {\n                return d / s;\n        }\n\n        public double divide(Character c) {\n                return d / c;\n        }\n\n        public double divide(Long l) {\n                return d / l;\n        }\n\n        public double divide(Float f) {\n                return d / f;\n        }\n\n        public double divide(Double d) {\n                return this.d / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return d >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return d >= b;\n        }\n\n        public boolean ge(Short s) {\n                return d >= s;\n        }\n\n        public boolean ge(Character c) {\n                return d >= c;\n        }\n\n        public boolean ge(Long l) {\n                return d >= l;\n        }\n\n        public boolean ge(Float f) {\n                return d >= f;\n        }\n\n        public boolean ge(Double d) {\n                return this.d >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return d > i;\n        }\n\n        public boolean gt(Byte b) {\n                return d > b;\n        }\n\n        public boolean gt(Short s) {\n                return d > s;\n        }\n\n        public boolean gt(Character c) {\n                return d > c;\n        }\n\n        public boolean gt(Long l) {\n                return d > l;\n        }\n\n        public boolean gt(Float f) {\n                return d > f;\n        }\n\n        public boolean gt(Double d) {\n                return this.d > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return d <= i;\n        }\n\n        public boolean le(Byte b) {\n                return d <= b;\n        }\n\n        public boolean le(Short s) {\n                return d <= s;\n        }\n\n        public boolean le(Character c) {\n                return d <= c;\n        }\n\n        public boolean le(Long l) {\n                return d <= l;\n        }\n\n        public boolean le(Float f) {\n                return d <= f;\n        }\n\n        public boolean le(Double d) {\n                return this.d <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return d < i;\n        }\n\n        public boolean lt(Byte b) {\n                return d < b;\n        }\n\n        public boolean lt(Short s) {\n                return d < s;\n        }\n\n        public boolean lt(Character c) {\n                return d < c;\n        }\n\n        public boolean lt(Long l) {\n                return d < l;\n        }\n\n        public boolean lt(Float f) {\n                return d < f;\n        }\n\n        public boolean lt(Double d) {\n                return this.d < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public double multiply(Integer i) {\n                return d * i;\n        }\n\n        public double multiply(Byte b) {\n                return d * b;\n        }\n\n        public double multiply(Short s) {\n                return d * s;\n        }\n\n        public double multiply(Character c) {\n                return d * c;\n        }\n\n        public double multiply(Long l) {\n                return d * l;\n        }\n\n        public double multiply(Float f) {\n                return d * f;\n        }\n\n        public double multiply(Double d) {\n                return this.d * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public double subtract(Integer i) {\n                return d - i;\n        }\n\n        public double subtract(Byte b) {\n                return d - b;\n        }\n\n        public double subtract(Short s) {\n                return d - s;\n        }\n\n        public double subtract(Character c) {\n                return d - c;\n        }\n\n        public double subtract(Long l) {\n                return d - l;\n        }\n\n        public double subtract(Float f) {\n                return d - f;\n        }\n\n        public double subtract(Double d) {\n                return this.d - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        // none\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(d) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(d, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(d, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(d, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(this.d, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(d, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(d, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(d, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichFloat.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Float\n */\npublic class RichFloat {\n        private Float f;\n\n        public RichFloat(Float f) {\n                this.f = f;\n        }\n\n        public float negate() {\n                return -f;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(f);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public float add(Integer i) {\n                return f + i;\n        }\n\n        public float add(Byte b) {\n                return f + b;\n        }\n\n        public float add(Short s) {\n                return f + s;\n        }\n\n        public float add(Character c) {\n                return f + c;\n        }\n\n        public float add(Long l) {\n                return f + l;\n        }\n\n        public float add(Float f) {\n                return this.f + f;\n        }\n\n        public double add(Double d) {\n                return f + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(f) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(f) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public float divide(Integer i) {\n                return f / i;\n        }\n\n        public float divide(Byte b) {\n                return f / b;\n        }\n\n        public float divide(Short s) {\n                return f / s;\n        }\n\n        public float divide(Character c) {\n                return f / c;\n        }\n\n        public float divide(Long l) {\n                return f / l;\n        }\n\n        public float divide(Float f) {\n                return this.f / f;\n        }\n\n        public double divide(Double d) {\n                return f / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return f >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return f >= b;\n        }\n\n        public boolean ge(Short s) {\n                return f >= s;\n        }\n\n        public boolean ge(Character c) {\n                return f >= c;\n        }\n\n        public boolean ge(Long l) {\n                return f >= l;\n        }\n\n        public boolean ge(Float f) {\n                return this.f >= f;\n        }\n\n        public boolean ge(Double d) {\n                return f >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return f > i;\n        }\n\n        public boolean gt(Byte b) {\n                return f > b;\n        }\n\n        public boolean gt(Short s) {\n                return f > s;\n        }\n\n        public boolean gt(Character c) {\n                return f > c;\n        }\n\n        public boolean gt(Long l) {\n                return f > l;\n        }\n\n        public boolean gt(Float f) {\n                return this.f > f;\n        }\n\n        public boolean gt(Double d) {\n                return f > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return f <= i;\n        }\n\n        public boolean le(Byte b) {\n                return f <= b;\n        }\n\n        public boolean le(Short s) {\n                return f <= s;\n        }\n\n        public boolean le(Character c) {\n                return f <= c;\n        }\n\n        public boolean le(Long l) {\n                return f <= l;\n        }\n\n        public boolean le(Float f) {\n                return this.f <= f;\n        }\n\n        public boolean le(Double d) {\n                return f <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return f < i;\n        }\n\n        public boolean lt(Byte b) {\n                return f < b;\n        }\n\n        public boolean lt(Short s) {\n                return f < s;\n        }\n\n        public boolean lt(Character c) {\n                return f < c;\n        }\n\n        public boolean lt(Long l) {\n                return f < l;\n        }\n\n        public boolean lt(Float f) {\n                return this.f < f;\n        }\n\n        public boolean lt(Double d) {\n                return f < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public float multiply(Integer i) {\n                return f * i;\n        }\n\n        public float multiply(Byte b) {\n                return f * b;\n        }\n\n        public float multiply(Short s) {\n                return f * s;\n        }\n\n        public float multiply(Character c) {\n                return f * c;\n        }\n\n        public float multiply(Long l) {\n                return f * l;\n        }\n\n        public float multiply(Float f) {\n                return this.f * f;\n        }\n\n        public double multiply(Double d) {\n                return f * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        // none\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public float subtract(Integer i) {\n                return f - i;\n        }\n\n        public float subtract(Byte b) {\n                return f - b;\n        }\n\n        public float subtract(Short s) {\n                return f - s;\n        }\n\n        public float subtract(Character c) {\n                return f - c;\n        }\n\n        public float subtract(Long l) {\n                return f - l;\n        }\n\n        public float subtract(Float f) {\n                return this.f - f;\n        }\n\n        public double subtract(Double d) {\n                return f - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        // none\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(f) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(f, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(f, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(this.f, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(f, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(f, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(f, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(f, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichInt.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\nimport lt.util.RangeList;\n\n/**\n * rich Integer\n */\npublic class RichInt {\n        private Integer i;\n\n        public RichInt(Integer i) {\n                this.i = i;\n        }\n\n        public int not() {\n                return ~i;\n        }\n\n        public int negate() {\n                return -i;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(i);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public int add(Integer i) {\n                return this.i + i;\n        }\n\n        public int add(Byte b) {\n                return i + b;\n        }\n\n        public int add(Short s) {\n                return i + s;\n        }\n\n        public int add(Character c) {\n                return i + c;\n        }\n\n        public long add(Long l) {\n                return i + l;\n        }\n\n        public float add(Float f) {\n                return i + f;\n        }\n\n        public double add(Double d) {\n                return i + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public int and(Integer i) {\n                return this.i & i;\n        }\n\n        public int and(Byte b) {\n                return i & b;\n        }\n\n        public int and(Short s) {\n                return i & s;\n        }\n\n        public int and(Character c) {\n                return i & c;\n        }\n\n        public long and(Long l) {\n                return i & l;\n        }\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(i) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public int or(Integer i) {\n                return this.i | i;\n        }\n\n        public int or(Byte b) {\n                return i | b;\n        }\n\n        public int or(Short s) {\n                return i | s;\n        }\n\n        public int or(Character c) {\n                return i | c;\n        }\n\n        public long or(Long l) {\n                return i | l;\n        }\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(i) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public int divide(Integer i) {\n                return this.i / i;\n        }\n\n        public int divide(Byte b) {\n                return i / b;\n        }\n\n        public int divide(Short s) {\n                return i / s;\n        }\n\n        public int divide(Character c) {\n                return i / c;\n        }\n\n        public long divide(Long l) {\n                return i / l;\n        }\n\n        public float divide(Float f) {\n                return i / f;\n        }\n\n        public double divide(Double d) {\n                return i / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return this.i >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return i >= b;\n        }\n\n        public boolean ge(Short s) {\n                return i >= s;\n        }\n\n        public boolean ge(Character c) {\n                return i >= c;\n        }\n\n        public boolean ge(Long l) {\n                return i >= l;\n        }\n\n        public boolean ge(Float f) {\n                return i >= f;\n        }\n\n        public boolean ge(Double d) {\n                return i >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return this.i > i;\n        }\n\n        public boolean gt(Byte b) {\n                return i > b;\n        }\n\n        public boolean gt(Short s) {\n                return i > s;\n        }\n\n        public boolean gt(Character c) {\n                return i > c;\n        }\n\n        public boolean gt(Long l) {\n                return i > l;\n        }\n\n        public boolean gt(Float f) {\n                return i > f;\n        }\n\n        public boolean gt(Double d) {\n                return i > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return this.i <= i;\n        }\n\n        public boolean le(Byte b) {\n                return i <= b;\n        }\n\n        public boolean le(Short s) {\n                return i <= s;\n        }\n\n        public boolean le(Character c) {\n                return i <= c;\n        }\n\n        public boolean le(Long l) {\n                return i <= l;\n        }\n\n        public boolean le(Float f) {\n                return i <= f;\n        }\n\n        public boolean le(Double d) {\n                return i <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return this.i < i;\n        }\n\n        public boolean lt(Byte b) {\n                return i < b;\n        }\n\n        public boolean lt(Short s) {\n                return i < s;\n        }\n\n        public boolean lt(Character c) {\n                return i < c;\n        }\n\n        public boolean lt(Long l) {\n                return i < l;\n        }\n\n        public boolean lt(Float f) {\n                return i < f;\n        }\n\n        public boolean lt(Double d) {\n                return i < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public int multiply(Integer i) {\n                return this.i * i;\n        }\n\n        public int multiply(Byte b) {\n                return i * b;\n        }\n\n        public int multiply(Short s) {\n                return i * s;\n        }\n\n        public int multiply(Character c) {\n                return i * c;\n        }\n\n        public long multiply(Long l) {\n                return i * l;\n        }\n\n        public float multiply(Float f) {\n                return i * f;\n        }\n\n        public double multiply(Double d) {\n                return i * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        public int remainder(Integer i) {\n                return this.i % i;\n        }\n\n        public int remainder(Byte b) {\n                return i % b;\n        }\n\n        public int remainder(Short s) {\n                return i % s;\n        }\n\n        public int remainder(Character c) {\n                return i % c;\n        }\n\n        public long remainder(Long l) {\n                return i % l;\n        }\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        public int shiftLeft(Integer i) {\n                return this.i << i;\n        }\n\n        public int shiftLeft(Byte b) {\n                return i << b;\n        }\n\n        public int shiftLeft(Short s) {\n                return i << s;\n        }\n\n        public int shiftLeft(Character c) {\n                return i << c;\n        }\n\n        public int shiftLeft(Long l) {\n                return i << l;\n        }\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        public int shiftRight(Integer i) {\n                return this.i >> i;\n        }\n\n        public int shiftRight(Byte b) {\n                return i >> b;\n        }\n\n        public int shiftRight(Short s) {\n                return i >> s;\n        }\n\n        public int shiftRight(Character c) {\n                return i >> c;\n        }\n\n        public int shiftRight(Long l) {\n                return i >> l;\n        }\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public int subtract(Integer i) {\n                return this.i - i;\n        }\n\n        public int subtract(Byte b) {\n                return i - b;\n        }\n\n        public int subtract(Short s) {\n                return i - s;\n        }\n\n        public int subtract(Character c) {\n                return i - c;\n        }\n\n        public long subtract(Long l) {\n                return i - l;\n        }\n\n        public float subtract(Float f) {\n                return i - f;\n        }\n\n        public double subtract(Double d) {\n                return i - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        public int unsignedShiftRight(Integer i) {\n                return this.i >>> i;\n        }\n\n        public int unsignedShiftRight(Byte b) {\n                return i >>> b;\n        }\n\n        public int unsignedShiftRight(Short s) {\n                return i >>> s;\n        }\n\n        public int unsignedShiftRight(Character c) {\n                return i >>> c;\n        }\n\n        public int unsignedShiftRight(Long l) {\n                return i >>> l;\n        }\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public int xor(Integer i) {\n                return this.i ^ i;\n        }\n\n        public int xor(Byte b) {\n                return i ^ b;\n        }\n\n        public int xor(Short s) {\n                return i ^ s;\n        }\n\n        public int xor(Character c) {\n                return i ^ c;\n        }\n\n        public long xor(Long l) {\n                return i ^ l;\n        }\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(i) ^ b;\n        }\n\n        /*\n         * =========\n         *   range\n         * =========\n         */\n\n        public RangeList to(Integer i) {\n                return new RangeList(this.i, i, true);\n        }\n\n        public RangeList until(Integer i) {\n                return new RangeList(this.i, i, false);\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(this.i, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(i, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(i, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(i, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(i, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(i, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(i, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichLong.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Long\n */\npublic class RichLong {\n        private Long l;\n\n        public RichLong(Long l) {\n                this.l = l;\n        }\n\n        public long not() {\n                return ~l;\n        }\n\n        public long negate() {\n                return -l;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(l);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public long add(Integer i) {\n                return l + i;\n        }\n\n        public long add(Byte b) {\n                return l + b;\n        }\n\n        public long add(Short s) {\n                return l + s;\n        }\n\n        public long add(Character c) {\n                return l + c;\n        }\n\n        public long add(Long l) {\n                return this.l + l;\n        }\n\n        public float add(Float f) {\n                return l + f;\n        }\n\n        public double add(Double d) {\n                return l + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public long and(Integer i) {\n                return l & i;\n        }\n\n        public long and(Byte b) {\n                return l & b;\n        }\n\n        public long and(Short s) {\n                return l & s;\n        }\n\n        public long and(Character c) {\n                return l & c;\n        }\n\n        public long and(Long l) {\n                return this.l & l;\n        }\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(l) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public long or(Integer i) {\n                return l | i;\n        }\n\n        public long or(Byte b) {\n                return l | b;\n        }\n\n        public long or(Short s) {\n                return l | s;\n        }\n\n        public long or(Character c) {\n                return l | c;\n        }\n\n        public long or(Long l) {\n                return this.l | l;\n        }\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(l) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public long divide(Integer i) {\n                return l / i;\n        }\n\n        public long divide(Byte b) {\n                return l / b;\n        }\n\n        public long divide(Short s) {\n                return l / s;\n        }\n\n        public long divide(Character c) {\n                return l / c;\n        }\n\n        public long divide(Long l) {\n                return this.l / l;\n        }\n\n        public float divide(Float f) {\n                return l / f;\n        }\n\n        public double divide(Double d) {\n                return l / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return l >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return l >= b;\n        }\n\n        public boolean ge(Short s) {\n                return l >= s;\n        }\n\n        public boolean ge(Character c) {\n                return l >= c;\n        }\n\n        public boolean ge(Long l) {\n                return this.l >= l;\n        }\n\n        public boolean ge(Float f) {\n                return l >= f;\n        }\n\n        public boolean ge(Double d) {\n                return l >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return l > i;\n        }\n\n        public boolean gt(Byte b) {\n                return l > b;\n        }\n\n        public boolean gt(Short s) {\n                return l > s;\n        }\n\n        public boolean gt(Character c) {\n                return l > c;\n        }\n\n        public boolean gt(Long l) {\n                return this.l > l;\n        }\n\n        public boolean gt(Float f) {\n                return l > f;\n        }\n\n        public boolean gt(Double d) {\n                return l > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return l <= i;\n        }\n\n        public boolean le(Byte b) {\n                return l <= b;\n        }\n\n        public boolean le(Short s) {\n                return l <= s;\n        }\n\n        public boolean le(Character c) {\n                return l <= c;\n        }\n\n        public boolean le(Long l) {\n                return this.l <= l;\n        }\n\n        public boolean le(Float f) {\n                return l <= f;\n        }\n\n        public boolean le(Double d) {\n                return l <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return l < i;\n        }\n\n        public boolean lt(Byte b) {\n                return l < b;\n        }\n\n        public boolean lt(Short s) {\n                return l < s;\n        }\n\n        public boolean lt(Character c) {\n                return l < c;\n        }\n\n        public boolean lt(Long l) {\n                return this.l < l;\n        }\n\n        public boolean lt(Float f) {\n                return l < f;\n        }\n\n        public boolean lt(Double d) {\n                return l < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public long multiply(Integer i) {\n                return l * i;\n        }\n\n        public long multiply(Byte b) {\n                return l * b;\n        }\n\n        public long multiply(Short s) {\n                return l * s;\n        }\n\n        public long multiply(Character c) {\n                return l * c;\n        }\n\n        public long multiply(Long l) {\n                return this.l * l;\n        }\n\n        public float multiply(Float f) {\n                return l * f;\n        }\n\n        public double multiply(Double d) {\n                return l * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        public long remainder(Integer i) {\n                return l % i;\n        }\n\n        public long remainder(Byte b) {\n                return l % b;\n        }\n\n        public long remainder(Short s) {\n                return l % s;\n        }\n\n        public long remainder(Character c) {\n                return l % c;\n        }\n\n        public long remainder(Long l) {\n                return this.l % l;\n        }\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        public long shiftLeft(Integer i) {\n                return l << i;\n        }\n\n        public long shiftLeft(Byte b) {\n                return l << b;\n        }\n\n        public long shiftLeft(Short s) {\n                return l << s;\n        }\n\n        public long shiftLeft(Character c) {\n                return l << c;\n        }\n\n        public long shiftLeft(Long l) {\n                return this.l << l;\n        }\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        public long shiftRight(Integer i) {\n                return l >> i;\n        }\n\n        public long shiftRight(Byte b) {\n                return l >> b;\n        }\n\n        public long shiftRight(Short s) {\n                return l >> s;\n        }\n\n        public long shiftRight(Character c) {\n                return l >> c;\n        }\n\n        public long shiftRight(Long l) {\n                return this.l >> l;\n        }\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public long subtract(Integer i) {\n                return l - i;\n        }\n\n        public long subtract(Byte b) {\n                return l - b;\n        }\n\n        public long subtract(Short s) {\n                return l - s;\n        }\n\n        public long subtract(Character c) {\n                return l - c;\n        }\n\n        public long subtract(Long l) {\n                return this.l - l;\n        }\n\n        public float subtract(Float f) {\n                return l - f;\n        }\n\n        public double subtract(Double d) {\n                return l - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        public long unsignedShiftRight(Integer i) {\n                return l >>> i;\n        }\n\n        public long unsignedShiftRight(Byte b) {\n                return l >>> b;\n        }\n\n        public long unsignedShiftRight(Short s) {\n                return l >>> s;\n        }\n\n        public long unsignedShiftRight(Character c) {\n                return l >>> c;\n        }\n\n        public long unsignedShiftRight(Long l) {\n                return this.l >>> l;\n        }\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public long xor(Integer i) {\n                return l ^ i;\n        }\n\n        public long xor(Byte b) {\n                return l ^ b;\n        }\n\n        public long xor(Short s) {\n                return l ^ s;\n        }\n\n        public long xor(Character c) {\n                return l ^ c;\n        }\n\n        public long xor(Long l) {\n                return this.l ^ l;\n        }\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(l) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(l, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(this.l, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(l, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(l, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(l, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(l, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(l, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichObject.java",
    "content": "package lt.lang.implicit;\n\n/**\n * rich Object\n */\npublic class RichObject {\n        private Object o;\n\n        public RichObject(Object o) {\n                this.o = o;\n        }\n\n        public String add(String s) {\n                return o + s;\n        }\n\n        public boolean eq(Object that) {\n                return o.equals(that);\n        }\n\n        public boolean ne(Object that) {\n                return !this.eq(that);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichShort.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.LtRuntime;\n\n/**\n * rich Short\n */\npublic class RichShort {\n        private Short s;\n\n        public RichShort(Short s) {\n                this.s = s;\n        }\n\n        public int not() {\n                return ~s;\n        }\n\n        public int negate() {\n                return -s;\n        }\n\n        public boolean logicNot() throws Throwable {\n                return !LtRuntime.castToBool(s);\n        }\n\n        /*\n         * ============\n         *     add\n         * ============\n         */\n\n        public int add(Integer i) {\n                return this.s + i;\n        }\n\n        public int add(Byte b) {\n                return this.s + b;\n        }\n\n        public int add(Short s) {\n                return this.s + s;\n        }\n\n        public int add(Character c) {\n                return s + c;\n        }\n\n        public long add(Long l) {\n                return s + l;\n        }\n\n        public float add(Float f) {\n                return s + f;\n        }\n\n        public double add(Double d) {\n                return s + d;\n        }\n\n        /*\n         * ============\n         *     and\n         * ============\n         */\n\n        public int and(Integer i) {\n                return this.s & i;\n        }\n\n        public int and(Byte b) {\n                return this.s & b;\n        }\n\n        public int and(Short s) {\n                return this.s & s;\n        }\n\n        public int and(Character c) {\n                return s & c;\n        }\n\n        public long and(Long l) {\n                return s & l;\n        }\n\n        public boolean and(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.s) & b;\n        }\n\n        /*\n         * ============\n         *     or\n         * ============\n         */\n\n        public int or(Integer i) {\n                return this.s | i;\n        }\n\n        public int or(Byte b) {\n                return this.s | b;\n        }\n\n        public int or(Short s) {\n                return this.s | s;\n        }\n\n        public int or(Character c) {\n                return s | c;\n        }\n\n        public long or(Long l) {\n                return s | l;\n        }\n\n        public boolean or(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.s) | b;\n        }\n\n        /*\n         * ============\n         *    divide\n         * ============\n         */\n\n        public int divide(Integer i) {\n                return this.s / i;\n        }\n\n        public int divide(Byte b) {\n                return this.s / b;\n        }\n\n        public int divide(Short s) {\n                return this.s / s;\n        }\n\n        public int divide(Character c) {\n                return s / c;\n        }\n\n        public long divide(Long l) {\n                return s / l;\n        }\n\n        public float divide(Float f) {\n                return s / f;\n        }\n\n        public double divide(Double d) {\n                return s / d;\n        }\n\n        /*\n         * ============\n         *      ge\n         * ============\n         */\n\n        public boolean ge(Integer i) {\n                return this.s >= i;\n        }\n\n        public boolean ge(Byte b) {\n                return this.s >= b;\n        }\n\n        public boolean ge(Short s) {\n                return this.s >= s;\n        }\n\n        public boolean ge(Character c) {\n                return s >= c;\n        }\n\n        public boolean ge(Long l) {\n                return s >= l;\n        }\n\n        public boolean ge(Float f) {\n                return s >= f;\n        }\n\n        public boolean ge(Double d) {\n                return s >= d;\n        }\n\n        /*\n         * ============\n         *      gt\n         * ============\n         */\n\n        public boolean gt(Integer i) {\n                return this.s > i;\n        }\n\n        public boolean gt(Byte b) {\n                return this.s > b;\n        }\n\n        public boolean gt(Short s) {\n                return this.s > s;\n        }\n\n        public boolean gt(Character c) {\n                return s > c;\n        }\n\n        public boolean gt(Long l) {\n                return s > l;\n        }\n\n        public boolean gt(Float f) {\n                return s > f;\n        }\n\n        public boolean gt(Double d) {\n                return s > d;\n        }\n\n        /*\n         * ============\n         *      le\n         * ============\n         */\n\n        public boolean le(Integer i) {\n                return this.s <= i;\n        }\n\n        public boolean le(Byte b) {\n                return this.s <= b;\n        }\n\n        public boolean le(Short s) {\n                return this.s <= s;\n        }\n\n        public boolean le(Character c) {\n                return s <= c;\n        }\n\n        public boolean le(Long l) {\n                return s <= l;\n        }\n\n        public boolean le(Float f) {\n                return s <= f;\n        }\n\n        public boolean le(Double d) {\n                return s <= d;\n        }\n\n        /*\n         * ============\n         *      lt\n         * ============\n         */\n\n        public boolean lt(Integer i) {\n                return this.s < i;\n        }\n\n        public boolean lt(Byte b) {\n                return this.s < b;\n        }\n\n        public boolean lt(Short s) {\n                return this.s < s;\n        }\n\n        public boolean lt(Character c) {\n                return s < c;\n        }\n\n        public boolean lt(Long l) {\n                return s < l;\n        }\n\n        public boolean lt(Float f) {\n                return s < f;\n        }\n\n        public boolean lt(Double d) {\n                return s < d;\n        }\n\n        /*\n         * ============\n         *   multiply\n         * ============\n         */\n\n        public int multiply(Integer i) {\n                return this.s * i;\n        }\n\n        public int multiply(Byte b) {\n                return this.s * b;\n        }\n\n        public int multiply(Short s) {\n                return this.s * s;\n        }\n\n        public int multiply(Character c) {\n                return s * c;\n        }\n\n        public long multiply(Long l) {\n                return s * l;\n        }\n\n        public float multiply(Float f) {\n                return s * f;\n        }\n\n        public double multiply(Double d) {\n                return s * d;\n        }\n\n        /*\n         * ============\n         *   remainder\n         * ============\n         */\n\n        public int remainder(Integer i) {\n                return this.s % i;\n        }\n\n        public int remainder(Byte b) {\n                return this.s % b;\n        }\n\n        public int remainder(Short s) {\n                return this.s % s;\n        }\n\n        public int remainder(Character c) {\n                return s % c;\n        }\n\n        public long remainder(Long l) {\n                return s % l;\n        }\n\n        /*\n         * ============\n         *   shiftLeft\n         * ============\n         */\n\n        public int shiftLeft(Integer i) {\n                return this.s << i;\n        }\n\n        public int shiftLeft(Byte b) {\n                return this.s << b;\n        }\n\n        public int shiftLeft(Short s) {\n                return this.s << s;\n        }\n\n        public int shiftLeft(Character c) {\n                return s << c;\n        }\n\n        public int shiftLeft(Long l) {\n                return s << l;\n        }\n\n        /*\n         * ============\n         *  shiftRight\n         * ============\n         */\n\n        public int shiftRight(Integer i) {\n                return this.s >> i;\n        }\n\n        public int shiftRight(Byte b) {\n                return this.s >> b;\n        }\n\n        public int shiftRight(Short s) {\n                return this.s >> s;\n        }\n\n        public int shiftRight(Character c) {\n                return s >> c;\n        }\n\n        public int shiftRight(Long l) {\n                return s >> l;\n        }\n\n        /*\n         * ============\n         *   subtract\n         * ============\n         */\n\n        public int subtract(Integer i) {\n                return this.s - i;\n        }\n\n        public int subtract(Byte b) {\n                return this.s - b;\n        }\n\n        public int subtract(Short s) {\n                return this.s - s;\n        }\n\n        public int subtract(Character c) {\n                return s - c;\n        }\n\n        public long subtract(Long l) {\n                return s - l;\n        }\n\n        public float subtract(Float f) {\n                return s - f;\n        }\n\n        public double subtract(Double d) {\n                return s - d;\n        }\n\n        /*\n         * ====================\n         *  unsignedShiftRight\n         * ====================\n         */\n\n        public int unsignedShiftRight(Integer i) {\n                return this.s >>> i;\n        }\n\n        public int unsignedShiftRight(Byte b) {\n                return this.s >>> b;\n        }\n\n        public int unsignedShiftRight(Short s) {\n                return this.s >>> s;\n        }\n\n        public int unsignedShiftRight(Character c) {\n                return s >>> c;\n        }\n\n        public int unsignedShiftRight(Long l) {\n                return s >>> l;\n        }\n\n        /*\n         * ============\n         *     xor\n         * ============\n         */\n\n        public int xor(Integer i) {\n                return this.s ^ i;\n        }\n\n        public int xor(Byte b) {\n                return this.s ^ b;\n        }\n\n        public int xor(Short s) {\n                return this.s ^ s;\n        }\n\n        public int xor(Character c) {\n                return s ^ c;\n        }\n\n        public long xor(Long l) {\n                return s ^ l;\n        }\n\n        public boolean xor(Boolean b) throws Throwable {\n                return LtRuntime.castToBool(this.s) ^ b;\n        }\n\n        /*\n         * ============\n         *     pow\n         * ============\n         */\n\n        public double pow(Integer i) {\n                return Math.pow(s, i);\n        }\n\n        public double pow(Long l) {\n                return Math.pow(s, l);\n        }\n\n        public double pow(Float f) {\n                return Math.pow(s, f);\n        }\n\n        public double pow(Double d) {\n                return Math.pow(s, d);\n        }\n\n        public double pow(Byte b) {\n                return Math.pow(s, b);\n        }\n\n        public double pow(Short s) {\n                return Math.pow(this.s, s);\n        }\n\n        public double pow(Character c) {\n                return Math.pow(s, c);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/RichString.java",
    "content": "package lt.lang.implicit;\n\nimport java.util.regex.Pattern;\n\n/**\n * rich String\n */\npublic class RichString {\n        private String s;\n        private char[] chars;\n\n        public RichString(String s) {\n                this.s = s;\n                this.chars = s.toCharArray();\n        }\n\n        public String add(Object o) {\n                return s + o;\n        }\n\n        public Pattern r() {\n                return Pattern.compile(s);\n        }\n\n        public Pattern r(int flags) {\n                return Pattern.compile(s, flags);\n        }\n\n        public char get(int index) {\n                return chars[index];\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/StringImplicit.java",
    "content": "package lt.lang.implicit;\n\nimport lt.runtime.Implicit;\nimport lt.runtime.LatteObject;\n\n/**\n * implicit casts for string\n */\n@Implicit\n@LatteObject\npublic class StringImplicit {\n        public static final StringImplicit singletonInstance = new StringImplicit();\n\n        private StringImplicit() {\n        }\n\n        @Implicit\n        public final RichString cast(String s) {\n                return new RichString(s);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/collection/RichIterable.java",
    "content": "package lt.lang.implicit.collection;\n\nimport lt.lang.function.Function1;\n\nimport java.util.LinkedList;\nimport java.util.List;\n\n/**\n * rich iterator\n */\npublic class RichIterable<T> {\n        private final Iterable<T> iterable;\n\n        public RichIterable(Iterable<T> iterable) {\n                this.iterable = iterable;\n        }\n\n        public void forEach(Function1<Void, ? super T> f) throws Exception {\n                for (T t : iterable) {\n                        f.apply(t);\n                }\n        }\n\n        public List<T> filter(Function1<Boolean, ? super T> f) throws Exception {\n                List<T> list = new LinkedList<T>();\n                for (T t : iterable) {\n                        if (f.apply(t)) {\n                                list.add(t);\n                        }\n                }\n                return list;\n        }\n\n        public <U> List<U> map(Function1<? extends U, ? super T> f) throws Exception {\n                List<U> list = new LinkedList<U>();\n                for (T t : iterable) {\n                        list.add(f.apply(t));\n                }\n                return list;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/collection/RichList.java",
    "content": "package lt.lang.implicit.collection;\n\nimport java.util.Collection;\nimport java.util.Collections;\nimport java.util.LinkedList;\nimport java.util.List;\n\n/**\n * rich list\n */\n@SuppressWarnings(\"unused\")\npublic class RichList<E> {\n        private final List<E> list;\n\n        public RichList(List<E> list) {\n                this.list = list;\n        }\n\n        /**\n         * concat one element and return a new List.\n         * the current list will not be modified\n         *\n         * @param elem the element to concat\n         * @return a new List containing elements in current list and the given element\n         */\n        public List<E> concat(E elem) {\n                if (elem instanceof Collection) {\n                        return concat((Collection) elem);\n                }\n                List<E> newList = new LinkedList<E>(list);\n                newList.add(elem);\n                return newList;\n        }\n\n        /**\n         * concat all elements and return a new List.\n         * the current list will not be modified\n         *\n         * @param collection elements to concat\n         * @return a new List containing elements in both current list and the given list\n         */\n        @SuppressWarnings(\"unchecked\")\n        public List<E> concat(Collection collection) {\n                List<E> newList = new LinkedList<E>(list);\n                newList.addAll(collection);\n                return newList;\n        }\n\n        /**\n         * put all elements into a string, the string is separated by the given separator\n         *\n         * @param separator separator\n         * @return a string containing all elements and separated by the separator\n         */\n        public String join(String separator) {\n                StringBuilder sb = new StringBuilder();\n                boolean isFirst = true;\n                for (E e : list) {\n                        if (isFirst) isFirst = false;\n                        else sb.append(separator);\n                        sb.append(e);\n                }\n                return sb.toString();\n        }\n\n        /**\n         * reverse the elements' sequence<br>\n         * the method will modify the current List and won't generate a new List\n         *\n         * @return the original List object, also known as <code>this</code>\n         */\n        public List<E> reverse() {\n                Collections.reverse(list);\n                return list;\n        }\n\n        /**\n         * remove and return the first element\n         *\n         * @return the removed value\n         */\n        public E shift() {\n                return list.remove(0);\n        }\n\n        /**\n         * select elements from current list\n         *\n         * @param fromIndex low endpoint (inclusive) of the subList (negative number means size()-fromIndex)\n         * @param toIndex   high endpoint (exclusive) of the subList (negative number means size()-toIndex)\n         * @return a List containing selected elements\n         */\n        public List<E> slice(int fromIndex, int toIndex) {\n                int size = list.size();\n                if (fromIndex < 0) fromIndex = size - fromIndex;\n                if (toIndex < 0) toIndex = size - toIndex;\n                return new LinkedList<E>(list.subList(fromIndex, toIndex));\n        }\n\n        /**\n         * select elements from current list\n         *\n         * @param fromIndex the subList starts at this position\n         * @return a List containing selected elements\n         */\n        public List slice(int fromIndex) {\n                return slice(fromIndex, list.size());\n        }\n\n        /**\n         * insert one element to the head of the List\n         *\n         * @param element the element to insert\n         * @return the original List object, also known as <code>this</code>\n         */\n        public List<E> unshift(E element) {\n                if (element instanceof Collection) {\n                        return unshift((Collection) element);\n                }\n                list.add(0, element);\n                return list;\n        }\n\n        /**\n         * insert all elements to the head of the List\n         *\n         * @param elements elements to be inserted\n         * @return the original List object, also known as <code>this</code>\n         */\n        @SuppressWarnings(\"unchecked\")\n        public List<E> unshift(Collection elements) {\n                list.addAll(0, elements);\n                return list;\n        }\n\n        /**\n         * Returns the number of elements in this list.\n         *\n         * @return the number of elements in this list\n         */\n        public int length() {\n                return list.size();\n        }\n\n        /**\n         * create an immutable list with all current elements contained\n         *\n         * @return an immutable list\n         */\n        public List<E> immutable() {\n                return Collections.unmodifiableList(list);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/collection/RichMap.java",
    "content": "package lt.lang.implicit.collection;\n\nimport java.util.Collections;\nimport java.util.Map;\n\n/**\n * rich map\n */\npublic class RichMap<K, V> {\n        private final Map<K, V> map;\n\n        public RichMap(Map<K, V> map) {\n                this.map = map;\n        }\n\n        /**\n         * create an immutable map with all current entries contained\n         *\n         * @return an immutable map\n         */\n        public Map<K, V> immutable() {\n                return Collections.unmodifiableMap(map);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/implicit/collection/RichSet.java",
    "content": "package lt.lang.implicit.collection;\n\nimport java.util.Collections;\nimport java.util.Set;\n\n/**\n * rich set\n */\npublic class RichSet<E> {\n        private final Set<E> set;\n\n        public RichSet(Set<E> set) {\n                this.set = set;\n        }\n\n        /**\n         * get an immutable set with all current elements contained\n         *\n         * @return an immutable set\n         */\n        public Set<E> immutable() {\n                return Collections.unmodifiableSet(set);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/lang/js.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.lang;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.SClassDef;\nimport lt.compiler.semantic.Value;\nimport lt.compiler.semantic.builtin.StringConstantValue;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.OneVariableOperation;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.operation.UnaryOneVariableOperation;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.generator.SourceGenerator;\n\nimport java.util.*;\n\n/**\n * transform latte AST into javascript code\n */\npublic class js implements SourceGenerator {\n        private static final int INDENT = 4;\n\n        private List<Statement> ast;\n        private SemanticProcessor processor;\n        private ErrorManager err;\n\n        @Override\n        public void init(List<Statement> ast, SemanticProcessor processor, SemanticScope scope, LineCol lineCol, ErrorManager err) {\n                this.ast = ast;\n                this.processor = processor;\n                this.err = err;\n        }\n\n        /**\n         * start the generation process\n         *\n         * @return js code\n         * @throws SyntaxException exception\n         */\n        @Override\n        public Value generate() throws SyntaxException {\n                StringBuilder sb = new StringBuilder();\n                buildStatements(sb, ast, 0);\n                StringConstantValue s = new StringConstantValue(sb.toString().trim());\n                s.setType((SClassDef) processor.getTypeWithName(\"java.lang.String\", LineCol.SYNTHETIC));\n                return s;\n        }\n\n        @Override\n        public int resultType() {\n                return VALUE;\n        }\n\n        /**\n         * build a list of statements. the `;` at the end is automatically generated.\n         *\n         * @param sb          string builder\n         * @param statements  statements\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildStatements(StringBuilder sb, List<Statement> statements, int indentation) throws SyntaxException {\n                for (Statement stmt : statements) {\n                        buildStatement(sb, stmt, indentation);\n                        if (sb.charAt(sb.length() - 1) != '\\n') {\n                                sb.append(\";\\n\");\n                        }\n                }\n        }\n\n        /**\n         * build indentation spaces.\n         *\n         * @param sb          string builder\n         * @param indentation spaces count\n         */\n        private void buildIndentation(StringBuilder sb, int indentation) {\n                for (int i = 0; i < indentation; ++i) {\n                        sb.append(\" \");\n                }\n        }\n\n        /**\n         * no annotations\n         *\n         * @param annos annotations' container\n         * @throws SyntaxException exception\n         */\n        private void assertNoAnno(Collection<AST.Anno> annos) throws SyntaxException {\n                if (!annos.isEmpty()) {\n                        err.SyntaxException(\"JavaScript don't have annotations\", annos.iterator().next().line_col());\n                }\n        }\n\n        /**\n         * no modifiers\n         *\n         * @param modifiers modifiers' container\n         * @throws SyntaxException exception\n         */\n        private void assertNoModifier(Collection<Modifier> modifiers) throws SyntaxException {\n                if (!modifiers.isEmpty()) {\n                        if (modifiers.size() != 1 || !modifiers.contains(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC))) {\n                                err.SyntaxException(\"JavaScript don't have modifiers\", modifiers.iterator().next().line_col());\n                        }\n                }\n        }\n\n        /**\n         * no type\n         *\n         * @param type the type, which asserts to be null.\n         * @throws SyntaxException exception\n         */\n        private void assertNoType(AST.Access type) throws SyntaxException {\n                if (type != null) {\n                        err.SyntaxException(\"JavaScript don't have type\", type.line_col());\n                }\n        }\n\n        /**\n         * build statements.\n         *\n         * @param sb          string builder\n         * @param stmt        statements\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildStatement(StringBuilder sb, Statement stmt, int indentation) throws SyntaxException {\n                if (stmt instanceof ClassDef) {\n                        buildClass(sb, (ClassDef) stmt, indentation);\n                } else if (stmt instanceof InterfaceDef) {\n                        err.SyntaxException(\"JavaScript don't have interfaces\", stmt.line_col());\n                } else if (stmt instanceof FunDef) {\n                        buildFun(sb, (FunDef) stmt, indentation);\n                } else if (stmt instanceof MethodDef) {\n                        buildMethod(sb, (MethodDef) stmt, indentation);\n                } else if (stmt instanceof Pre) {\n                        err.SyntaxException(\"JavaScript don't support \" + stmt, stmt.line_col());\n                } else if (stmt instanceof Expression) {\n                        buildIndentation(sb, indentation);\n                        buildExpression(sb, (Expression) stmt, indentation);\n                } else if (stmt instanceof AST.Anno) {\n                        err.SyntaxException(\"JavaScript don't support annotations\", stmt.line_col());\n                } else if (stmt instanceof AST.For) {\n                        buildFor(sb, (AST.For) stmt, indentation);\n                } else if (stmt instanceof AST.If) {\n                        buildIf(sb, (AST.If) stmt, indentation);\n                } else if (stmt instanceof AST.Pass) {\n                        // do nothing\n                        buildIndentation(sb, indentation);\n                        sb.append(\"/* pass */\");\n                } else if (stmt instanceof AST.Return) {\n                        buildIndentation(sb, indentation);\n                        sb.append(\"return \");\n\n                        buildExpression(sb, ((AST.Return) stmt).exp, indentation);\n                } else if (stmt instanceof AST.StaticScope) {\n                        err.SyntaxException(\"JavaScript don't support static\", stmt.line_col());\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"function static() {\\n\");\n\n                        buildStatements(sb, ((AST.StaticScope) stmt).statements, indentation + INDENT);\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"}\\n\");\n                } else if (stmt instanceof AST.Synchronized) {\n                        err.SyntaxException(\"JavaScript don't support synchronized\", stmt.line_col());\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"function synchronized() {\\n\");\n\n                        buildStatements(sb, ((AST.Synchronized) stmt).statements, indentation + INDENT);\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"}\\n\");\n                } else if (stmt instanceof AST.Throw) {\n                        buildIndentation(sb, indentation);\n                        sb.append(\"throw \");\n\n                        buildExpression(sb, ((AST.Throw) stmt).exp, indentation);\n                } else if (stmt instanceof AST.Try) {\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"try {\\n\");\n\n                        buildStatements(sb, ((AST.Try) stmt).statements, indentation + INDENT);\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"} catch (\").append(((AST.Try) stmt).varName).append(\") {\\n\");\n\n                        buildStatements(sb, ((AST.Try) stmt).catchStatements, indentation + INDENT);\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"} finally {\\n\");\n\n                        buildStatements(sb, ((AST.Try) stmt).fin, indentation + INDENT);\n\n                        buildIndentation(sb, indentation);\n                        sb.append(\"}\\n\");\n                } else if (stmt instanceof AST.While) {\n                        if (((AST.While) stmt).doWhile) {\n                                buildIndentation(sb, indentation);\n                                sb.append(\"do {\\n\");\n\n                                buildStatements(sb, ((AST.While) stmt).statements, indentation + INDENT);\n\n                                buildIndentation(sb, indentation);\n                                sb.append(\"} while (\");\n\n                                buildExpression(sb, ((AST.While) stmt).condition, indentation);\n\n                                sb.append(\");\\n\");\n                        } else {\n                                buildIndentation(sb, indentation);\n                                sb.append(\"while (\");\n\n                                buildExpression(sb, ((AST.While) stmt).condition, indentation);\n                                sb.append(\") {\\n\");\n                                buildStatements(sb, ((AST.While) stmt).statements, indentation + INDENT);\n\n                                buildIndentation(sb, indentation);\n                                sb.append(\"}\\n\");\n                        }\n                } else if (stmt instanceof AST.Continue) {\n                        buildIndentation(sb, indentation);\n                        sb.append(\"continue\");\n                } else if (stmt instanceof AST.Break) {\n                        buildIndentation(sb, indentation);\n                        sb.append(\"break\");\n                } else throw new LtBug(\"unknown token \" + stmt);\n        }\n\n        /**\n         * build expressions.\n         *\n         * @param sb          string builder\n         * @param exp         expression\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildExpression(StringBuilder sb, Expression exp, int indentation) throws SyntaxException {\n                if (exp instanceof VariableDef) {\n                        assertNoAnno(((VariableDef) exp).getAnnos());\n                        assertNoModifier(((VariableDef) exp).getModifiers());\n                        assertNoType(((VariableDef) exp).getType());\n\n                        // var xxx\n                        sb.append(\"var \").append(((VariableDef) exp).getName());\n                        if (((VariableDef) exp).getInit() != null) {\n                                // =\n                                sb.append(\" = \");\n                                // expression\n                                buildExpression(sb, ((VariableDef) exp).getInit(), indentation);\n                        }\n                } else if (exp instanceof Literal) {\n                        String literal = ((Literal) exp).literal();\n                        if (exp instanceof BoolLiteral) {\n                                if (literal.equals(\"true\") || literal.equals(\"yes\")) {\n                                        sb.append(\"true\");\n                                } else {\n                                        sb.append(\"false\");\n                                }\n                        } else if (exp instanceof NumberLiteral) {\n                                sb.append(literal);\n                        } else if (exp instanceof StringLiteral) {\n                                sb.append(literal);\n                        } else throw new LtBug(\"unknown literal type \" + exp.getClass());\n                } else if (exp instanceof Operation) {\n                        if (exp instanceof UnaryOneVariableOperation) {\n                                sb.append(((UnaryOneVariableOperation) exp).operator());\n                                buildExpression(sb, ((UnaryOneVariableOperation) exp).expressions().get(0), indentation);\n                        } else if (exp instanceof OneVariableOperation) {\n                                buildExpression(sb, ((OneVariableOperation) exp).expressions().get(0), indentation);\n                                sb.append(((OneVariableOperation) exp).operator());\n                        } else if (exp instanceof TwoVariableOperation) {\n                                buildExpression(sb, ((TwoVariableOperation) exp).expressions().get(0), indentation);\n                                sb.append(\" \").append(((TwoVariableOperation) exp).operator()).append(\" \");\n                                buildExpression(sb, ((TwoVariableOperation) exp).expressions().get(1), indentation);\n                        } else throw new LtBug(\"unknown operation type \" + exp.getClass());\n                } else if (exp instanceof AST.Access) {\n                        if (((AST.Access) exp).exp != null) {\n                                buildExpression(sb, ((AST.Access) exp).exp, indentation);\n                                sb.append(\".\");\n                        }\n                        sb.append(((AST.Access) exp).name);\n                } else if (exp instanceof AST.AnnoExpression) {\n                        err.SyntaxException(\"JavaScript don't support annotations\", exp.line_col());\n                } else if (exp instanceof AST.ArrayExp) {\n                        sb.append(\"[\");\n                        buildArguments(sb, ((AST.ArrayExp) exp).list, indentation);\n                        sb.append(\"]\");\n                } else if (exp instanceof AST.Assignment) {\n                        buildExpression(sb, ((AST.Assignment) exp).assignTo, indentation);\n                        sb.append(\" = \");\n                        buildExpression(sb, ((AST.Assignment) exp).assignFrom, indentation);\n                } else if (exp instanceof AST.GeneratorSpec) {\n                        err.SyntaxException(\"JavaScript don't support generator specifying\", exp.line_col());\n                } else if (exp instanceof AST.AsType) {\n                        err.SyntaxException(\"JavaScript don't support type\", exp.line_col());\n                } else if (exp instanceof AST.Procedure) {\n                        sb.append(\"(function(){\\n\");\n                        buildStatements(sb, ((AST.Procedure) exp).statements, indentation + INDENT);\n                        sb.append(\"})()\");\n                } else if (exp instanceof AST.Index) {\n                        buildExpression(sb, ((AST.Index) exp).exp, indentation);\n                        for (Expression e : ((AST.Index) exp).args) {\n                                sb.append(\"[\");\n                                buildExpression(sb, e, indentation);\n                                sb.append(\"]\");\n                        }\n                } else if (exp instanceof AST.Invocation) {\n                        if (((AST.Invocation) exp).invokeWithNames) {\n                                err.SyntaxException(\"JavaScript don't support invoke with name\", exp.line_col());\n                        }\n                        buildExpression(sb, ((AST.Invocation) exp).exp, indentation);\n                        sb.append(\"(\");\n                        buildArguments(sb, ((AST.Invocation) exp).args, indentation);\n                        sb.append(\")\");\n                } else if (exp instanceof AST.Lambda) {\n                        // check last statement\n                        AST.Lambda l = (AST.Lambda) exp;\n                        if (!l.statements.isEmpty()) {\n                                Statement stmt = l.statements.get(l.statements.size() - 1);\n                                if (stmt instanceof Expression) {\n                                        l.statements.set(l.statements.size() - 1, new AST.Return((Expression) stmt, stmt.line_col()));\n                                }\n                        }\n\n                        sb.append(\"function(\");\n                        buildParameters(sb, ((AST.Lambda) exp).params);\n                        sb.append(\") {\\n\");\n                        buildStatements(sb, ((AST.Lambda) exp).statements, indentation + INDENT);\n                        sb.append(\"}\");\n                } else if (exp instanceof AST.MapExp) {\n                        sb.append(\"{\\n\");\n                        boolean isFirst = true;\n                        for (Map.Entry<Expression, Expression> entry : ((AST.MapExp) exp).map.entrySet()) {\n                                if (isFirst) {\n                                        isFirst = false;\n                                } else {\n                                        sb.append(\",\\n\");\n                                }\n                                buildIndentation(sb, indentation + INDENT);\n                                buildExpression(sb, entry.getKey(), indentation + INDENT);\n                                sb.append(\" : \");\n                                buildExpression(sb, entry.getValue(), indentation + INDENT);\n                        }\n                        sb.append(\"\\n\");\n                        buildIndentation(sb, indentation);\n                        sb.append(\"}\");\n                } else if (exp instanceof AST.New) {\n                        sb.append(\"new \");\n                        buildExpression(sb, ((AST.New) exp).invocation, indentation);\n                } else if (exp instanceof AST.Null) {\n                        sb.append(\"null\");\n                } else if (exp instanceof AST.PackageRef) {\n                        err.SyntaxException(\"JavaScript don't support packages\", exp.line_col());\n                        sb.append(\"'(compile error)'\");\n                } else if (exp instanceof AST.Require) {\n                        sb.append(\"require(\");\n                        buildExpression(sb, ((AST.Require) exp).required, indentation);\n                        sb.append(\")\");\n                } else if (exp instanceof AST.TypeOf) {\n                        err.SyntaxException(\"JavaScript don't have type\", exp.line_col());\n                        sb.append(\"'compile error'\");\n                } else throw new LtBug(\"unknown token \" + exp);\n        }\n\n        /**\n         * build method/function parameters\n         *\n         * @param sb     string builder\n         * @param params parameters\n         * @throws SyntaxException exception\n         */\n        private void buildParameters(StringBuilder sb, List<VariableDef> params) throws SyntaxException {\n                boolean isFirst = true;\n                for (VariableDef v : params) {\n                        assertNoAnno(v.getAnnos());\n                        assertNoModifier(v.getModifiers());\n                        assertNoType(v.getType());\n\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\", \");\n                        }\n                        sb.append(v.getName());\n                }\n        }\n\n        /**\n         * build arguments\n         *\n         * @param sb          string builder\n         * @param args        arguments\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildArguments(StringBuilder sb, List<Expression> args, int indentation) throws SyntaxException {\n                boolean isFirst = true;\n                for (Expression e : args) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\", \");\n                        }\n                        buildExpression(sb, e, indentation);\n                }\n        }\n\n        /**\n         * build statements for default values\n         *\n         * @param sb          string builder\n         * @param params      parameters\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildDefaultValues(StringBuilder sb, List<VariableDef> params, int indentation) throws SyntaxException {\n                for (VariableDef v : params) {\n                        if (v.getInit() != null) {\n                                buildIndentation(sb, indentation);\n                                sb.append(v.getName()).append(\" = \").append(v.getName()).append(\" ? \").append(v.getName()).append(\" : \");\n                                buildExpression(sb, v.getInit(), indentation);\n                                sb.append(\";\\n\");\n                        }\n                }\n        }\n\n        /**\n         * build a class definition.\n         *\n         * @param sb          string builder\n         * @param classDef    class definition\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildClass(StringBuilder sb, ClassDef classDef, int indentation) throws SyntaxException {\n                assertNoAnno(classDef.annos);\n                assertNoModifier(classDef.modifiers);\n                if (classDef.superWithInvocation != null)\n                        err.SyntaxException(\"JavaScript don't have parent classes\", classDef.superWithInvocation.line_col());\n                if (!classDef.superWithoutInvocation.isEmpty())\n                        err.SyntaxException(\"JavaScript don't have parent classes or interfaces\", classDef.superWithoutInvocation.get(0).line_col());\n\n                // function xxx(\n                sb.append(\"function \").append(classDef.name).append(\"(\");\n                // parameters\n                buildParameters(sb, classDef.params);\n                // ) {\n                sb.append(\") {\\n\");\n                // default values\n                buildDefaultValues(sb, classDef.params, indentation + INDENT);\n                // statements\n                buildStatements(sb, classDef.statements, indentation + INDENT);\n                // set fields\n                for (VariableDef v : classDef.params) {\n                        buildIndentation(sb, indentation + INDENT);\n                        sb.append(\"this.\").append(v.getName()).append(\" = \").append(v.getName()).append(\";\\n\");\n                }\n                sb.append(\"}\\n\");\n        }\n\n        /**\n         * build a function\n         *\n         * @param sb          sb\n         * @param funDef      function definition\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildFun(StringBuilder sb, FunDef funDef, int indentation) throws SyntaxException {\n                assertNoAnno(funDef.annos);\n\n                // function xxx(\n                buildIndentation(sb, indentation);\n                sb.append(\"function \").append(funDef.name).append(\"(\");\n                // parameters\n                buildParameters(sb, funDef.params);\n                // ) {\n                buildIndentation(sb, indentation);\n                sb.append(\") {\\n\");\n                // statements\n                buildStatements(sb, funDef.statements, indentation + INDENT);\n                // }\n                buildIndentation(sb, indentation);\n                sb.append(\"}\\n\");\n        }\n\n        /**\n         * build a method\n         *\n         * @param sb          sb\n         * @param methodDef   method definition\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildMethod(StringBuilder sb, MethodDef methodDef, int indentation) throws SyntaxException {\n                assertNoAnno(methodDef.annos);\n                assertNoType(methodDef.returnType);\n                assertNoModifier(methodDef.modifiers);\n\n                // this.xxx = function(\n                buildIndentation(sb, indentation);\n                if (indentation == 0) {\n                        sb.append(\"function \").append(methodDef.name).append(\"(\");\n                } else {\n                        sb.append(\"this.\").append(methodDef.name).append(\" = function(\");\n                }\n                // parameters\n                buildParameters(sb, methodDef.params);\n                // ) {\n                sb.append(\") {\\n\");\n                // default values\n                buildDefaultValues(sb, methodDef.params, indentation + INDENT);\n                // statements\n                buildStatements(sb, methodDef.body, indentation + INDENT);\n                // }\n                buildIndentation(sb, indentation);\n                sb.append(\"}\\n\");\n        }\n\n        /**\n         * build for statements\n         *\n         * @param sb          sb\n         * @param aFor        for\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildFor(StringBuilder sb, AST.For aFor, int indentation) throws SyntaxException {\n                // for (var xx in\n                buildIndentation(sb, indentation);\n                sb.append(\"for (var \").append(aFor.name).append(\" in \");\n                // expression\n                buildExpression(sb, aFor.exp, indentation);\n                // ) {\n                sb.append(\") {\\n\");\n                // statements\n                buildStatements(sb, aFor.body, indentation + INDENT);\n                // }\n                buildIndentation(sb, indentation);\n                sb.append(\"}\\n\");\n        }\n\n        /**\n         * build if statement\n         *\n         * @param sb          sb\n         * @param anIf        if\n         * @param indentation indentation\n         * @throws SyntaxException exception\n         */\n        private void buildIf(StringBuilder sb, AST.If anIf, int indentation) throws SyntaxException {\n                boolean isFirst = true;\n                for (AST.If.IfPair pair : anIf.ifs) {\n                        if (isFirst) {\n                                isFirst = false;\n                                // if (\n                                buildIndentation(sb, indentation);\n                                sb.append(\"if (\");\n                        } else {\n                                if (pair.condition == null) {\n                                        // else\n                                        sb.append(\"else\");\n                                } else {\n                                        // else if (\n                                        sb.append(\"else if (\");\n                                }\n                        }\n                        if (pair.condition != null) {\n                                // expressions)\n                                buildExpression(sb, pair.condition, indentation);\n                                sb.append(\")\");\n                        }\n                        // {\n                        sb.append(\" {\\n\");\n                        // statements\n                        buildStatements(sb, pair.body, indentation + INDENT);\n                        // }\n                        buildIndentation(sb, indentation);\n                        sb.append(\"} \");\n                }\n                sb.append(\"\\n\");\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/ClassPathLoader.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport java.io.IOException;\nimport java.net.URL;\nimport java.net.URLClassLoader;\n\n/**\n * jar class loader\n */\npublic class ClassPathLoader extends URLClassLoader {\n        public ClassPathLoader(ClassLoader loader) {\n                super(new URL[0], loader);\n        }\n\n        /**\n         * add the url for loading in the future\n         *\n         * @param url url\n         * @throws IOException            exception\n         * @throws ClassNotFoundException exception\n         */\n        public void load(URL url) throws IOException, ClassNotFoundException {\n                addURL(url);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/Compiler.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.Scanner;\nimport lt.compiler.lexical.ElementStartNode;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport lt.runtime.Wrapper;\n\nimport java.io.*;\nimport java.net.URL;\nimport java.util.*;\nimport java.util.concurrent.*;\nimport java.util.zip.ZipEntry;\nimport java.util.zip.ZipOutputStream;\n\n/**\n * a compiler with full functions provided. lt.repl.Compiler is a small set of this compiler<br>\n * first record all necessary info<br>\n * then creates a ThreadPool to run Scanner and Parser<br>\n * then summaries these AST to do semantic analysis in a single thread<br>\n * finally creates a ThreadPool to run Code Generation and write files to disk (or store these byte code for loading)<br>\n * if requires loading, then load all these generated classes\n */\npublic class Compiler {\n        private static final int availableProcessors = Runtime.getRuntime().availableProcessors();\n\n        public static class Config {\n                /**\n                 * class-path\n                 */\n                public List<URL> classpath = new ArrayList<URL>();\n\n                /**\n                 * configuration about each step use how many threads\n                 */\n                public static class Threads {\n                        /**\n                         * thread count for scanners\n                         */\n                        public int scanner = availableProcessors;\n                        /**\n                         * thread count for parsers\n                         */\n                        public int parser = availableProcessors;\n                        /**\n                         * thread count for codeGen\n                         */\n                        public int codeGen = availableProcessors;\n                }\n\n                /**\n                 * thread configuration\n                 */\n                public Threads threads = new Threads();\n\n                /**\n                 * configuration about coding\n                 */\n                public static class Code {\n                        /**\n                         * these imports will be added when doing semantic analysis\n                         */\n                        public List<String> autoImport = new ArrayList<String>();\n                        /**\n                         * indentation of the source code\n                         */\n                        public int indentation = 4;\n                        /**\n                         * line base\n                         */\n                        public int lineBase = 0;\n                        /**\n                         * column base\n                         */\n                        public int columnBase = 0;\n                }\n\n                /**\n                 * code configuration\n                 */\n                public Code code = new Code();\n\n                /**\n                 * out configuration\n                 */\n                public ErrorManager.Out out = new ErrorManager.Out();\n\n                /**\n                 * throw exception immediately when meets a syntax exception\n                 */\n                public boolean fastFail = true;\n\n                /**\n                 * configuration about the result\n                 */\n                public static class Result {\n                        /**\n                         * output directory\n                         */\n                        public File outputDir = null;\n                        /**\n                         * the jar file name\n                         */\n                        public String pkg = null;\n                        /**\n                         * main class\n                         */\n                        public String main = null;\n                        /**\n                         * include Latte runtime libraries\n                         */\n                        public boolean with_lib = false;\n                }\n\n                /**\n                 * result configuration\n                 */\n                public Result result = new Result();\n        }\n\n        public final Config config = new Config();\n        private final ClassLoader baseLoader;\n\n        /**\n         * construct the compiler\n         */\n        public Compiler() {\n                baseLoader = Thread.currentThread().getContextClassLoader();\n        }\n\n        /**\n         * construct the compiler with base class loader\n         *\n         * @param baseLoader the base class loader\n         */\n        public Compiler(ClassLoader baseLoader) {\n                this.baseLoader = baseLoader;\n        }\n\n        /**\n         * add a jarFile to class-path\n         *\n         * @param dirOrJar directory or jar file location\n         * @return the compiler itself\n         * @throws IOException exceptions\n         */\n        public Compiler add(String dirOrJar) throws IOException {\n                return add(new File(dirOrJar));\n        }\n\n        /**\n         * add a jarFile to class-path\n         *\n         * @param file the file representing url\n         * @return the compiler itself\n         * @throws IOException exceptions\n         */\n        public Compiler add(File file) throws IOException {\n                return add(new URL(file.toURI().toString()));\n        }\n\n        /**\n         * add a jarFile to class-path\n         *\n         * @param url the url\n         * @return the compiler itself\n         */\n        public Compiler add(URL url) {\n                config.classpath.add(url);\n                return this;\n        }\n\n        /**\n         * configure using given config\n         *\n         * @param config a map containing configuration\n         * @return this\n         * @throws Exception all kinds of exceptions\n         */\n        public Compiler configure(Map config) throws Exception {\n                if (config != null) {\n\n                        List<URL> classpathToSet = new ArrayList<URL>();\n                        Config.Threads threads = new Config.Threads();\n                        Config.Code code = new Config.Code();\n                        ErrorManager.Out out = new ErrorManager.Out();\n                        boolean fastFail = true;\n                        Config.Result result = new Config.Result();\n\n                        if (config.containsKey(\"classpath\")) {\n                                final String exMsg = \"config.classpath should be a list of JarFile/File/String\";\n\n                                Object o = config.get(\"classpath\");\n                                if (o instanceof List) {\n                                        for (Object e : (List) o) {\n                                                if (e instanceof String) {\n                                                        addIntoClasspathList(classpathToSet, (String) e);\n                                                } else if (e instanceof File) {\n                                                        addIntoClasspathList(classpathToSet, (File) e);\n                                                } else if (e instanceof URL) {\n                                                        addIntoClasspathList(classpathToSet, (URL) e);\n                                                } else throw new IllegalArgumentException(exMsg);\n                                        }\n                                } else throw new IllegalArgumentException(exMsg);\n                        }\n                        if (config.containsKey(\"threads\")) {\n                                Object o = config.get(\"threads\");\n                                if (o instanceof Map) {\n                                        Map t = (Map) o;\n                                        if (t.containsKey(\"scanner\")) {\n                                                Object scanner = t.get(\"scanner\");\n                                                if (scanner instanceof Integer && ((Integer) scanner) >= 1) {\n                                                        threads.scanner = (Integer) scanner;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.threads.scanner should be Integer and >=1\");\n                                        }\n                                        if (t.containsKey(\"parser\")) {\n                                                Object parser = t.get(\"parser\");\n                                                if (parser instanceof Integer && ((Integer) parser) >= 1) {\n                                                        threads.parser = (Integer) parser;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.threads.parser should be Integer and >= 1\");\n                                        }\n                                        if (t.containsKey(\"codeGen\")) {\n                                                Object codeGen = t.get(\"codeGen\");\n                                                if (codeGen instanceof Integer && ((Integer) codeGen) >= 1) {\n                                                        threads.codeGen = (Integer) codeGen;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.threads.codeGen should be Integer and >=1\");\n                                        }\n                                } else\n                                        throw new IllegalArgumentException(\"config.threads should be {scanner:?, parser:?, codeGen:?}\");\n                        }\n                        if (config.containsKey(\"code\")) {\n                                Object o = config.get(\"code\");\n                                if (o instanceof Map) {\n                                        Map c = (Map) o;\n                                        if (c.containsKey(\"autoImport\")) {\n                                                Object ai = c.get(\"autoImport\");\n                                                final String exMsg = \"config.code.autoImport should be List of strings\";\n\n                                                if (ai instanceof List) {\n                                                        for (Object autoImport : (List) ai) {\n                                                                if (autoImport instanceof String) {\n                                                                        code.autoImport.add((String) autoImport);\n                                                                } else throw new IllegalArgumentException(exMsg);\n                                                        }\n\n                                                } else throw new IllegalArgumentException(exMsg);\n                                        }\n                                        if (c.containsKey(\"indentation\")) {\n                                                Object i = c.get(\"indentation\");\n                                                if (i instanceof Integer && ((Integer) i) >= 1) {\n                                                        code.indentation = (Integer) i;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.code.indentation should be Integer and >=1\");\n                                        }\n                                        if (c.containsKey(\"lineBase\")) {\n                                                Object l = c.get(\"lineBase\");\n                                                if (l instanceof Integer) {\n                                                        code.lineBase = (Integer) l;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.code.lineBase should be Integer\");\n                                        }\n                                        if (c.containsKey(\"columnBase\")) {\n                                                Object co = c.get(\"columnBase\");\n                                                if (co instanceof Integer) {\n                                                        code.columnBase = (Integer) co;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.code.columnBase should be Integer\");\n                                        }\n                                } else\n                                        throw new IllegalArgumentException(\"config.code should be {autoImport:?, indentation:?, lineBase:?, columnBase:?}\");\n                        }\n                        if (config.containsKey(\"out\")) {\n                                Object o = config.get(\"out\");\n                                if (o instanceof Map) {\n                                        Map ou = (Map) o;\n                                        if (ou.containsKey(\"debug\")) {\n                                                Object debug = ou.get(\"debug\");\n                                                if (debug == null || debug instanceof PrintStream) {\n                                                        out.debug = (PrintStream) debug;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.out.debug should be PrintStream\");\n                                        }\n                                        if (ou.containsKey(\"info\")) {\n                                                Object info = ou.get(\"info\");\n                                                if (info == null || info instanceof PrintStream) {\n                                                        out.info = (PrintStream) info;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.out.info should be PrintStream\");\n                                        }\n                                        if (ou.containsKey(\"warn\")) {\n                                                Object warn = ou.get(\"warn\");\n                                                if (warn == null || warn instanceof PrintStream) {\n                                                        out.warn = (PrintStream) warn;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.out.warn should be PrintStream\");\n                                        }\n                                        if (ou.containsKey(\"err\")) {\n                                                Object error = ou.get(\"err\");\n                                                if (error == null || error instanceof PrintStream) {\n                                                        out.err = (PrintStream) error;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.out.err should be PrintStream\");\n                                        }\n                                } else\n                                        throw new IllegalArgumentException(\"config.out should be {debug:?, info:?, warn:?, err:?}\");\n                        }\n                        if (config.containsKey(\"fastFail\")) {\n                                Object f = config.get(\"fastFail\");\n                                if (f instanceof Boolean) {\n                                        fastFail = (Boolean) f;\n                                } else throw new IllegalArgumentException(\"config.fastFail should be Boolean\");\n                        }\n                        if (config.containsKey(\"result\")) {\n                                Object r = config.get(\"result\");\n                                if (r instanceof Map) {\n                                        Map re = (Map) r;\n                                        if (re.containsKey(\"outputDir\")) {\n                                                Object o = re.get(\"outputDir\");\n                                                if (o instanceof String) {\n                                                        File f = new File((String) o);\n                                                        if (!f.exists()) //noinspection ResultOfMethodCallIgnored\n                                                                f.mkdirs();\n                                                        if (f.isDirectory()) {\n                                                                result.outputDir = f;\n                                                        } else\n                                                                throw new IllegalArgumentException(\"config.result.outputDir should be a directory\");\n                                                } else if (o instanceof File) {\n                                                        if (((File) o).isDirectory()) {\n                                                                result.outputDir = (File) o;\n                                                        } else\n                                                                throw new IllegalArgumentException(\"config.result.outputDir should be a directory\");\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.result.outputDir should be File/String\");\n                                        }\n                                        if (re.containsKey(\"package\")) {\n                                                Object o = re.get(\"package\");\n                                                if (o != null) {\n                                                        if (o instanceof String) {\n                                                                result.pkg = (String) o;\n                                                        } else\n                                                                throw new IllegalArgumentException(\"config.result.package should be String\");\n                                                }\n                                        }\n                                        if (re.containsKey(\"main\")) {\n                                                Object o = re.get(\"main\");\n                                                if (o != null) {\n                                                        if (o instanceof String) {\n                                                                result.main = (String) o;\n                                                        } else\n                                                                throw new IllegalArgumentException(\"config.result.main should be String\");\n                                                }\n                                        }\n                                        if (re.containsKey(\"with-lib\")) {\n                                                Object o = re.get(\"with-lib\");\n                                                if (o instanceof Boolean) {\n                                                        result.with_lib = (Boolean) o;\n                                                } else\n                                                        throw new IllegalArgumentException(\"config.result.with-lib should be bool\");\n                                        }\n                                } else\n                                        throw new IllegalArgumentException(\"config.result should be {outputDir:?, statistic:?}\");\n                        }\n\n                        this.config.classpath = classpathToSet;\n                        this.config.threads = threads;\n                        this.config.code = code;\n                        this.config.out = out;\n                        this.config.fastFail = fastFail;\n                        this.config.result = result;\n                }\n\n                return this;\n        }\n\n        private void addIntoClasspathList(List<URL> list, String fileName) throws IOException {\n                File f = new File(fileName);\n                if (f.exists()) {\n                        addIntoClasspathList(list, f);\n                } else throw new IllegalArgumentException(fileName + \" does not exist\");\n        }\n\n        private void addIntoClasspathList(List<URL> list, File file) throws IOException {\n                if (file.isDirectory()\n                        || (file.isFile() && file.getName().endsWith(\".jar\"))) {\n                        addIntoClasspathList(list, new URL(file.toURI().toString()));\n                } else throw new IllegalArgumentException(\"requiring a directory or jarFile, got \" + file);\n        }\n\n        private void addIntoClasspathList(List<URL> list, URL url) {\n                list.add(url);\n        }\n\n        /**\n         * specify the output directory\n         *\n         * @param fileDir file directory\n         * @return the compiler itself\n         */\n        public Compiler shiftRight(String fileDir) {\n                return shiftRight(new File(fileDir));\n        }\n\n        /**\n         * specify the output directory\n         *\n         * @param file the directory\n         * @return the compiler itself\n         */\n        public Compiler shiftRight(File file) {\n                if (!file.isDirectory()) throw new IllegalArgumentException(file + \" is not a directory\");\n                config.result.outputDir = file;\n                return this;\n        }\n\n        /**\n         * compile the given files\n         *\n         * @param fileNameToCode a map containing fileName to source_code/File/InputStream/Reader\n         * @return the retrieved class loader\n         * @throws Exception the exception occurred when compiling,\n         *                   or lt.runtime.Wrapper whose object field is a List of {@link lt.compiler.ErrorManager.CompilingError}\n         */\n        public ClassLoader compile(Map<String, ?> fileNameToCode) throws Exception {\n                // validate and transform compile input\n                Map<String, Reader> input = new HashMap<String, Reader>();\n\n                for (Map.Entry<String, ?> entry : fileNameToCode.entrySet()) {\n                        String name = entry.getKey();\n                        Object v = entry.getValue();\n                        if (v instanceof String) {\n                                input.put(name, new StringReader((String) v));\n                        } else if (v instanceof File) {\n                                if (((File) v).isFile()) {\n                                        input.put(name, new FileReader((File) v));\n                                } else throw new IllegalArgumentException(v + \" is not a file\");\n                        } else if (v instanceof InputStream) {\n                                input.put(name, new InputStreamReader((InputStream) v));\n                        } else if (v instanceof Reader) {\n                                input.put(name, (Reader) v);\n                        } else\n                                throw new IllegalArgumentException(\"the mapped values should be String/File/InputStream/Reader\");\n                }\n\n                // validate configuration\n                if (config.threads.codeGen < 1) throw new IllegalArgumentException(\"config.threads.codeGen should >=1\");\n                if (config.threads.parser < 1) throw new IllegalArgumentException(\"config.threads.parser should >=1\");\n                if (config.threads.scanner < 1) throw new IllegalArgumentException(\"config.threads.scanner should >=1\");\n\n                if (config.code.indentation < 1)\n                        throw new IllegalArgumentException(\"config.code.indentation should >=1\");\n\n                if (config.result.outputDir != null && config.result.outputDir.exists() && !config.result.outputDir.isDirectory())\n                        throw new IllegalArgumentException(\"config.result.outputDir should be a directory\");\n\n                // load jars\n                ClassPathLoader classPathLoader = new ClassPathLoader(baseLoader);\n                for (URL url : config.classpath) {\n                        classPathLoader.load(url);\n                }\n\n                // construct thread pool for scanners and parsers\n                ExecutorService scannerPool = Executors.newFixedThreadPool(config.threads.scanner);\n                final ExecutorService parserPool = Executors.newFixedThreadPool(config.threads.parser);\n\n                final ErrorManager errorManager = new ErrorManager(config.fastFail);\n                errorManager.out = config.out;\n\n                List<Scan> scans = new ArrayList<Scan>();\n                Properties properties = new Properties();\n                properties._COLUMN_BASE_ = config.code.columnBase;\n                properties._LINE_BASE_ = config.code.lineBase;\n                for (Map.Entry<String, Reader> entry : input.entrySet()) {\n                        Scan scan = new Scan(entry.getKey(), entry.getValue(), properties, errorManager);\n                        scans.add(scan);\n                }\n\n                List<Future<FileRoot>> scanRes = scannerPool.invokeAll(scans);\n                Map<String, List<Statement>> parseRes = new ConcurrentHashMap<String, List<Statement>>();\n                final List<Future<Map<String, List<Statement>>>> parseState = new Vector<Future<Map<String, List<Statement>>>>();\n\n                final Exception[] caughtException = new Exception[]{null};\n\n                for (final Future<FileRoot> f : scanRes) {\n                        new Thread(new Runnable() {\n                                @Override\n                                public void run() {\n                                        try {\n                                                FileRoot root;\n                                                try {\n                                                        root = f.get();\n                                                } catch (ExecutionException e) {\n                                                        caughtException[0] = (Exception) e.getCause();\n                                                        return;\n                                                }\n                                                Future<Map<String, List<Statement>>> future = parserPool.submit(new Parse(root.fileName, root.root, errorManager));\n                                                parseState.add(future);\n                                        } catch (InterruptedException ignore) {\n                                        }\n                                }\n                        }).start();\n                }\n\n                // wait until all all Parse objects are added into the list\n                while (parseState.size() != input.size()) {\n                        // check whether occurred any exceptions\n                        if (caughtException[0] != null) {\n                                scannerPool.shutdown();\n                                parserPool.shutdown();\n\n                                throw caughtException[0];\n                        }\n                        Thread.sleep(1);\n                }\n\n                // wait until all parse process finishes\n                for (Future<Map<String, List<Statement>>> f : parseState) {\n                        while (!f.isDone()) Thread.sleep(1);\n                        try {\n                                parseRes.putAll(f.get());\n                        } catch (ExecutionException e) {\n                                scannerPool.shutdown();\n                                parserPool.shutdown();\n\n                                throw (Exception) e.getCause();\n                        }\n                }\n\n                // all parsing finished\n\n                scannerPool.shutdown();\n                parserPool.shutdown();\n\n                if (!errorManager.errorList.isEmpty()) {\n                        throw new Wrapper(errorManager.errorList);\n                }\n\n                final SemanticProcessor processor = new SemanticProcessor(parseRes, classPathLoader, errorManager);\n                Set<STypeDef> types = processor.parse();\n\n                // code gen\n                int size = types.size() / config.threads.codeGen + types.size() % config.threads.codeGen;\n                List<Set<STypeDef>> toGenerate = new ArrayList<Set<STypeDef>>();\n                for (int i = 0; i < size; ++i) toGenerate.add(new HashSet<STypeDef>());\n                int currentCount = 0;\n                for (STypeDef type : types) {\n                        toGenerate.get(currentCount % size).add(type);\n                }\n\n                final Map<String, byte[]> byteCodes = new ConcurrentHashMap<String, byte[]>();\n\n                List<Thread> threads = new ArrayList<Thread>();\n\n                // the following process should not throw any exception\n\n                for (final Set<STypeDef> toGen : toGenerate) {\n                        Thread t = new Thread(new Runnable() {\n                                @Override\n                                public void run() {\n                                        CodeGenerator codeGenerator = new CodeGenerator(toGen, processor.getTypes());\n                                        byteCodes.putAll(codeGenerator.generate());\n                                }\n                        });\n                        threads.add(t);\n                        t.start();\n                }\n\n                for (Thread t : threads) {\n                        t.join();\n                }\n\n                // codes are generated\n                ClassLoader loader = new ClassLoader(classPathLoader) {\n                        @Override\n                        protected Class<?> findClass(String name) throws ClassNotFoundException {\n                                if (byteCodes.containsKey(name)) {\n                                        byte[] bytes = byteCodes.get(name);\n                                        if (bytes == null) throw new ClassNotFoundException(name);\n                                        return defineClass(name, bytes, 0, bytes.length);\n                                } else throw new ClassNotFoundException(name);\n                        }\n                };\n\n                if (config.result.outputDir != null) {\n                        // the jar file\n                        ZipOutputStream zipOutputStream = null;\n                        if (config.result.pkg != null) {\n                                String name = config.result.pkg;\n                                if (!name.endsWith(\".jar\")) {\n                                        name += \".jar\";\n                                }\n                                File jarPath = new File(config.result.outputDir.getAbsolutePath() + File.separator + name);\n                                if (!jarPath.exists()) //noinspection ResultOfMethodCallIgnored\n                                        jarPath.createNewFile();\n                                zipOutputStream = new ZipOutputStream(new FileOutputStream(jarPath));\n                        }\n\n                        for (Map.Entry<String, byte[]> result : byteCodes.entrySet()) {\n                                String className = result.getKey();\n                                byte[] bytes = result.getValue();\n\n                                File outputDir = config.result.outputDir;\n\n                                // the root dir\n                                String dir = outputDir.getAbsolutePath();\n                                // the sub directory relevant to root\n                                String theDir = (className.contains(\".\") ? className.substring(0, className.lastIndexOf('.')).replace(\".\", \"/\") : \"\");\n                                // the file\n                                File path = new File(dir + File.separator + (File.separator.equals(\"/\") ? theDir : theDir.replace(\"/\", File.separator)));\n                                if (!path.exists())\n                                        if (!path.mkdirs()) throw new IOException(\"cannot create directory \" + path);\n\n                                // simple name\n                                String simpleName = (className.contains(\".\") ? className.substring(className.lastIndexOf('.') + 1) : className) + \".class\";\n                                File newFile = new File(path.getAbsolutePath() + File.separator + simpleName);\n                                if (!newFile.exists()) if (!newFile.createNewFile())\n                                        throw new IOException(\"cannot create file \" + newFile);\n\n                                FileOutputStream fos = new FileOutputStream(newFile);\n                                fos.write(bytes);\n\n                                // classes in jar file\n                                if (zipOutputStream != null) {\n                                        putZipEntry(zipOutputStream, theDir.isEmpty() ? simpleName : (theDir + \"/\" + simpleName), bytes);\n                                }\n\n                                fos.close();\n                        }\n\n                        // manifest.mf\n                        if (zipOutputStream != null) {\n                                zipOutputStream.putNextEntry(new ZipEntry(\"META-INF/MANIFEST.MF\"));\n\n                                String MANIFEST = \"\" +\n                                        \"Manifest-Version: 1.0\\n\" +\n                                        \"Created-By: Latte lang Compiler\\n\";\n                                if (config.result.main != null) {\n                                        MANIFEST += \"Main-Class: \" + config.result.main.replace(\"::\", \".\") + \"\\n\";\n                                }\n                                zipOutputStream.write((MANIFEST).getBytes());\n                                zipOutputStream.closeEntry();\n\n                                // add the libraries\n                                if (config.result.with_lib) {\n                                        InputStream classesInputStream = Compiler.class.getClassLoader().getResourceAsStream(\"classes.txt\");\n\n                                        if (classesInputStream != null) {\n                                                BufferedReader br = new BufferedReader(\n                                                        new InputStreamReader(classesInputStream));\n\n                                                List<String> CLASSES = new ArrayList<String>();\n\n                                                String CLASS;\n                                                while ((CLASS = br.readLine()) != null) {\n                                                        if (CLASS.trim().isEmpty()) continue;\n                                                        CLASSES.add(CLASS);\n                                                }\n\n                                                Collections.sort(CLASSES);\n\n                                                for (String C : CLASSES) {\n                                                        InputStream is = Compiler.class.getClassLoader().getResourceAsStream(C);\n                                                        ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);\n                                                        byte[] bs = new byte[1024];\n                                                        int n;\n                                                        while ((n = is.read(bs)) != -1) {\n                                                                baos.write(bs, 0, n);\n                                                        }\n                                                        putZipEntry(zipOutputStream, C, baos.toByteArray());\n                                                }\n                                        }\n                                }\n\n                                List<String> requireFiles = new ArrayList<String>(Arrays.asList(\"classes.txt\", \"build.lts.template\", \"run.lts.template\"));\n                                if (Compiler.class.getClassLoader().getResourceAsStream(\"lib-classes.txt\") != null) {\n                                        requireFiles.add(\"lib-classes.txt\");\n                                }\n                                // add required files\n                                for (String f : requireFiles) {\n                                        InputStream is = Compiler.class.getClassLoader().getResourceAsStream(f);\n                                        if (is != null) {\n                                                ByteArrayOutputStream baos = new ByteArrayOutputStream(1024);\n                                                byte[] bs = new byte[1024];\n                                                int n;\n                                                while ((n = is.read(bs)) != -1) {\n                                                        baos.write(bs, 0, n);\n                                                }\n                                                putZipEntry(zipOutputStream, f, baos.toByteArray());\n                                        }\n                                }\n\n                                zipOutputStream.close();\n                        }\n                }\n\n                return loader;\n        }\n\n        /**\n         * put the zip entry into the zip output stream\n         *\n         * @param zos   ZipOutputStream\n         * @param file  the entry name\n         * @param bytes bytes\n         * @throws IOException exception\n         */\n        private void putZipEntry(ZipOutputStream zos, String file, byte[] bytes) throws IOException {\n                zos.putNextEntry(new ZipEntry(file));\n                zos.write(bytes);\n                zos.closeEntry();\n        }\n\n        private class FileRoot {\n                public String fileName;\n                public ElementStartNode root;\n        }\n\n        private class Scan implements Callable<FileRoot> {\n                private final String fileName;\n                private final Reader reader;\n                private final Properties properties;\n                private final ErrorManager err;\n\n                private Scan(String fileName, Reader reader, Properties properties, ErrorManager err) {\n                        this.fileName = fileName;\n                        this.reader = reader;\n                        this.properties = properties;\n                        this.err = err;\n                }\n\n                @Override\n                public FileRoot call() throws Exception {\n                        Scanner scanner = new ScannerSwitcher(fileName, reader, properties, err);\n                        FileRoot fileRoot = new FileRoot();\n                        fileRoot.fileName = fileName;\n                        fileRoot.root = scanner.scan();\n                        return fileRoot;\n                }\n        }\n\n        private class Parse implements Callable<Map<String, List<Statement>>> {\n                private final String fileName;\n                private final ElementStartNode root;\n                private final ErrorManager err;\n\n                private Parse(String fileName,\n                              ElementStartNode root,\n                              ErrorManager err) {\n                        this.fileName = fileName;\n                        this.root = root;\n                        this.err = err;\n                }\n\n                @Override\n                public Map<String, List<Statement>> call() throws Exception {\n                        Parser parser = new Parser(root, err);\n                        Map<String, List<Statement>> resultMap = new HashMap<String, List<Statement>>();\n                        resultMap.put(\n                                fileName,\n                                parser.parse()\n                        );\n                        return resultMap;\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/Evaluator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.repl.scripting.*;\n\nimport javax.script.ScriptContext;\nimport javax.script.ScriptException;\n\n/**\n * evaluator for Latte\n */\npublic class Evaluator {\n        private final LatteEngine latteEngine;\n        private final String varNameBase;\n        private int scannerType = Config.SCANNER_TYPE_INDENT;\n\n        public Evaluator(ClassPathLoader classPathLoader) {\n                this(\"res\", classPathLoader);\n        }\n\n        public Evaluator(String varNameBase, ClassPathLoader classPathLoader) {\n                this.varNameBase = varNameBase;\n                this.latteEngine = new LatteEngine(classPathLoader);\n                this.latteEngine.setContext(new LatteContext(new LatteScope()));\n        }\n\n        public void setScannerType(int type) {\n                this.scannerType = type;\n        }\n\n        public void put(String name, Object var) {\n                latteEngine.put(name, var);\n        }\n\n        public EvalEntry eval(String stmt) throws Exception {\n                try {\n                        return (EvalEntry) latteEngine.eval(stmt, latteEngine.getBindings(ScriptContext.ENGINE_SCOPE),\n                                new Config()\n                                        .setScannerType(scannerType).setVarNamePrefix(varNameBase).setEval(true));\n                } catch (ScriptException e) {\n                        throw (Exception) e.getCause();\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/Run.java",
    "content": "package lt.repl;\n\nimport java.io.File;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.MalformedURLException;\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport java.util.ArrayList;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * run the main method\n */\npublic class Run {\n        private List<URL> classPath;\n        private String mainClass;\n\n        /**\n         * construct the Run class\n         */\n        public Run() {\n        }\n\n        /**\n         * construct the Run class with class paths and main class\n         *\n         * @param classPath class paths\n         * @param mainClass main class\n         * @throws MalformedURLException    the string in the list is not a file/directory\n         * @throws IllegalArgumentException the list contain elements that are not URL nor String\n         */\n        public Run(List<?> classPath, String mainClass) throws MalformedURLException {\n                this.setMainClass(mainClass);\n                this.setClassPath(classPath);\n        }\n\n        /**\n         * retrieve class path\n         *\n         * @return a list of URL representing the class paths\n         */\n        public List<URL> getClassPath() {\n                return classPath;\n        }\n\n        /**\n         * set class path\n         *\n         * @param classPath a list of URL or String representing the class paths\n         * @throws MalformedURLException    the string in the list is not a file/directory\n         * @throws IllegalArgumentException the list contain elements that are not URL nor String\n         */\n        public void setClassPath(List<?> classPath) throws MalformedURLException {\n                List<URL> urls = new ArrayList<URL>();\n                for (Object o : classPath) {\n                        if (o instanceof URL) {\n                                urls.add((URL) o);\n                        } else if (o instanceof String) {\n                                urls.add(new URL(new File((String) o).toURI().toString()));\n                        } else throw new IllegalArgumentException(o == null ? null : o.getClass() + \" is not URL\");\n                }\n                this.classPath = urls;\n        }\n\n        /**\n         * retrieve the main class\n         *\n         * @return main class\n         */\n        public String getMainClass() {\n                return mainClass;\n        }\n\n        /**\n         * set main class\n         *\n         * @param mainClass main class\n         */\n        public void setMainClass(String mainClass) {\n                this.mainClass = mainClass.replace(\"::\", \".\");\n        }\n\n        /**\n         * execute with given arguments\n         *\n         * @param args arguments\n         * @throws Throwable exception\n         */\n        public void exec(List<String> args) throws Throwable {\n                exec(args.toArray(new String[args.size()]));\n        }\n\n        /**\n         * execute with given arguments\n         *\n         * @param args arguments\n         * @throws Throwable exception\n         */\n        public void exec(String[] args) throws Throwable {\n                URLClassLoader urlClassLoader = new URLClassLoader(classPath.toArray(new URL[classPath.size()]));\n                Class<?> cls = urlClassLoader.loadClass(mainClass);\n                Method method = cls.getDeclaredMethod(\"main\", String[].class);\n                method.setAccessible(true);\n                try {\n                        method.invoke(null, new Object[]{args});\n                } catch (InvocationTargetException e) {\n                        throw e.getTargetException();\n                }\n        }\n\n        /**\n         * execute\n         *\n         * @throws Throwable exception\n         */\n        public void exec() throws Throwable {\n                exec(Collections.<String>emptyList());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/ScriptCompiler.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.Scanner;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.pre.Import;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\n\nimport java.io.*;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.net.URL;\nimport java.util.*;\n\n/**\n * script compiler. The script compiler first transform the script into<br>\n * <pre>\n * class Script$generatedName\n *     static\n *         method(args:[]String)\n *             ... ; the script\n * </pre>\n */\npublic class ScriptCompiler {\n        /**\n         * holder of the compiling results\n         */\n        public static class Script {\n                /**\n                 * class loader\n                 */\n                public final ClassLoader classLoader;\n                /**\n                 * the script class\n                 */\n                public final Class<?> scriptClass;\n                /**\n                 * the script method (<code>method([]String)</code>)\n                 */\n                public final Method scriptMethod;\n\n                /**\n                 * the return value of {@link #scriptMethod}\n                 */\n                private Object result;\n\n                /**\n                 * constructing the result\n                 *\n                 * @param classLoader  class loader\n                 * @param scriptClass  the script class\n                 * @param scriptMethod the script method\n                 */\n                Script(ClassLoader classLoader, Class<?> scriptClass, Method scriptMethod) {\n                        this.classLoader = classLoader;\n                        this.scriptClass = scriptClass;\n                        this.scriptMethod = scriptMethod;\n                }\n\n                /**\n                 * invoke {@link #scriptMethod} with a zero-length String array\n                 *\n                 * @return the Result object itself (invoke {@link #getResult()}) to get the return value\n                 * @throws Throwable throwable\n                 */\n                public Script run() throws Throwable {\n                        return run(new String[0]);\n                }\n\n                /**\n                 * invoke {@link #scriptMethod} with given arguments\n                 *\n                 * @param args arguments\n                 * @return the Result object itself (invoke {@link #getResult()}) to get the return value\n                 * @throws Throwable throwable\n                 */\n                public Script run(String[] args) throws Throwable {\n                        try {\n                                result = scriptMethod.invoke(scriptClass.newInstance(), new Object[]{args});\n                        } catch (InvocationTargetException e) {\n                                throw e.getTargetException();\n                        }\n                        return this;\n                }\n\n                /**\n                 * get the return value of {@link #scriptMethod}\n                 *\n                 * @return the return value\n                 */\n                public Object getResult() {\n                        return result;\n                }\n        }\n\n        private final Compiler compiler;\n\n        private Map<String, Object> sources = new HashMap<String, Object>();\n\n        /**\n         * construct a script compiler\n         *\n         * @param parentLoader parent loader\n         */\n        public ScriptCompiler(ClassLoader parentLoader) {\n                this.compiler = new Compiler(parentLoader);\n        }\n\n        /**\n         * add class path\n         *\n         * @param classPath class path\n         * @return the ScriptCompiler itself\n         * @throws IOException exception\n         */\n        public ScriptCompiler add(String classPath) throws IOException {\n                compiler.add(classPath);\n                return this;\n        }\n\n        /**\n         * add class path\n         *\n         * @param classPath class path\n         * @return the ScriptCompiler itself\n         * @throws IOException exception\n         */\n        public ScriptCompiler add(File classPath) throws IOException {\n                compiler.add(classPath);\n                return this;\n        }\n\n        /**\n         * add class path\n         *\n         * @param classPath class path\n         * @return the ScriptCompiler itself\n         */\n        public ScriptCompiler add(URL classPath) {\n                compiler.add(classPath);\n                return this;\n        }\n\n        /**\n         * add source code\n         *\n         * @param sourceName source code name\n         * @param source     source\n         * @return the ScriptCompiler itself\n         */\n        public ScriptCompiler shiftLeft(String sourceName, String source) {\n                sources.put(sourceName, source);\n                return this;\n        }\n\n        /**\n         * add source code\n         *\n         * @param source source\n         * @return the ScriptCompiler itself\n         */\n        public ScriptCompiler shiftLeft(File source) {\n                if (source.isFile()) {\n                        sources.put(source.getName(), source);\n                } else throw new IllegalArgumentException(\"not a file\");\n                return this;\n        }\n\n        /**\n         * add source code\n         *\n         * @param sourceName source code name\n         * @param source     source\n         * @return the ScriptCompiler itself\n         */\n        public ScriptCompiler shiftLeft(String sourceName, Reader source) {\n                sources.put(sourceName, source);\n                return this;\n        }\n\n        /**\n         * add source codes\n         *\n         * @param sources sources\n         * @return the ScriptCompiler itself\n         */\n        public ScriptCompiler shiftLeft(Map<String, ?> sources) {\n                this.sources.putAll(sources);\n                return this;\n        }\n\n        /**\n         * compile the script\n         *\n         * @param name   the script name\n         * @param script script\n         * @return compiling result\n         * @throws Exception exception\n         */\n        public Script compile(String name, String script) throws Exception {\n                return compile(name, new StringReader(script));\n        }\n\n        /**\n         * compile the script\n         *\n         * @param scriptFile script file\n         * @return compiling result\n         * @throws Exception exception\n         */\n        public Script compile(File scriptFile) throws Exception {\n                return compile(scriptFile.getName(), new FileReader(scriptFile));\n        }\n\n        private boolean scriptNameAlreadyUsed(ClassLoader loader, String name) {\n                try {\n                        Class.forName(name);\n                        return true;\n                } catch (ClassNotFoundException e) {\n                        try {\n                                loader.loadClass(name);\n                                return true;\n                        } catch (ClassNotFoundException e2) {\n                                return false;\n                        }\n                }\n        }\n\n        /**\n         * compile the script\n         *\n         * @param name         the script name\n         * @param scriptReader script reader\n         * @return compiling result\n         * @throws Exception exception\n         */\n        public Script compile(final String name, Reader scriptReader) throws Exception {\n                ClassLoader theCompiledClasses = compiler.compile(sources);\n\n                String nameForTheScript = \"Script$Latte$\";\n                int i = 0;\n                while (scriptNameAlreadyUsed(theCompiledClasses, nameForTheScript + i)) ++i;\n\n                nameForTheScript += i;\n\n                // class N\n                //     static\n                //         method(args:String[])\n                //             ...\n                //\n                ErrorManager err = new ErrorManager(true);\n                Scanner scanner = new ScannerSwitcher(name, scriptReader, new Properties(), err);\n                Parser parser = new Parser(scanner.scan(), err);\n                List<Statement> statements = parser.parse();\n\n                List<Statement> innerStatements = new ArrayList<Statement>();\n                final List<Statement> defsAndImports = new ArrayList<Statement>();\n\n                for (Statement stmt : statements) {\n                        if (stmt instanceof ClassDef || stmt instanceof InterfaceDef || stmt instanceof Import || stmt instanceof FunDef) {\n                                defsAndImports.add(stmt);\n                        } else if (stmt instanceof PackageDeclare) {\n                                err.SyntaxException(\"scripts cannot have package declaration\", stmt.line_col());\n                        } else {\n                                innerStatements.add(stmt);\n                        }\n                }\n\n                VariableDef v = new VariableDef(\"args\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(new AST.Access(null, \"String\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC));\n                ClassDef classDef = new ClassDef(\n                        nameForTheScript,\n                        Collections.<AST.Access>emptyList(),\n                        Collections.<Modifier>emptySet(),\n                        Collections.<VariableDef>emptyList(),\n                        null,\n                        Collections.<AST.Access>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(\n                                new MethodDef(\n                                        \"method\",\n                                        Collections.<Modifier>emptySet(),\n                                        null,\n                                        Collections.singletonList(v),\n                                        Collections.<AST.Anno>emptySet(),\n                                        innerStatements,\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        new LineCol(name, 0, 0)\n                );\n\n                defsAndImports.add(classDef);\n                defsAndImports.add(new Import(new AST.PackageRef(\"java::util\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                defsAndImports.add(new Import(new AST.PackageRef(\"java::math\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                defsAndImports.add(new Import(new AST.PackageRef(\"java::io\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                defsAndImports.add(new Import(new AST.PackageRef(\"lt::repl\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n\n                SemanticProcessor sp = new SemanticProcessor(new HashMap<String, List<Statement>>() {{\n                        put(name, defsAndImports);\n                }}, theCompiledClasses, err);\n                CodeGenerator cg = new CodeGenerator(sp.parse(), sp.getTypes());\n                final Map<String, byte[]> map = cg.generate();\n                ClassLoader loader = new ClassLoader(theCompiledClasses) {\n                        @Override\n                        protected Class<?> findClass(String name) throws ClassNotFoundException {\n                                if (map.containsKey(name)) {\n                                        byte[] bs = map.get(name);\n                                        return defineClass(name, bs, 0, bs.length);\n                                } else throw new ClassNotFoundException(name);\n                        }\n                };\n\n                Class<?> scriptCls = loader.loadClass(nameForTheScript);\n                Method scriptMethod = scriptCls.getMethod(\"method\", String[].class);\n\n                return new Script(loader, scriptCls, scriptMethod);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/CL.java",
    "content": "package lt.repl.scripting;\n\nimport java.util.HashMap;\nimport java.util.Map;\n\npublic class CL extends ClassLoader {\n        private Map<String, byte[]> byteCodes = new HashMap<String, byte[]>();\n\n        public CL(ClassLoader cl) {\n                super(cl);\n        }\n\n        @Override\n        protected Class<?> findClass(String name) throws ClassNotFoundException {\n                byte[] byteCode = byteCodes.get(name);\n                if (byteCode == null) throw new ClassNotFoundException(name);\n                return defineClass(name, byteCode, 0, byteCode.length);\n        }\n\n        public void addByteCodes(String name, byte[] bytes) {\n                byteCodes.put(name, bytes);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/Config.java",
    "content": "package lt.repl.scripting;\n\n/**\n * configurations for source code to compile\n */\npublic class Config {\n        public static final int SCANNER_TYPE_INDENT = 0;\n        public static final int SCANNER_TYPE_BRACE = 1;\n\n        private int scannerType;\n        private String varNamePrefix;\n        private boolean eval;\n\n        public int getScannerType() {\n                return scannerType;\n        }\n\n        public Config setScannerType(int scannerType) {\n                this.scannerType = scannerType;\n                return this;\n        }\n\n        public String getVarNamePrefix() {\n                return varNamePrefix;\n        }\n\n        public Config setVarNamePrefix(String varNamePrefix) {\n                this.varNamePrefix = varNamePrefix;\n                return this;\n        }\n\n        public boolean isEval() {\n                return eval;\n        }\n\n        public Config setEval(boolean eval) {\n                this.eval = eval;\n                return this;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/EvalEntry.java",
    "content": "package lt.repl.scripting;\n\n/**\n * the entry containing variable name and it's corresponding object\n */\npublic class EvalEntry {\n        public final String name;\n        public final Object result;\n        public final Class<?> type;\n\n        public EvalEntry(String name, Object result, Class<?> type) {\n                this.name = name;\n                this.result = result;\n                this.type = type;\n        }\n\n        @Override\n        public String toString() {\n                return \"EvalEntry{\" +\n                        \"name='\" + name + '\\'' +\n                        \", result=\" + result +\n                        \", type=\" + type +\n                        '}';\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/LatteContext.java",
    "content": "package lt.repl.scripting;\n\nimport javax.script.Bindings;\nimport javax.script.ScriptContext;\nimport java.io.InputStreamReader;\nimport java.io.PrintWriter;\nimport java.io.Reader;\nimport java.io.Writer;\nimport java.util.*;\n\n/**\n * script context\n */\npublic class LatteContext implements ScriptContext {\n        private Bindings engineScope;\n        private Bindings globalScope;\n\n        public LatteContext(Bindings engineScope) {\n                this.engineScope = engineScope;\n        }\n\n        @Override\n        public void setBindings(Bindings bindings, int scope) {\n                switch (scope) {\n                        case ENGINE_SCOPE:\n                                engineScope = bindings;\n                                break;\n                        case GLOBAL_SCOPE:\n                                globalScope = bindings;\n                                break;\n                        default:\n                                throw new IllegalArgumentException(\"invalid scope\");\n                }\n        }\n\n        private void validateScope(int scope) {\n                if (scope != ENGINE_SCOPE && scope != GLOBAL_SCOPE) {\n                        throw new IllegalArgumentException(\"invalid scope, not current|engine|global\");\n                }\n        }\n\n        private void validateName(String name) {\n                if (name == null || name.isEmpty()) {\n                        throw new IllegalArgumentException(\"invalid name, empty\");\n                }\n        }\n\n        private Bindings getScope(int scope) {\n                switch (scope) {\n                        case ENGINE_SCOPE:\n                                return engineScope;\n                        case GLOBAL_SCOPE:\n                                return globalScope;\n                        default:\n                                throw new Error(\"won't reach here!\");\n                }\n        }\n\n        @Override\n        public Bindings getBindings(int scope) {\n                validateScope(scope);\n                return getScope(scope);\n        }\n\n        @Override\n        public void setAttribute(String name, Object value, int scope) {\n                validateScope(scope);\n                validateName(name);\n                getScope(scope).put(name, value);\n        }\n\n        @Override\n        public Object getAttribute(String name, int scope) {\n                validateScope(scope);\n                validateName(name);\n                return getScope(scope).get(name);\n        }\n\n        @Override\n        public Object removeAttribute(String name, int scope) {\n                validateScope(scope);\n                validateName(name);\n                return getScope(scope).remove(name);\n        }\n\n        @Override\n        public Object getAttribute(String name) {\n                if (engineScope.containsKey(name)) return engineScope.get(name);\n                if (globalScope.containsKey(name)) return globalScope.get(name);\n                return null;\n        }\n\n        @Override\n        public int getAttributesScope(String name) {\n                if (engineScope.containsKey(name)) return ENGINE_SCOPE;\n                if (globalScope.containsKey(name)) return GLOBAL_SCOPE;\n                return -1;\n        }\n\n        @Override\n        public Writer getWriter() {\n                return new PrintWriter(System.out);\n        }\n\n        @Override\n        public Writer getErrorWriter() {\n                return new PrintWriter(System.err);\n        }\n\n        @Override\n        public void setWriter(Writer writer) {\n                throw new UnsupportedOperationException(\"Latte is compiled to jvm byte code and run directly on JVM, set System.out if you really want to.\");\n        }\n\n        @Override\n        public void setErrorWriter(Writer writer) {\n                throw new UnsupportedOperationException(\"Latte is compiled to jvm byte code and run directly on JVM, set System.err if you really want to.\");\n        }\n\n        @Override\n        public Reader getReader() {\n                return new InputStreamReader(System.in);\n        }\n\n        @Override\n        public void setReader(Reader reader) {\n                throw new UnsupportedOperationException(\"Latte is compiled to jvm byte code and run directly on JVM, set System.in if you really want to.\");\n        }\n\n        @Override\n        public List<Integer> getScopes() {\n                return Arrays.asList(ENGINE_SCOPE, GLOBAL_SCOPE);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/LatteEngine.java",
    "content": "package lt.repl.scripting;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.Scanner;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.pre.Import;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\nimport lt.lang.Pointer;\nimport lt.lang.Unit;\nimport lt.runtime.LtRuntimeException;\n\nimport javax.script.*;\nimport java.io.IOException;\nimport java.io.Reader;\nimport java.io.StringReader;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.*;\n\n/**\n * the script engine\n */\npublic class LatteEngine implements ScriptEngine {\n        private static final String SCRIPT_CLASS_NAME = \"LATTE_SCRIPTING\";\n        private final LatteEngineFactory factory;\n        private ScriptContext context;\n        private final ClassLoader classLoader;\n\n        LatteEngine(LatteEngineFactory factory) {\n                this.factory = factory;\n                Bindings engineScope = new LatteScope();\n                context = new LatteContext(engineScope);\n                classLoader = new MultipleClassLoader(\n                        factory.getClass().getClassLoader(),\n                        Thread.currentThread().getContextClassLoader());\n        }\n\n        public LatteEngine(ClassLoader loader) {\n                factory = null;\n                classLoader = loader;\n        }\n\n        @Override\n        public Object eval(String script, ScriptContext context) throws ScriptException {\n                return eval(script, context.getBindings(ScriptContext.ENGINE_SCOPE));\n        }\n\n        @Override\n        public Object eval(Reader reader, ScriptContext context) throws ScriptException {\n                return eval(readFully(reader), context);\n        }\n\n        @Override\n        public Object eval(String script) throws ScriptException {\n                return eval(script, context);\n        }\n\n        @Override\n        public Object eval(Reader reader) throws ScriptException {\n                return eval(readFully(reader));\n        }\n\n        @Override\n        public Object eval(String script, Bindings n) throws ScriptException {\n                return eval(script, n, new Config()\n                        .setScannerType(Config.SCANNER_TYPE_INDENT)\n                        .setVarNamePrefix(\"res\")\n                        .setEval(false));\n        }\n\n        public Object eval(String script, Bindings n, Config config) throws ScriptException {\n                List<Import> imports = initImports(n);\n                CL cl = initCL(n);\n                List<MethodDef> recordedMethods = initMethodList(n);\n                final String scriptName = \"latte-scripting.lts\";\n                boolean isLatteScope = n instanceof LatteScope;\n                boolean recordVarIfPresent = true;\n\n                try {\n                        ErrorManager err = new ErrorManager(true);\n                        Scanner scanner;\n                        switch (config.getScannerType()) {\n                                case Config.SCANNER_TYPE_BRACE:\n                                        scanner = new BraceScanner(scriptName, new StringReader(script), new Properties(), err);\n                                        break;\n                                case Config.SCANNER_TYPE_INDENT:\n                                default:\n                                        scanner = new IndentScanner(scriptName, new StringReader(script), new Properties(), err);\n                        }\n                        Parser parser = new Parser(scanner.scan(), err);\n                        List<Statement> statements = parser.parse();\n                        Statement lastStatement = statements.isEmpty() ? null : statements.get(statements.size() - 1);\n                        String varName = null;\n                        if (null != lastStatement) {\n                                if (lastStatement instanceof VariableDef) {\n                                        // variable def\n                                        // so, the name can be retrieved\n                                        VariableDef v = (VariableDef) lastStatement;\n                                        varName = v.getName();\n                                } else if (lastStatement instanceof AST.Assignment) {\n                                        // it's an assignment\n                                        // the name can be retrieved\n                                        AST.Assignment ass = (AST.Assignment) lastStatement;\n                                        AST.Access assignTo = ass.assignTo;\n                                        if (assignTo.exp == null) {\n                                                // assign to the field\n                                                varName = assignTo.name;\n                                        } else {\n                                                // cannot capture the name\n                                                // generate a name\n                                                varName = config.getVarNamePrefix() + incAndGetResCount(n);\n                                                lastStatement = defineAVariable(varName, (Expression) lastStatement);\n                                        }\n                                } else if (lastStatement instanceof Expression) {\n                                        // the last statement is an expression\n                                        // it can be assigned to a variable\n                                        // the variable should be generated\n                                        varName = config.getVarNamePrefix() + incAndGetResCount(n);\n                                        lastStatement = defineAVariable(varName, (Expression) lastStatement);\n                                        if (!config.isEval()) {\n                                                recordVarIfPresent = false;\n                                        }\n                                }\n\n                                // replace the last statement\n                                statements.remove(statements.size() - 1);\n                                statements.add(lastStatement);\n                        }\n\n                        List<Statement> scriptStatements = new ArrayList<Statement>();\n                        final List<Statement> defList = new ArrayList<Statement>();\n                        // buffer these imports and add them if pass compile\n                        List<Import> readyToAddIntoImport = new ArrayList<Import>();\n\n                        for (Statement s : statements) {\n                                if (s instanceof ClassDef || s instanceof InterfaceDef || s instanceof FunDef || s instanceof ObjectDef) {\n                                        defList.add(s);\n                                } else if (s instanceof Import) {\n                                        readyToAddIntoImport.add((Import) s);\n                                } else if (s instanceof PackageDeclare) {\n                                        err.SyntaxException(\"scripts cannot have package declaration\", s.line_col());\n                                } else if (s instanceof MethodDef) {\n                                        recordedMethods.add((MethodDef) s);\n                                } else {\n                                        scriptStatements.add(s);\n                                }\n                        }\n                        // validate innerStatements\n                        // VariableDef might be transformed into assign\n                        for (int i = 0; i < scriptStatements.size(); ++i) {\n                                Statement s = scriptStatements.get(i);\n                                if (s instanceof VariableDef) {\n                                        String name = ((VariableDef) s).getName();\n                                        boolean found = false;\n                                        for (String key : n.keySet()) {\n                                                if (key.equals(name)) {\n                                                        found = true;\n                                                        break;\n                                                }\n                                        }\n\n                                        if (found) {\n                                                if (((VariableDef) s).getAnnos().isEmpty()\n                                                        && ((VariableDef) s).getModifiers().isEmpty()\n                                                        && ((VariableDef) s).getInit() != null) {\n                                                        scriptStatements.set(i, new AST.Assignment(\n                                                                new AST.Access(null, name, s.line_col()),\n                                                                \"=\",\n                                                                ((VariableDef) s).getInit(),\n                                                                s.line_col()\n                                                        ));\n                                                }\n                                        }\n                                }\n                        }\n                        // fill the methods\n                        scriptStatements.addAll(recordedMethods);\n\n                        // parameters and args of the class\n                        List<VariableDef> parameters = new ArrayList<VariableDef>();\n                        List<Class<?>> paramClasses = new ArrayList<Class<?>>();\n                        List<Object> paramInstances = new ArrayList<Object>();\n                        for (Map.Entry<String, Object> entry : n.entrySet()) {\n                                String name = entry.getKey();\n                                Object value = entry.getValue();\n                                if (!isValidName(name)) continue;\n                                // parameter\n                                VariableDef v = new VariableDef(\n                                        name,\n                                        Collections.<Modifier>emptySet(),\n                                        Collections.<AST.Anno>emptySet(),\n                                        LineCol.SYNTHETIC);\n                                parameters.add(v);\n                                // class\n                                if (isLatteScope) {\n                                        Class<?> cls = ((LatteScope) n).getType(name);\n                                        paramClasses.add(cls);\n\n                                        String clsName = cls.getName();\n                                        if (clsName.contains(\".\")) {\n                                                v.setType(new AST.Access(\n                                                        new AST.PackageRef(\n                                                                clsName.substring(0, clsName.lastIndexOf(\".\")),\n                                                                LineCol.SYNTHETIC),\n                                                        clsName.substring(clsName.lastIndexOf(\".\") + 1),\n                                                        LineCol.SYNTHETIC)\n                                                );\n                                        } else {\n                                                v.setType(new AST.Access(\n                                                        null, clsName, LineCol.SYNTHETIC\n                                                ));\n                                        }\n                                } else {\n                                        paramClasses.add(Object.class);\n                                }\n                                // instance\n                                paramInstances.add(value);\n                        }\n\n                        final String className = SCRIPT_CLASS_NAME + '_' + new Date().getTime() + '_' + UUID.randomUUID().toString().replace(\"-\", \"\");\n                        ClassDef evalClass = new ClassDef(\n                                className,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<Modifier>emptySet(),\n                                parameters,\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                scriptStatements,\n                                new LineCol(scriptName, 0, 0)\n                        );\n\n                        // fill the eval class into the def list\n                        defList.add(evalClass);\n                        defList.add(new Import(new AST.PackageRef(\"java::util\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        defList.add(new Import(new AST.PackageRef(\"java::math\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        defList.add(new Import(new AST.PackageRef(\"java::io\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        defList.add(new Import(new AST.PackageRef(\"lt::repl\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC));\n                        defList.addAll(imports);\n                        defList.addAll(readyToAddIntoImport);\n\n                        SemanticProcessor processor = new SemanticProcessor(new HashMap<String, List<Statement>>() {{\n                                put(scriptName, defList);\n                        }}, cl, err);\n                        CodeGenerator codeGen = new CodeGenerator(processor.parse(), processor.getTypes());\n                        // the imports are valid now, add into import list\n                        imports.addAll(readyToAddIntoImport);\n                        Map<String, byte[]> byteCodes = codeGen.generate();\n                        List<Class<?>> classes = new ArrayList<Class<?>>();\n                        for (Map.Entry<String, byte[]> entry : byteCodes.entrySet()) {\n                                cl.addByteCodes(entry.getKey(), entry.getValue());\n                        }\n                        for (Map.Entry<String, byte[]> entry : byteCodes.entrySet()) {\n                                Class<?> c = cl.loadClass(entry.getKey());\n                                if (!entry.getKey().equals(className))\n                                        classes.add(c);\n                                c.getDeclaredFields(); // check the class format and throw exception\n                        }\n\n                        // get real class\n                        Class<?> cls = cl.loadClass(className);\n                        Class<?>[] consParams = paramClasses.toArray(new Class[paramClasses.size()]);\n                        Object[] args = paramInstances.toArray(new Object[paramInstances.size()]);\n                        Constructor<?> con = cls.getDeclaredConstructor(consParams);\n                        Object o;\n                        try {\n                                o = con.newInstance(args);\n                        } catch (InvocationTargetException ite) {\n                                throw ite.getTargetException();\n                        }\n\n                        // record the entry if name is not null\n                        for (Field f : cls.getDeclaredFields()) {\n                                f.setAccessible(true);\n                                Object value = f.get(o);\n                                if (!recordVarIfPresent && !config.isEval() && f.getName().equals(varName)) {\n                                        continue;\n                                }\n                                if (!isLatteScope || n.containsKey(f.getName())) {\n                                        n.put(f.getName(), value);\n                                } else {\n                                        ((LatteScope) n).putNew(f.getName(), value, f.getType());\n                                }\n                        }\n\n                        // the result\n                        Object result;\n                        if (varName == null) {\n                                // there's nothing to print\n                                if (classes.isEmpty()) {\n                                        // simply return the instance\n                                        if (config.isEval()) {\n                                                result = new EvalEntry(null, o, o.getClass());\n                                        } else {\n                                                result = null;\n                                        }\n                                } else {\n                                        if (config.isEval()) {\n                                                result = new EvalEntry(\"definedClasses\", classes, List.class);\n                                        } else {\n                                                result = Unit.get();\n                                        }\n                                }\n                        } else {\n                                Field f = cls.getDeclaredField(varName);\n                                f.setAccessible(true);\n                                Object v = f.get(o);\n                                if (config.isEval()) {\n                                        result = new EvalEntry(varName, v, f.getType());\n                                } else {\n                                        result = v;\n                                }\n                        }\n\n                        return result;\n                } catch (Throwable t) {\n                        if (t instanceof Exception) {\n                                throw new ScriptException((Exception) t);\n                        } else {\n                                throw new ScriptException(new Exception(t));\n                        }\n                }\n        }\n\n        private VariableDef defineAVariable(String name, Expression initValue) {\n                VariableDef v = new VariableDef(name, Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(initValue);\n                return v;\n        }\n\n        @Override\n        public Object eval(Reader reader, Bindings n) throws ScriptException {\n                return eval(readFully(reader), n);\n        }\n\n        @Override\n        public void put(String key, Object value) {\n                getBindings(ScriptContext.ENGINE_SCOPE).put(key, value);\n        }\n\n        @Override\n        public Object get(String key) {\n                return getBindings(ScriptContext.ENGINE_SCOPE).get(key);\n        }\n\n        @Override\n        public Bindings getBindings(int scope) {\n                return context.getBindings(scope);\n        }\n\n        @Override\n        public void setBindings(Bindings bindings, int scope) {\n                context.setBindings(bindings, scope);\n        }\n\n        @Override\n        public Bindings createBindings() {\n                return new LatteScope();\n        }\n\n        @Override\n        public ScriptContext getContext() {\n                return context;\n        }\n\n        @Override\n        public void setContext(ScriptContext context) {\n                this.context = context;\n        }\n\n        @Override\n        public ScriptEngineFactory getFactory() {\n                return factory;\n        }\n\n        private static String readFully(Reader reader) throws ScriptException {\n                char[] arr = new char[8 * 1024]; // 8K at a time\n                StringBuilder buf = new StringBuilder();\n                int numChars;\n                try {\n                        while ((numChars = reader.read(arr, 0, arr.length)) > 0) {\n                                buf.append(arr, 0, numChars);\n                        }\n                } catch (IOException exp) {\n                        throw new ScriptException(exp);\n                }\n                return buf.toString();\n        }\n\n        private static List<Import> initImports(Bindings n) {\n                final String importsName = \"$latte.scripting.imports\";\n                @SuppressWarnings(\"unchecked\")\n                List<Import> imports = (List<Import>) n.get(importsName);\n                if (imports == null) {\n                        imports = new ArrayList<Import>();\n                        n.put(importsName, imports);\n                }\n                return imports;\n        }\n\n        private CL initCL(Bindings n) {\n                final String clName = \"$latte.scripting.CL\";\n                CL cl = (CL) n.get(clName);\n                if (cl == null) {\n                        if (this.classLoader == null) {\n                                cl = new CL(Thread.currentThread().getContextClassLoader());\n                        } else {\n                                cl = new CL(this.classLoader);\n                        }\n                        n.put(clName, cl);\n                }\n                return cl;\n        }\n\n        private static List<MethodDef> initMethodList(Bindings n) {\n                final String methodsName = \"$latte.scripting.methods\";\n                @SuppressWarnings(\"unchecked\")\n                List<MethodDef> methodDefs = (List<MethodDef>) n.get(methodsName);\n                if (methodDefs == null) {\n                        methodDefs = new ArrayList<MethodDef>();\n                        n.put(methodsName, methodDefs);\n                }\n                return methodDefs;\n        }\n\n        private static int incAndGetResCount(Bindings n) {\n                final String resCountName = \"$latte.scripting.res_count\";\n                Integer resCount = (Integer) n.get(resCountName);\n                if (resCount == null) {\n                        resCount = 0;\n                } else {\n                        ++resCount;\n                }\n                n.put(resCountName, resCount);\n                return resCount;\n        }\n\n        private static boolean isValidName(String name) {\n                return CompileUtil.isValidName(name);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/LatteEngineFactory.java",
    "content": "package lt.repl.scripting;\n\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineFactory;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.List;\n\n/**\n * the script factory\n */\npublic class LatteEngineFactory implements ScriptEngineFactory {\n        @Override\n        public String getEngineName() {\n                return \"Latte-lang Scripting Engine\";\n        }\n\n        @Override\n        public String getEngineVersion() {\n                return \"ALPHA\";\n        }\n\n        @Override\n        public List<String> getExtensions() {\n                return Collections.singletonList(\"lts\");\n        }\n\n        @Override\n        public List<String> getMimeTypes() {\n                return Arrays.asList(\"application/x-latte\", \"text/latte\", \"application/latte\");\n        }\n\n        @Override\n        public List<String> getNames() {\n                return Arrays.asList(\"latte\", \"Latte\", \"latte-lang\", \"Latte-lang\", \"Latte-Lang\");\n        }\n\n        @Override\n        public String getLanguageName() {\n                return \"Latte-lang\";\n        }\n\n        @Override\n        public String getLanguageVersion() {\n                return \"ALPHA\";\n        }\n\n        @Override\n        public Object getParameter(String key) {\n                if (key.equals(ScriptEngine.ENGINE)) {\n                        return getEngineName();\n                } else if (key.equals(ScriptEngine.ENGINE_VERSION)) {\n                        return getEngineVersion();\n                } else if (key.equals(ScriptEngine.NAME)) {\n                        return getNames().get(0);\n                } else if (key.equals(ScriptEngine.LANGUAGE)) {\n                        return getLanguageName();\n                } else if (key.equals(ScriptEngine.LANGUAGE_VERSION)) {\n                        return getLanguageVersion();\n                } else if (key.equals(\"THREADING\")) {\n                        return null;\n                } else {\n                        return null;\n                }\n        }\n\n        @Override\n        public String getMethodCallSyntax(String obj, String m, String... args) {\n                StringBuilder sb = new StringBuilder();\n                if (obj == null) {\n                        sb.append(\"`\").append(m).append(\"`\");\n                } else {\n                        sb.append(obj).append(\".`\").append(m).append(\"`(\");\n                }\n                boolean isFirst = true;\n                for (String a : args) {\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(a);\n                }\n                sb.append(\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public String getOutputStatement(String toDisplay) {\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"println(\\\"\");\n                int len = toDisplay.length();\n                for (int i = 0; i < len; i++) {\n                        char ch = toDisplay.charAt(i);\n                        switch (ch) {\n                                case '\"':\n                                        sb.append(\"\\\\\\\"\");\n                                        break;\n                                case '\\\\':\n                                        sb.append(\"\\\\\\\\\");\n                                        break;\n                                default:\n                                        sb.append(ch);\n                                        break;\n                        }\n                }\n                sb.append(\"\\\")\");\n                return sb.toString();\n        }\n\n        @Override\n        public String getProgram(String... statements) {\n                StringBuilder sb = new StringBuilder();\n                for (String s : statements) {\n                        sb.append(s).append(\"\\n\");\n                }\n                return sb.toString();\n        }\n\n        @Override\n        public ScriptEngine getScriptEngine() {\n                return new LatteEngine(this);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/LatteScope.java",
    "content": "package lt.repl.scripting;\n\nimport javax.script.Bindings;\nimport java.util.*;\n\n/**\n * eval scope\n */\npublic class LatteScope implements Bindings {\n        private final Map<String, Class<?>> types = new HashMap<String, Class<?>>();\n        private final Map<String, Object> objects = new LinkedHashMap<String, Object>();\n\n        public LatteScope() {\n        }\n\n        @Override\n        public synchronized Object put(String name, Object value) {\n                if (name == null || name.isEmpty()) throw new IllegalArgumentException(\"invalid name, empty\");\n                if (types.containsKey(name)) {\n                        Class<?> type = types.get(name);\n                        if (type.isPrimitive()) {\n                                if (value == null) {\n                                        throw new NullPointerException(\"assign null to primitive type variable\");\n                                }\n                                if (type == int.class) {\n                                        type = Integer.class;\n                                } else if (type == long.class) {\n                                        type = Long.class;\n                                } else if (type == float.class) {\n                                        type = Float.class;\n                                } else if (type == double.class) {\n                                        type = Double.class;\n                                } else if (type == short.class) {\n                                        type = Short.class;\n                                } else if (type == byte.class) {\n                                        type = Byte.class;\n                                } else if (type == char.class) {\n                                        type = Character.class;\n                                } else if (type == boolean.class) {\n                                        type = Boolean.class;\n                                } else throw new IllegalArgumentException(\"unknown primitive type \" + type);\n                        }\n                        if (value == null || type.isInstance(value)) {\n                                return objects.put(name, value);\n                        } else {\n                                throw new IllegalArgumentException(name + \" is not of type \" + type.getName());\n                        }\n                } else {\n                        return putNew(name, value, Object.class);\n                }\n        }\n\n        public synchronized Object putNew(String name, Object value, Class<?> type) {\n                types.put(name, type);\n                return objects.put(name, value);\n        }\n\n        @Override\n        public synchronized void putAll(Map<? extends String, ?> toMerge) {\n                for (Entry<? extends String, ?> e : toMerge.entrySet()) {\n                        put(e.getKey(), e.getValue());\n                }\n        }\n\n        @Override\n        public void clear() {\n                objects.clear();\n        }\n\n        @Override\n        public Set<String> keySet() {\n                return objects.keySet();\n        }\n\n        @Override\n        public Collection<Object> values() {\n                return objects.values();\n        }\n\n        @Override\n        public Set<Entry<String, Object>> entrySet() {\n                return objects.entrySet();\n        }\n\n        @Override\n        public int size() {\n                return objects.size();\n        }\n\n        @Override\n        public boolean isEmpty() {\n                return objects.isEmpty();\n        }\n\n        @Override\n        public boolean containsKey(Object key) {\n                return objects.containsKey(key);\n        }\n\n        @Override\n        public boolean containsValue(Object value) {\n                return objects.containsValue(value);\n        }\n\n        @Override\n        public Object get(Object key) {\n                return objects.get(key);\n        }\n\n        public Class<?> getType(String key) {\n                return types.get(key);\n        }\n\n        @Override\n        public Object remove(Object key) {\n                return objects.remove(key);\n        }\n\n        @Override\n        public String toString() {\n                StringBuilder sb = new StringBuilder(\"{\");\n                boolean isFirst = true;\n                for (Entry<String, Object> entry : objects.entrySet()) {\n                        String name = entry.getKey();\n                        Object value = entry.getValue();\n                        Class<?> type = types.get(name);\n                        if (isFirst) {\n                                isFirst = false;\n                        } else {\n                                sb.append(\",\");\n                        }\n                        sb.append(name).append(\":\").append(type.getName()).append(\"=\").append(value);\n                }\n                sb.append(\"}\");\n                return sb.toString();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/repl/scripting/package-info.java",
    "content": "/**\n * This package is an implementation of jsr223 for Latte-lang<br>\n * Also, it's used by the evaluator.\n */\npackage lt.repl.scripting;"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/Dynamic.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport lt.compiler.LtBug;\nimport lt.lang.FunctionalAbstractClass;\nimport lt.lang.FunctionalInterface;\nimport lt.lang.Unit;\nimport lt.lang.function.Function;\nimport lt.lang.function.Function1;\n\nimport java.lang.reflect.*;\nimport java.util.*;\nimport java.util.List;\nimport java.util.Map;\n\n/**\n * invoke dynamic\n */\npublic class Dynamic {\n        private static final int PRIMITIVE_BOX_CAST_BASE = 233;\n        private static final int COLLECTION_OBJECT_CAST_BASE = 2333;\n\n        /**\n         * check cast when parameter and argument are both primitive\n         * the primitive argument would be cast to box type when handled\n         * so add box types into list\n         */\n        private static final Map<Class<?>, Set<Class<?>>> primitiveCast = new HashMap<Class<?>, Set<Class<?>>>() {{\n                final Map<Class<?>, Set<Class<?>>> self = this;\n                put(int.class, new HashSet<Class<?>>() {{\n                        add(Byte.class);\n                        add(Short.class);\n                        add(Character.class);\n                        add(Integer.class);\n                }});\n                put(long.class, new HashSet<Class<?>>() {{\n                        addAll(self.get(int.class));\n                        add(Long.class);\n                }});\n                put(float.class, new HashSet<Class<?>>() {{\n                        addAll(self.get(long.class));\n                        add(Float.class);\n                }});\n                put(double.class, new HashSet<Class<?>>() {{\n                        addAll(self.get(long.class));\n                        addAll(self.get(float.class));\n                        add(Double.class);\n                }});\n                put(byte.class, new HashSet<Class<?>>() {{\n                        add(Byte.class);\n                }});\n                put(short.class, new HashSet<Class<?>>() {{\n                        add(Short.class);\n                }});\n                put(char.class, new HashSet<Class<?>>() {{\n                        add(Character.class);\n                }});\n                put(boolean.class, new HashSet<Class<?>>() {{\n                        add(Boolean.class);\n                }});\n        }};\n\n        private Dynamic() {\n        }\n\n        /**\n         * check whether the parameters' declaring type can be candidate of invoking by these arguments.\n         *\n         * @param params     parameters\n         * @param args       arguments\n         * @param primitives whether the arg is a primitive\n         * @return true or false\n         */\n        private static boolean canBeCandidate(Class<?>[] params, Object[] args, boolean[] primitives) {\n                for (int i = 0; i < args.length; ++i) {\n                        if (!params[i].isInstance(args[i]) &&\n                                (\n                                        // null can be assigned to any reference type\n                                        params[i].isPrimitive()\n                                                ||\n                                                args[i] != null\n                                )) {\n                                // is not instance\n                                // check primitive\n                                Class<?> cls = params[i];\n\n                                Object obj = args[i];\n                                if (null == obj) continue;\n\n                                if (cls.isPrimitive() && primitives[i]) {\n                                        if (!primitiveCast.get(cls).contains(obj.getClass())) {\n                                                return false;\n                                        }\n                                        continue;\n                                }\n                                if (cls.equals(int.class)) {\n                                        if (!(obj instanceof Integer)) return false;\n                                } else if (cls.equals(short.class)) {\n                                        if (!(obj instanceof Short)) return false;\n                                } else if (cls.equals(byte.class)) {\n                                        if (!(obj instanceof Byte)) return false;\n                                } else if (cls.equals(boolean.class)) {\n                                        if (!(obj instanceof Boolean)) return false;\n                                } else if (cls.equals(char.class)) {\n                                        if (!(obj instanceof Character)) return false;\n                                } else if (cls.equals(long.class)) {\n                                        if (!(obj instanceof Long)) return false;\n                                } else if (cls.equals(double.class)) {\n                                        if (!(obj instanceof Double)) return false;\n                                } else if (cls.equals(float.class)) {\n                                        if (!(obj instanceof Float)) return false;\n                                } else if (cls.isArray()) {\n                                        if (!(obj instanceof java.util.List)) return false;\n                                } else if (!cls.isArray() && !cls.isInterface() && !cls.isAnonymousClass()\n                                        && !cls.isAnnotation() && !cls.isEnum() && !cls.isLocalClass()\n                                        && !cls.isMemberClass() && !cls.isPrimitive() && !cls.isSynthetic()\n                                        && (obj instanceof java.util.Map || obj instanceof java.util.List)) {\n                                        // obj is map\n                                        // and cast to a java object\n                                        Constructor<?> con;\n                                        try {\n                                                con = cls.getConstructor();\n                                        } catch (Exception e) {\n                                                // constructor without parameter\n                                                return false;\n                                        }\n                                        // constructor modifier public\n                                        if (!Modifier.isPublic(con.getModifiers())) return false;\n\n                                        if (obj instanceof Map) {\n                                                // each key is string\n                                                Map map = (Map) obj;\n                                                for (Object key : map.keySet()) {\n                                                        if (!(key instanceof String)) {\n                                                                return false;\n                                                        }\n                                                }\n                                        }\n\n                                        return true;\n\n                                } else if (cls.isInterface() && isFunctionalInterface(cls)) {\n                                        if (!(obj instanceof Function)) return false;\n                                } else if (!cls.isAnnotation() && !cls.isAnonymousClass() && !cls.isArray() &&\n                                        !cls.isEnum() && !cls.isLocalClass() && !cls.isMemberClass()\n                                        && !cls.isPrimitive() && !cls.isSynthetic() &&\n                                        isFunctionalAbstractClass(cls)) {\n                                        if (!(obj instanceof Function)) return false;\n                                } else {\n                                        notFunctionalAbstractClass.put(cls, null);\n                                        notFunctionalInterfaces.put(cls, null);\n                                        return false;\n                                }\n                        }\n                }\n                return true;\n        }\n\n        private static Class<?> chooseType(Class<?> targetType, Object target) {\n                if (target == null) return targetType;\n                if (targetType.isAnnotationPresent(Implicit.class)) return targetType;\n                if (targetType.isInstance(target)) return target.getClass();\n                return targetType;\n        }\n\n        public static Method findMethod(Class<?> invoker, Class<?> targetType, Object target, String method, boolean[] primitives, Object[] args) throws Throwable {\n                if (primitives.length != args.length) throw new LtBug(\"primitives.length should equal to args.length\");\n                List<Method> methodList = new ArrayList<Method>();\n\n                Queue<Class<?>> interfaces = new ArrayDeque<Class<?>>();\n                Class<?> c = chooseType(targetType, target);\n                while (c != null) {\n                        Collections.addAll(interfaces, c.getInterfaces());\n                        fillMethodCandidates(c, invoker, method, primitives, args, methodList, target == null);\n                        c = c.getSuperclass();\n                }\n                c = chooseType(targetType, target);\n\n                Collections.addAll(interfaces, c.getInterfaces());\n                while (!interfaces.isEmpty()) {\n                        Class<?> i = interfaces.remove();\n                        fillMethodCandidates(i, invoker, method, primitives, args, methodList, target == null);\n                        Collections.addAll(interfaces, i.getInterfaces());\n                }\n\n                if (methodList.isEmpty()) {\n                        return null;\n                }\n\n                // find best match\n                Method methodToInvoke = findBestMatch(methodList, args, primitives);\n                // trans to required type\n                transToRequiredType(args, methodToInvoke.getParameterTypes());\n\n                return methodToInvoke;\n        }\n\n        /**\n         * fill in method candidates\n         *\n         * @param c          class\n         * @param invoker    invoker\n         * @param method     method\n         * @param args       arguments\n         * @param methodList method list (fill into this list)\n         * @param onlyStatic only find static methods\n         */\n        private static void fillMethodCandidates(Class<?> c,\n                                                 Class<?> invoker,\n                                                 String method,\n                                                 boolean[] primitives,\n                                                 Object[] args,\n                                                 List<Method> methodList,\n                                                 boolean onlyStatic) {\n                for (Method m : c.getDeclaredMethods()) {\n                        if (!m.getName().equals(method)) continue;\n                        if (m.getParameterTypes().length != args.length) continue;\n\n                        // access check\n                        if (!LtRuntime.haveAccess(m.getModifiers(), c, invoker)) continue;\n\n                        if (onlyStatic) {\n                                if (!Modifier.isStatic(m.getModifiers())) continue;\n                        }\n\n                        // else public\n                        // do nothing\n\n                        if (canBeCandidate(m.getParameterTypes(), args, primitives)) {\n                                methodList.add(m);\n                        }\n                }\n        }\n\n        /**\n         * overridden methods\n         * (superClass method) => (subClass method)\n         */\n        private static Map<Method, Set<Method>> overriddenMethods = new WeakHashMap<Method, Set<Method>>();\n        /**\n         * classes already done override analysis\n         */\n        private static Map<Class<?>, Object> classesDoneOverrideAnalysis = new WeakHashMap<Class<?>, Object>();\n        /**\n         * functional abstract classes\n         */\n        private static Map<Class<?>, Object> functionalAbstractClasses = new WeakHashMap<Class<?>, Object>();\n        /**\n         * not functional abstract classes\n         */\n        private static Map<Class<?>, Object> notFunctionalAbstractClass = new WeakHashMap<Class<?>, Object>();\n        /**\n         * functional interfaces\n         */\n        private static Map<Class<?>, Object> functionalInterfaces = new WeakHashMap<Class<?>, Object>();\n        /**\n         * not functional interfaces\n         */\n        private static Map<Class<?>, Object> notFunctionalInterfaces = new WeakHashMap<Class<?>, Object>();\n        /**\n         * abstract method of a functional interface/abstract class\n         */\n        private static Map<Class<?>, Method> abstractMethod = new WeakHashMap<Class<?>, Method>();\n\n        /**\n         * check signature, whether they are the same.\n         *\n         * @param subM    the method in sub class\n         * @param parentM the method in super class\n         * @return true or false\n         */\n        private static boolean signaturesAreTheSame(Method subM, Method parentM) {\n                String name = parentM.getName();\n\n                if (subM.getName().equals(name)) {\n                        if (subM.getParameterTypes().length == parentM.getParameterTypes().length) {\n                                for (int i = 0; i < subM.getParameterTypes().length; ++i) {\n                                        Class<?> subP = subM.getParameterTypes()[i];\n                                        Class<?> parentP = parentM.getParameterTypes()[i];\n                                        if (!subP.equals(parentP)) return false;\n                                }\n                        }\n                        // parentM is overridden by subM\n                        Set<Method> set;\n                        if (overriddenMethods.containsKey(parentM)) {\n                                set = overriddenMethods.get(parentM);\n                        } else {\n                                set = new HashSet<Method>();\n                                overriddenMethods.put(parentM, set);\n                        }\n                        set.add(subM);\n                        return true;\n                }\n\n                return false;\n        }\n\n        /**\n         * analyse the override relation of the methods in the class/interface\n         *\n         * @param c class object\n         */\n        private static void analyseClassOverride(Class<?> c) {\n                if (classesDoneOverrideAnalysis.containsKey(c)) return;\n\n                if (!c.isInterface()) {\n                        // classes should check super classes\n                        // interfaces don't have super classes (except java.lang.Object)\n\n                        // find overridden abstract methods\n                        Class<?> parent = c.getSuperclass();\n\n                        if (parent != null) {\n\n                                for (Method parentM : parent.getDeclaredMethods()) {\n                                        for (Method subM : c.getDeclaredMethods()) {\n                                                if (signaturesAreTheSame(subM, parentM)) break;\n                                        }\n                                }\n\n                                analyseClassOverride(parent);\n                        }\n                }\n\n                // check interfaces\n                for (Class<?> i : c.getInterfaces()) {\n                        for (Method iM : i.getDeclaredMethods()) {\n                                for (Method cM : c.getDeclaredMethods()) {\n                                        if (signaturesAreTheSame(cM, iM)) break;\n                                }\n                        }\n\n                        analyseClassOverride(i);\n                }\n\n                classesDoneOverrideAnalysis.put(c, null);\n        }\n\n        /**\n         * check whether the method is overridden in the sub class\n         *\n         * @param parentM method in parent class\n         * @param sub     sub class\n         * @return true or false\n         */\n        private static boolean isOverriddenInClass(Method parentM, Class<?> sub) {\n                Set<Method> methods = overriddenMethods.get(parentM);\n                if (methods == null) return false;\n                for (Method m : methods) {\n                        if (m.getDeclaringClass().equals(sub)) return true;\n                        if (isOverriddenInClass(m, sub)) return true;\n                }\n                return false;\n        }\n\n        /**\n         * find one abstract method in the class\n         *\n         * @param c the class to retrieve method from\n         * @return the retrieved abstract method\n         * @throws LtRuntimeException no abstract method found\n         */\n        public static Method findAbstractMethod(Class<?> c) {\n                if (abstractMethod.containsKey(c)) return abstractMethod.get(c);\n\n                // find in current class\n                for (Method m : c.getDeclaredMethods()) {\n                        if (Modifier.isAbstract(m.getModifiers())) {\n                                abstractMethod.put(c, m);\n                                return m;\n                        }\n                }\n\n                if (!c.isInterface()) {\n                        // check super class\n                        Class<?> tmp = c.getSuperclass();\n                        while (tmp != null) {\n                                if (!Modifier.isAbstract(tmp.getModifiers())) break;\n\n                                for (Method method : tmp.getDeclaredMethods()) {\n                                        if (Modifier.isAbstract(method.getModifiers())) {\n                                                if (isOverriddenInClass(method, c)) continue;\n\n                                                abstractMethod.put(c, method);\n                                                return method;\n                                        }\n                                }\n                                tmp = tmp.getSuperclass();\n                        }\n                }\n\n                // check interfaces\n\n                Set<Class<?>> visited = new HashSet<Class<?>>();\n                Queue<Class<?>> interfaces = new ArrayDeque<Class<?>>();\n\n                Collections.addAll(interfaces);\n\n                while (!interfaces.isEmpty()) {\n                        Class<?> ii = interfaces.remove();\n                        if (visited.contains(ii)) continue;\n                        for (Method m : ii.getDeclaredMethods()) {\n                                if (Modifier.isAbstract(m.getModifiers())) {\n                                        if (isOverriddenInClass(m, c)) continue;\n\n                                        abstractMethod.put(c, m);\n                                        return m;\n                                }\n                        }\n\n                        visited.add(ii);\n                        Collections.addAll(interfaces, ii.getInterfaces());\n                }\n\n                throw new LtRuntimeException(\"cannot find abstract method in \" + c);\n        }\n\n        /**\n         * check whether the interface is a <tt>functional interface</tt>\n         *\n         * @param i the interface to be checked\n         * @return true/false\n         */\n        public static boolean isFunctionalInterface(Class<?> i) {\n                if (i.isAnnotationPresent(FunctionalInterface.class)) return true;\n\n                if (functionalInterfaces.containsKey(i)) return true;\n                if (notFunctionalInterfaces.containsKey(i)) return false;\n\n                analyseClassOverride(i);\n\n                Set<Class<?>> visited = new HashSet<Class<?>>();\n\n                boolean found = false;\n                Queue<Class<?>> interfaces = new ArrayDeque<Class<?>>();\n                interfaces.add(i);\n\n                while (!interfaces.isEmpty()) {\n                        Class<?> ii = interfaces.remove();\n                        if (visited.contains(ii)) continue;\n                        for (Method m : ii.getDeclaredMethods()) {\n                                if (Modifier.isAbstract(m.getModifiers())) {\n                                        if (isOverriddenInClass(m, i)) continue;\n\n                                        if (found) return false;\n                                        found = true;\n                                }\n                        }\n\n                        visited.add(ii);\n                        Collections.addAll(interfaces, ii.getInterfaces());\n                }\n\n                if (found)\n                        functionalInterfaces.put(i, null);\n                return found;\n        }\n\n        /**\n         * check whether the class is a <tt>functional abstract class</tt>\n         *\n         * @param c the class to be checked\n         * @return true/false\n         */\n        public static boolean isFunctionalAbstractClass(Class<?> c) {\n                if (!Modifier.isAbstract(c.getModifiers())) return false;\n\n                if (c.isAnnotationPresent(FunctionalAbstractClass.class)) return true;\n\n                if (functionalAbstractClasses.containsKey(c)) return true;\n                if (notFunctionalAbstractClass.containsKey(c)) return false;\n\n                Constructor<?>[] cons = c.getDeclaredConstructors();\n                boolean containsPublicZeroParamConstructor = false;\n                for (Constructor<?> con : cons) {\n                        if (Modifier.isPublic(con.getModifiers())) {\n                                if (con.getParameterTypes().length == 0) {\n                                        containsPublicZeroParamConstructor = true;\n                                        break;\n                                }\n                        }\n                }\n\n                if (!containsPublicZeroParamConstructor) return false;\n\n                analyseClassOverride(c);\n\n                Set<Class<?>> visited = new HashSet<Class<?>>();\n\n                boolean found = false;\n\n                Class<?> tmpCls = c;\n                while (tmpCls != null) {\n                        for (Method m : tmpCls.getDeclaredMethods()) {\n                                if (Modifier.isAbstract(m.getModifiers())) {\n                                        if (isOverriddenInClass(m, c)) continue;\n\n                                        if (found) return false;\n                                        found = true;\n                                }\n                        }\n\n                        visited.add(tmpCls);\n                        tmpCls = tmpCls.getSuperclass();\n                }\n\n                Queue<Class<?>> interfaces = new ArrayDeque<Class<?>>();\n                Collections.addAll(interfaces);\n\n                while (!interfaces.isEmpty()) {\n                        Class<?> ii = interfaces.remove();\n                        if (visited.contains(ii)) continue;\n                        for (Method m : ii.getDeclaredMethods()) {\n                                if (Modifier.isAbstract(m.getModifiers())) {\n                                        if (isOverriddenInClass(m, c)) continue;\n\n                                        if (found) return false;\n                                        found = true;\n                                }\n                        }\n\n                        visited.add(ii);\n                        Collections.addAll(interfaces, ii.getInterfaces());\n                }\n\n                if (found)\n                        functionalAbstractClasses.put(c, null);\n                return found;\n        }\n\n        /**\n         * bfs search the required type\n         *\n         * @param current  current\n         * @param required required\n         * @return cast steps - 0 means no cast\n         */\n        private static int bfsSearch(Class<?> current, Class<?> required) {\n                if (current.isArray() && required.isArray()) {\n                        return bfsSearch(current.getComponentType(), required.getComponentType());\n                }\n                Set<Class<?>> visited = new HashSet<Class<?>>();\n                Queue<Class<?>> queue = new ArrayDeque<Class<?>>();\n                List<Class<?>> ready = new LinkedList<Class<?>>();\n                queue.add(current);\n                visited.add(current);\n                int count = 0;\n                while (!queue.isEmpty() || !ready.isEmpty()) {\n                        if (queue.isEmpty()) {\n                                queue.addAll(ready);\n                                ready.clear();\n                                ++count;\n                        }\n\n                        Class<?> c = queue.remove();\n                        if (c.equals(required)) return count;\n                        // fill in super\n                        if (c.getSuperclass() != null\n                                &&\n                                !visited.contains(c.getSuperclass())) {\n\n                                ready.add(c.getSuperclass());\n                                visited.add(c.getSuperclass());\n                        }\n                        for (Class<?> i : c.getInterfaces()) {\n                                if (!visited.contains(i)) {\n                                        ready.add(i);\n                                        visited.add(i);\n                                }\n                        }\n                }\n                throw new LtBug(required + \" is not assignable from \" + current);\n        }\n\n        /**\n         * transform the argument into required types. the transformed object will replace elements in the argument array.\n         *\n         * @param args   arguments\n         * @param params required types\n         * @throws Exception exception\n         */\n        private static void transToRequiredType(Object[] args, Class<?>[] params) throws Throwable {\n                for (int i = 0; i < params.length; ++i) {\n                        Class<?> c = params[i];\n                        if (c.isPrimitive()) continue;\n                        Object o = args[i];\n\n                        if (o == null || c.isInstance(o)) continue;\n\n                        args[i] = LtRuntime.cast(o, c, null);\n                }\n        }\n\n        /**\n         * get number type primitives cast depth\n         *\n         * @param from from type\n         * @param to   to type\n         * @return depth\n         */\n        private static int getNumberPrimitiveCastDepth(Class<?> from, Class<?> to) {\n                if (from == Integer.class) from = int.class;\n                if (from == Float.class) from = float.class;\n                if (from == Long.class) from = long.class;\n                if (from == Double.class) from = double.class;\n                if (from == Short.class) from = short.class;\n                if (from == Byte.class) from = byte.class;\n                if (from == Character.class) from = char.class;\n\n                if (from == to) return 0;\n                if (from == byte.class || from == short.class || from == char.class) {\n                        if (to == int.class) {\n                                return 1;\n                        } else if (to == long.class) {\n                                return 2;\n                        } else if (to == float.class) {\n                                return 3;\n                        } else if (to == double.class) {\n                                return 4;\n                        } else throw new LtBug(\"should not reach here, from: \" + from + \" to: \" + to);\n                } else if (from == int.class) {\n                        if (to == long.class) {\n                                return 1;\n                        } else if (to == float.class) {\n                                return 2;\n                        } else if (to == double.class) {\n                                return 3;\n                        } else throw new LtBug(\"should not reach here, from: \" + from + \" to: \" + to);\n                } else if (from == long.class) {\n                        if (to == float.class) {\n                                return 1;\n                        } else if (to == double.class) {\n                                return 2;\n                        } else throw new LtBug(\"should not reach here, from: \" + from + \" to: \" + to);\n                } else if (from == float.class) {\n                        if (to == double.class) {\n                                return 1;\n                        } else throw new LtBug(\"should not reach here, from: \" + from + \" to: \" + to);\n                } else throw new LtBug(\"should not reach here, from: \" + from);\n        }\n\n        /**\n         * find best match.\n         *\n         * @param methodList method list (constructors or methods)\n         * @param args       arguments\n         * @param primitives whether the argument is a primitive\n         * @param <T>        {@link Constructor} or {@link Method}\n         * @return the found method\n         */\n        private static <T> T findBestMatch(List<T> methodList, Object[] args, boolean[] primitives) {\n                // calculate every method's cast steps\n                Map<T, int[]> steps = new HashMap<T, int[]>();\n                for (T m : methodList) {\n                        int[] step = new int[args.length];\n                        for (int i = 0; i < args.length; ++i) {\n                                Class<?> type;\n                                if (m instanceof Method) {\n                                        type = ((Method) m).getParameterTypes()[i];\n                                } else {\n                                        type = ((Constructor) m).getParameterTypes()[i];\n                                }\n                                if (primitives[i] && type.isPrimitive()) {\n                                        if (args[i] instanceof Number || args[i] instanceof Character) {\n                                                step[i] = getNumberPrimitiveCastDepth(args[i].getClass(), type);\n                                        } else {\n                                                // for non number type (bool)\n                                                step[i] = 0;\n                                        }\n                                } else if (primitives[i]) {\n                                        // param is not primitive\n                                        step[i] = PRIMITIVE_BOX_CAST_BASE; // first cast to box type\n                                        step[i] += bfsSearch(args[i].getClass(), type);\n                                } else if (type.isPrimitive()) {\n                                        // arg is not primitive\n                                        step[i] = PRIMITIVE_BOX_CAST_BASE; // cast to primitive\n                                } else {\n                                        // both not primitive\n                                        // check null\n                                        if (args[i] == null) step[i] = 0;\n                                        else {\n                                                if (type.isAssignableFrom(args[i].getClass()))\n                                                        step[i] = bfsSearch(args[i].getClass(), type);\n                                                else {\n                                                        if (type.isArray()\n                                                                || isFunctionalAbstractClass(type)\n                                                                || isFunctionalInterface(type)) {\n                                                                step[i] = 1;\n                                                        } else if (args[i] instanceof Map || args[i] instanceof List) {\n                                                                step[i] = COLLECTION_OBJECT_CAST_BASE;\n                                                        } else throw new LtBug(\"unsupported type cast\");\n                                                }\n                                        }\n                                }\n                        }\n                        steps.put(m, step);\n                }\n\n                // choose the best match\n                T methodToInvoke = null;\n                int[] step = null;\n                for (Map.Entry<T, int[]> entry : steps.entrySet()) {\n                        if (methodToInvoke == null) {\n                                methodToInvoke = entry.getKey();\n                                step = entry.getValue();\n                        } else {\n                                int[] newStep = entry.getValue();\n                                boolean isBetter = false;\n                                boolean isWorse = false;\n                                for (int i = 0; i < step.length; ++i) {\n                                        if (step[i] == newStep[i]) continue;\n                                        else if (step[i] > newStep[i]) isBetter = true;\n                                        else if (step[i] < newStep[i]) isWorse = true;\n\n                                        if (isBetter && isWorse)\n                                                throw new LtRuntimeException(\n                                                        \"cannot decide which method to invoke:\\n\"\n                                                                + methodToInvoke + \":\" + Arrays.toString(step) + \"\\n\"\n                                                                + entry.getKey() + \":\" + Arrays.toString(newStep));\n                                }\n\n                                if (isBetter) {\n                                        methodToInvoke = entry.getKey();\n                                        step = entry.getValue();\n                                }\n                        }\n                }\n\n                assert methodToInvoke != null;\n\n                return methodToInvoke;\n        }\n\n        /**\n         * construct an object.\n         *\n         * @param targetType the type to instantiate.\n         * @param invoker    from which class invokes the method\n         * @param primitives whether the argument is primitive\n         * @param args       arguments\n         * @return the constructed object\n         * @throws Throwable exceptions\n         */\n        public static Object construct(Class<?> targetType, Class<?> invoker, boolean[] primitives, Object[] args) throws Throwable {\n                if (primitives.length != args.length) throw new LtBug(\"primitives.length should equal to args.length\");\n\n                Constructor<?>[] constructors = targetType.getDeclaredConstructors();\n\n                // select candidates\n                List<Constructor<?>> candidates = new ArrayList<Constructor<?>>();\n                for (Constructor<?> con : constructors) {\n                        if (!LtRuntime.haveAccess(con.getModifiers(), targetType, invoker)) continue;\n\n                        if (con.getParameterTypes().length == args.length) {\n                                if (canBeCandidate(con.getParameterTypes(), args, primitives)) {\n                                        candidates.add(con);\n                                }\n                        }\n                }\n\n                if (candidates.isEmpty()) {\n                        StringBuilder sb = new StringBuilder().append(targetType.getName()).append(\"(\");\n                        buildErrorMessageArgsPart(sb, args);\n                        sb.append(\")\");\n                        throw new LtRuntimeException(\"cannot find constructor \" + sb.toString());\n                } else {\n                        Constructor<?> constructor = findBestMatch(candidates, args, primitives);\n                        transToRequiredType(args, constructor.getParameterTypes());\n\n                        constructor.setAccessible(true);\n\n                        try {\n                                return constructor.newInstance(args);\n                        } catch (InvocationTargetException e) {\n                                throw e.getTargetException();\n                        }\n                }\n        }\n\n        /**\n         * the invocation state.\n         */\n        public static class InvocationState {\n                /**\n                 * whether the method is found\n                 */\n                public boolean methodFound = false;\n                /**\n                 * the method that invokes this, is trying to get or put a field\n                 */\n                public boolean fromField = false;\n        }\n\n        /**\n         * invoke method with a invocationState.\n         *\n         * @param invocationState  invocationState\n         * @param targetClass      the method is in this class\n         * @param o                invoke the method on the object (or null if invoke static)\n         * @param isStatic         whether the invocation is static\n         * @param functionalObject the object to invoke functional method on if method not found\n         * @param invoker          from which class invokes the method\n         * @param method           method name\n         * @param primitives       whether the argument is primitive\n         * @param args             the arguments\n         * @param canInvokeImport  the method is invoked directly by the method's name, which could be invoking an import static method\n         * @return the method result (void methods' results are <tt>Unit</tt>)\n         * @throws Throwable exception\n         */\n        public static Object invoke(InvocationState invocationState,\n                                    Class<?> targetClass,\n                                    Object o,\n                                    boolean isStatic,\n                                    Object functionalObject,\n                                    Class<?> invoker,\n                                    String method,\n                                    boolean[] primitives,\n                                    Object[] args,\n                                    boolean canInvokeImport) throws Throwable {\n\n                if (primitives.length != args.length) throw new LtBug(\"primitives.length should equal to args.length\");\n                Method methodToInvoke = findMethod(invoker, targetClass, o, method, primitives, args);\n                // method found ?\n                if (null != methodToInvoke) {\n                        try {\n                                return invokeMethod(methodToInvoke, o, args);\n                        } catch (InvocationTargetException e) {\n                                throw e.getTargetException();\n                        }\n                }\n\n                ExceptionContainer ec = new ExceptionContainer();\n\n                Class<?> c = o == null ? targetClass : o.getClass();\n                if (c.isArray()) {\n                        if (method.equals(\"get\") && args.length >= 1 && args[0] instanceof Integer) {\n                                Object res = Array.get(o, (Integer) args[0]);\n                                if (args.length == 1) return res;\n\n                                boolean[] bs = new boolean[primitives.length - 1];\n                                Object[] as = new Object[args.length - 1];\n                                for (int i = 1; i < args.length; ++i) {\n                                        bs[i - 1] = primitives[i];\n                                        as[i - 1] = args[i];\n                                }\n\n                                return invoke(invocationState, targetClass, res, isStatic, null, invoker, \"get\", bs, as, canInvokeImport);\n                        } else if (method.equals(\"set\") && args.length >= 2 && args[0] instanceof Integer) {\n                                if (args.length == 2) {\n                                        Array.set(o, (Integer) args[0], args[1]);\n                                        return args[1];\n                                } else {\n                                        Object elem = Array.get(o, (Integer) args[0]);\n\n                                        boolean[] bs = new boolean[primitives.length - 1];\n                                        Object[] as = new Object[args.length - 1];\n                                        for (int i = 1; i < args.length; ++i) {\n                                                bs[i - 1] = primitives[i];\n                                                as[i - 1] = args[i];\n                                        }\n\n                                        return invoke(invocationState, targetClass, elem, isStatic, null, invoker, \"set\", bs, as, canInvokeImport);\n                                }\n                        } else {\n                                ec.add(\"Target is array but method is not get(int)\");\n                                ec.add(\"Target is array but method is not set(int, ...)\");\n                        }\n                } else {\n                        // null string append\n                        if (!isStatic && o == null && method.equals(\"add\") && args.length == 1 && args[0] instanceof String) {\n                                return \"null\" + args[0];\n                        }\n                        // implicit cast\n                        if (o != null && invoker.isAnnotationPresent(ImplicitImports.class)) {\n                                Class<?>[] implicitClasses = invoker.getAnnotation(ImplicitImports.class).implicitImports();\n                                if (implicitClasses.length == 0) {\n                                        ec.add(\"No implicit casts enabled\");\n                                } else {\n                                        for (Class<?> ic : implicitClasses) {\n                                                if (!ic.isAnnotationPresent(LatteObject.class)) continue;\n                                                Method[] methods = ic.getDeclaredMethods();\n                                                for (Method m : methods) {\n                                                        if (m.isAnnotationPresent(Implicit.class) && m.getParameterTypes().length == 1 && m.getReturnType() != void.class) {\n                                                                Class<?> inputType = m.getParameterTypes()[0];\n                                                                if (inputType.isInstance(o)) {\n                                                                        Class<?> outputType = m.getReturnType();\n                                                                        Method foundMethod = findMethod(invoker, outputType, o, method, primitives, args);\n                                                                        if (foundMethod == null) {\n                                                                                ec.add(\"Still cannot find method if casting \" + o.getClass().getName() + \" to \" + m.getReturnType());\n                                                                                continue;\n                                                                        }\n                                                                        // get object instance\n                                                                        Object implicitInstance = ic.getField(\"singletonInstance\").get(null);\n                                                                        // invoke method\n                                                                        m.setAccessible(true);\n                                                                        Object castInstance = m.invoke(implicitInstance, o);\n                                                                        return invokeMethod(foundMethod, castInstance, args);\n                                                                }\n                                                        }\n                                                }\n                                        }\n                                }\n                        } else {\n                                ec.add(\"No implicit casts enabled\");\n                        }\n\n                        if (method.equals(\"set\")) {\n                                return invoke(invocationState, targetClass, o, isStatic, functionalObject, invoker, \"put\", primitives, args, canInvokeImport);\n                        } else {\n                                ec.add(\"Is not set/put transform\");\n                        }\n                }\n\n                // functional object\n                if (functionalObject != null) {\n                        InvocationState callFunctionalState = new InvocationState();\n                        try {\n                                return callFunctionalObject(callFunctionalState, functionalObject, invoker, args);\n                        } catch (Throwable t) {\n                                if (callFunctionalState.methodFound) throw t;\n                                ec.add(\"Cannot invoke functional object\");\n                        }\n                } else {\n                        ec.add(\"No functional object\");\n                }\n\n                invocationState.methodFound = false; // method still not found\n\n                // dynamically get field `o.methodName`\n                // if it's not `null` and not `Unit` then invoke the retrieved object\n                if (!invocationState.fromField && o != null) {\n                        Object result = null;\n                        boolean fieldFound = false;\n                        try {\n                                result = LtRuntime.getField(o, method, invoker);\n                                fieldFound = true;\n                        } catch (NoSuchFieldException e) {\n                                ec.add(\"Cannot get field \" + targetClass.getName() + \"#\" + e.getMessage());\n                        }\n                        if (fieldFound) {\n                                if (result != null && !result.equals(Unit.get())) {\n                                        invocationState.methodFound = true;\n                                        return callFunctionalObject(result, invoker, args);\n                                } else {\n                                        ec.add(\"Field \" + targetClass.getName() + \"#\" + method + \" is null or Unit\");\n                                }\n                        }\n                }\n\n                // check import static\n                if (canInvokeImport) {\n                        if (invoker.isAnnotationPresent(StaticImports.class)) {\n                                StaticImports si = invoker.getAnnotation(StaticImports.class);\n                                Class<?>[] classes = si.staticImports();\n                                for (Class<?> cls : classes) {\n                                        Method m = findMethod(invoker, cls, null, method, primitives, args);\n                                        if (m == null) continue;\n                                        return invokeMethod(m, null, args);\n                                }\n                        }\n                }\n\n                // method not found\n                // build exception message\n                StringBuilder sb = new StringBuilder().append(\n                        o == null\n                                ? targetClass.getName()\n                                : o.getClass().getName()\n                ).append(\"#\").append(method).append(\"(\");\n                buildErrorMessageArgsPart(sb, args);\n                sb.append(\")\");\n                ec.throwIfNotEmpty(\"Cannot find method to invoke: \" + sb.toString(), new Function1<Throwable, String>() {\n                        @Override\n                        public Throwable apply(String s) {\n                                return new LtRuntimeException(s);\n                        }\n                });\n                // code won't reach here\n                throw new LtBug(\"code won't reach here\");\n        }\n\n        private static Object invokeMethod(Method m, Object target, Object[] args) throws InvocationTargetException, IllegalAccessException {\n                m.setAccessible(true);\n                Object res = m.invoke(target, args);\n                if (m.getReturnType().equals(void.class)) return Unit.get();\n                return res;\n        }\n\n        private static void buildErrorMessageArgsPart(StringBuilder sb, Object[] args) {\n                boolean isFirst = true;\n                for (Object arg : args) {\n                        if (isFirst) isFirst = false;\n                        else sb.append(\", \");\n                        sb.append(arg == null ? \"null\" : arg.getClass().getName());\n                }\n        }\n\n        /**\n         * call the functional object. This method is the CallSite method.\n         *\n         * @param functionalObject the functional object.\n         * @param callerClass      caller class\n         * @param args             arguments.\n         * @return the calling result.\n         * @throws Throwable exception when calling the functional object.\n         */\n        @SuppressWarnings(\"unused\")\n        public static Object callFunctionalObject(Object functionalObject,\n                                                  Class<?> callerClass,\n                                                  Object[] args) throws Throwable {\n                return callFunctionalObject(new InvocationState(), functionalObject, callerClass, args);\n        }\n\n        /**\n         * call the functional object. This method is the actual method which can be directly used by other methods.\n         *\n         * @param invocationState  invocation state.\n         * @param functionalObject the functional object.\n         * @param callerClass      caller class\n         * @param args             arguments.\n         * @return the calling result.\n         * @throws Throwable exception when calling the functional object.\n         */\n        public static Object callFunctionalObject(InvocationState invocationState,\n                                                  Object functionalObject,\n                                                  Class<?> callerClass,\n                                                  Object[] args) throws Throwable {\n                if (functionalObject == null) throw new NullPointerException();\n\n                // check whether it's a functional object\n                Class<?> cls = functionalObject.getClass();\n                Method theMethodToInvoke;\n                if (cls.getSuperclass() != null && isFunctionalAbstractClass(cls.getSuperclass())) {\n                        theMethodToInvoke = findAbstractMethod(cls.getSuperclass());\n                } else if (cls.getInterfaces().length == 1 && isFunctionalInterface(cls.getInterfaces()[0])) {\n                        theMethodToInvoke = findAbstractMethod(cls.getInterfaces()[0]);\n                } else {\n                        // try to invoke apply(...) on this object\n                        return invoke(invocationState,\n                                functionalObject.getClass(), functionalObject, false, null, callerClass, \"apply\", new boolean[args.length], args, false);\n                }\n\n                // continue processing `theMethodToInvoke`\n                invocationState.methodFound = true;\n                try {\n                        transToRequiredType(args, theMethodToInvoke.getParameterTypes());\n                        Object theRes = theMethodToInvoke.invoke(functionalObject, args);\n                        if (theMethodToInvoke.getReturnType().equals(Void.TYPE)) {\n                                return Unit.get();\n                        }\n                        return theRes;\n                } catch (InvocationTargetException e) {\n                        throw e.getTargetException();\n                }\n        }\n\n        /**\n         * invoke a method.\n         *\n         * @param targetClass      the method is in this class\n         * @param o                invoke the method on the object (or null if invoke static)\\\n         * @param isStatic         whether the invocation is static\n         * @param functionalObject the object to invoke functional method on if method not found\n         * @param invoker          from which class invokes the method\n         * @param method           method name\n         * @param primitives       whether the argument is primitive\n         * @param args             the arguments\n         * @param canInvokeImport  whether the invocation is allowed to invoke methods from import static\n         * @return the method result (void methods' results are <tt>Unit</tt>)\n         * @throws Throwable exception\n         */\n        @SuppressWarnings(\"unused\")\n        public static Object invoke(Class<?> targetClass, Object o, boolean isStatic, Object functionalObject, Class<?> invoker,\n                                    String method, boolean[] primitives, Object[] args, boolean canInvokeImport) throws Throwable {\n                return invoke(new InvocationState(), targetClass, o, isStatic, functionalObject, invoker, method, primitives, args, canInvokeImport);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/ExceptionContainer.java",
    "content": "package lt.runtime;\n\nimport lt.lang.function.Function1;\n\nimport java.util.ArrayList;\nimport java.util.List;\n\n/**\n * exception container\n */\npublic class ExceptionContainer {\n        private List<String> exceptionMsgList = new ArrayList<String>();\n\n        public void add(String msg) {\n                exceptionMsgList.add(msg);\n        }\n\n        /**\n         * throw if the exception message list is not empty\n         *\n         * @param msg head message\n         * @param f   the function accepts a string of message and return an exception\n         * @throws Throwable throwable\n         */\n        public void throwIfNotEmpty(String msg, Function1<Throwable, String> f) throws Throwable {\n                if (exceptionMsgList.isEmpty()) return;\n\n                StringBuilder sb = new StringBuilder();\n                sb.append(msg);\n                int count = 0;\n                for (String tMsg : exceptionMsgList) {\n                        String[] lines = tMsg.split(\"\\\\n\");\n                        boolean isFirst = true;\n                        for (String line : lines) {\n                                sb.append(\"\\n\\t\");\n                                if (isFirst) {\n                                        isFirst = false;\n                                        sb.append(++count).append(\".\").append(\" \");\n                                }\n                                if (!line.trim().isEmpty()) {\n                                        sb.append(line);\n                                }\n                        }\n                }\n\n                throw f.apply(sb.toString());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/Implicit.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * mark the class as implicit cast\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target({ElementType.TYPE, ElementType.METHOD})\npublic @interface Implicit {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/ImplicitImports.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * records the implicit import classes\n */\n@Target(ElementType.TYPE)\n@Retention(RetentionPolicy.RUNTIME)\npublic @interface ImplicitImports {\n        Class<?>[] implicitImports();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LambdaGen.java",
    "content": "package lt.runtime;\n\nimport lt.compiler.LtBug;\nimport lt.dependencies.asm.ClassWriter;\nimport lt.dependencies.asm.FieldVisitor;\nimport lt.dependencies.asm.MethodVisitor;\nimport lt.dependencies.asm.Opcodes;\nimport lt.lang.function.Function;\n\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.Map;\nimport java.util.NoSuchElementException;\n\n/**\n * it's used to generate for an implementation for a functional interface or abstract class\n */\npublic class LambdaGen {\n        private static final String FUNC_FIELD_NAME = \"func\";\n        private static final String F_FIELD_NAME = \"f\";\n        private static final String FIELD_DESC = \"Ljava/lang/reflect/Field;\";\n\n        public static Map.Entry<String, byte[]> gen(Function f, Class<?> targetType) {\n                Method abstractMethod = Dynamic.findAbstractMethod(targetType);\n                Method funcMethod = f.getClass().getDeclaredMethods()[0];\n\n                final String className = getLambdaName(targetType);\n                String functionInternal = typeToInternalName(f.getClass().getInterfaces()[0]);\n                String functionDesc = \"L\" + functionInternal + \";\";\n\n                // class X\n                final ClassWriter classVisitor = new ClassWriter(ClassWriter.COMPUTE_MAXS);\n                String superClass;\n                String[] interfaces;\n                if (targetType.isInterface()) {\n                        superClass = \"java/lang/Object\";\n                        interfaces = new String[]{typeToInternalName(targetType)};\n                } else {\n                        superClass = typeToInternalName(targetType);\n                        interfaces = new String[0];\n                }\n                classVisitor.visit(Opcodes.V1_6, Opcodes.ACC_PUBLIC, className, null, superClass, interfaces);\n\n                // func (field)\n                FieldVisitor funcVisitor = classVisitor.visitField(Opcodes.ACC_PRIVATE, FUNC_FIELD_NAME, functionDesc, null, null);\n                funcVisitor.visitEnd();\n\n                // f (field Field)\n                FieldVisitor fVisitor = classVisitor.visitField(Opcodes.ACC_PRIVATE, F_FIELD_NAME, typeToDesc(Field.class), null, null);\n                fVisitor.visitEnd();\n\n                MethodVisitor constructorVisitor = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, \"<init>\", \"(\" + functionDesc + \")V\", null, null);\n                constructorVisitor.visitCode();\n                // this\n                visitThis(constructorVisitor);\n                // invoke super\n                constructorVisitor.visitMethodInsn(Opcodes.INVOKESPECIAL, superClass, \"<init>\", \"()V\", false);\n                // this\n                visitThis(constructorVisitor);\n                // func (local)\n                constructorVisitor.visitVarInsn(Opcodes.ALOAD, 1);\n                // this.func = func\n                constructorVisitor.visitFieldInsn(Opcodes.PUTFIELD, className, FUNC_FIELD_NAME, functionDesc);\n                // invoke var1.getClass()\n                constructorVisitor.visitVarInsn(Opcodes.ALOAD, 1);\n                constructorVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/lang/Object\", \"getClass\", \"()Ljava/lang/Class;\", false);\n                // getField('self')\n                constructorVisitor.visitLdcInsn(\"self\");\n                constructorVisitor.visitMethodInsn(Opcodes.INVOKEVIRTUAL, \"java/lang/Class\", \"getField\", \"(Ljava/lang/String;)Ljava/lang/reflect/Field;\", false);\n                // this.f = (field)\n                visitThis(constructorVisitor);\n                constructorVisitor.visitInsn(Opcodes.SWAP);\n                constructorVisitor.visitFieldInsn(Opcodes.PUTFIELD, className, F_FIELD_NAME, FIELD_DESC);\n                // return\n                constructorVisitor.visitInsn(Opcodes.RETURN);\n                constructorVisitor.visitMaxs(0, 0);\n                constructorVisitor.visitEnd();\n\n                // method\n                MethodVisitor implMethod = classVisitor.visitMethod(Opcodes.ACC_PUBLIC, abstractMethod.getName(), getDescFromMethod(abstractMethod), null, null);\n                implMethod.visitCode();\n                // this.f\n                visitThis(implMethod);\n                implMethod.visitFieldInsn(Opcodes.GETFIELD, className, F_FIELD_NAME, FIELD_DESC);\n                // setAccessible(true)\n                implMethod.visitLdcInsn(true);\n                try {\n                        implMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeToInternalName(Field.class), \"setAccessible\", getDescFromMethod(Field.class.getMethod(\"setAccessible\", boolean.class)), false);\n                } catch (NoSuchMethodException e) {\n                        throw new LtBug(e);\n                }\n                // this.f\n                visitThis(implMethod);\n                implMethod.visitFieldInsn(Opcodes.GETFIELD, className, F_FIELD_NAME, FIELD_DESC);\n                // set(this.func, this)\n                visitThis(implMethod);\n                implMethod.visitFieldInsn(Opcodes.GETFIELD, className, FUNC_FIELD_NAME, functionDesc);\n                visitThis(implMethod);\n                try {\n                        implMethod.visitMethodInsn(Opcodes.INVOKEVIRTUAL, typeToInternalName(Field.class), \"set\", getDescFromMethod(Field.class.getMethod(\"set\", Object.class, Object.class)), false);\n                } catch (NoSuchMethodException e) {\n                        throw new LtBug(e);\n                }\n\n                // this.func\n                visitThis(implMethod);\n                implMethod.visitFieldInsn(Opcodes.GETFIELD, className, FUNC_FIELD_NAME, functionDesc);\n                // each param\n                for (int i = 1; i <= abstractMethod.getParameterTypes().length; ++i) {\n                        visitLocal(implMethod, abstractMethod, i);\n                        Class<?> param = abstractMethod.getParameterTypes()[i - 1];\n                        if (param.isPrimitive()) {\n                                try {\n                                        boxPrimitive(param, implMethod);\n                                } catch (NoSuchMethodException e) {\n                                        throw new LtBug(e);\n                                }\n                        }\n                }\n                // invoke\n                implMethod.visitMethodInsn(Opcodes.INVOKEINTERFACE, functionInternal, funcMethod.getName(), getDescFromMethod(funcMethod), true);\n                // return?void?\n                if (abstractMethod.getReturnType() == void.class) {\n                        // void\n                        implMethod.visitInsn(Opcodes.POP);\n                        implMethod.visitInsn(Opcodes.RETURN);\n                } else {\n                        // return\n                        if (abstractMethod.getReturnType().isPrimitive()) {\n                                Class<?> returnType = abstractMethod.getReturnType();\n                                castToPrimitive(returnType, implMethod);\n                                if (returnType == long.class) {\n                                        implMethod.visitInsn(Opcodes.LRETURN);\n                                } else if (returnType == float.class) {\n                                        implMethod.visitInsn(Opcodes.FRETURN);\n                                } else if (returnType == double.class) {\n                                        implMethod.visitInsn(Opcodes.DRETURN);\n                                } else {\n                                        implMethod.visitInsn(Opcodes.IRETURN);\n                                }\n                        } else {\n                                // check type\n                                if (abstractMethod.getReturnType().equals(Object.class)) {\n                                        implMethod.visitInsn(Opcodes.ARETURN);\n                                } else {\n                                        checkcast(abstractMethod.getReturnType(), implMethod);\n                                        implMethod.visitInsn(Opcodes.ARETURN);\n                                }\n                        }\n                }\n                implMethod.visitMaxs(0, 0);\n                implMethod.visitEnd();\n\n                classVisitor.visitEnd();\n                return new Map.Entry<String, byte[]>() {\n                        @Override\n                        public String getKey() {\n                                return className;\n                        }\n\n                        @Override\n                        public byte[] getValue() {\n                                return classVisitor.toByteArray();\n                        }\n\n                        @Override\n                        public byte[] setValue(byte[] bytes) {\n                                throw new UnsupportedOperationException();\n                        }\n                };\n        }\n\n        private static void castToPrimitive(Class<?> c, MethodVisitor visitor) throws NoSuchElementException {\n                String name = \"castTo\";\n                if (c == int.class) {\n                        name += \"Int\";\n                } else if (c == short.class) {\n                        name += \"Short\";\n                } else if (c == byte.class) {\n                        name += \"Byte\";\n                } else if (c == boolean.class) {\n                        name += \"Bool\";\n                } else if (c == float.class) {\n                        name += \"Float\";\n                } else if (c == long.class) {\n                        name += \"Long\";\n                } else if (c == double.class) {\n                        name += \"Double\";\n                } else if (c == char.class) {\n                        name += \"Char\";\n                } else {\n                        throw new LtBug(\"unknown primitive \" + c);\n                }\n                visitor.visitMethodInsn(Opcodes.INVOKESTATIC,\n                        typeToInternalName(LtRuntime.class), name,\n                        \"(Ljava/lang/Object;)\" + typeToDesc(c), false);\n        }\n\n        private static void checkcast(Class<?> c, MethodVisitor visitor) {\n                visitor.visitTypeInsn(Opcodes.CHECKCAST, typeToDesc(c));\n        }\n\n        private static void boxPrimitive(Class<?> c, MethodVisitor visitor) throws NoSuchMethodException {\n                String owner;\n                String name = \"valueOf\";\n                String desc;\n                if (c == int.class) {\n                        owner = \"java/lang/Integer\";\n                        desc = getDescFromMethod(Integer.class.getMethod(name, int.class));\n                } else if (c == float.class) {\n                        owner = \"java/lang/Float\";\n                        desc = getDescFromMethod(Float.class.getMethod(name, float.class));\n                } else if (c == long.class) {\n                        owner = \"java/lang/Long\";\n                        desc = getDescFromMethod(Long.class.getMethod(name, long.class));\n                } else if (c == double.class) {\n                        owner = \"java/lang/Double\";\n                        desc = getDescFromMethod(Double.class.getMethod(name, double.class));\n                } else if (c == byte.class) {\n                        owner = \"java/lang/Byte\";\n                        desc = getDescFromMethod(Byte.class.getMethod(name, byte.class));\n                } else if (c == short.class) {\n                        owner = \"java/lang/Short\";\n                        desc = getDescFromMethod(Short.class.getMethod(name, short.class));\n                } else if (c == boolean.class) {\n                        owner = \"java/lang/Boolean\";\n                        desc = getDescFromMethod(Boolean.class.getMethod(name, boolean.class));\n                } else if (c == char.class) {\n                        owner = \"java/lang/Character\";\n                        desc = getDescFromMethod(Character.class.getMethod(name, char.class));\n                } else {\n                        throw new LtBug(\"unknown primitive type \" + c);\n                }\n                visitor.visitMethodInsn(Opcodes.INVOKESTATIC, owner, name, desc, false);\n        }\n\n        private static String typeToInternalName(Class<?> type) {\n                return type.getName().replace('.', '/');\n        }\n\n        private static String typeToDesc(Class<?> type) {\n                StringBuilder sb = new StringBuilder();\n                if (type.isPrimitive()) {\n                        if (type == int.class) sb.append(\"I\");\n                        else if (type == long.class) sb.append(\"J\");\n                        else if (type == short.class) sb.append(\"S\");\n                        else if (type == byte.class) sb.append(\"B\");\n                        else if (type == boolean.class) sb.append(\"Z\");\n                        else if (type == float.class) sb.append(\"F\");\n                        else if (type == double.class) sb.append(\"D\");\n                        else if (type == char.class) sb.append(\"C\");\n                        else if (type == void.class) sb.append(\"V\"); // java 1.8 void is primitive\n                        else throw new LtBug(\"unknown primitive: \" + type);\n                } else if (type.isArray()) {\n                        Class<?> tmp = type;\n                        while (tmp.isArray()) {\n                                sb.append(\"[\");\n                                tmp = tmp.getComponentType();\n                        }\n                        sb.append(typeToDesc(tmp));\n                } else if (type == void.class) {\n                        sb.append(\"V\"); // java 1.6 void is not primitive\n                } else {\n                        // object L...;\n                        sb.append(\"L\").append(typeToInternalName(type)).append(\";\");\n                }\n                return sb.toString();\n        }\n\n        private static String getDescFromMethod(Method method) {\n                StringBuilder sb = new StringBuilder(\"(\");\n                for (Class<?> cls : method.getParameterTypes()) {\n                        sb.append(typeToDesc(cls));\n                }\n                sb.append(\")\").append(typeToDesc(method.getReturnType()));\n                return sb.toString();\n        }\n\n        private static void visitLocal(MethodVisitor visitor, Method method, int local) {\n                Class<?> c = method.getParameterTypes()[local - 1];\n                if (c.isPrimitive()) {\n                        int code;\n                        if (c == float.class) {\n                                code = Opcodes.FLOAD;\n                        } else if (c == double.class) {\n                                code = Opcodes.DLOAD;\n                        } else if (c == long.class) {\n                                code = Opcodes.LLOAD;\n                        } else {\n                                code = Opcodes.ILOAD;\n                        }\n                        visitor.visitVarInsn(code, local);\n                } else {\n                        visitor.visitVarInsn(Opcodes.ALOAD, local);\n                }\n        }\n\n        private static void visitThis(MethodVisitor visitor) {\n                visitor.visitVarInsn(Opcodes.ALOAD, 0);\n        }\n\n        private static synchronized String getLambdaName(Class<?> targetType) {\n                int i = 0;\n                while (true) {\n                        try {\n                                Class.forName(targetType.getSimpleName() + \"$Latte$lambda$\" + i);\n                        } catch (ClassNotFoundException e) {\n                                break;\n                        }\n                }\n                return targetType.getSimpleName() + \"$Latte$lambda$\" + i;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LatteFun.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * mark the class as a latte function\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface LatteFun {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LatteObject.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * represents that the class is a singleton class\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface LatteObject {\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LtIterator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.reflect.Array;\nimport java.util.Enumeration;\nimport java.util.Iterator;\nimport java.util.Map;\n\n/**\n * iterable\n */\npublic abstract class LtIterator implements Iterator {\n        static class PrimitiveArrayIt extends LtIterator {\n                final Object array;\n                final int len;\n                int index = 0;\n\n                PrimitiveArrayIt(Object array) {\n                        this.array = array;\n                        len = Array.getLength(array);\n                }\n\n                @Override\n                public boolean hasNext() {\n                        return index < len;\n                }\n\n                @Override\n                public Object next() {\n                        return Array.get(array, index++);\n                }\n        }\n\n        static class ArrayIt extends LtIterator {\n                final Object[] array;\n                int index = 0;\n\n                ArrayIt(Object[] array) {\n                        this.array = array;\n                }\n\n                @Override\n                public boolean hasNext() {\n                        return index < array.length; // index from 0 to array.length\n                }\n\n                @Override\n                public Object next() {\n                        return array[index++]; // index from 0 to array.length\n                }\n        }\n\n        static class It extends LtIterator {\n                final Iterator it;\n\n                It(Iterator it) {\n                        this.it = it;\n                }\n\n                @Override\n                public boolean hasNext() {\n                        return it.hasNext();\n                }\n\n                @Override\n                public Object next() {\n                        return it.next();\n                }\n        }\n\n        static class EnIt extends LtIterator {\n                final Enumeration en;\n\n                EnIt(Enumeration en) {\n                        this.en = en;\n                }\n\n                @Override\n                public boolean hasNext() {\n                        return en.hasMoreElements();\n                }\n\n                @Override\n                public Object next() {\n                        return en.nextElement();\n                }\n        }\n\n        public static LtIterator getIterator(Object o) {\n                if (o.getClass().isArray()) {\n                        if (o.getClass().getComponentType().isPrimitive()) {\n                                return new PrimitiveArrayIt(o);\n                        } else {\n                                return new ArrayIt((Object[]) o);\n                        }\n                } else if (o instanceof Iterable) {\n                        return new It(((Iterable) o).iterator());\n                } else if (o instanceof Iterator) {\n                        return new It((Iterator) o);\n                } else if (o instanceof Enumeration) {\n                        return new EnIt((Enumeration) o);\n                } else if (o instanceof Map) {\n                        return new It(((Map) o).entrySet().iterator());\n                } else throw new RuntimeException(\"cannot iterate on \" + o);\n        }\n\n        public abstract boolean hasNext();\n\n        public abstract Object next();\n\n        @Override\n        public void remove() {\n                throw new UnsupportedOperationException();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LtRuntime.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport lt.compiler.MultipleClassLoader;\nimport lt.compiler.SemanticProcessor;\nimport lt.lang.Unit;\nimport lt.repl.scripting.CL;\nimport lt.lang.function.Function;\nimport lt.lang.function.Function1;\nimport lt.repl.ScriptCompiler;\n\nimport java.io.FileReader;\nimport java.io.InputStream;\nimport java.io.InputStreamReader;\nimport java.io.Reader;\nimport java.lang.ref.WeakReference;\nimport java.lang.reflect.*;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.WeakHashMap;\n\n/**\n * Defines Latte Runtime behavior.\n * The Runtime provides type cast, field getting and setting, comparison, ref comparison,\n * <b>is</b> and <b>not</b> operator behavior, wrapping object for throwing, hashCode retrieving.\n */\npublic class LtRuntime {\n        /**\n         * the lambda function map. maps \"required class\" to \"create the required object\"\n         */\n        private static final Map<Class<?>, Function1<Object, Object>> lambdaFunctionMap = new WeakHashMap<Class<?>, Function1<Object, Object>>();\n\n        /**\n         * Check whether the given type is {@link Integer} {@link Short}\n         * {@link Byte} {@link Character} {@link Long} {@link Boolean}\n         * {@link Float} {@link Double}.\n         *\n         * @param type the type to check.\n         * @return true if it's a box type.\n         */\n        private static boolean isBoxType(Class<?> type) {\n                return type.equals(Integer.class) || type.equals(Short.class) || type.equals(Byte.class) || type.equals(Character.class)\n                        || type.equals(Long.class) || type.equals(Boolean.class) || type.equals(Float.class) || type.equals(Double.class);\n        }\n\n        /**\n         * Cast the object to a {@link Throwable}. If the object is instance of throwable,\n         * it's directly returned. Otherwise, a {@link Wrapper} object would be returned.\n         *\n         * @param o the object to cast.\n         * @return a Throwable object.\n         */\n        public static Throwable castToThrowable(Object o) {\n                if (o instanceof Throwable) return (Throwable) o;\n                return new Wrapper(o);\n        }\n\n        /**\n         * generate {@link ClassCastException} for throwing.\n         *\n         * @param o    the object to cast.\n         * @param type the target type.\n         * @return {@link ClassCastException}\n         */\n        private static ClassCastException generateClassCastException(Object o, Class<?> type) {\n                return new ClassCastException(\"Cannot cast \" +\n                        (o == null ? \"null\" : o.getClass().getName()) +\n                        \" to \" + type.getName());\n        }\n\n        /**\n         * Cast the object to given type.\n         *\n         * @param o           the object to cast.\n         * @param targetType  the type that the object cast to.\n         * @param callerClass the caller class\n         * @return the casting result.\n         * @throws Exception maybe {@link ClassCastException} if the cast fails,\n         *                   or some errors when casting.\n         */\n        public static Object cast(Object o, Class<?> targetType, Class<?> callerClass) throws Throwable {\n                if (targetType.isInstance(o)) return o;\n\n                if (o == null) {\n                        if (targetType.isPrimitive()) {\n                                throw generateClassCastException(null, targetType);\n                        } else {\n                                return null;\n                        }\n                }\n\n                // implicit cast\n                if (callerClass != null && callerClass.isAnnotationPresent(ImplicitImports.class)) {\n                        Class<?>[] implicitTypes = callerClass.getAnnotation(ImplicitImports.class).implicitImports();\n                        for (Class<?> ic : implicitTypes) {\n                                if (!ic.isAnnotationPresent(LatteObject.class)) continue;\n                                Method[] methods = ic.getDeclaredMethods();\n                                for (Method m : methods) {\n                                        if (m.isAnnotationPresent(Implicit.class)\n                                                && m.getParameterTypes().length == 1\n                                                && m.getParameterTypes()[0].equals(o.getClass())\n                                                && targetType.isAssignableFrom(m.getReturnType())) {\n\n                                                m.setAccessible(true);\n                                                // get singleton instance\n                                                Object singletonInstance = ic.getField(\"singletonInstance\").get(null);\n                                                return m.invoke(singletonInstance, o);\n                                        }\n                                }\n                        }\n                }\n\n                if (isBoxType(targetType)) {\n                        if (targetType.equals(Integer.class)) {\n                                return castToInt(o);\n                        } else if (targetType.equals(Short.class)) {\n                                return castToShort(o);\n                        } else if (targetType.equals(Byte.class)) {\n                                return castToByte(o);\n                        } else if (targetType.equals(Character.class)) {\n                                return castToChar(o);\n                        } else if (targetType.equals(Long.class)) {\n                                return castToLong(o);\n                        } else if (targetType.equals(Boolean.class)) {\n                                return castToBool(o);\n                        } else if (targetType.equals(Float.class)) {\n                                return castToFloat(o);\n                        } else if (targetType.equals(Double.class)) {\n                                return castToDouble(o);\n                        } else throw new RuntimeException(\"unknown box type \" + targetType);\n                }\n                if (targetType.equals(int.class)) return castToInt(o);\n                if (targetType.equals(short.class)) return castToShort(o);\n                if (targetType.equals(byte.class)) return castToByte(o);\n                if (targetType.equals(char.class)) return castToChar(o);\n                if (targetType.equals(long.class)) return castToLong(o);\n                if (targetType.equals(boolean.class)) return castToBool(o);\n                if (targetType.equals(float.class)) return castToFloat(o);\n                if (targetType.equals(double.class)) return castToDouble(o);\n\n                if (targetType.isAnnotationPresent(Implicit.class)) {\n                        Constructor<?> con = targetType.getConstructors()[0];\n                        Class<?> paramType = con.getParameterTypes()[0];\n                        if (paramType.isInstance(o)) {\n                                return con.newInstance(o);\n                        }\n                }\n                if (targetType.isArray()) {\n                        if (o instanceof java.util.List) {\n                                Class<?> component = targetType.getComponentType();\n                                java.util.List<?> list = (java.util.List<?>) o;\n                                Object arr = Array.newInstance(component, list.size());\n\n                                for (int cursor = 0; cursor < list.size(); ++cursor) {\n                                        Object elem = list.get(cursor);\n                                        Array.set(arr, cursor, cast(elem, component, callerClass));\n                                }\n\n                                return arr;\n                        }\n                } else if (o instanceof java.util.Map) {\n                        @SuppressWarnings(\"unchecked\")\n                        java.util.Map<Object, Object> map = (java.util.Map) o;\n                        boolean canInject = true;\n                        for (Object tmp : map.keySet()) {\n                                if (!(tmp instanceof String)) {\n                                        canInject = false;\n                                        break;\n                                }\n                        }\n                        if (canInject) {\n                                Object targetNewInstance = null;\n                                try {\n                                        targetNewInstance = targetType.newInstance();\n                                } catch (Exception ignore) {\n                                }\n                                if (targetNewInstance != null) {\n                                        for (Map.Entry entry : map.entrySet()) {\n                                                String k = (String) entry.getKey();\n                                                Object v = entry.getValue();\n                                                putField(targetNewInstance, k, v, LtRuntime.class);\n                                        }\n                                        return targetNewInstance;\n                                }\n                        }\n                } else if (o instanceof java.util.List) {\n                        @SuppressWarnings(\"unchecked\")\n                        java.util.List<Object> list = (java.util.List<Object>) o;\n                        Object targetNewInstance = null;\n                        try {\n                                targetNewInstance = targetType.newInstance();\n                        } catch (Exception ignore) {\n                        }\n                        if (targetNewInstance != null) {\n                                for (Object item : list) {\n                                        Dynamic.invoke(new Dynamic.InvocationState(), targetType, targetNewInstance, false, null,\n                                                LtRuntime.class, \"add\", new boolean[]{false}, new Object[]{item}, false);\n                                }\n                                return targetNewInstance;\n                        }\n                } else if (Dynamic.isFunctionalAbstractClass(targetType)\n                        || Dynamic.isFunctionalInterface(targetType)) {\n                        if (lambdaFunctionMap.containsKey(targetType)) {\n                                return lambdaFunctionMap.get(targetType).apply(o);\n                        }\n\n                        if (o instanceof Function) {\n                                Method method = Dynamic.findAbstractMethod(targetType);\n                                Method funcMethod = o.getClass().getDeclaredMethods()[0];\n                                if (method.getParameterTypes().length == funcMethod.getParameterTypes().length) {\n                                        Map.Entry<String, byte[]> pair = LambdaGen.gen((Function) o, targetType);\n\n                                        ClassLoader targetTypeCL = targetType.getClassLoader();\n                                        if (targetTypeCL == null) {\n                                                targetTypeCL = new MultipleClassLoader(\n                                                        o.getClass().getClassLoader(),\n                                                        Thread.currentThread().getContextClassLoader());\n                                        } else {\n                                                targetTypeCL = new MultipleClassLoader(\n                                                        o.getClass().getClassLoader(),\n                                                        targetTypeCL, Thread.currentThread().getContextClassLoader()\n                                                );\n                                        }\n\n                                        CL cl = new CL(targetTypeCL);\n                                        cl.addByteCodes(pair.getKey(), pair.getValue());\n\n                                        Class<?> cls = cl.loadClass(pair.getKey());\n                                        final Constructor<?> con = cls.getConstructor(funcMethod.getDeclaringClass().getInterfaces()[0]);\n                                        Function1<Object, Object> func = new Function1<Object, Object>() {\n                                                @Override\n                                                public Object apply(Object o) throws Exception {\n                                                        return con.newInstance(o);\n                                                }\n                                        };\n                                        lambdaFunctionMap.put(targetType, func); // put into map\n                                        return func.apply(o);\n                                }\n                        }\n                }// else throw new LtBug(\"unsupported type cast (targetType:\" + targetType.getName() + \", o:\" + o.getClass().getName() + \")\");\n                throw generateClassCastException(o, targetType);\n        }\n\n        private static String getLatteTypeName(String javaTypeName) {\n                if (javaTypeName.equals(\"boolean\")) return \"bool\";\n                if (javaTypeName.equals(\"void\")) return \"Unit\";\n                return javaTypeName.replace(\".\", \"::\");\n        }\n\n        /**\n         * Cast the object to int value. Only {@link Number} can be cast to int.\n         *\n         * @param o the object to cast.\n         * @return int value.\n         */\n        public static int castToInt(Object o) {\n                if (o instanceof Number) return ((Number) o).intValue();\n                if (o instanceof Character) return (Character) o;\n                throw generateClassCastException(o, int.class);\n        }\n\n        /**\n         * Cast the object to long value. Only {@link Number} can be cast to long.\n         *\n         * @param o the object to cast.\n         * @return long value.\n         */\n        public static long castToLong(Object o) {\n                if (o instanceof Number) return ((Number) o).longValue();\n                throw generateClassCastException(o, long.class);\n        }\n\n        /**\n         * Cast the object to short value. Only {@link Number} can be cast to short.\n         *\n         * @param o the object to cast.\n         * @return short value.\n         */\n        public static short castToShort(Object o) {\n                if (o instanceof Number) return ((Number) o).shortValue();\n                throw generateClassCastException(o, short.class);\n        }\n\n        /**\n         * Cast the object to byte value. Only {@link Number} can be cast to byte.\n         *\n         * @param o the object to cast.\n         * @return byte value.\n         */\n        public static byte castToByte(Object o) {\n                if (o instanceof Number) return ((Number) o).byteValue();\n                throw generateClassCastException(o, byte.class);\n        }\n\n        /**\n         * Cast the object to float value. Only {@link Number} can be cast to float.\n         *\n         * @param o the object to cast.\n         * @return float value.\n         */\n        public static float castToFloat(Object o) {\n                if (o instanceof Number) return ((Number) o).floatValue();\n                throw generateClassCastException(o, float.class);\n        }\n\n        /**\n         * Cast the object to double value. Only {@link Number} can be cast to double.\n         *\n         * @param o the object to cast.\n         * @return double value.\n         */\n        public static double castToDouble(Object o) {\n                if (o instanceof Number) return ((Number) o).doubleValue();\n                throw generateClassCastException(o, double.class);\n        }\n\n        /**\n         * Cast the object to boolean value. All types can be cast to bool.\n         * If the object is null or Unit, the result is false.\n         * Else if the object is {@link Boolean}, the result is the unboxing value.\n         * Else if the object is {@link Number}, the result is number != 0.\n         * Else the result is true.\n         *\n         * @param o the object to cast.\n         * @return bool value.\n         * @throws Throwable exceptions\n         */\n        public static boolean castToBool(Object o) throws Throwable {\n                // check null and Unit\n                if (o == null || o instanceof Unit) return false;\n                // check Boolean object\n                if (o instanceof Boolean) return (Boolean) o;\n                // check number not 0\n                if (o instanceof Number) return ((Number) o).doubleValue() != 0;\n                // check Character\n                if (o instanceof Character) return (Character) o != 0;\n                // check `isEmpty()`\n                try {\n                        Method m = o.getClass().getMethod(\"isEmpty\");\n                        if (m.getReturnType().equals(boolean.class) || m.getReturnType().equals(Boolean.class)) {\n                                try {\n                                        Object res = m.invoke(o);\n                                        return res != null && !(Boolean) res;\n                                } catch (InvocationTargetException e) {\n                                        throw e.getTargetException();\n                                }\n                        }\n                } catch (NoSuchMethodException ignore) {\n                }\n                // otherwise return true\n                return true;\n        }\n\n        /**\n         * Cast the object to char.\n         * If the object is {@link Number}, get the {@link Number#intValue()} and cast to char.\n         * Else if the object is {@link Character}, the result is the unboxing value.\n         * Else if the object is CharSequence and the length is 1, the result is {@link CharSequence#charAt(int)}(0).\n         * Else throw a {@link ClassCastException}.\n         *\n         * @param o the object to cast.\n         * @return char value.\n         */\n        public static char castToChar(Object o) {\n                if (o instanceof Number) return (char) ((Number) o).intValue();\n                if (o instanceof Character) return (Character) o;\n                if (o instanceof CharSequence && ((CharSequence) o).length() == 1) return ((CharSequence) o).charAt(0);\n                throw generateClassCastException(o, char.class);\n        }\n\n        private static void throwNonRuntime(Dynamic.InvocationState state, Throwable t) throws Throwable {\n                if (state.methodFound && !(t instanceof LtRuntimeException)) throw t;\n        }\n\n        /**\n         * get field value.<br>\n         * if field not found , then the method would try to invoke get(fieldName)<br>\n         * or the method would return <tt>Unit</tt>\n         *\n         * @param o           object\n         * @param fieldName   field name\n         * @param callerClass caller class\n         * @return the value or Unit\n         * @throws Throwable exceptions\n         */\n        public static Object getField(Object o, String fieldName, Class<?> callerClass) throws Throwable {\n                if (o == null) throw new NullPointerException(\"null.\" + fieldName + \" not exist\");\n                if (o.equals(Unit.get())) throw new IllegalArgumentException(\"Unit.\" + fieldName + \" not exist\");\n                if (o.getClass().isArray()) {\n                        if (fieldName.equals(\"length\")) {\n                                return Array.getLength(o);\n                        } else if (fieldName.startsWith(\"_\")) {\n                                try {\n                                        int index = Integer.parseInt(fieldName.substring(1));\n                                        return Array.get(o, index);\n                                } catch (NumberFormatException ignore) {\n                                }\n                        }\n                        return Unit.get();\n                }\n\n                ExceptionContainer ec = new ExceptionContainer();\n                // try to get field\n                try {\n                        Field f = o.getClass().getDeclaredField(fieldName);\n                        if (haveAccess(f.getModifiers(), o.getClass(), callerClass)) {\n                                f.setAccessible(true);\n                                return f.get(o);\n                        } else {\n                                ec.add(\"Cannot access \" + o.getClass().getName() + \"#\" + fieldName + \" from \" + callerClass);\n                        }\n                } catch (Throwable ignore) {\n                        ec.add(\"Cannot find field \" + o.getClass().getName() + \"#\" + fieldName);\n                }\n\n                Dynamic.InvocationState invocationState = new Dynamic.InvocationState();\n                invocationState.fromField = true;\n\n                // try to find `fieldName()`\n                try {\n                        return Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass, fieldName, new boolean[0], new Object[0], false);\n                } catch (Throwable t) {\n                        throwNonRuntime(invocationState, t);\n                        ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#\" + fieldName + \"()\\n\\t\" + t.getMessage());\n                }\n                // try to find `getFieldName()`\n                String getter = null;\n                try {\n                        getter = \"get\" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);\n                        return Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass, getter, new boolean[0], new Object[0], false);\n                } catch (Throwable t) {\n                        throwNonRuntime(invocationState, t);\n                        assert getter != null;\n                        ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#\" + getter + \"()\\n\\t\" + t.getMessage());\n                }\n                // try _number\n                if (fieldName.startsWith(\"_\")) {\n                        try {\n                                int i = Integer.parseInt(fieldName.substring(1));\n                                try {\n                                        return Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass, \"get\", new boolean[]{true}, new Object[]{i}, false);\n                                } catch (Throwable t) {\n                                        throwNonRuntime(invocationState, t);\n                                        ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#get(\" + i + \")\\n\\t\" + t.getMessage());\n                                }\n                        } catch (NumberFormatException ignore) {\n                                ec.add(\"Field name is not `_{int}`, cannot be transformed into #get({int})\");\n                        }\n                }\n                // try to find `get(fieldName)`\n                try {\n                        return Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass, \"get\", new boolean[]{false}, new Object[]{fieldName}, false);\n                } catch (Throwable t) {\n                        throwNonRuntime(invocationState, t);\n                        ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#get(\" + fieldName + \")\\n\\t\" + t.getMessage());\n                }\n                ec.throwIfNotEmpty(fieldName, new Function1<Throwable, String>() {\n                        @Override\n                        public Throwable apply(String s) throws Exception {\n                                return new NoSuchFieldException(s);\n                        }\n                });\n                // won't reach here\n                return null;\n        }\n\n        /**\n         * retrieve package name of the class object.\n         * first try to get name from {@link Class#getPackage()}, if the result is null\n         * then extract the package name from the class name\n         *\n         * @param c class object\n         * @return package name\n         */\n        private static String getPackage(Class<?> c) {\n                if (c.getPackage() == null) {\n                        String clsName = c.getName();\n                        if (clsName.contains(\".\")) {\n                                return clsName.substring(clsName.lastIndexOf(\".\"));\n                        } else {\n                                return \"\";\n                        }\n                } else {\n                        return c.getPackage().getName();\n                }\n        }\n\n        /**\n         * check whether the caller can have access to the class(or its members).\n         *\n         * @param modifiers modifiers\n         * @param target    target class\n         * @param caller    caller class\n         * @return true if can access, false otherwise\n         */\n        public static boolean haveAccess(int modifiers, Class<?> target, Class<?> caller) {\n                if (Modifier.isPrivate(modifiers)) {\n                        // private\n                        if (!caller.equals(target)) return false;\n                } else if (Modifier.isProtected(modifiers)) {\n                        // protected\n                        if (!getPackage(target).equals(getPackage(caller)) && !target.isAssignableFrom(caller))\n                                return false;\n                } else if (!Modifier.isPublic(modifiers)) {\n                        // package access\n                        if (!getPackage(target).equals(getPackage(caller))) return false;\n                }\n                return true;\n        }\n\n        /**\n         * put field.<br>\n         * if field not found , then the method would try to invoke set(fieldName, value)<br>\n         * the method calls {@link Dynamic#invoke(Class, Object, boolean, Object, Class, String, boolean[], Object[], boolean)}, and <code>set(fieldName,value)</code> may be changed to <code>put(fieldName, value)</code>\n         *\n         * @param o           object\n         * @param fieldName   field name\n         * @param value       the value to set\n         * @param callerClass caller class\n         * @throws Throwable exceptions\n         */\n        public static void putField(Object o, String fieldName, Object value, Class<?> callerClass) throws Throwable {\n                if (o == null) throw new NullPointerException(\"null.\" + fieldName + \" not exist\");\n                if (o.equals(Unit.get())) throw new IllegalArgumentException(\"Unit.\" + fieldName + \" not exist\");\n                // try to put field\n                ExceptionContainer ec = new ExceptionContainer();\n                try {\n                        Field f = o.getClass().getDeclaredField(fieldName);\n                        if (haveAccess(f.getModifiers(), o.getClass(), callerClass)) {\n                                f.setAccessible(true);\n                                f.set(o, cast(value, f.getType(), callerClass));\n                                return;\n                        } else {\n                                ec.add(\"Cannot access \" + o.getClass().getName() + \"#\" + fieldName + \" from \" + callerClass);\n                        }\n                } catch (Throwable ignore) {\n                        ec.add(\"Cannot find field \" + o.getClass().getName() + \"#\" + fieldName);\n                }\n\n                Dynamic.InvocationState invocationState = new Dynamic.InvocationState();\n                invocationState.fromField = true;\n\n                // try `setFieldName(value)`\n                String setter = null;\n                try {\n                        setter = \"set\" + fieldName.substring(0, 1).toUpperCase() + fieldName.substring(1);\n                        Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass, setter, new boolean[]{false}, new Object[]{value}, false);\n                } catch (Throwable t) {\n                        throwNonRuntime(invocationState, t);\n                        assert setter != null;\n                        ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#\" + setter + \"(...)\\n\\t\" + t.getMessage());\n                        // try to find `set(fieldName,value)`\n                        // invoke dynamic would try to find set then try to find put\n                        try {\n                                Dynamic.invoke(invocationState, o.getClass(), o, false, null, callerClass,\n                                        \"set\",\n                                        new boolean[]{false, false},\n                                        new Object[]{fieldName, value}, false);\n                        } catch (Throwable t2) {\n                                throwNonRuntime(invocationState, t2);\n                                ec.add(\"Cannot invoke method \" + o.getClass().getName() + \"#set(\" + fieldName + \",...)\\n\\t\" + t2.getMessage());\n                                ec.throwIfNotEmpty(fieldName, new Function1<Throwable, String>() {\n                                        @Override\n                                        public Throwable apply(String s) throws Exception {\n                                                return new NoSuchFieldException(s);\n                                        }\n                                });\n                        }\n                }\n        }\n\n        /**\n         * change compare result into boolean\n         *\n         * @param result compare result.\n         * @param mode   {@link SemanticProcessor#COMPARE_MODE_EQ}\n         *               {@link SemanticProcessor#COMPARE_MODE_GT}\n         *               {@link SemanticProcessor#COMPARE_MODE_LT},\n         *               can be linked with + or | operator\n         * @return boolean value\n         */\n        public static boolean compare(int result, int mode) {\n                // mode is EQ\n                if ((mode & SemanticProcessor.COMPARE_MODE_EQ) == SemanticProcessor.COMPARE_MODE_EQ && result == 0)\n                        return true;\n                // mode is GT\n                if ((mode & SemanticProcessor.COMPARE_MODE_GT) == SemanticProcessor.COMPARE_MODE_GT && result > 0)\n                        return true;\n                // mode is LT\n                if ((mode & SemanticProcessor.COMPARE_MODE_LT) == SemanticProcessor.COMPARE_MODE_LT && result < 0)\n                        return true;\n                // otherwise\n                return false;\n        }\n\n        /**\n         * compare two refs\n         *\n         * @param a a\n         * @param b b\n         * @return true or false\n         */\n        public static boolean compareRef(Object a, Object b) {\n                if (a == b) return true;\n                //\n                return false;\n        }\n\n        /**\n         * <code>is</code> operator<br>\n         *\n         * @param a           a\n         * @param b           b\n         * @param callerClass caller class\n         * @return true/false\n         * @throws Throwable exceptions\n         */\n        public static boolean is(Object a, Object b, @SuppressWarnings(\"unused\") Class<?> callerClass) throws Throwable {\n                if (a == null && b == null) return true;\n                // not both a and b are null\n                if (a == null || b == null) return false;\n                // a and b are not null\n                if (a == b || a.equals(b)) return true;\n                // a!=b and a.equals(b) is false\n                return false;\n        }\n\n        /**\n         * <code>not</code> operator\n         *\n         * @param a           a\n         * @param b           b\n         * @param callerClass caller class\n         * @return true/false\n         * @throws Throwable exceptions\n         */\n        public static boolean not(Object a, Object b, @SuppressWarnings(\"unused\") Class<?> callerClass) throws Throwable {\n                if (a == null && b == null) return false;\n                // not both a and b are null\n                if (a == null || b == null) return true;\n                // a and b are not null\n                if (a == b || a.equals(b)) return false;\n                // a!=b and a.equals(b) is false\n                return true;\n        }\n\n        /**\n         * get wrapped object in {@link Wrapper#object} or simply return the throwable object\n         *\n         * @param t the wrapper object or other throwable\n         * @return the retrieved object\n         */\n        public static Object throwableWrapperObject(Throwable t) {\n                if (t instanceof Wrapper) return ((Wrapper) t).object;\n                return t;\n        }\n\n        /**\n         * get hash code of a object\n         *\n         * @param o the object\n         * @return hash code of the object (or 0 if it's null)\n         */\n        @SuppressWarnings(\"unused\")\n        public static int getHashCode(Object o) {\n                if (o == null) return 0;\n                return o.hashCode();\n        }\n\n        /**\n         * destruct the object into a list of values\n         *\n         * @param count         destruct result size count\n         * @param destructClass the class that defines method `unapply(o)`\n         * @param o             the object to destruct\n         * @param invoker       the caller class\n         * @return a list of values\n         * @throws Throwable any exceptions\n         */\n        @SuppressWarnings(\"unused\")\n        public static List<?> destruct(int count, Class<?> destructClass, Object o, Class<?> invoker) throws Throwable {\n                if (o == null) throw new LtRuntimeException(\"null cannot be destructed\");\n                if (destructClass == null) destructClass = o.getClass();\n                Method method = Dynamic.findMethod(invoker, destructClass, null, \"unapply\", new boolean[1], new Object[]{o});\n                if (method == null) return null;\n                if (!List.class.isAssignableFrom(method.getReturnType()) && !method.getReturnType().isAssignableFrom(List.class))\n                        throw new LtRuntimeException(\"unapply result should be java::util::List\");\n                List<?> res;\n                try {\n                        Object r = method.invoke(null, o);\n                        if (r instanceof List) {\n                                res = (List<?>) r;\n                        } else throw new LtRuntimeException(\"unapply result is not List\");\n                } catch (InvocationTargetException e) {\n                        throw e.getTargetException();\n                }\n                if (res.size() != count) return null;\n                return res;\n        }\n\n        private static final Map<String, Object> requiredObjects = new HashMap<String, Object>();\n\n        /**\n         * run a script and retrieve the script result. One file would only be run for only once.\n         * The result value would be recorded, and the value would be retrieved when required.\n         *\n         * @param callerClass caller class\n         * @param file        file. use cp:xx to retrieve from ClassPath\n         * @return the script result\n         * @throws Throwable throwable\n         */\n        public static Object require(Class<?> callerClass, String file) throws Throwable {\n                ScriptCompiler sc = new ScriptCompiler(callerClass.getClassLoader());\n                file = file.trim();\n\n                String tmp = file;\n\n                // `file` format\n                if (file.startsWith(\"cp:\")) {\n                        tmp = tmp.substring(\"cp:\".length()).trim();\n                        if (tmp.startsWith(\"/\")) {\n                                tmp = tmp.substring(1);\n                        }\n                        file = \"cp:\" + tmp;\n                }\n\n                // get reader\n                Reader r;\n                if (file.startsWith(\"cp:\")) {\n                        // get from recorder\n                        if (requiredObjects.containsKey(file)) return requiredObjects.get(file);\n\n                        // get reader\n                        ClassLoader loader = callerClass.getClassLoader();\n                        InputStream is = loader.getResourceAsStream(tmp);\n                        if (is == null) {\n                                throw new RuntimeException(\"cannot find \" + file + \" in class loader \" + loader);\n                        }\n                        r = new InputStreamReader(is);\n                } else {\n                        // get from recorder\n                        if (requiredObjects.containsKey(file)) return requiredObjects.get(file);\n\n                        // get reader\n                        r = new FileReader(file);\n                }\n\n                // get script file name\n                if (tmp.contains(\"/\")) {\n                        tmp = tmp.substring(tmp.indexOf(\"/\") + 1);\n                }\n                if (tmp.contains(\"\\\\\")) {\n                        tmp = tmp.substring(tmp.indexOf(\"\\\\\") + 1);\n                }\n\n                // compile and run\n                Object o = sc.compile(tmp, r)\n                        .run().getResult();\n                requiredObjects.put(file, o);\n                return o;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/LtRuntimeException.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\n/**\n * runtime exception thrown by Latte-lang.\n */\npublic class LtRuntimeException extends RuntimeException {\n        public LtRuntimeException() {\n        }\n\n        public LtRuntimeException(String message) {\n                super(message);\n        }\n\n        public LtRuntimeException(String message, Throwable cause) {\n                super(message, cause);\n        }\n\n        public LtRuntimeException(Throwable cause) {\n                super(cause);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/MatchError.java",
    "content": "package lt.runtime;\n\n/**\n * thrown when nothing matches in a pattern matching\n */\npublic class MatchError extends Error {\n        public MatchError() {\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/StaticImports.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * record the static imports\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface StaticImports {\n        Class<?>[] staticImports();\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/runtime/Wrapper.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.runtime;\n\n/**\n * a wrapper containing required object\n */\npublic class Wrapper extends RuntimeException {\n        public final Object object;\n\n        public Wrapper(Object object) {\n                this.object = object;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/util/RangeList.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.util;\n\nimport java.util.*;\n\n/**\n * range list. The list is used to support <code>..</code> and <code>.:</code> operators,\n * and the list is immutable\n */\npublic class RangeList extends AbstractList {\n        private final int start;\n        private final int end;\n        // [start,end]\n        private final boolean end_inclusive;\n\n        private final int increment;\n\n        public RangeList(int start, int end, boolean end_inclusive) {\n                this.end = end;\n                this.start = start;\n                this.end_inclusive = end_inclusive;\n\n                if (end == start) increment = 0;\n                else increment = end - start > 0 ? 1 : -1;\n        }\n\n        @Override\n        public Object get(int index) {\n                if (index >= 0 && index < size()) {\n                        return index * increment + start;\n                } else throw new IndexOutOfBoundsException(String.valueOf(index));\n        }\n\n        @Override\n        public int size() {\n                if (end - start >= 0) {\n                        return end - start + (end_inclusive ? 1 : 0);\n                } else {\n                        return start - end + (end_inclusive ? 1 : 0);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/java/lt/util/Utils.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.util;\n\nimport lt.repl.Evaluator;\nimport lt.repl.ClassPathLoader;\n\nimport java.io.*;\nimport java.util.LinkedHashMap;\nimport java.util.Map;\nimport java.util.regex.Pattern;\n\n/**\n * automatically import static this class\n */\n@SuppressWarnings(\"unused\")\npublic class Utils {\n\n        private Utils() {\n        }\n\n        /**\n         * print the object and new line\n         *\n         * @param o the object to print\n         */\n        public static void println(Object o) {\n                if (o instanceof char[]) {\n                        System.out.println((char[]) o);\n                } else {\n                        System.out.println(o);\n                }\n        }\n\n        /**\n         * print the char array and new line\n         *\n         * @param o the char array to print\n         */\n        public static void println(char[] o) {\n                System.out.println(o);\n        }\n\n        /**\n         * print a new line\n         */\n        public static void println() {\n                System.out.println();\n        }\n\n        /**\n         * print the object\n         *\n         * @param o the object to print\n         */\n        public static void print(Object o) {\n                System.out.print(o);\n        }\n\n        /**\n         * evaluate the expression\n         *\n         * @param e expression or statement\n         * @return if the input defines types, then the result is a list of {@link Class} objects.\n         * otherwise, it's the evaluated result object.\n         * @throws Exception exception\n         */\n        public static Object eval(String e) throws Exception {\n                return eval(Thread.currentThread().getContextClassLoader(), e);\n        }\n\n        /**\n         * evaluate the expression\n         *\n         * @param loader the classloader\n         * @param e      expression or statement\n         * @return if the input defines types, then the result is a list of {@link Class} objects.\n         * otherwise, it's the evaluated result object.\n         * @throws Exception exception\n         */\n        public static Object eval(ClassLoader loader, String e) throws Exception {\n                Evaluator evaluator = new Evaluator(new ClassPathLoader(loader));\n                return evaluator.eval(e).result;\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir   the base directory\n         * @param regex file pattern\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(String dir, String regex) {\n                return filesInDirectory(dir, regex, false);\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir   the base directory\n         * @param regex file pattern\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(String dir, Pattern regex) {\n                return filesInDirectory(dir, regex, false);\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir         the base directory\n         * @param regex       file pattern\n         * @param recursively scan the children directories\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(String dir, String regex, boolean recursively) {\n                return filesInDirectory(new File(dir), regex, recursively);\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir         the base directory\n         * @param regex       file pattern\n         * @param recursively scan the children directories\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(String dir, Pattern regex, boolean recursively) {\n                return filesInDirectory(new File(dir), regex, recursively);\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir         the base directory\n         * @param regex       file pattern\n         * @param recursively scan the children directories\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(File dir, String regex, boolean recursively) {\n                return filesInDirectory(dir, Pattern.compile(regex), recursively);\n        }\n\n        /**\n         * get files in the directory. the result would be a fileName =&gt; File map.\n         *\n         * @param dir         the base directory\n         * @param regex       file name pattern\n         * @param recursively scan the children directories\n         * @return a map.\n         */\n        public static Map<String, File> filesInDirectory(File dir, Pattern regex, boolean recursively) {\n                if (dir == null) throw new NullPointerException(\"dir is null\");\n                Map<String, File> map = new LinkedHashMap<String, File>();\n                if (dir.isDirectory()) {\n                        File[] listFiles = dir.listFiles();\n                        if (listFiles != null) {\n                                for (File f : listFiles) {\n                                        if (f.isFile()) {\n                                                if (regex.matcher(f.getName()).matches()) {\n                                                        map.put(f.getName(), f);\n                                                }\n                                        } else if (f.isDirectory() && recursively) {\n                                                Map<String, File> files = filesInDirectory(f, regex, true);\n                                                map.putAll(files);\n                                        }\n                                }\n                        }\n                } else throw new IllegalArgumentException(dir + \" is not a directory\");\n                return map;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/main/resources/META-INF/services/javax.script.ScriptEngineFactory",
    "content": "lt.repl.scripting.LatteEngineFactory"
  },
  {
    "path": "latte-compiler/src/main/resources/build.lts.template",
    "content": "; This configuration is used for compiling Latte projects\n\nCompiler() configure {\n    'classpath':[],          ; class path. classes in these URLs will be loaded for compiling\n    'threads':{              ; threads for scanner, parser and code generator\n                             ;   scanner threads         (default value is machine CPU core)\n        'scanner': ${core},\n                             ;   parser threads          (default value is machine CPU core)\n        'parser':  ${core},\n                             ;   code generator threads  (default value is machine CPU core)\n        'codeGen': ${core}\n    },\n    'code':{                 ; some config about code\n        'autoImport': [],    ;   append these imports to the end of import list in all files\n        'indentation':4,     ;   indentation of the source code\n        'lineBase':   0,     ;   all line info += lineBase\n        'columnBase': 0      ;   all column info += columnBase\n    },\n    'out':{\n        'debug': null,       ; output debug msg\n        'info':System.out,   ; output info msg\n        'warn':System.err,   ; output warn msg\n        'err': System.err    ; output err msg\n    },\n    'fastFail':false,        ; the compiling process stops when any exception occurres\n                             ; set this to `true` when Latte is used as a script\n    'result':{               ; some info about compiling result\n                             ;   output directory, or don't write to disk if it's not set (or is set to null)\n        'outputDir':\"${dir}${separator}target${separator}classes\"\n        'package':  null     ;   the jar file name, or null if don't wan't to pack jar. effective only when outputDir is not null\n        'main':     null     ;   main class, or null if there's no main class. effective only when package is not null\n        'with-lib': false    ;   include Latte runtime libraries. effective only when package is not null\n    }\n} compile filesInDirectory(\"${dir}\", //.*\\.lt//)\n                             ; compile these files\n                             ; use filesInDirectory('...', //.*\\.lt//, true) to recursively\n                             ; compile all `lt` files in children directories\n\n"
  },
  {
    "path": "latte-compiler/src/main/resources/run.lts.template",
    "content": "Run(\n           ; the class path. classes in these URLs will be loaded\n    classPath=[\n        \"${dir}${separator}target${separator}classes\"\n    ],\n           ; the main class. the main method is retrieved from the class\n    mainClass=\"\"\n) exec []  ; the main method arguments. should be a list of Strings"
  },
  {
    "path": "latte-compiler/src/test/java/SimpleTest.java",
    "content": "import lt.compiler.*;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\n\nimport javax.script.ScriptContext;\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\nimport javax.script.ScriptException;\nimport java.io.*;\nimport java.net.URL;\nimport java.net.URLConnection;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\n/**\n * Created by wkgcass on 16/6/4.\n */\n/*\npublic class SimpleTest {\n        public static void main(String[] args) throws ScriptException {\n                ScriptEngine engine = new ScriptEngineManager().getEngineByName(\"Latte-lang\");\n                engine.eval(\"a = ['key': 'value']\");\n                System.out.println(engine.get(\"a\"));\n        }\n}\n*/\npublic class SimpleTest {\n        public static void main(String[] args) throws Exception {\n                ErrorManager err = new ErrorManager(true);\n\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"\" +\n                        \"class X<:T:>\\n\" +\n                        \"    def method(a:T):T=a\\n\" +\n                        \"class M\\n\" +\n                        \"  x = X<:M:>\\n\" +\n                        \"  x.method(this)\"\n                );\n\n                lt.compiler.Scanner lexicalProcessor = new lt.compiler.IndentScanner(\"test.lt\", new StringReader(sb.toString()), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n                byte[] b = list.get(\"X_$G$_M\");\n                FileOutputStream fos = new FileOutputStream(new File(\"/Users/wkgcass/OpenSource/Latte-lang/hehe.class\"));\n                fos.write(b);\n                fos.flush();\n                fos.close();\n        }\n\n        public static boolean test() {\n                Object a = new Object();\n                Object b = new Object();\n                return a == b;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/LatteObjectOutputStream.java",
    "content": "package lt;\n\nimport java.io.IOException;\nimport java.io.InputStream;\nimport java.io.ObjectInputStream;\nimport java.io.ObjectStreamClass;\n\n/**\n * Object input stream for Latte<br>\n * The latte classes that built at runtime are loaded via customized class loaders,\n * so it cannot be located by the default class loader.<br>\n * The {@link java.io.ObjectInputStream} looks for the class loader via\n * {@link ObjectInputStream#latestUserDefinedLoader()}, which might not get\n * the correct class loader.\n */\npublic class LatteObjectOutputStream extends ObjectInputStream {\n        private final ClassLoader cl;\n\n        public LatteObjectOutputStream(ClassLoader cl, InputStream in) throws IOException {\n                super(in);\n                this.cl = cl;\n        }\n\n        @Override\n        protected Class<?> resolveClass(ObjectStreamClass desc) throws IOException, ClassNotFoundException {\n                return Class.forName(desc.getName(), true, cl);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/RepeatRule.java",
    "content": "package lt;\n\nimport org.junit.rules.TestRule;\nimport org.junit.runner.Description;\nimport org.junit.runners.model.Statement;\n\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\npublic class RepeatRule implements TestRule {\n        @Retention(RetentionPolicy.RUNTIME)\n        @Target({\n                java.lang.annotation.ElementType.METHOD\n        })\n        public @interface Repeat {\n                int times();\n        }\n\n        private static class RepeatStatement extends Statement {\n                private final int times;\n                private final Statement statement;\n\n                private RepeatStatement(int times, Statement statement) {\n                        this.times = times;\n                        this.statement = statement;\n                }\n\n                @Override\n                public void evaluate() throws Throwable {\n                        for (int i = 0; i < times; i++) {\n                                statement.evaluate();\n                        }\n                }\n        }\n\n        @Override\n        public Statement apply(\n                Statement statement, Description description) {\n                Statement result = statement;\n                Repeat repeat = description.getAnnotation(Repeat.class);\n                if (repeat != null) {\n                        int times = repeat.times();\n                        result = new RepeatStatement(times, statement);\n                }\n                return result;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/AnnoAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * anno anno\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface AnnoAnno {\n        MyAnno myAnno();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/AnnotationTest.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.SModifier;\n\n/**\n * annotation for testing\n */\npublic @interface AnnotationTest {\n        String str() default \"str\";\n\n        int i() default 100;\n\n        long l() default 100;\n\n        short s() default 100;\n\n        byte b() default 100;\n\n        boolean bo() default true;\n\n        char c() default 'a';\n\n        float f() default 100;\n\n        double d() default 100;\n\n        MyAnno anno() default @MyAnno(str = \"a\");\n\n        Class<?> cls() default String.class;\n\n        SModifier e() default SModifier.PUBLIC;\n\n        String[] strArr() default {\"a\", \"b\"};\n\n        Class<?>[] clsArr() default {Class.class, String.class};\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/F.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * class for testing functional abstract class\n */\npublic abstract class F {\n        public abstract Object func(Object e);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/MyAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(value = {ElementType.METHOD, ElementType.FIELD, ElementType.TYPE, ElementType.LOCAL_VARIABLE, ElementType.PARAMETER})\npublic @interface MyAnno {\n        String str();\n\n        int i() default 100;\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/TestAllKindsOfAnnos.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\nimport lt.compiler.semantic.SModifier;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test all kinds of annos\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface TestAllKindsOfAnnos {\n        String str();\n\n        String[] strArr();\n\n        int i();\n\n        int[] iArr();\n\n        short s();\n\n        short[] sArr();\n\n        byte b();\n\n        byte[] bArr();\n\n        char c();\n\n        char[] cArr();\n\n        boolean bo();\n\n        boolean[] boArr();\n\n        long l();\n\n        long[] lArr();\n\n        float f();\n\n        float[] fArr();\n\n        double d();\n\n        double[] dArr();\n\n        Class<?> cls();\n\n        Class<?>[] clsArr();\n\n        SModifier en();\n\n        SModifier[] enArr();\n\n        MyAnno anno();\n\n        MyAnno[] annos();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/TestLambdaFunc.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler;\n\n/**\n * used to test lambda\n */\npublic abstract class TestLambdaFunc {\n        public abstract Object apply(Object o);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestAnnotations.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.cases.anno.*;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.Method;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.junit.Assert.*;\n\n/**\n * test annotations\n */\npublic class TestAnnotations {\n        private Class<?> retrieveClass(String code, String clsName) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                final Map<String, byte[]> list = codeGenerator.generate();\n\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                byte[] bs = list.get(name);\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                return classLoader.loadClass(clsName);\n        }\n\n        @Test\n        public void testType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"@TestTypeAnno\\n\" +\n                        \"class TestType\"\n                        , \"TestType\");\n                assertTrue(cls.isAnnotationPresent(TestTypeAnno.class));\n        }\n\n        @Test\n        public void testConstructor() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"@TestConstructorAnno\\n\" +\n                        \"class TestConstructor\"\n                        , \"TestConstructor\");\n                Constructor<?> cons = cls.getConstructor();\n                assertTrue(cons.isAnnotationPresent(TestConstructorAnno.class));\n        }\n\n        @Test\n        public void testConsParameter() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestConsParameter(\\n\" +\n                        \"    @TestParamAnno\\n\" +\n                        \"    a\\n\" +\n                        \")\"\n                        , \"TestConsParameter\");\n                Annotation[] annos = cls.getConstructor(Object.class).getParameterAnnotations()[0];\n                assertEquals(1, annos.length);\n                assertTrue(TestParamAnno.class.isAssignableFrom(annos[0].getClass()));\n        }\n\n        @Test\n        public void testPField() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestPField(\\n\" +\n                        \"    @TestFieldAnno\\n\" +\n                        \"    a\\n\" +\n                        \")\"\n                        , \"TestPField\");\n                Field f = cls.getDeclaredField(\"a\");\n                assertTrue(f.isAnnotationPresent(TestFieldAnno.class));\n        }\n\n        @Test\n        public void testField() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestField\\n\" +\n                        \"    @TestFieldAnno\\n\" +\n                        \"    a\\n\"\n                        , \"TestField\");\n                Field f = cls.getDeclaredField(\"a\");\n                assertTrue(f.isAnnotationPresent(TestFieldAnno.class));\n        }\n\n        @Test\n        public void testMethod() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestMethod\\n\" +\n                        \"    @TestMethodAnno\\n\" +\n                        \"    method():Unit\\n\"\n                        , \"TestMethod\");\n                Method method = cls.getMethod(\"method\");\n                assertTrue(method.isAnnotationPresent(TestMethodAnno.class));\n        }\n\n        @Test\n        public void testMethodParam() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestMethod\\n\" +\n                        \"    method(\\n\" +\n                        \"        @TestParamAnno\\n\" +\n                        \"        a\\n\" +\n                        \"    ):Unit\\n\"\n                        , \"TestMethod\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                Annotation[] annotations = method.getParameterAnnotations()[0];\n                assertTrue(TestParamAnno.class.isAssignableFrom(annotations[0].getClass()));\n        }\n\n        @Test\n        public void testClassDefaultValue() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"@TestConstructorAnno\\n\" +\n                        \"class TestClassDefaultValue(a=1)\"\n                        , \"TestClassDefaultValue\");\n                Constructor<?> cons = cls.getConstructor(Object.class);\n                assertTrue(cons.isAnnotationPresent(TestConstructorAnno.class));\n                cons = cls.getConstructor();\n                assertTrue(cons.isAnnotationPresent(TestConstructorAnno.class));\n        }\n\n        @Test\n        public void testMethodDefaultValue() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"class TestMethod\\n\" +\n                        \"    @TestMethodAnno\\n\" +\n                        \"    method(a=1):Unit\\n\"\n                        , \"TestMethod\");\n                Method method = cls.getMethod(\"method\");\n                assertTrue(method.isAnnotationPresent(TestMethodAnno.class));\n                method = cls.getMethod(\"method\", Object.class);\n                assertTrue(method.isAnnotationPresent(TestMethodAnno.class));\n        }\n\n        @Test\n        public void testDataClass() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"import lt::compiler::cases::anno::_\\n\" +\n                        \"@TestConstructorAnno\\n\" +\n                        \"data class TestDataClass(a,b)\"\n                        , \"TestDataClass\");\n                Constructor<?> cons = cls.getConstructor();\n                assertTrue(cons.isAnnotationPresent(TestConstructorAnno.class));\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestBraceScanner.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.BraceScanner;\nimport lt.compiler.ErrorManager;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.*;\nimport org.junit.Test;\n\nimport java.io.StringReader;\n\nimport static org.junit.Assert.assertEquals;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * test\n */\npublic class TestBraceScanner {\n        @Test\n        public void testPkg() throws Exception {\n                // package lt.test\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"package lt::test\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"package\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"lt\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"test\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testImport() throws Exception {\n                // import packageName._\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"\" +\n                        \"import Package::name::_\\n\" +\n                        \"import Package::name::Test\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"import\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"Package\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"name\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"_\", TokenType.VALID_NAME);\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"import\", TokenType.KEY);\n                args.previous = new Element(args, \"Package\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"name\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                new Element(args, \"Test\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testCls1() throws Exception {\n                // class ClassName\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"class ClassName\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                new Element(args, \"ClassName\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testCls2() throws Exception {\n                // class ClassName(arg1:Type1,arg2:Type2)\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"class ClassName(arg1,arg2=value2)\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"ClassName\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"arg1\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n\n                args.previous = new Element(args, \"arg2\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"value2\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testVariable3() throws Exception {\n                // val value:Type = 1\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"val value = 1\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"value\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testMethod1() throws Exception {\n                //val trim(input)\n                //    <input.trim()\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"\" +\n                        \"val trim(input) {\\n\" +\n                        \"    return input.trim()\\n\" +\n                        \"}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testMethod2() throws Exception {\n                // voidMethod(input)=0\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"voidMethod(input)=0\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"voidMethod\", TokenType.VALID_NAME);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"0\", TokenType.NUMBER);\n\n                args.previous = null;\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testModifiers() throws Exception {\n                //pub val abs class X\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"public val abstract class X\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"public\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                args.previous = new Element(args, \"abstract\", TokenType.MODIFIER);\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                args.previous = new Element(args, \"X\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                //if true\n                //    <\"hello world\"\n                //elseif false\n                //    <\"hello\"\n                //else\n                //    <\"world\"\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"if true {\\n\" +\n                                \"    return \\\"hello world\\\"\\n\" +\n                                \"} elseif false {\\n\" +\n                                \"    return \\\"hello\\\"\\n\" +\n                                \"} else {\\n\" +\n                                \"    return \\\"world\\\"\\n\" +\n                                \"}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"if\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"elseif\", TokenType.KEY);\n                args.previous = new Element(args, \"false\", TokenType.BOOL);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"else\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello world\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"world\\\"\", TokenType.STRING);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testFor1() throws Exception {\n                //for i @ iterable\n                //    i\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"for i in iterable {\\n\" +\n                                \"    i\\n\" +\n                                \"}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"for\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"in\", TokenType.KEY);\n                args.previous = new Element(args, \"iterable\", TokenType.VALID_NAME);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                startNode.setLinkedNode(new Element(args, \"i\", TokenType.VALID_NAME));\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile1() throws Exception {\n                //while true\n                //    i+=1\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"while true {\\n\" +\n                                \"    i+=1\\n\" +\n                                \"}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile2() throws Exception {\n                // do\n                //     i+=1\n                // while true\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"do {\\n\" +\n                                \"    i+=1\\n\" +\n                                \"} while true\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"do\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testTry() throws Exception {\n                //try\n                //    throw e\n                //catch e\n                //    SomeException,AnotherException\n                //        throw RuntimeException(e)\n                //    OtherException\n                //finally\n                //    <ret\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"try {\\n\" +\n                                \"    throw e\\n\" +\n                                \"} catch e {\\n\" +\n                                \"    SomeException,AnotherException {\\n\" +\n                                \"        throw RuntimeException(e)\\n\" +\n                                \"    }\\n\" +\n                                \"    OtherException {}\\n\" +\n                                \"} finally {\\n\" +\n                                \"    return ret\\n\" +\n                                \"}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"try\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"catch\", TokenType.KEY);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"finally\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"SomeException\", TokenType.VALID_NAME);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"AnotherException\", TokenType.VALID_NAME);\n                ElementStartNode startNode1_1 = new ElementStartNode(args, new Indent(8));\n                args.previous = startNode1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"OtherException\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1_1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"RuntimeException\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode1_1_1 = new ElementStartNode(args, new Indent(12));\n                args.previous = startNode1_1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode1_1_1.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"ret\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testLambda() throws Exception {\n                //list.stream().filter(\n                //    (e)-> {\n                //        e>10\n                //    }\n                //)\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\"\" +\n                        \"list.stream().filter(\\n\" +\n                        \"    (e)->{\\n\" +\n                        \"        e > 10\\n\" +\n                        \"    }\\n\" +\n                        \")\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"list\", TokenType.VALID_NAME);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"stream\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"filter\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                startNode1.setLinkedNode(args.previous);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(8));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"->\", TokenType.SYMBOL);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(8));\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode2.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \">\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"10\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testOperators() throws Exception {\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"1+2\\n\" +\n                                \"3-4\\n\" +\n                                \"5*6\\n\" +\n                                \"7/8\\n\" +\n                                \"9%10\\n\" +\n                                \"i+=11\\n\" +\n                                \"i-=12\\n\" +\n                                \"i*=13\\n\" +\n                                \"i/=14\\n\" +\n                                \"i%=15\\n\" +\n                                \"i++\\n\" +\n                                \"i--\\n\" +\n                                \"++i\\n\" +\n                                \"--i\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"2\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"3\", TokenType.NUMBER);\n                args.previous = new Element(args, \"-\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"4\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"5\", TokenType.NUMBER);\n                args.previous = new Element(args, \"*\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"6\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"7\", TokenType.NUMBER);\n                args.previous = new Element(args, \"/\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"8\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"9\", TokenType.NUMBER);\n                args.previous = new Element(args, \"%\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"10\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"11\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"-=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"12\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"*=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"13\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"/=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"14\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"%=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"15\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"++\", TokenType.SYMBOL);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"--\", TokenType.SYMBOL);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"++\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"--\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testSpacesAtTheFront() throws Exception {\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"  import package::name::_\"\n                ), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n                Node n = root.getLinkedNode();\n                assertTrue(n instanceof Element);\n                Element e = (Element) n;\n                assertEquals(1, e.getLineCol().line);\n                assertEquals(3, e.getLineCol().column);\n        }\n\n        @Test\n        public void testIndent() throws Exception {\n                Properties properties = new Properties();\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        // the statements is copied from testIf\n                        // but changed indentation to 2\n                        \"\" +\n                                \"if true\\n\" +\n                                \"  return \\\"hello world\\\"\\n\" +\n                                \"elseif false\\n\" +\n                                \"  return \\\"hello\\\"\\n\" +\n                                \"else\\n\" +\n                                \"  return \\\"world\\\"\"), properties, new ErrorManager(true));\n                processor.scan();\n        }\n\n        @Test\n        public void testMultipleLineComment() throws Exception {\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"a=1/**/\\n\" + // inline comment 1\n                                \"a/**/=2\\n\" + // inline comment 2\n                                \"a/* a */=3\\n\" + // inline comment 3\n                                \"a=4/* a */\\n\" + // inline comment 4\n                                \"a/*\\n\" +\n                                \"*/=5\\n\" +// multiple line 1\n                                \"/*\\n\" +\n                                \"*/a=6\\n\" + // multiple line 2\n                                \"/*\\n\" +\n                                \"a\\n\" +\n                                \"*/a=7\" + // multiple line 3\n                                \"\"),\n                        new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                Element e = new Element(args, \"a\", TokenType.VALID_NAME);\n                root2.setLinkedNode(e);\n                args.previous = e;\n\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n                for (int i = 2; i <= 7; ++i) {\n                        args.previous = new EndingNode(args, EndingNode.WEAK);\n                        args.previous = new Element(args, \"a\", TokenType.VALID_NAME);\n                        args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                        args.previous = new Element(args, \"\" + i, TokenType.NUMBER);\n                }\n\n                assertEquals(root2, root);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestCodeGen.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.Scanner;\nimport lt.compiler.semantic.SModifier;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.util.Consts;\nimport lt.generator.SourceGenerator;\nimport lt.lang.Pointer;\nimport lt.lang.Unit;\nimport lt.lang.function.Function0;\nimport lt.lang.function.Function1;\nimport lt.lang.function.Function3;\nimport lt.repl.ScriptCompiler;\nimport lt.runtime.*;\nimport lt.util.RangeList;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.annotation.Annotation;\nimport java.lang.reflect.*;\nimport java.math.BigInteger;\nimport java.util.*;\nimport java.util.regex.Pattern;\n\nimport static org.junit.Assert.*;\n\n/**\n * test code generator\n */\npublic class TestCodeGen {\n        public static Map<String, byte[]> retrieveByteCode(String code) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n                Scanner lexicalProcessor = new ScannerSwitcher(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                return codeGenerator.generate();\n        }\n\n        public static Class<?> retrieveClass(String code, String clsName) throws IOException, SyntaxException, ClassNotFoundException {\n                final Map<String, byte[]> list = retrieveByteCode(code);\n\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                byte[] bs = list.get(name);\n                                if (bs == null) throw new ClassNotFoundException(name);\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                return classLoader.loadClass(clsName);\n        }\n\n        @Test\n        public void testPkg() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"package my::test\\n\" +\n                                \"class TestPkg\",\n                        \"my.test.TestPkg\");\n                assertEquals(\"my.test.TestPkg\", cls.getName());\n        }\n\n        @Test\n        public void testClass() throws Exception {\n                Class<?> cls = retrieveClass(\"class TestClass\", \"TestClass\");\n                assertEquals(\"TestClass\", cls.getName());\n                assertEquals(Modifier.PUBLIC, cls.getModifiers());\n                assertEquals(1, cls.getDeclaredConstructors().length);\n                assertEquals(0, cls.getDeclaredConstructors()[0].getParameterTypes().length);\n        }\n\n        @Test\n        public void testConstructorParam() throws Exception {\n                Class<?> cls = retrieveClass(\"class TestConstructorParam(a,b)\\n\", \"TestConstructorParam\");\n                assertEquals(\"TestConstructorParam\", cls.getName());\n                assertEquals(Modifier.PUBLIC, cls.getModifiers());\n                assertEquals(1, cls.getDeclaredConstructors().length);\n                assertEquals(2, cls.getDeclaredConstructors()[0].getParameterTypes().length);\n        }\n\n        @Test\n        public void testField() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestField\\n\" +\n                                \"    a=1\\n\" +\n                                \"    b:int\\n\" +\n                                \"    c:Integer\",\n                        \"TestField\");\n                assertEquals(3, cls.getDeclaredFields().length);\n                assertEquals(Object.class, cls.getDeclaredField(\"a\").getType());\n                assertEquals(int.class, cls.getDeclaredField(\"b\").getType());\n                assertEquals(Integer.class, cls.getDeclaredField(\"c\").getType());\n        }\n\n        @Test\n        public void testMethod() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestMethod\\n\" +\n                                \"    method():Unit\",\n                        \"TestMethod\");\n                assertEquals(1, cls.getDeclaredMethods().length);\n                Method m = cls.getDeclaredMethods()[0];\n                assertEquals(\"method\", m.getName());\n                assertEquals(void.class, m.getReturnType());\n                assertEquals(0, m.getParameterTypes().length);\n                assertEquals(Modifier.PUBLIC, m.getModifiers());\n        }\n\n        @Test\n        public void testModifier() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"private class TestModifier\\n\" +\n                                \"    public field\\n\" +\n                                \"    protected method():Unit\",\n                        \"TestModifier\");\n                assertEquals(Modifier.PUBLIC, cls.getModifiers());\n\n                assertEquals(1, cls.getDeclaredConstructors().length);\n                assertEquals(Modifier.PRIVATE, cls.getDeclaredConstructors()[0].getModifiers());\n\n                assertEquals(1, cls.getDeclaredFields().length);\n                assertEquals(Modifier.PUBLIC, cls.getDeclaredFields()[0].getModifiers());\n\n                assertEquals(1, cls.getDeclaredMethods().length);\n                assertEquals(Modifier.PROTECTED, cls.getDeclaredMethods()[0].getModifiers());\n        }\n\n        @Test\n        public void testReturnStr() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestReturnStr\\n\" +\n                                \"    static\\n\" +\n                                \"        method()='abc'\",\n                        \"TestReturnStr\");\n                Method method = cls.getMethod(\"method\");\n                String str = (String) method.invoke(null);\n                assertEquals(\"abc\", str);\n        }\n\n        @Test\n        public void testInvokeStatic() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeStatic\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=System.getProperties()\",\n                        \"TestInvokeStatic\");\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(null);\n                assertTrue(o instanceof java.util.Properties);\n        }\n\n        @Test\n        public void testInvokeVirtual() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeVirtual\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=System.getProperties().get('java.version')\",\n                        \"TestInvokeVirtual\");\n\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(null);\n                assertEquals(System.getProperties().get(\"java.version\"), o);\n        }\n\n        @Test\n        public void testInvokeInterface() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestInvokeInterface\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return Collections.singletonList('abc').size()\",\n                        \"TestInvokeInterface\");\n\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(null);\n                assertEquals(1, o);\n        }\n\n        @Test\n        public void testInvokeSpecial() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeSpecial\\n\" +\n                                \"    private priMethod()\\n\" +\n                                \"        return 1\\n\" +\n                                \"    def method()\\n\" +\n                                \"        return priMethod()\",\n                        \"TestInvokeSpecial\");\n\n                Object o = cls.newInstance();\n                Method method = cls.getMethod(\"method\");\n                Object res = method.invoke(o);\n                assertEquals(1, res);\n        }\n\n        @Test\n        public void testInvokeDynamic() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeDynamic\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)\\n\" +\n                                \"            return o.size()\",\n                        \"TestInvokeDynamic\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                List<Integer> l = new ArrayList<Integer>();\n                l.add(1);\n                l.add(2);\n                Object o = method.invoke(null, l);\n                assertEquals(2, o);\n        }\n\n        @Test\n        public void testInvokeDynamic_WithArgs() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeDynamic\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)\\n\" +\n                                \"            return o.add(3)\",\n                        \"TestInvokeDynamic\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                List<Integer> l = new ArrayList<Integer>();\n                l.add(1);\n                l.add(2);\n                method.invoke(null, l);\n                assertEquals(Arrays.asList(1, 2, 3), l);\n        }\n\n        @Test\n        public void testInvokeDynamic_WithArgs_Method_Primitive() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeDynamic\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)\\n\" +\n                                \"            return o.add(0,3)\",\n                        \"TestInvokeDynamic\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                List<Integer> l = new ArrayList<Integer>();\n                l.add(1);\n                l.add(2);\n                method.invoke(null, l);\n                assertEquals(Arrays.asList(3, 1, 2), l);\n        }\n\n        @Test\n        public void testTstore() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeDynamic\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            i=1\\n\" +\n                                \"            return i\",\n                        \"TestInvokeDynamic\");\n\n                Method method = cls.getMethod(\"method\");\n                assertEquals(1, method.invoke(null));\n        }\n\n        @Test\n        public void testNew() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestNew\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return ArrayList()\",\n                        \"TestNew\");\n\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(null);\n                assertTrue(o instanceof ArrayList);\n        }\n\n        @Test\n        public void testTwoVarOp() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestTwoVarOp\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b)\\n\" +\n                                \"            return a|b\",\n                        \"TestTwoVarOp\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(3, method.invoke(null, 1, 2));\n                assertEquals(true, method.invoke(null, false, true));\n                BigInteger a = new BigInteger(\"1\");\n                BigInteger b = new BigInteger(\"2\");\n                assertEquals(new BigInteger(\"3\"), method.invoke(null, a, b)); // BigInteger.or(BigInteger)\n        }\n\n        @Test\n        public void testRange() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestRange\\n\" +\n                                \"    static\\n\" +\n                                \"        def method1()\\n\" +\n                                \"            return 1 to 10\\n\" +\n                                \"        def method2()\\n\" +\n                                \"            return 1 until 10\\n\" +\n                                \"        def method3()\\n\" +\n                                \"            return 10 to 1\\n\" +\n                                \"        def method4()\\n\" +\n                                \"            return 10 until 1\",\n                        \"TestRange\");\n\n                Method method1 = cls.getMethod(\"method1\");\n                List range1 = (RangeList) method1.invoke(null);\n                assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10), range1);\n\n                Method method2 = cls.getMethod(\"method2\");\n                List range2 = (RangeList) method2.invoke(null);\n                assertEquals(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9), range2);\n\n                Method method3 = cls.getMethod(\"method3\");\n                List range3 = (RangeList) method3.invoke(null);\n                assertEquals(Arrays.asList(10, 9, 8, 7, 6, 5, 4, 3, 2, 1), range3);\n\n                Method method4 = cls.getMethod(\"method4\");\n                List range4 = (RangeList) method4.invoke(null);\n                assertEquals(Arrays.asList(10, 9, 8, 7, 6, 5, 4, 3, 2), range4);\n        }\n\n        @Test\n        public void testPow() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestPow\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return 2^^4\\n\",\n                        \"TestPow\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(16.0, method.invoke(null));\n        }\n\n        @Test\n        public void testPowObj() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestPowObj\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b)\\n\" +\n                                \"            return a^^b\\n\",\n                        \"TestPowObj\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(new BigInteger(\"16\"), method.invoke(null, new BigInteger(\"2\"), 4));\n        }\n\n        @Test\n        public void testIn() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestIn\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,ls)\\n\" +\n                                \"            return a in ls\\n\",\n                        \"TestIn\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(true, method.invoke(null, 1, Arrays.asList(1, 2)));\n                assertEquals(false, method.invoke(null, 3, Arrays.asList(1, 2)));\n        }\n\n        @Test\n        public void testInRange() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestInRange\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return 2 in (1 to 2)\\n\",\n                        \"TestInRange\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(true, method.invoke(null));\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestIf\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a)\\n\" +\n                                \"            if a\\n\" +\n                                \"                return 1\\n\" +\n                                \"            else\\n\" +\n                                \"                return 2\",\n                        \"TestIf\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(1, method.invoke(null, true));\n                assertEquals(2, method.invoke(null, false));\n\n                assertEquals(1, method.invoke(null, 1)); // if 1\n                assertEquals(2, method.invoke(null, 0)); // if 0\n\n                assertEquals(2, method.invoke(null, (Object) null)); // if null\n\n                assertEquals(2, method.invoke(null, Unit.get())); // unit\n        }\n\n        @Test\n        public void testIfComplex() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestIfComplex\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b,c)\\n\" +\n                                \"            i=0\\n\" +\n                                \"            if a\\n\" +\n                                \"                i=1\\n\" +\n                                \"            elseif b\\n\" +\n                                \"                i=2\\n\" +\n                                \"            elseif c\\n\" +\n                                \"                i=3\\n\" +\n                                \"            else\\n\" +\n                                \"                i=4\\n\" +\n                                \"            return i\",\n                        \"TestIfComplex\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n                assertEquals(1, method.invoke(null, true, false, false));\n                assertEquals(1, method.invoke(null, true, true, false));\n                assertEquals(1, method.invoke(null, true, false, true));\n                assertEquals(1, method.invoke(null, true, true, true));\n\n                assertEquals(2, method.invoke(null, false, true, false));\n                assertEquals(2, method.invoke(null, false, true, true));\n\n                assertEquals(3, method.invoke(null, false, false, true));\n\n                assertEquals(4, method.invoke(null, false, false, false));\n        }\n\n        @Test\n        public void testWhile() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhile\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int)\\n\" +\n                                \"            s=StringBuilder()\\n\" +\n                                \"            while a\\n\" +\n                                \"                s.append(a)\\n\" +\n                                \"                a=a-1\\n\" +\n                                \"            return s.toString()\",\n                        \"TestWhile\");\n\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(\"321\", method.invoke(null, 3));\n        }\n\n        @Test\n        public void testDoWhile() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhile\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int)\\n\" +\n                                \"            s=StringBuilder()\\n\" +\n                                \"            do\\n\" +\n                                \"                s.append(a)\\n\" +\n                                \"                a=a-1\\n\" +\n                                \"            while a\\n\" +\n                                \"            return s.toString()\",\n                        \"TestWhile\");\n\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(\"321\", method.invoke(null, 3));\n        }\n\n        @Test\n        public void testFor() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFor\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            s=StringBuilder()\\n\" +\n                                \"            for i in 1 to 3\\n\" +\n                                \"                s.append(i)\\n\" +\n                                \"            return s.toString()\",\n                        \"TestFor\");\n\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"123\", method.invoke(null));\n        }\n\n        @Test\n        public void testThrow() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestThrow\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            throw RuntimeException('ex')\",\n                        \"TestThrow\");\n\n                Method method = cls.getMethod(\"method\");\n                try {\n                        method.invoke(null);\n                        fail(\"method should throw an exception\");\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getCause() instanceof RuntimeException);\n                        assertEquals(\"ex\", e.getCause().getMessage());\n                }\n        }\n\n        @Test\n        public void testTryCatch() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestTryCatch\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(func)\\n\" +\n                                \"            try\\n\" +\n                                \"                func.apply()\\n\" +\n                                \"            catch e\\n\" +\n                                \"                if e is type NullPointerException or e is type ClassCastException\\n\" +\n                                \"                    return 1\\n\" +\n                                \"                elseif e is type Error\\n\" +\n                                \"                    return e.getMessage()\\n\" +\n                                \"                elseif e is type Throwable\\n\" +\n                                \"                    return 3\\n\" +\n                                \"            return 4\",\n                        \"TestTryCatch\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                // null pointer exception\n                assertEquals(1, method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new NullPointerException();\n                        }\n                }));\n                // class cast exception\n                assertEquals(1, method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new ClassCastException();\n                        }\n                }));\n                // error\n                assertEquals(\"msg\", method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Error(\"msg\");\n                        }\n                }));\n                // throwable\n                assertEquals(3, method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Throwable();\n                        }\n                }));\n                // none\n                assertEquals(4, method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                        }\n                }));\n        }\n\n        @Test\n        public void testTryCatchTemp() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestTryCatch\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(func)\\n\" +\n                                \"            try\\n\" +\n                                \"                func.apply()\\n\" +\n                                \"            catch e\\n\" +\n                                \"                if 1===1\\n\" +\n                                \"                    return 1\\n\" +\n                                \"            finally\\n\" +\n                                \"            return 4\",\n                        \"TestTryCatch\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                // null pointer exception\n                assertEquals(1, method.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new NullPointerException();\n                        }\n                }));\n        }\n\n        interface I {\n                @SuppressWarnings(\"unused\")\n                void apply() throws Throwable;\n        }\n\n        @Test\n        public void testContinualAssign() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestContinualAssign\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            b=a=2\\n\" +\n                                \"            return b\",\n                        \"TestContinualAssign\");\n\n                Method method = cls.getMethod(\"method\");\n                assertEquals(2, method.invoke(null));\n        }\n\n        @Test\n        public void testUnit() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestUnit\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return Unit\",\n                        \"TestUnit\");\n\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Unit.get(), method.invoke(null));\n        }\n\n        @Test\n        public void testStringAdd() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestStringAdd\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return 'abc'+'d'+1\",\n                        \"TestStringAdd\");\n\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"abcd1\", method.invoke(null));\n        }\n\n        @Test\n        public void testLogicAnd() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicAnd\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b)\\n\" +\n                                \"            return a&&b\",\n                        \"TestLogicAnd\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(true, method.invoke(null, true, true));\n                assertEquals(false, method.invoke(null, false, true));\n                assertEquals(false, method.invoke(null, true, false));\n                assertEquals(false, method.invoke(null, false, false));\n        }\n\n        @Test\n        public void testLogicAnd2() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicAnd\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,ls)\\n\" +\n                                \"            a&&ls.add(1)\",\n                        \"TestLogicAnd\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n\n                List<Integer> ls = new ArrayList<Integer>();\n                method.invoke(null, true, ls);\n                assertEquals(Collections.singletonList(1), ls);\n\n                ls.clear();\n                method.invoke(null, false, ls);\n                assertTrue(ls.isEmpty());\n        }\n\n        @Test\n        public void testLogicAnd3() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicAnd\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b,c)\\n\" +\n                                \"            return a&&b&&c\",\n                        \"TestLogicAnd\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n\n                assertEquals(true, method.invoke(null, true, true, true));\n                assertEquals(false, method.invoke(null, false, true, true));\n                assertEquals(false, method.invoke(null, true, false, true));\n                assertEquals(false, method.invoke(null, true, true, false));\n                assertEquals(false, method.invoke(null, false, false, true));\n                assertEquals(false, method.invoke(null, false, true, false));\n                assertEquals(false, method.invoke(null, true, false, false));\n                assertEquals(false, method.invoke(null, false, false, false));\n        }\n\n        @Test\n        public void testLogicOr() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicOr\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b)\\n\" +\n                                \"            return a||b\",\n                        \"TestLogicOr\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(true, method.invoke(null, true, true));\n                assertEquals(true, method.invoke(null, false, true));\n                assertEquals(true, method.invoke(null, true, false));\n                assertEquals(false, method.invoke(null, false, false));\n        }\n\n        @Test\n        public void testLogicOr2() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicOr\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,ls)\\n\" +\n                                \"            return a||(\\n\" +\n                                \"                ls.add(1)\\n\" +\n                                \"                return 10\\n\" +\n                                \"            )\",\n                        \"TestLogicOr\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n\n                List<Integer> ls = new ArrayList<Integer>();\n                assertEquals(10, method.invoke(null, false, ls));\n                assertEquals(Collections.singletonList(1), ls);\n\n                ls.clear();\n                assertEquals(true, method.invoke(null, true, ls));\n                assertTrue(ls.isEmpty());\n        }\n\n        @Test\n        public void testLogicOr3() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicOr\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b,c)\\n\" +\n                                \"            return a||b||c\",\n                        \"TestLogicOr\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n\n                assertEquals(true, method.invoke(null, true, true, true));\n                assertEquals(true, method.invoke(null, false, true, true));\n                assertEquals(true, method.invoke(null, true, false, true));\n                assertEquals(true, method.invoke(null, true, true, false));\n                assertEquals(true, method.invoke(null, false, false, true));\n                assertEquals(true, method.invoke(null, false, true, false));\n                assertEquals(true, method.invoke(null, true, false, false));\n                assertEquals(false, method.invoke(null, false, false, false));\n        }\n\n        @Test\n        public void testLogicAndOr() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestLogicAndOr\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b,c)\\n\" +\n                                \"            return a or b and c\",\n                        \"TestLogicAndOr\");\n\n                // && has higher priority than ||\n                // a or b and c\n                // ==\n                // a or (b and c)\n                Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n\n                //                                       a  or ( b  and  c )\n                assertEquals(true, method.invoke(null, true, false, false));\n                assertEquals(false, method.invoke(null, false, false, true));\n                assertEquals(true, method.invoke(null, false, true, true));\n        }\n\n        @Test\n        public void testUnaryInc() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestUnaryInc\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int)\\n\" +\n                                \"            return ++a\",\n                        \"TestUnaryInc\");\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(2, method.invoke(null, 1));\n        }\n\n        @Test\n        public void testSelfInc() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestSelfInc\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int)\\n\" +\n                                \"            return a++\",\n                        \"TestSelfInc\");\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(1, method.invoke(null, 1));\n        }\n\n        @Test\n        public void testInvokeVoidMethodReturnUnit() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeVoidMethodReturnUnit\\n\" +\n                                \"    static\\n\" +\n                                \"        private m():Unit\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return m()\",\n                        \"TestInvokeVoidMethodReturnUnit\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Unit.get(), method.invoke(null));\n        }\n\n        @Test\n        public void testVoidMethodLogicAnd() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestVoidMethodLogicAnd\\n\" +\n                                \"    static\\n\" +\n                                \"        i:int\\n\" +\n                                \"        private m():Unit\\n\" +\n                                \"            i=100\\n\" +\n                                \"        def method(a)\\n\" +\n                                \"            return a&&m()\\n\" +\n                                \"        getI()=i\",\n                        \"TestVoidMethodLogicAnd\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                Method getI = cls.getMethod(\"getI\");\n\n                assertEquals(false, method.invoke(null, false));\n                assertEquals(0, getI.invoke(null));\n\n                assertEquals(false, method.invoke(null, true));\n                assertEquals(100, getI.invoke(null));\n        }\n\n        @Test\n        public void testTAStore() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestTAStore\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:[]int)\\n\" +\n                                \"            return a[1]=100\",\n                        \"TestTAStore\");\n                Method method = cls.getMethod(\"method\", int[].class);\n\n                int[] arr = new int[]{1, 2};\n                method.invoke(null, (Object) arr);\n                assertEquals(100, arr[1]);\n        }\n\n        @Test\n        public void testIndexAccessObject() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestIndexAccessObject\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a)\\n\" +\n                                \"            return a[1]=100\",\n                        \"TestIndexAccessObject\");\n                Method method = cls.getMethod(\"method\", Object.class);\n\n                List<Integer> arr = new ArrayList<Integer>();\n                arr.add(1);\n                arr.add(2);\n                method.invoke(null, arr);\n                assertEquals(Integer.valueOf(100), arr.get(1));\n\n                Map<Integer, Integer> map = new HashMap<Integer, Integer>();\n                map.put(1, 1);\n                map.put(2, 2);\n                method.invoke(null, map);\n                assertEquals(Integer.valueOf(100), map.get(1));\n        }\n\n        @Test\n        public void testNull() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNull\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=null\",\n                        \"TestNull\");\n                Method method = cls.getMethod(\"method\");\n                assertNull(method.invoke(null));\n        }\n\n        @Test\n        public void testArrayLength() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestArrayLength\\n\" +\n                                \"    static\\n\" +\n                                \"        method(arr:[]int)=arr.length\",\n                        \"TestArrayLength\");\n                Method method = cls.getMethod(\"method\", int[].class);\n                int[] arr = new int[]{1, 1, 1, 1};\n                assertEquals(4, method.invoke(null, (Object) arr));\n        }\n\n        @Test\n        public void testNot() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNot\\n\" +\n                                \"    static\\n\" +\n                                \"        method(i:int)=~i\",\n                        \"TestNot\");\n                Method method = cls.getMethod(\"method\", int.class);\n\n                assertEquals(-3, method.invoke(null, 2));\n        }\n\n        @Test\n        public void testNot2() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNot\\n\" +\n                                \"    static\\n\" +\n                                \"        method(arr)=~arr\",\n                        \"TestNot\");\n                Method method = cls.getMethod(\"method\", Object.class);\n\n                BigInteger bigInteger = new BigInteger(\"2\");\n                BigInteger result = (BigInteger) method.invoke(null, bigInteger); // invoke bigInteger.not();\n                assertEquals(new BigInteger(\"-3\"), result);\n        }\n\n        @Test\n        public void testNeg() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNeg\\n\" +\n                                \"    static\\n\" +\n                                \"        method(i:int)=-i\",\n                        \"TestNeg\");\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(-2, method.invoke(null, 2));\n        }\n\n        @Test\n        public void testNeg2() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNeg\\n\" +\n                                \"    static\\n\" +\n                                \"        method(i)=-i\",\n                        \"TestNeg\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(new BigInteger(\"-2\"), method.invoke(null, new BigInteger(\"2\")));\n        }\n\n        @Test\n        public void testNewArray() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNewArray\\n\" +\n                                \"    static\\n\" +\n                                \"        method():[]int=[10,20]\",\n                        \"TestNewArray\");\n                Method method = cls.getMethod(\"method\");\n                int[] arr = (int[]) method.invoke(null);\n                assertEquals(2, arr.length);\n                assertEquals(10, arr[0]);\n                assertEquals(20, arr[1]);\n        }\n\n        @Test\n        public void testANewArray() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestANewArray\\n\" +\n                                \"    static\\n\" +\n                                \"        method():[]Object=[10,20]\",\n                        \"TestANewArray\");\n                Method method = cls.getMethod(\"method\");\n                Object[] arr = (Object[]) method.invoke(null);\n                assertEquals(2, arr.length);\n                assertEquals(10, arr[0]);\n                assertEquals(20, arr[1]);\n        }\n\n        @Test\n        public void testNewList() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestANewArray\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=[10,20]\",\n                        \"TestANewArray\");\n                Method method = cls.getMethod(\"method\");\n                @SuppressWarnings(\"unchecked\")\n                List<Integer> list = (List<Integer>) method.invoke(null);\n\n                assertEquals(java.util.LinkedList.class, list.getClass());\n\n                assertEquals(10, list.get(0).intValue());\n                assertEquals(20, list.get(1).intValue());\n        }\n\n        @Test\n        public void test2DArray() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class Test2DArray\\n\" +\n                                \"    static\\n\" +\n                                \"        method():[][]int=[[1,2],[],[3]]\",\n                        \"Test2DArray\");\n                Method method = cls.getMethod(\"method\");\n                int[][] arr = (int[][]) method.invoke(null);\n                assertArrayEquals(new int[]{1, 2}, arr[0]);\n                assertArrayEquals(new int[]{}, arr[1]);\n                assertArrayEquals(new int[]{3}, arr[2]);\n        }\n\n        @Test\n        public void testNewMap() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestNewMap\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=[\\n\" +\n                                \"            \\\"a\\\":1\\n\" +\n                                \"            \\\"b\\\":2\" +\n                                \"        ]\",\n                        \"TestNewMap\");\n                Method method = cls.getMethod(\"method\");\n                LinkedHashMap<String, Integer> expected = new LinkedHashMap<String, Integer>();\n                expected.put(\"a\", 1);\n                expected.put(\"b\", 2);\n                Object res = method.invoke(null);\n                assertEquals(expected, res);\n                assertEquals(java.util.LinkedHashMap.class, res.getClass());\n        }\n\n        @Test\n        public void testAnnotation() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import lt::compiler::_\\n\" +\n                                \"\" +\n                                \"class TestAnnotation\\n\" +\n                                \"    static\\n\" +\n                                \"        @MyAnno(str='abc')\\n\" +\n                                \"        method():Unit\",\n                        \"TestAnnotation\");\n                Method method = cls.getMethod(\"method\");\n                MyAnno myAnno = method.getAnnotation(MyAnno.class);\n                assertNotNull(myAnno);\n                assertEquals(\"abc\", myAnno.str());\n                assertEquals(100, myAnno.i());\n        }\n\n        @Test\n        public void testTryCatchCanLoad() throws Exception {\n                retrieveClass(\n                        \"\" +\n                                \"class TestTryCatchCanLoad\\n\" +\n                                \"    method():int\\n\" +\n                                \"        i:int=1\\n\" +\n                                \"        try\\n\" +\n                                \"            i=2\\n\" +\n                                \"            if i==3\\n\" +\n                                \"                i=10\\n\" +\n                                \"                return 1\\n\" +\n                                \"            else\\n\" +\n                                \"                i=11\\n\" +\n                                \"                return 2\\n\" +\n                                \"        catch e\\n\" +\n                                \"            if e is type RuntimeException\\n\" +\n                                \"                i=4\\n\" +\n                                \"                if i==5\\n\" +\n                                \"                    i=12\\n\" +\n                                \"                    return 3\\n\" +\n                                \"                else\\n\" +\n                                \"                    i=13\\n\" +\n                                \"                    return 4\\n\" +\n                                \"        finally\\n\" +\n                                \"            i=6\",\n                        \"TestTryCatchCanLoad\"\n                );\n        }\n\n        @Test\n        public void testInnerMethod1() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            inner():int=1\\n\" +\n                                \"            return inner()\",\n                        \"TestInnerMethod\");\n                assertEquals(2, cls.getDeclaredMethods().length);\n                Method m = cls.getDeclaredMethod(\"method\");\n                assertEquals(1, m.invoke(null));\n        }\n\n        @Test\n        public void testInnerMethod2() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            i:int=1\\n\" +\n                                \"            j:int=2\\n\" +\n                                \"            inner():int=i+j\\n\" +\n                                \"            return inner()\",\n                        \"TestInnerMethod\");\n                assertEquals(2, cls.getDeclaredMethods().length);\n                Method m = cls.getDeclaredMethod(\"method\");\n                assertEquals(3, m.invoke(null));\n        }\n\n        @Test\n        public void testInnerMethod3() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethod\\n\" +\n                                \"    def method()\\n\" +\n                                \"        i:int=1\\n\" +\n                                \"        j:int=2\\n\" +\n                                \"        inner():int=i+j\\n\" +\n                                \"        return inner()\",\n                        \"TestInnerMethod\");\n                assertEquals(2, cls.getDeclaredMethods().length);\n                Method m = cls.getDeclaredMethod(\"method\");\n                assertEquals(3, m.invoke(cls.newInstance()));\n        }\n\n        @Test\n        public void testInnerMethod4() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            i:int=1\\n\" +\n                                \"            j:int=2\\n\" +\n                                \"            inner(k:int):int=i+j+k\\n\" +\n                                \"            return inner(3)\",\n                        \"TestInnerMethod\");\n                assertEquals(2, cls.getDeclaredMethods().length);\n                Method m = cls.getDeclaredMethod(\"method\");\n                assertEquals(6, m.invoke(null));\n        }\n\n        @Test\n        public void testLambdaStatic1() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import lt::lang::function::_\\n\" +\n                                \"class TestLambdaStatic1\\n\" +\n                                \"    static\\n\" +\n                                \"        method():Function1\\n\" +\n                                \"            return (o)->o+1\",\n                        \"TestLambdaStatic1\");\n                Method m = cls.getDeclaredMethod(\"method\");\n                @SuppressWarnings(\"unchecked\")\n                Function1<Object, Object> f = (Function1<Object, Object>) m.invoke(null);\n                assertEquals(2, f.apply(1));\n        }\n\n        @Test\n        public void testLambdaStatic2() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import lt::lang::function::_\\n\" +\n                                \"class TestLambdaStatic2\\n\" +\n                                \"    static\\n\" +\n                                \"        method():Function1\\n\" +\n                                \"            i=1\\n\" +\n                                \"            return (o)->o+1+i\",\n                        \"TestLambdaStatic2\");\n                Method m = cls.getDeclaredMethod(\"method\");\n                @SuppressWarnings(\"unchecked\")\n                Function1<Object, Object> f = (Function1<Object, Object>) m.invoke(null);\n                assertEquals(3, f.apply(1));\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testLambdaStatic3() throws Throwable {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaStatic3\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            i=1\\n\" +\n                                \"            return (o)->o+1+i\",\n                        \"TestLambdaStatic3\");\n                Method m = cls.getDeclaredMethod(\"method\");\n                Function1 f = (Function1) m.invoke(null);\n                assertEquals(3, f.apply(1));\n        }\n\n        @Test\n        public void testLambdaLT1() throws Exception {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(\"\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"class TestLambdaLT\\n\" +\n                        \"    static\\n\" +\n                        \"        method():TestLambdaFunc\\n\" +\n                        \"            i=1\\n\" +\n                        \"            return (o)->o+1+i\"), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n\n                final byte[] b1 = list.get(\"TestLambdaLT\");\n                final byte[] b2 = list.get(\"TestLambdaLT$Latte$Lambda$0\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                if (name.equals(\"TestLambdaLT\")) {\n                                        return defineClass(name, b1, 0, b1.length);\n                                } else {\n                                        return defineClass(name, b2, 0, b2.length);\n                                }\n                        }\n                };\n\n                Class<?> TestLambdaLT = classLoader.loadClass(\"TestLambdaLT\");\n                Class<?> lambda = classLoader.loadClass(\"TestLambdaLT$Latte$Lambda$0\");\n\n                TestLambdaFunc func = (TestLambdaFunc) TestLambdaLT.getDeclaredMethod(\"method\").invoke(null);\n                assertEquals(3, func.apply(1));\n\n                assertEquals(2, lambda.getDeclaredFields().length);\n        }\n\n        @Test\n        public void testLambdaLT2() throws Exception {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(\"\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"class TestLambdaLT\\n\" +\n                        \"    method():TestLambdaFunc\\n\" +\n                        \"        i=1\\n\" +\n                        \"        return (o)->o+1+i\"), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n\n                final byte[] b1 = list.get(\"TestLambdaLT\");\n                final byte[] b2 = list.get(\"TestLambdaLT$Latte$Lambda$0\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                if (name.equals(\"TestLambdaLT\")) {\n                                        return defineClass(name, b1, 0, b1.length);\n                                } else {\n                                        return defineClass(name, b2, 0, b2.length);\n                                }\n                        }\n                };\n\n                Class<?> TestLambdaLT = classLoader.loadClass(\"TestLambdaLT\");\n                Class<?> lambda = classLoader.loadClass(\"TestLambdaLT$Latte$Lambda$0\");\n\n                TestLambdaFunc func = (TestLambdaFunc) TestLambdaLT.getDeclaredMethod(\"method\").invoke(TestLambdaLT.newInstance());\n                assertEquals(3, func.apply(1));\n\n                assertEquals(3, lambda.getDeclaredFields().length);\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testLambdaLT3() throws Throwable {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(\"\" +\n                        \"import lt::lang::function::_\\n\" +\n                        \"class TestLambdaLT\\n\" +\n                        \"    method():Function1\\n\" +\n                        \"        i=1\\n\" +\n                        \"        return (o)->o+1+i\"), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n\n                final byte[] b1 = list.get(\"TestLambdaLT\");\n                final byte[] b2 = list.get(\"TestLambdaLT$Latte$Lambda$0\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                if (name.equals(\"TestLambdaLT\")) {\n                                        return defineClass(name, b1, 0, b1.length);\n                                } else {\n                                        return defineClass(name, b2, 0, b2.length);\n                                }\n                        }\n                };\n\n                Class<?> TestLambdaLT = classLoader.loadClass(\"TestLambdaLT\");\n                Class<?> lambda = classLoader.loadClass(\"TestLambdaLT$Latte$Lambda$0\");\n\n                Function1 func = (Function1) TestLambdaLT.getDeclaredMethod(\"method\").invoke(TestLambdaLT.newInstance());\n                assertEquals(3, func.apply(1));\n\n                assertEquals(3, lambda.getDeclaredFields().length);\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testLambdaMultipleArguments() throws Exception {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(\"\" +\n                        \"class TestLambdaMultipleArguments\\n\" +\n                        \"    method() = (a,b,c)->a+b+c\"), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n\n                final byte[] b1 = list.get(\"TestLambdaMultipleArguments\");\n                final byte[] b2 = list.get(\"TestLambdaMultipleArguments$Latte$Lambda$0\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                if (name.equals(\"TestLambdaMultipleArguments\")) {\n                                        return defineClass(name, b1, 0, b1.length);\n                                } else {\n                                        return defineClass(name, b2, 0, b2.length);\n                                }\n                        }\n                };\n\n                Class<?> TestLambdaLT = classLoader.loadClass(\"TestLambdaMultipleArguments\");\n                Class<?> lambda = classLoader.loadClass(\"TestLambdaMultipleArguments$Latte$Lambda$0\");\n\n                Function3 func = (Function3) TestLambdaLT.getDeclaredMethod(\"method\").invoke(TestLambdaLT.newInstance());\n                assertEquals(6, func.apply(1, 2, 3));\n\n                assertEquals(3, lambda.getDeclaredFields().length);\n        }\n\n        @Test\n        public void testListRemove() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestInvokeInterface\\n\" +\n                                \"    static\\n\" +\n                                \"        def methodRemoveInt1(ls)\\n\" +\n                                \"            ls.remove(1)\\n\" +\n                                \"        def methodRemoveInteger1(ls)\\n\" +\n                                \"            ls.remove(Integer(1))\",\n                        \"TestInvokeInterface\");\n\n                List<Integer> list = new ArrayList<Integer>();\n                list.add(1);\n                list.add(2);\n                list.add(3);\n                Method methodRemoveInt1 = cls.getMethod(\"methodRemoveInt1\", Object.class);\n                methodRemoveInt1.invoke(null, list);\n                assertEquals(Arrays.asList(1, 3), list);\n\n                list.clear();\n                list.add(1);\n                list.add(2);\n                list.add(3);\n                Method methodRemoveInteger1 = cls.getMethod(\"methodRemoveInteger1\", Object.class);\n                methodRemoveInteger1.invoke(null, list);\n                assertEquals(Arrays.asList(2, 3), list);\n        }\n\n        @Test\n        public void testArrayAccess() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestArrayAccess\\n\" +\n                                \"    static\\n\" +\n                                \"        arr:[]String = ['test1','test2']\\n\" +\n                                \"        def method(i,o)\\n\" +\n                                \"            arr[i]=o\",\n                        \"TestArrayAccess\");\n                Field f = cls.getDeclaredField(\"arr\");\n                f.setAccessible(true);\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                method.invoke(null, 1, \"changed\");\n                String[] arr = (String[]) f.get(null);\n                assertEquals(\"test1\", arr[0]);\n                assertEquals(\"changed\", arr[1]);\n        }\n\n        @Test\n        public void testPrimitiveType() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestPrimitiveType\\n\" +\n                                \"    static\\n\" +\n                                \"        typeInt=type int\\n\" +\n                                \"        typeLong=type long\\n\" +\n                                \"        typeShort=type short\\n\" +\n                                \"        typeByte=type byte\\n\" +\n                                \"        typeChar=type char\\n\" +\n                                \"        typeBool=type bool\\n\" +\n                                \"        typeFloat=type float\\n\" +\n                                \"        typeDouble=type double\\n\" +\n                                \"        typeUnit=type Unit\",\n                        \"TestPrimitiveType\");\n                Field typeInt = cls.getDeclaredField(\"typeInt\");\n                typeInt.setAccessible(true);\n                Field typeLong = cls.getDeclaredField(\"typeLong\");\n                typeLong.setAccessible(true);\n                Field typeShort = cls.getDeclaredField(\"typeShort\");\n                typeShort.setAccessible(true);\n                Field typeByte = cls.getDeclaredField(\"typeByte\");\n                typeByte.setAccessible(true);\n                Field typeChar = cls.getDeclaredField(\"typeChar\");\n                typeChar.setAccessible(true);\n                Field typeBool = cls.getDeclaredField(\"typeBool\");\n                typeBool.setAccessible(true);\n                Field typeFloat = cls.getDeclaredField(\"typeFloat\");\n                typeFloat.setAccessible(true);\n                Field typeDouble = cls.getDeclaredField(\"typeDouble\");\n                typeDouble.setAccessible(true);\n                Field typeUnit = cls.getDeclaredField(\"typeUnit\");\n                typeUnit.setAccessible(true);\n\n                assertEquals(int.class, typeInt.get(null));\n                assertEquals(long.class, typeLong.get(null));\n                assertEquals(short.class, typeShort.get(null));\n                assertEquals(byte.class, typeByte.get(null));\n                assertEquals(char.class, typeChar.get(null));\n                assertEquals(boolean.class, typeBool.get(null));\n                assertEquals(float.class, typeFloat.get(null));\n                assertEquals(double.class, typeDouble.get(null));\n                assertEquals(void.class, typeUnit.get(null));\n        }\n\n        @Test\n        public void testThrowAnyObject() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestThrowAnyObject\\n\" +\n                                \"    static\\n\" +\n                                \"        def testThrow()\\n\" +\n                                \"            throw 'abc'\\n\" +\n                                \"        def testCatch(func)\\n\" +\n                                \"            try\\n\" +\n                                \"                func.apply()\\n\" +\n                                \"            catch e\\n\" +\n                                \"                return e\",\n                        \"TestThrowAnyObject\");\n                Method testThrow = cls.getMethod(\"testThrow\");\n                try {\n                        testThrow.invoke(null);\n                        fail();\n                } catch (InvocationTargetException in) {\n                        Wrapper w = (Wrapper) in.getCause();\n                        assertEquals(\"abc\", w.object);\n                }\n\n                Method testCatch = cls.getMethod(\"testCatch\", Object.class);\n                assertEquals(\"abc\", testCatch.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Wrapper(\"abc\");\n                        }\n                }));\n                assertEquals(1, testCatch.invoke(null, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Wrapper(1);\n                        }\n                }));\n        }\n\n        @Test\n        public void testForBreak() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestForBreak\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            for i in 1 to 10\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    break\\n\" +\n                                \"                sum+=i\\n\" +\n                                \"            return sum\",\n                        \"TestForBreak\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(21, method.invoke(null));\n        }\n\n        @Test\n        public void testForContinue() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestForContinue\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            for i in 1 to 10\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    continue\\n\" +\n                                \"                sum+=i\\n\" +\n                                \"            return sum\",\n                        \"TestForContinue\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(48, method.invoke(null));\n        }\n\n        @Test\n        public void testWhileBreak() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhileBreak\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            i=1\\n\" +\n                                \"            while i<=10\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    break\\n\" +\n                                \"                sum+=(i++)\\n\" +\n                                \"            return sum\",\n                        \"TestWhileBreak\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(21, method.invoke(null));\n        }\n\n        @Test\n        public void testWhileContinue() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhileContinue\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            i=1\\n\" +\n                                \"            while i<=10\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    ++i\\n\" +\n                                \"                    continue\\n\" +\n                                \"                sum+=(i++)\\n\" +\n                                \"            return sum\",\n                        \"TestWhileContinue\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(48, method.invoke(null));\n        }\n\n        @Test\n        public void testDoWhileBreak() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhileBreak\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            i=1\\n\" +\n                                \"            do\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    break\\n\" +\n                                \"                sum+=(i++)\\n\" +\n                                \"            while i<=10\\n\" +\n                                \"            return sum\",\n                        \"TestWhileBreak\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(21, method.invoke(null));\n        }\n\n        @Test\n        public void testDoWhileContinue() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestWhileContinue\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            sum=0\\n\" +\n                                \"            i=1\\n\" +\n                                \"            do\\n\" +\n                                \"                if i==7\\n\" +\n                                \"                    ++i\\n\" +\n                                \"                    continue\\n\" +\n                                \"                sum+=(i++)\\n\" +\n                                \"            while i<=10\\n\" +\n                                \"            return sum\",\n                        \"TestWhileContinue\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(48, method.invoke(null));\n        }\n\n        @Test\n        public void testForTryBreak() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestForTryBreak\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            n=0\\n\" +\n                                \"            for i in 1 to 10\\n\" +\n                                \"                try\\n\" +\n                                \"                    if i==3\\n\" +\n                                \"                        break\\n\" +\n                                \"                    n+=i\\n\" +\n                                \"                finally\\n\" +\n                                \"                    ++n\\n\" +\n                                \"            return n\",\n                        \"TestForTryBreak\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(6, method.invoke(null));\n        }\n\n        @Test\n        public void testConsParamUseField() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestConsParamUseField(i)\\n\" +\n                                \"    i=10\",\n                        \"TestConsParamUseField\");\n                Object o = cls.getConstructor(Object.class).newInstance(1);\n                Field i = cls.getDeclaredField(\"i\");\n                i.setAccessible(true);\n\n                assertEquals(10, i.get(o));\n        }\n\n        @Test\n        public void testMethodDefaultParam() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestMethodDefaultParam\\n\" +\n                                \"    def methodNonStatic(a,b=1)\\n\" +\n                                \"        return a+b\\n\" +\n                                \"    static\\n\" +\n                                \"        def methodStatic(a,b=1)\\n\" +\n                                \"            return a-b\",\n                        \"TestMethodDefaultParam\");\n                Object o = cls.newInstance();\n\n                assertEquals(3, cls.getMethod(\"methodNonStatic\", Object.class).invoke(o, 2));\n                assertEquals(3, cls.getMethod(\"methodNonStatic\", Object.class, Object.class).invoke(o, 2, 1));\n\n                assertEquals(1, cls.getMethod(\"methodStatic\", Object.class).invoke(null, 2));\n                assertEquals(1, cls.getMethod(\"methodStatic\", Object.class, Object.class).invoke(null, 2, 1));\n        }\n\n        @Test\n        public void testConcatOp() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestConcatOp\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b)\\n\" +\n                                \"            return a:::b\\n\" +\n                                \"        def method2()\\n\" +\n                                \"            return [\\\"a\\\",\\\"b\\\"]:::[\\\"c\\\"]\",\n                        \"TestConcatOp\");\n\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(\"ab\", method.invoke(null, \"a\", \"b\"));\n                assertEquals(\n                        Arrays.asList(1, 2, 3),\n                        method.invoke(null, Arrays.asList(1, 2), Collections.singletonList(3))\n                );\n                assertEquals(Arrays.asList(\"a\", \"b\", \"c\"), cls.getMethod(\"method2\").invoke(null));\n        }\n\n        @Test\n        public void testInvokeMethodWithoutPar() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeMethodWithoutPar\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)\\n\" +\n                                \"            return o.toString\",\n                        \"TestInvokeMethodWithoutPar\");\n\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(\"[]\", method.invoke(null, Collections.emptyList()));\n        }\n\n        @Test\n        public void testFunctionalInterfaces() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalInterfaces\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(list)\\n\" +\n                                \"            return list.map((e)->e.toString)\",\n                        \"TestFunctionalInterfaces\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(Arrays.asList(\"1\", \"2\", \"3\"), method.invoke(null, Arrays.asList(1, 2, 3)));\n        }\n\n        @Test\n        public void testImplicitArray() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestImplicitArray\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return (type TestImplicitArray).getMethod('method', [])\",\n                        \"TestImplicitArray\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(method, method.invoke(null));\n        }\n\n        @Test\n        public void testFunctionalAbstractClass() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalAbstractClass\\n\" +\n                                \"    m(c:lt::compiler::F)=c\\n\" +\n                                \"    def method()\\n\" +\n                                \"        return m((e)->e)\",\n                        \"TestFunctionalAbstractClass\");\n                Object TestFunctionalAbstractClass_inst = cls.newInstance();\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(TestFunctionalAbstractClass_inst);\n                assertTrue(o instanceof F);\n                F f = (F) o;\n                assertEquals(\"test\", f.func(\"test\"));\n        }\n\n        @Test\n        public void testInvokeDynamicThisAndStatic() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInvokeDynamicThisAndStatic\\n\" +\n                                \"    def m(list:java::util::List)\\n\" +\n                                \"        list add 1\\n\" +\n                                \"        return list\\n\" +\n                                \"    indyThis(ls)=m(ls)\\n\" +\n                                \"    static\\n\" +\n                                \"        def mm(list:java::util::List)\\n\" +\n                                \"            list add 0\\n\" +\n                                \"            return list\\n\" +\n                                \"        indyStatic(ls)=mm(ls)\",\n                        \"TestInvokeDynamicThisAndStatic\");\n                Object TestInvokeDynamicThisAndStatic_inst = cls.newInstance();\n                Method indyThis = cls.getMethod(\"indyThis\", Object.class);\n                List<Integer> list = new ArrayList<Integer>();\n                list.add(3);\n                list.add(2);\n                assertEquals(Arrays.asList(3, 2, 1), indyThis.invoke(TestInvokeDynamicThisAndStatic_inst, list));\n\n                Method indyStatic = cls.getMethod(\"indyStatic\", Object.class);\n                assertEquals(Arrays.asList(3, 2, 1, 0), indyStatic.invoke(null, list));\n        }\n\n        @Test\n        public void testAccessElementVia$_$() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestAccessElementVia$_$\\n\" +\n                                \"    static\\n\" +\n                                \"        method(list)=list._1\",\n                        \"TestAccessElementVia$_$\");\n\n                assertEquals(2, cls.getMethod(\"method\", Object.class).invoke(null, Arrays.asList(1, 2, 3)));\n        }\n\n        @Test\n        public void testInnerMethodRecursive() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInnerMethodRecursive\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int,b:int)\\n\" +\n                                \"            def gcd(i:int, j:int)\\n\" +\n                                \"                if j\\n\" +\n                                \"                    return gcd(j, i % j)\\n\" +\n                                \"                else\\n\" +\n                                \"                    return i\\n\" +\n                                \"            return gcd(a,b)\",\n                        \"TestInnerMethodRecursive\");\n\n                Method method = cls.getMethod(\"method\", int.class, int.class);\n                assertEquals(2, method.invoke(null, 8, 2));\n                assertEquals(1, method.invoke(null, 1, 2));\n        }\n\n        @Test\n        public void testDataClass() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"data class TestDataClass(a:int,b=1,c=2)\",\n                        \"TestDataClass\");\n\n                Constructor<?> con = cls.getConstructor(int.class, Object.class, Object.class);\n                Object instance = con.newInstance(3, 4, 5);\n                Constructor<?> con2 = cls.getConstructor(int.class);\n                Object instance2 = con2.newInstance(6);\n\n                Method toStringMethod = cls.getMethod(\"toString\");\n                assertEquals(\"TestDataClass(a=3, b=4, c=5)\", toStringMethod.invoke(instance));\n\n                Method hashCodeMethod = cls.getMethod(\"hashCode\");\n                assertEquals(12, hashCodeMethod.invoke(instance));\n\n                assertNotEquals(instance, instance2);\n                assertEquals(con.newInstance(3, 4, 5), instance);\n                assertEquals(con.newInstance(6, 1, 2), instance2);\n\n                Constructor<?> con3 = cls.getConstructor();\n                Object instance3 = con3.newInstance();\n                assertEquals(con.newInstance(0, 1, 2), instance3);\n\n                Method getA = cls.getMethod(\"getA\");\n                Method getB = cls.getMethod(\"getB\");\n                Method getC = cls.getMethod(\"getC\");\n                Method setA = cls.getMethod(\"setA\", int.class);\n                Method setB = cls.getMethod(\"setB\", Object.class);\n                Method setC = cls.getMethod(\"setC\", Object.class);\n\n                assertEquals(3, getA.invoke(instance));\n                assertEquals(4, getB.invoke(instance));\n                assertEquals(5, getC.invoke(instance));\n\n                setA.invoke(instance, 6);\n                setB.invoke(instance, 7);\n                setC.invoke(instance, 8);\n\n                assertEquals(6, getA.invoke(instance));\n                assertEquals(7, getB.invoke(instance));\n                assertEquals(8, getC.invoke(instance));\n        }\n\n        @Test\n        public void testConstructingDataClass() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"data class User(id:int, name)\\n\" +\n                                \"class TestConstructingDataClass\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=User(id=1, name='cass')\",\n                        \"TestConstructingDataClass\");\n                Method method = cls.getMethod(\"method\");\n                Object o = method.invoke(null);\n                Class<?> User = o.getClass();\n                assertEquals(\"User\", User.getName());\n\n                Method getId = User.getMethod(\"getId\");\n                assertEquals(1, getId.invoke(o));\n\n                Method getName = User.getMethod(\"getName\");\n                assertEquals(\"cass\", getName.invoke(o));\n        }\n\n        @Test\n        public void testGetterSetter() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class User\\n\" +\n                                \"    a=1\\n\" +\n                                \"    b='cass'\\n\" +\n                                \"    getId()=a\\n\" +\n                                \"    setId(id)=a=id\\n\" +\n                                \"    getName()=b\\n\" +\n                                \"    setName(name)=b=name\\n\" +\n                                \"class TestGetterSetter\\n\" +\n                                \"    static\\n\" +\n                                \"        getUser()=User()\\n\" +\n                                \"        testIdGetter(u)=u.id\\n\" +\n                                \"        testNameGetter(u)=u.name\\n\" +\n                                \"        testIdSetter(u)=u.id=2\\n\" +\n                                \"        testNameSetter(u)=u.name='abc'\",\n                        \"TestGetterSetter\");\n                Method testIdGetter = cls.getMethod(\"testIdGetter\", Object.class);\n                Method testNameGetter = cls.getMethod(\"testNameGetter\", Object.class);\n\n                Method getUser = cls.getMethod(\"getUser\");\n                Object u = getUser.invoke(null);\n\n                assertEquals(1, testIdGetter.invoke(null, u));\n                assertEquals(\"cass\", testNameGetter.invoke(null, u));\n\n                Method testIdSetter = cls.getMethod(\"testIdSetter\", Object.class);\n                testIdSetter.invoke(null, u);\n                assertEquals(2, testIdGetter.invoke(null, u));\n\n                Method testNameSetter = cls.getMethod(\"testNameSetter\", Object.class);\n                testNameSetter.invoke(null, u);\n                assertEquals(\"abc\", testNameGetter.invoke(null, u));\n        }\n\n        @Test\n        public void testAllKindsOfAnnotations() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import lt::compiler::_\\n\" +\n                                \"@lt::compiler::TestAllKindsOfAnnos(\\n\" +\n                                \"    str='theStr'\\n\" +\n                                \"    strArr=['a','b']\\n\" +\n                                \"    i=1\\n\" +\n                                \"    iArr=[1,2]\\n\" +\n                                \"    s=1\\n\" +\n                                \"    sArr=[1,2]\\n\" +\n                                \"    b=1\\n\" +\n                                \"    bArr=[1,2]\\n\" +\n                                \"    c='a'\\n\" +\n                                \"    cArr=['a','b']\\n\" +\n                                \"    bo=true\\n\" +\n                                \"    boArr=[true,false]\\n\" +\n                                \"    l=1\\n\" +\n                                \"    lArr=[1,2]\\n\" +\n                                \"    f=1\\n\" +\n                                \"    fArr=[1,2]\\n\" +\n                                \"    d=1\\n\" +\n                                \"    dArr=[1,2]\\n\" +\n                                \"    cls=type Class\\n\" +\n                                \"    clsArr=[type Class,type Object]\\n\" +\n                                \"    en=lt::compiler::semantic::SModifier.PUBLIC\\n\" +\n                                \"    enArr=[\\n\" +\n                                \"        lt::compiler::semantic::SModifier.PUBLIC\\n\" +\n                                \"        lt::compiler::semantic::SModifier.PRIVATE\" +\n                                \"    ]\\n\" +\n                                \"    anno=@MyAnno(str='a')\\n\" +\n                                \"    annos=[@MyAnno(str='b', i=200),@MyAnno(str='c')]\\n\" +\n                                \")\\n\" +\n                                \"class TestAllKindsOfAnnotations\",\n                        \"TestAllKindsOfAnnotations\");\n                TestAllKindsOfAnnos test = cls.getAnnotation(TestAllKindsOfAnnos.class);\n                assertEquals(\"theStr\", test.str());\n                assertArrayEquals(new String[]{\"a\", \"b\"}, test.strArr());\n                assertEquals(1, test.i());\n                assertArrayEquals(new int[]{1, 2}, test.iArr());\n                assertEquals((short) 1, test.s());\n                assertArrayEquals(new short[]{1, 2}, test.sArr());\n                assertEquals((byte) 1, test.b());\n                assertArrayEquals(new byte[]{1, 2}, test.bArr());\n                assertEquals('a', test.c());\n                assertArrayEquals(new char[]{'a', 'b'}, test.cArr());\n                assertEquals(true, test.bo());\n                assertArrayEquals(new boolean[]{true, false}, test.boArr());\n                assertEquals((long) 1, test.l());\n                assertArrayEquals(new long[]{1, 2}, test.lArr());\n                assertEquals((float) 1, test.f(), 0);\n                assertArrayEquals(new float[]{1, 2}, test.fArr(), 0);\n                assertEquals((double) 1, test.d(), 0);\n                assertArrayEquals(new double[]{1, 2}, test.dArr(), 0);\n                assertEquals(Class.class, test.cls());\n                assertArrayEquals(new Class[]{Class.class, Object.class}, test.clsArr());\n                assertEquals(SModifier.PUBLIC, test.en());\n                assertArrayEquals(new SModifier[]{SModifier.PUBLIC, SModifier.PRIVATE}, test.enArr());\n                MyAnno myAnno = test.anno();\n                assertEquals(\"a\", myAnno.str());\n                MyAnno[] myAnnos = test.annos();\n                assertEquals(2, myAnnos.length);\n                assertEquals(\"b\", myAnnos[0].str());\n                assertEquals(200, myAnnos[0].i());\n                assertEquals(\"c\", myAnnos[1].str());\n        }\n\n        @Test\n        public void testAnnotationAnnotation() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import lt::compiler::_\\n\" +\n                                \"@AnnoAnno(myAnno=@MyAnno(str='a'))\\n\" +\n                                \"class TestAnnotationAnnotation\",\n                        \"TestAnnotationAnnotation\");\n                AnnoAnno annoAnno = cls.getAnnotation(AnnoAnno.class);\n                assertEquals(\"a\", annoAnno.myAnno().str());\n        }\n\n        @Test\n        public void testAssignOp() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"data class X(x)\\n\" +\n                                \"    assign(x)=x+1\\n\" +\n                                \"class TestAssignOp\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return X():=1\\n\",\n                        \"TestAssignOp\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(2, method.invoke(null));\n        }\n\n        @Test\n        public void testIndexAccessAssign() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestIndexAccessAssign\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(arr)\\n\" +\n                                \"            i=0\\n\" +\n                                \"            a=0\\n\" +\n                                \"            while i<arr.size\\n\" +\n                                \"                a+=arr[i++]\\n\" +\n                                \"            def m()\\n\" +\n                                \"                return 1+1\\n\" +\n                                \"            return a\"\n                        , \"TestIndexAccessAssign\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(3, method.invoke(null, Arrays.asList(1, 2)));\n        }\n\n        @Test\n        public void testDynamicConstruct() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"import java::util::LinkedList\\n\" +\n                                \"class TestDynamicConstruct\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            a=[1]\\n\" +\n                                \"            return LinkedList(a)\"\n                        , \"TestDynamicConstruct\"\n                );\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Collections.singletonList(1), method.invoke(null));\n        }\n\n        @Test\n        public void testFun() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"fun TestFun(o):lt::compiler::F\\n\" +\n                                \"    return o+1\"\n                        , \"TestFun\"\n                );\n                F f = (F) cls.newInstance();\n                assertEquals(3, f.func(2));\n        }\n\n        @Test\n        public void testFunAnno() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"fun TestFunAnno(o)\\n\" +\n                                \"    return o+1\"\n                        , \"TestFunAnno\");\n                assertTrue(cls.isAnnotationPresent(LatteFun.class));\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testGetFunWithTypeName() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"fun TheFun(o)\\n\" +\n                                \"    return o + 1\\n\" +\n                                \"class TestGetFunWithTypeName\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=TheFun\"\n                        , \"TestGetFunWithTypeName\");\n                Method method = cls.getMethod(\"method\");\n                Function1 f1 = (Function1) method.invoke(null);\n                assertEquals(3, f1.apply(2));\n        }\n\n        @Test\n        public void testCallFunWithTypeName() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"fun TheFun(o)\\n\" +\n                                \"    return o+1\\n\" +\n                                \"class TestCallFunWithTypeName\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=TheFun(3)\"\n                        , \"TestCallFunWithTypeName\"\n                );\n                Method method = cls.getMethod(\"method\");\n                assertEquals(4, method.invoke(null));\n        }\n\n        @Test\n        public void testTypeAccess() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class A\\n\" +\n                                \"    static\\n\" +\n                                \"        a=1\\n\" +\n                                \"    b = 2\\n\" +\n                                \"    static\\n\" +\n                                \"        m1()=A + 1\\n\" +\n                                \"        m2()=A() + 1\\n\" +\n                                \"        m3()=A.a + 1\\n\" +\n                                \"        m4()=A().b + 1\\n\" +\n                                \"        m5()=a + 1\\n\" +\n                                \"\\n\" +\n                                \"    add(o)=10+o\"\n                        , \"A\");\n                Method m1 = cls.getMethod(\"m1\");\n                Method m2 = cls.getMethod(\"m2\");\n                Method m3 = cls.getMethod(\"m3\");\n                Method m4 = cls.getMethod(\"m4\");\n                Method m5 = cls.getMethod(\"m5\");\n\n                assertEquals(11, m1.invoke(null));\n                assertEquals(11, m2.invoke(null));\n                assertEquals(2, m3.invoke(null));\n                assertEquals(3, m4.invoke(null));\n                assertEquals(2, m5.invoke(null));\n        }\n\n        @Test\n        public void testRequire() throws Throwable {\n                ScriptCompiler scriptCompiler = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n                ScriptCompiler.Script script = scriptCompiler.compile(\n                        \"script\",\n                        \"return require('cp:test_require'+'.lts')\"\n                );\n                Object res = script.run().getResult();\n                assertEquals(2, res);\n        }\n\n        @Test\n        public void test3DArray() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class Test3DArray\\n\" +\n                                \"    static\\n\" +\n                                \"        get(o,i,j,k)=o[i,j,k]\\n\" +\n                                \"        set(o,i,j,k,v)=o[i,j,k]=v\"\n                        , \"Test3DArray\"\n                );\n\n                int[][][] arr = {\n                        {\n                                {1, 2, 3},\n                                {4, 5}\n                        },\n                        {\n                                {6, 7, 8, 9},\n                                {},\n                                {10}\n                        },\n                        {\n                                {},\n                                {11, 12}\n                        }\n                };\n\n                Method get = cls.getMethod(\"get\", Object.class, Object.class, Object.class, Object.class);\n                assertEquals(5, get.invoke(null, arr, 0, 1, 1));\n                assertEquals(10, get.invoke(null, arr, 1, 2, 0));\n                assertEquals(11, get.invoke(null, arr, 2, 1, 0));\n                assertEquals(7, get.invoke(null, arr, 1, 0, 1));\n                Method set = cls.getMethod(\"set\", Object.class, Object.class, Object.class, Object.class, Object.class);\n                set.invoke(null, arr, 0, 1, 1, 13);\n                assertEquals(13, arr[0][1][1]);\n\n                set.invoke(null, arr, 1, 2, 0, 14);\n                assertEquals(14, arr[1][2][0]);\n\n                set.invoke(null, arr, 2, 1, 0, 15);\n                assertEquals(15, arr[2][1][0]);\n\n                set.invoke(null, arr, 1, 0, 1, 16);\n                assertEquals(16, arr[1][0][1]);\n\n                Object[][] arr2 = {\n                        {Arrays.asList(1, 2, 3)}\n                };\n\n                assertEquals(2, get.invoke(null, arr2, 0, 0, 1));\n                set.invoke(null, arr2, 0, 0, 1, 10);\n                assertEquals(10, get.invoke(null, arr2, 0, 0, 1));\n        }\n\n        @Test\n        public void testHandlingVoidValues() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestHandlingVoidValues\\n\" +\n                                \"    println().a\\n\" + // get field\n                                \"    println().invoke()\\n\" + // method\n                                \"    println() + 1\\n\" + // operator\n                                \"    invoke(println())\\n\" + // arg\n                                \"    1 + println()\" // operator right\n                        , \"TestHandlingVoidValues\"\n                );\n                cls.getConstructors();\n                // compiling pass\n        }\n\n        @Test\n        public void testKeyNew() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class C(public i:int=1)\\n\" +\n                                \"\" +\n                                \"class TestKeyNew\\n\" +\n                                \"    static\\n\" +\n                                \"        test1()=new C\\n\" +\n                                \"        test2()=new C(2)\\n\" +\n                                \"        test3(o)=new C(o)\"\n                        , \"TestKeyNew\");\n                Method test1 = cls.getMethod(\"test1\");\n                Object test1obj = test1.invoke(null);\n                assertEquals(\"C\", test1obj.getClass().getName());\n                Field i = test1obj.getClass().getField(\"i\");\n                assertEquals(1, i.getInt(test1obj));\n\n                Method test2 = cls.getMethod(\"test2\");\n                Object test2obj = test2.invoke(null);\n                assertEquals(2, i.getInt(test2obj));\n\n                Method test3 = cls.getMethod(\"test3\", Object.class);\n                Object test3obj = test3.invoke(null, 3);\n                assertEquals(3, i.getInt(test3obj));\n        }\n\n        @Test\n        public void testGeneratorSpec() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestGeneratorSpec\\n\" +\n                                \"    static\\n\" +\n                                \"        method1()=#js\\n\" +\n                                \"            a=1\\n\" +\n                                \"            b=2\\n\" +\n                                \"        method2(i)=(\\n\" +\n                                \"            #js\\n\" +\n                                \"                a=1\\n\" +\n                                \"        ).charAt(i)\"\n                        , \"TestGeneratorSpec\");\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(\"var a = 1;\\nvar b = 2;\", method1.invoke(null));\n\n                Method method2 = cls.getMethod(\"method2\", Object.class);\n                assertEquals('v', method2.invoke(null, 0));\n                assertEquals('a', method2.invoke(null, 1));\n                assertEquals('r', method2.invoke(null, 2));\n        }\n\n        @Test\n        public void testFunctionalObject() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalObject\\n\" +\n                                \"    static\\n\" +\n                                \"        b = ()->2\\n\" +\n                                \"        def method1()\\n\" +\n                                \"            a = ()->1\\n\" +\n                                \"            return a()\\n\" +\n                                \"        def method2()\\n\" +\n                                \"            return b()\\n\" +\n                                \"    c = ()->3\\n\" +\n                                \"    def method3()\\n\" +\n                                \"        return c()\"\n                        , \"TestFunctionalObject\");\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(1, method1.invoke(null));\n\n                Method method2 = cls.getMethod(\"method2\");\n                assertEquals(2, method2.invoke(null));\n\n                Method method3 = cls.getMethod(\"method3\");\n                assertEquals(3, method3.invoke(cls.newInstance()));\n        }\n\n        @Test\n        public void testFunctionalObjectFromOtherClass() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalObjectFromOtherClass\\n\" +\n                                \"    static\\n\" +\n                                \"        method1()=(new Functions).a()\\n\" +\n                                \"        method2()=Functions.b()\\n\" +\n                                \"class Functions\\n\" +\n                                \"    public a = ()->1\\n\" +\n                                \"    static\\n\" +\n                                \"        public b = ()->2\"\n                        , \"TestFunctionalObjectFromOtherClass\");\n\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(1, method1.invoke(null));\n\n                Method method2 = cls.getMethod(\"method2\");\n                assertEquals(2, method2.invoke(null));\n        }\n\n        @Test\n        public void testFunctionalObjectWithArgs() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalObject\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(n)\\n\" +\n                                \"            a = (x,y)->x+1+y\\n\" +\n                                \"            return a(n,3)\"\n                        , \"TestFunctionalObject\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(6, method.invoke(null, 2));\n        }\n\n        @Test\n        public void testFunctionalObjectUpgradeVersion() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestFunctionalObjectUpgradeVersion\\n\" +\n                                \"    static\\n\" +\n                                \"        def method1(n)\\n\" +\n                                \"            a = (x,y)->(z)->x+y+z\\n\" +\n                                \"            return a(n,3)(2)\\n\" +\n                                \"        def method2(o)\\n\" +\n                                \"            return o[0](3)\"\n                        , \"TestFunctionalObjectUpgradeVersion\");\n                Method method1 = cls.getMethod(\"method1\", Object.class);\n                assertEquals(7, method1.invoke(null, 2));\n                Method method2 = cls.getMethod(\"method2\", Object.class);\n                assertEquals(4, method2.invoke(null,\n                        (Object) new Function1[]{new Function1<Object, Integer>() {\n                                @Override\n                                public Object apply(Integer o) throws Exception {\n                                        return o + 1;\n                                }\n                        }}));\n        }\n\n        @Test\n        public void testOperatorAssign() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestOperatorAssign\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            i = 2\\n\" +\n                                \"            i <<= 3\\n\" +\n                                \"            return i\"\n                        , \"TestOperatorAssign\");\n                Method method1 = cls.getMethod(\"method\");\n                assertEquals(16, method1.invoke(null));\n        }\n\n        @Test\n        public void testInternalSyntaxLambda() throws Exception {\n                Class<?> cls = retrieveClass(\n                        \"\" +\n                                \"class TestInternalSyntaxLambda\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            return T()\\n\" +\n                                \"                return 1 + 2\\n\" +\n                                \"class T\\n\" +\n                                \"    apply(o)=o(this)\"\n                        , \"TestInternalSyntaxLambda\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(3, method.invoke(null));\n        }\n\n        public static class ASTGen implements SourceGenerator {\n                private Statement stmt;\n\n                @Override\n                public void init(List<Statement> ast, SemanticProcessor processor, SemanticScope scope, LineCol lineCol, ErrorManager err) {\n                        this.stmt = ast.get(0);\n                }\n\n                @Override\n                public Object generate() throws SyntaxException {\n                        return new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                (Expression) stmt,\n                                LineCol.SYNTHETIC\n                        );\n                }\n\n                @Override\n                public int resultType() {\n                        return EXPRESSION;\n                }\n        }\n\n        @Test\n        public void testGenerator_AST() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestGenerator_AST\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=#\" + ASTGen.class.getName().replace(\".\", \"::\") + \"\\n\" +\n                                \"            123\"\n                        , \"TestGenerator_AST\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(124, method.invoke(null));\n        }\n\n        @Test\n        public void testGenerator_Serialize() throws Throwable {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestGenerator_Serialize\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=#ast\\n\" +\n                                \"            1+2\"\n                        , \"TestGenerator_Serialize\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Collections.singletonList(new TwoVariableOperation(\"+\",\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC)), method.invoke(null));\n        }\n\n        @Test\n        public void testGenerator_in_one_line() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestGenerator_in_one_line\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=#ast#1+2\"\n                        , \"TestGenerator_in_one_line\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Collections.singletonList(new TwoVariableOperation(\"+\",\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC)), method.invoke(null));\n        }\n\n        @Test\n        public void testArrayFieldIndex() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestArrayFieldIndex\\n\" +\n                                \"    static\\n\" +\n                                \"        method(o)=o._1\"\n                        , \"TestArrayFieldIndex\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(2, method.invoke(null, (Object) new int[]{1, 2, 3}));\n        }\n\n        @Test\n        public void testStringExpression() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class TestStringExpression {\\n\" +\n                                \"  static {\\n\" +\n                                \"    test1()=\\\"abc\\\"\\n\" + // normal string\n                                \"    test2()=\\\"abc${1}\\\"\\n\" + // exp at the end\n                                \"    test3()=\\\"${1}abc\\\"\\n\" + // exp at the start\n                                \"    test4()=\\\"ab${1}c\\\"\\n\" + // exp at the middle\n                                \"    test5()=\\\"ab${test1()}c\\\"\\n\" + // exp outside\n                                \"    def test6() {\\n\" +\n                                \"      \\\"ab${x=1}c\\\"\\n\" +\n                                \"      return x\\n\" +\n                                \"    }\\n\" + // exp define a variable\n                                \"  }\\n\" +\n                                \"}\"\n                        , \"TestStringExpression\");\n                Method test = cls.getMethod(\"test1\");\n                assertEquals(\"abc\", test.invoke(null));\n                test = cls.getMethod(\"test2\");\n                assertEquals(\"abc1\", test.invoke(null));\n                test = cls.getMethod(\"test3\");\n                assertEquals(\"1abc\", test.invoke(null));\n                test = cls.getMethod(\"test4\");\n                assertEquals(\"ab1c\", test.invoke(null));\n                test = cls.getMethod(\"test5\");\n                assertEquals(\"ababcc\", test.invoke(null));\n                test = cls.getMethod(\"test6\");\n                assertEquals(1, test.invoke(null));\n        }\n\n        @Test\n        public void testOrReturnsObject() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestOrReturnsObject\\n\" +\n                                \"    static\" +\n                                \"        method(a, b, c)=a || b || c\"\n                        , \"TestOrReturnsObject\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n                assertEquals(10, method.invoke(null, 10, 20, 30));\n                assertEquals(20, method.invoke(null, 0, 20, 30));\n                assertEquals(30, method.invoke(null, 0, 0, 30));\n        }\n\n        @Test\n        public void testCompileMultipleIndexAccess() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestCompileMultipleIndexAccess\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            arr:[][]int = [[1,2],[3,4]]\\n\" +\n                                \"            return arr[1,0]\"\n                        , \"TestCompileMultipleIndexAccess\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(3, method.invoke(null));\n        }\n\n        @Test\n        public void testArrayMap() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestArrayMap\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=[\\\"a\\\":1, \\\"b\\\":2]\"\n                        , \"TestArrayMap\");\n                Method method = cls.getMethod(\"method\");\n                LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>();\n                map.put(\"a\", 1);\n                map.put(\"b\", 2);\n                assertEquals(map, method.invoke(null));\n        }\n\n        @Test\n        public void testArrayMap2() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class TestArrayMap2 {\\n\" +\n                                \"    static {\\n\" +\n                                \"        method()=[\\\"a\\\":1, \\\"b\\\":2]\\n\" +\n                                \"    }\\n\" +\n                                \"}\"\n                        , \"TestArrayMap2\");\n                Method method = cls.getMethod(\"method\");\n                LinkedHashMap<String, Integer> map = new LinkedHashMap<String, Integer>();\n                map.put(\"a\", 1);\n                map.put(\"b\", 2);\n                assertEquals(map, method.invoke(null));\n        }\n\n        @Test\n        public void testAutoReturn() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestAutoReturn\\n\" +\n                                \"    static\\n\" +\n                                \"        def method()\\n\" +\n                                \"            1\"\n                        , \"TestAutoReturn\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(1, method.invoke(null));\n        }\n\n        @Test\n        public void testAutoReturnWithType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestAutoReturnWithType\\n\" +\n                                \"    static\\n\" +\n                                \"        method1():int\\n\" +\n                                \"            1\\n\" +\n                                \"        method2():Unit\\n\" +\n                                \"            Object()\"\n                        , \"TestAutoReturnWithType\");\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(1, method1.invoke(null));\n\n                Method method2 = cls.getMethod(\"method2\");\n                assertEquals(null, method2.invoke(null));\n        }\n\n        @Test\n        public void testAutoReturnIf() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class TestAutoReturnIf {\\n\" +\n                                \"    static {\\n\" +\n                                \"        def method(a) {\\n\" +\n                                \"            if a { 1 } else { 2 }\\n\" +\n                                \"        }\\n\" +\n                                \"    }\\n\" +\n                                \"}\"\n                        , \"TestAutoReturnIf\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(1, method.invoke(null, true));\n                assertEquals(2, method.invoke(null, false));\n        }\n\n        @Test\n        public void testBraceLambda() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class TestBraceLambda {\\n\" +\n                                \"    static {\\n\" +\n                                \"        def method() {\\n\" +\n                                \"            x = 1\\n\" +\n                                \"            f = ()->2\\n\" +\n                                \"            x + f()\\n\" +\n                                \"        }\\n\" +\n                                \"    }\\n\" +\n                                \"}\"\n                        , \"TestBraceLambda\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(3, method.invoke(null));\n        }\n\n        @Test\n        public void testBraceInternalSyntaxLambda() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class TestBraceInternalSyntaxLambda {\\n\" +\n                                \"    static {\\n\" +\n                                \"        method()= [1, 2, 3, 4].filter{it > 2}.map{it + 1}\" +\n                                \"    }\\n\" +\n                                \"}\"\n                        , \"TestBraceInternalSyntaxLambda\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(4, 5), method.invoke(null));\n        }\n\n        @Test\n        public void testIndentInternalSyntaxLambda() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestIndentInternalSyntaxLambda\\n\" +\n                                \"    static\\n\" +\n                                \"        method()=\\n\" +\n                                \"        [1, 2, 3, 4].filter{it > 2}.map{it + 1}\"\n                        , \"TestIndentInternalSyntaxLambda\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(4, 5), method.invoke(null));\n        }\n\n        @Test\n        public void testInnerMethodChangeParam() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethodChangeParam\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a)\\n\" +\n                                \"            def inner()\\n\" +\n                                \"                a=2\\n\" +\n                                \"            inner()\\n\" +\n                                \"            return a\"\n                        , \"TestInnerMethodChangeParam\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(2, method.invoke(null, new Object()));\n        }\n\n        @Test\n        public void testInnerMethodContainRealType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInnerMethodContainRealType\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a:int)\\n\" +\n                                \"            def inner()\\n\" +\n                                \"                a=Object()\\n\" +\n                                \"            inner()\\n\" +\n                                \"            return a\"\n                        , \"TestInnerMethodContainRealType\");\n                Method method = cls.getMethod(\"method\", int.class);\n                try {\n                        method.invoke(null, 1);\n                        fail();\n                } catch (Exception e) {\n                        if (e instanceof InvocationTargetException) {\n                                InvocationTargetException i = (InvocationTargetException) e;\n                                Throwable t = i.getTargetException();\n                                if (!(t instanceof ClassCastException)) {\n                                        fail();\n                                } // cast object to int fail\n                        } else {\n                                fail();\n                        }\n                }\n        }\n\n        @Test\n        public void testLambdaCallSelf() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaCallSelf\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(x)\\n\" +\n                                \"            var count = 0\\n\" +\n                                \"            var f = a->\\n\" +\n                                \"                if a > 2\\n\" +\n                                \"                    return null\\n\" +\n                                \"                count ++\\n\" +\n                                \"                f(a+1)\\n\" +\n                                \"            f(x)\\n\" +\n                                \"            return count\"\n                        , \"TestLambdaCallSelf\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(3, method.invoke(null, 0));\n        }\n\n        @Test\n        public void testLambdaCallSelfVal() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaCallSelfVal\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(x)\\n\" +\n                                \"            var count = 0\\n\" +\n                                \"            val f = a->\\n\" +\n                                \"                if a > 2\\n\" +\n                                \"                    return null\\n\" +\n                                \"                count ++\\n\" +\n                                \"                f(a+1)\\n\" +\n                                \"            f(x)\\n\" +\n                                \"            return count\"\n                        , \"TestLambdaCallSelfVal\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(2, method.invoke(null, 1));\n        }\n\n        @Test\n        public void testLambdaCallSelfField() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaCallSelfField\\n\" +\n                                \"    static\\n\" +\n                                \"        count = 0\\n\" +\n                                \"        f = a->\\n\" +\n                                \"            if a > 2\\n\" +\n                                \"                return null\\n\" +\n                                \"            count ++\\n\" +\n                                \"            f(a+1)\\n\" +\n                                \"        def method(x)\\n\" +\n                                \"            f(x)\\n\" +\n                                \"            return count\"\n                        , \"TestLambdaCallSelfField\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(4, method.invoke(null, -1));\n        }\n\n        @Test\n        public void testMethodWithoutPar() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                        \"class TestMethodWithoutPar\\n\" +\n                        \"    def m\\n\" +\n                        \"    def n\\n\" +\n                        \"        ...\\n\" +\n                        \"    def o:int\\n\" +\n                        \"    def p:int\\n\" +\n                        \"        ...\\n\" +\n                        \"    def q=1\\n\" +\n                        \"    def r:int=1\", \"TestMethodWithoutPar\");\n                Method m = cls.getMethod(\"m\");\n                Method n = cls.getMethod(\"n\");\n                Method o = cls.getMethod(\"o\");\n                Method p = cls.getMethod(\"p\");\n                Method q = cls.getMethod(\"q\");\n                Method r = cls.getMethod(\"r\");\n\n                Function1<Void, Method> noParam = new Function1<Void, Method>() {\n                        @Override\n                        public Void apply(Method method) throws Exception {\n                                assertEquals(0, method.getParameterTypes().length);\n                                return null;\n                        }\n                };\n                noParam.apply(m);\n                noParam.apply(n);\n                noParam.apply(o);\n                noParam.apply(p);\n                noParam.apply(q);\n                noParam.apply(r);\n\n                Function1<Void, Method> returnInt = new Function1<Void, Method>() {\n                        @Override\n                        public Void apply(Method method) throws Exception {\n                                assertEquals(int.class, method.getReturnType());\n                                return null;\n                        }\n                };\n                returnInt.apply(o);\n                returnInt.apply(p);\n                returnInt.apply(r);\n        }\n\n        @Test\n        public void testNotNull() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNotNull\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(nonnull a, nonnull b)= a + b\"\n                        , \"TestNotNull\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(3, method.invoke(null, 1, 2));\n                try {\n                        method.invoke(null, null, 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        method.invoke(null, 1, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        method.invoke(null, null, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        method.invoke(null, Unit.get(), 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 1, Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, Unit.get(), Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testNotEmpty() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNotEmpty\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(nonempty a, nonempty b)= a + b\"\n                        , \"TestNotEmpty\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                assertEquals(3, method.invoke(null, 1, 2));\n                try {\n                        method.invoke(null, 0, 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 1, 0);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 0, 0);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testNotNullCons() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNotNullCons(nonnull a, nonnull b)\"\n                        , \"TestNotNullCons\");\n                Constructor<?> cons = cls.getConstructor(Object.class, Object.class);\n                cons.newInstance(1, 2); // pass\n                try {\n                        cons.newInstance(null, 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        cons.newInstance(1, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        cons.newInstance(null, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        cons.newInstance(Unit.get(), 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        cons.newInstance(1, Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        cons.newInstance(Unit.get(), Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testNotEmptyCons() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNotEmptyCons(nonempty a, nonempty b)\"\n                        , \"TestNotEmptyCons\");\n                Constructor<?> cons = cls.getConstructor(Object.class, Object.class);\n                cons.newInstance(1, 2); // pass\n                try {\n                        cons.newInstance(0, 1);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        cons.newInstance(1, 0);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        cons.newInstance(0, 0);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testNullEmptyCapability() throws Exception {\n                retrieveClass(\"\" +\n                                \"fun TestNullEmptyCapability(nonnull a, nonempty b)\\n\" +\n                                \"    (nonnull c, nonempty d)->a+b+c+d\\n\" +\n                                \"    def xx(nonnull e, nonempty f)=1\"\n                        , \"TestNullEmptyCapability\");\n        }\n\n        @Test\n        public void testObject() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"object TestObject\\n\" +\n                                \"    public a=1\\n\" +\n                                \"    def method=2\\n\" +\n                                \"    static\\n\" +\n                                \"        public val b=3\\n\" +\n                                \"        def staticMethod=4\"\n                        , \"TestObject\");\n                Constructor<?> cons = cls.getDeclaredConstructor();\n                assertTrue(Modifier.isPrivate(cons.getModifiers()));\n                Field singletonInstance = cls.getField(\"singletonInstance\");\n                Object o = singletonInstance.get(null);\n\n                Field a = cls.getField(\"a\");\n                Method method = cls.getMethod(\"method\");\n                Field b = cls.getField(\"b\");\n                Method staticMethod = cls.getMethod(\"staticMethod\");\n                assertEquals(1, a.get(o));\n                assertEquals(2, method.invoke(o));\n                assertEquals(3, b.get(null));\n                assertEquals(4, staticMethod.invoke(null));\n        }\n\n        @Test\n        public void testConstructSingletonObject() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"object Test\\n\" +\n                                \"class TestConstructSingletonObject\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=Test\\n\" +\n                                \"        def getCls = type Test\"\n                        , \"TestConstructSingletonObject\");\n                Method method = cls.getMethod(\"method\");\n\n                Object o1 = method.invoke(null);\n\n                Method getCls = cls.getMethod(\"getCls\");\n                Class<?> Test = (Class<?>) getCls.invoke(null);\n                Field f = Test.getField(\"singletonInstance\");\n                Object o = f.get(null);\n\n                assertTrue(o1 == o);\n        }\n\n        @Test\n        public void testVarNonnull() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestVarNonnull\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a, b)\\n\" +\n                                \"            nonnull c = a\\n\" +\n                                \"            nonnull d = b\"\n                        , \"TestVarNonnull\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                method.invoke(null, 1, 2);\n\n                try {\n                        method.invoke(null, null, 2);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        method.invoke(null, 1, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof NullPointerException);\n                }\n                try {\n                        method.invoke(null, Unit.get(), 2);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 1, Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testVarNonempty() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestVarNonempty\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a, b)\\n\" +\n                                \"            nonempty c = a\\n\" +\n                                \"            nonempty d = b\"\n                        , \"TestVarNonempty\");\n                Method method = cls.getMethod(\"method\", Object.class, Object.class);\n                method.invoke(null, 1, 2);\n\n                try {\n                        method.invoke(null, null, 2);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 1, null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, Unit.get(), 2);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n                try {\n                        method.invoke(null, 1, Unit.get());\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getTargetException() instanceof IllegalArgumentException);\n                }\n        }\n\n        @Test\n        public void testLambdaGetSelf() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaGetSelf\\n\" +\n                                \"    static\\n\" +\n                                \"        method1()=()->$\\n\" +\n                                \"    method2()=()->$\"\n                        , \"TestLambdaGetSelf\");\n                Method method1 = cls.getMethod(\"method1\");\n                Function0 lambda1 = (Function0) method1.invoke(null);\n                Class<?> lambdaClass1 = lambda1.getClass();\n                assertEquals(2, lambdaClass1.getDeclaredFields().length);\n\n                Field field_self = lambdaClass1.getField(\"self\");\n                assertTrue(lambda1 == field_self.get(lambda1));\n                assertTrue(lambda1 == lambda1.apply());\n\n                Method method2 = cls.getMethod(\"method2\");\n                Object o = cls.newInstance();\n                Function0 lambda2 = (Function0) method2.invoke(o);\n                Class<?> lambdaClass2 = lambda2.getClass();\n\n                assertEquals(3, lambdaClass2.getDeclaredFields().length);\n\n                field_self = lambdaClass2.getField(\"self\");\n\n                assertTrue(lambda2 == field_self.get(lambda2));\n                assertTrue(lambda2 == lambda2.apply());\n        }\n\n        @Test\n        public void testLambdaSelfName() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaSelfName\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            $=1\\n\" +\n                                \"            ()->$\"\n                        , \"TestLambdaSelfName\");\n                Method method = cls.getMethod(\"method\");\n                Function0 func = (Function0) method.invoke(null);\n                assertTrue(func == func.apply());\n        }\n\n        @Test\n        public void testLambdaSelfChange() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestLambdaSelfChange\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            invoke(()->$ defaultMethod)\\n\" +\n                                \"        def invoke(f:F)=f()\\n\" +\n                                \"@FunctionalAbstractClass\\n\" +\n                                \"abstract class F\\n\" +\n                                \"    abstract method()=...\\n\" +\n                                \"    def defaultMethod=1\"\n                        , \"TestLambdaSelfChange\");\n                Method method = cls.getMethod(\"method\");\n                Object res = method.invoke(null);\n                assertEquals(1, res);\n        }\n\n        @Test\n        public void testInvokeWithNameParams() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestInvokeWithNameParams\\n\" +\n                                \"    static\\n\" +\n                                \"        def method = open('file', \\\"w\\\", encoding='utf-8')\\n\" +\n                                \"class open(file, mode)\\n\" +\n                                \"    public encoding\"\n                        , \"TestInvokeWithNameParams\");\n                Method method = cls.getMethod(\"method\");\n                Object result = method.invoke(null);\n                Field field_file = result.getClass().getDeclaredField(\"file\");\n                field_file.setAccessible(true);\n                Field field_mode = result.getClass().getDeclaredField(\"mode\");\n                field_mode.setAccessible(true);\n                Field field_encoding = result.getClass().getDeclaredField(\"encoding\");\n\n                assertEquals(\"file\", field_file.get(result));\n                assertEquals(\"w\", field_mode.get(result));\n                assertEquals(\"utf-8\", field_encoding.get(result));\n        }\n\n        @Test\n        public void testIndentBrace() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"/// :scanner-indent\\n\" +\n                                \"class TestIndentBrace\\n\" +\n                                \"    static\\n\" +\n                                \"        def method1 = {}\\n\" +\n                                \"        def method2 {1}\\n\" +\n                                \"        def method3 = [\\\"a\\\":1, \\\"b\\\":2]\\n\" +\n                                \"        def method4(a,b) = (if a > b {1} else {2})\\n\" +\n                                \"        def method5 {\\n\" +\n                                \"            [   \\\"a\\\": 1\\n\" +\n                                \"                \\\"b\\\": 2]\\n\" +\n                                \"        }\"\n                        , \"TestIndentBrace\");\n                Method method1 = cls.getMethod(\"method1\");\n                Method method2 = cls.getMethod(\"method2\");\n                Method method3 = cls.getMethod(\"method3\");\n                Method method4 = cls.getMethod(\"method4\", Object.class, Object.class);\n                Method method5 = cls.getMethod(\"method5\");\n\n                assertEquals(new LinkedHashMap<Object, Object>(), method1.invoke(null));\n                assertEquals(1, method2.invoke(null));\n                Map<Object, Object> map = new LinkedHashMap<Object, Object>() {{\n                        put(\"a\", 1);\n                        put(\"b\", 2);\n                }};\n                assertEquals(map, method3.invoke(null));\n                assertEquals(1, method4.invoke(null, 3, 2));\n                assertEquals(2, method4.invoke(null, 2, 3));\n                assertEquals(map, method5.invoke(null));\n        }\n\n        @Test\n        public void testMapCast() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestMapCast\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            ['hello': 'world', 'foo': 'bar'] as Bean\\n\" +\n                                \"data class Bean(hello, foo)\"\n                        , \"TestMapCast\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"Bean(hello=world, foo=bar)\", method.invoke(null).toString());\n        }\n\n        @Test\n        public void testMapCastInvokeMethod() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestMapCastInvokeMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=invoke(1, ['foo':'bar'])\\n\" +\n                                \"        private invoke(i, x:Bean)=[i,x]\\n\" +\n                                \"data class Bean(foo)\"\n                        , \"TestMapCastInvokeMethod\");\n                Method method = cls.getMethod(\"method\");\n                List list = (List) method.invoke(null);\n                Object i = list.get(0);\n                Object x = list.get(1);\n                assertEquals(1, i);\n                assertEquals(\"Bean(foo=bar)\", x.toString());\n        }\n\n        @Test\n        public void testMapCastInvokeConstructor() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestMapCastInvokeConstructor\\n\" +\n                                \"    static\\n\" +\n                                \"        def method = Container(1, ['foo':'bar'])\\n\" +\n                                \"data class Bean(foo)\\n\" +\n                                \"data class Container(i, x:Bean)\"\n                        , \"TestMapCastInvokeConstructor\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"Container(i=1, x=Bean(foo=bar))\", method.invoke(null).toString());\n        }\n\n        @Test\n        public void testListCast() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestListCast\\n\" +\n                                \"    static\\n\" +\n                                \"        def method:Bean=[1,2,3]\\n\" +\n                                \"class Bean\\n\" +\n                                \"    public list = []\\n\" +\n                                \"    def add(o)=list.add(o)\"\n                        , \"TestListCast\");\n                Method method = cls.getMethod(\"method\");\n                Object bean = method.invoke(null);\n                assertEquals(\"Bean\", bean.getClass().getName());\n                List list = (List) bean.getClass().getField(\"list\").get(bean);\n                assertEquals(Arrays.asList(1, 2, 3), list);\n        }\n\n        @Test\n        public void testListCastInvokeMethod() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestListCastInvokeMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=invoke(10, [1,2,3])\\n\" +\n                                \"        private invoke(i,b:Bean)=[i,b]\\n\" +\n                                \"data class Bean\\n\" +\n                                \"    public list = []\\n\" +\n                                \"    def add(o)=list.add(o)\"\n                        , \"TestListCastInvokeMethod\");\n                Method method = cls.getMethod(\"method\");\n                List resultPair = (List) method.invoke(null);\n                Object result = resultPair.get(1);\n                List list = (List) result.getClass().getField(\"list\").get(result);\n                assertEquals(Arrays.asList(1, 2, 3), list);\n                assertEquals(10, resultPair.get(0));\n        }\n\n        @Test\n        public void testListCastInvokeConstructor() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestListCastInvokeMethod\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=Container(10, [1,2,3])\\n\" +\n                                \"data class Bean\\n\" +\n                                \"    public list = []\\n\" +\n                                \"    def add(o)=list.add(o)\\n\" +\n                                \"data class Container(i, x:Bean)\"\n                        , \"TestListCastInvokeMethod\");\n                Method method = cls.getMethod(\"method\");\n                Object result = method.invoke(null);\n                Object i = result.getClass().getMethod(\"getI\").invoke(result);\n                assertEquals(10, i);\n\n                Object bean = result.getClass().getMethod(\"getX\").invoke(result);\n                List list = (List) bean.getClass().getField(\"list\").get(bean);\n                assertEquals(Arrays.asList(1, 2, 3), list);\n        }\n\n        @Test\n        public void testUnitReturnValue() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestUnitReturnValue\\n\" +\n                                \"    static\\n\" +\n                                \"        public field1 = 0\\n\" +\n                                \"        private def x()\\n\" +\n                                \"            field1 = 1\\n\" +\n                                \"        def method1:Unit\\n\" +\n                                \"            return x()\\n\" +\n                                \"        def method2\\n\" +\n                                \"            return\"\n                        , \"TestUnitReturnValue\");\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(void.class, method1.getReturnType());\n                assertEquals(null, method1.invoke(null));\n                Field field1 = cls.getField(\"field1\");\n                assertEquals(1, field1.get(null));\n\n                Method method2 = cls.getMethod(\"method2\");\n                assertEquals(Unit.get(), method2.invoke(null));\n        }\n\n        @Test\n        public void testNotType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNotType\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o) = o not type Integer\"\n                        , \"TestNotType\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(true, method.invoke(null, 1.2));\n                assertEquals(false, method.invoke(null, 1));\n        }\n\n        @Test\n        public void testImportImplicit() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import implicit XX\\n\" +\n                                \"class TestImportImplicit\\n\" +\n                                \"    static\\n\" +\n                                \"        def method= + 1 s\\n\" +\n                                \"class X(x:Integer)\\n\" +\n                                \"    def s = x + ' s'\\n\" +\n                                \"implicit object XX\\n\" +\n                                \"    implicit def cast(x:Integer):X=X(x)\"\n                        , \"TestImportImplicit\");\n\n                assertTrue(cls.isAnnotationPresent(ImplicitImports.class));\n                ImplicitImports implicitImports = cls.getAnnotation(ImplicitImports.class);\n                Class<?>[] classes = implicitImports.implicitImports();\n                assertEquals(5, classes.length); // X and 8 primitives\n                assertEquals(\"XX\", classes[0].getName());\n                assertEquals(\"1 s\", cls.getMethod(\"method\").invoke(null));\n        }\n\n        @Test\n        public void testImportImplicit2() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import implicit TestImportImplicit2\\n\" +\n                                \"implicit object TestImportImplicit2\"\n                        , \"TestImportImplicit2\");\n                assertTrue(cls.isAnnotationPresent(ImplicitImports.class));\n                assertEquals(4, cls.getAnnotation(ImplicitImports.class).implicitImports().length);\n        }\n\n        @Test\n        public void testImportImplicit3() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import implicit XX\\n\" +\n                                \"class TestImportImplicit3\\n\" +\n                                \"    static\\n\" +\n                                \"        def method= Integer(1) as X\\n\" +\n                                \"class X(x:Integer)\\n\" +\n                                \"    def s = x + ' s'\\n\" +\n                                \"implicit object XX\\n\" +\n                                \"    implicit def cast(x:Integer):X=X(x)\"\n                        , \"TestImportImplicit3\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"X\", method.invoke(null).getClass().getName());\n        }\n\n        @Test\n        public void testAccessInnerClass() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import java::util::Map\\n\" +\n                                \"class TestAccessInnerClass\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=type Map.Entry\"\n                        , \"TestAccessInnerClass\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Map.Entry.class, method.invoke(null));\n        }\n\n        @Test\n        public void testDestruct() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestruct\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            res = X(a,b) <- [1,2]\\n\" +\n                                \"            return [res, a,b]\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\"\n                        , \"TestDestruct\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(true, 1, 2), method.invoke(null));\n        }\n\n        @Test\n        public void testDestructIf() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructIf\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)\\n\" +\n                                \"            if X(a,b) <- o\\n\" +\n                                \"                return [a,b]\\n\" +\n                                \"            return null\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\"\n                        , \"TestDestructIf\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                List ls = (List) method.invoke(null, Arrays.asList(1, 2));\n                assertEquals(Arrays.asList(1, 2), ls);\n                ls = (List) method.invoke(null, Collections.singletonList(1));\n                assertNull(ls);\n                ls = (List) method.invoke(null, Arrays.asList(1, 2, 3));\n                assertNull(ls);\n        }\n\n        @Test\n        public void testDestructClassField() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructClassField\\n\" +\n                                \"    X(a,b)<-[1,2]\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\\n\"\n                        , \"TestDestructClassField\");\n                Object o = cls.newInstance();\n                Field aField = cls.getDeclaredField(\"a\");\n                aField.setAccessible(true);\n                Field bField = cls.getDeclaredField(\"b\");\n                bField.setAccessible(true);\n                assertEquals(1, aField.get(o));\n                assertEquals(2, bField.get(o));\n        }\n\n        @Test\n        public void testDestructClassStatic() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructClassStatic\\n\" +\n                                \"    static\\n\" +\n                                \"        X(a,b)<-[1,2]\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\\n\"\n                        , \"TestDestructClassStatic\");\n                Field aField = cls.getDeclaredField(\"a\");\n                aField.setAccessible(true);\n                Field bField = cls.getDeclaredField(\"b\");\n                bField.setAccessible(true);\n                assertEquals(1, aField.get(null));\n                assertEquals(2, bField.get(null));\n        }\n\n        @Test\n        public void testDestructInterfaceField() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"interface TestDestructInterfaceField\\n\" +\n                                \"    X(a,b)<-[1,2]\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\\n\"\n                        , \"TestDestructInterfaceField\");\n                Field aField = cls.getDeclaredField(\"a\");\n                aField.setAccessible(true);\n                Field bField = cls.getDeclaredField(\"b\");\n                bField.setAccessible(true);\n                assertEquals(1, aField.get(null));\n                assertEquals(2, bField.get(null));\n        }\n\n        @Test\n        public void testDestructInterfaceStatic() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"interface TestDestructInterfaceStatic\\n\" +\n                                \"    static\\n\" +\n                                \"        X(a,b)<-[1,2]\\n\" +\n                                \"class X\\n\" +\n                                \"    static unapply(ls)=ls\\n\"\n                        , \"TestDestructInterfaceStatic\");\n                Field aField = cls.getDeclaredField(\"a\");\n                aField.setAccessible(true);\n                Field bField = cls.getDeclaredField(\"b\");\n                bField.setAccessible(true);\n                assertEquals(1, aField.get(null));\n                assertEquals(2, bField.get(null));\n        }\n\n        @Test\n        public void testDestructDataClass() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructDataClass\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            val bean = Bean(1,2 as long,'c',4 as double)\\n\" +\n                                \"            Bean(a,b,c,d) <- bean\\n\" +\n                                \"            [a,b,c,d]\\n\" +\n                                \"data class Bean(a,b,c,d)\"\n                        , \"TestDestructDataClass\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(\n                        1, 2L, 'c', 4d\n                ), method.invoke(null));\n        }\n\n        @Test\n        public void testDestructWithoutType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructWithoutType\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            val bean = Bean(1,2 as long, 'c', 4 as double)\\n\" +\n                                \"            (a,b,c,d) <- bean\\n\" +\n                                \"            [a,b,c,d]\\n\" +\n                                \"data class Bean(a,b,c,d)\"\n                        , \"TestDestructWithoutType\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(\n                        1, 2L, 'c', 4d\n                ), method.invoke(null));\n        }\n\n        @Test\n        public void testDestructModifiers() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructModifiers\\n\" +\n                                \"    static\\n\" +\n                                \"        val (f1) <- Bean(1)\\n\" +\n                                \"        var (f2) <- Bean(2)\\n\" +\n                                \"    val (f3) <- Bean(3)\\n\" +\n                                \"    var (f4) <- Bean(4)\\n\" +\n                                \"data class Bean(x)\"\n                        , \"TestDestructModifiers\");\n                Field f1 = cls.getDeclaredField(\"f1\");\n                Field f2 = cls.getDeclaredField(\"f2\");\n                assertTrue(Modifier.isFinal(f1.getModifiers()));\n                assertFalse(Modifier.isFinal(f2.getModifiers()));\n                f1.setAccessible(true);\n                f2.setAccessible(true);\n                assertEquals(1, f1.get(null));\n                assertEquals(2, f2.get(null));\n\n                Field f3 = cls.getDeclaredField(\"f3\");\n                Field f4 = cls.getDeclaredField(\"f4\");\n                assertTrue(Modifier.isFinal(f3.getModifiers()));\n                assertFalse(Modifier.isFinal(f4.getModifiers()));\n                f3.setAccessible(true);\n                f4.setAccessible(true);\n                Object o = cls.newInstance();\n                assertEquals(3, f3.get(o));\n                assertEquals(4, f4.get(o));\n        }\n\n        @Test\n        public void testDestructModifiers2() throws Exception {\n                try {\n                        retrieveClass(\"\" +\n                                        \"class TestDestructModifiers2\\n\" +\n                                        \"    static\\n\" +\n                                        \"        def method\\n\" +\n                                        \"            val (f1) <- Bean(1)\\n\" +\n                                        \"            f1 = 2\\n\" +\n                                        \"data class Bean(x)\"\n                                , \"TestDestructModifiers2\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n\n                retrieveClass(\"\" +\n                                \"class TestDestructModifiers2\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            var (f1) <- Bean(1)\\n\" +\n                                \"            f1 = 2\\n\" +\n                                \"data class Bean(x)\"\n                        , \"TestDestructModifiers2\");\n        }\n\n        @Test\n        public void testDestructAnnos() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import lt::compiler::_\\n\" +\n                                \"class TestDestructAnnos\\n\" +\n                                \"    @MyAnno\\n\" +\n                                \"    (f1) <- Bean(1)\\n\" +\n                                \"data class Bean(x)\"\n                        , \"TestDestructAnnos\");\n                Field f1 = cls.getDeclaredField(\"f1\");\n                MyAnno anno = f1.getAnnotation(MyAnno.class);\n                assertNotNull(anno);\n        }\n\n        @Test\n        public void testSimplePatternMatching() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestSimplePatternMatching\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o) = o match\\n\" +\n                                \"            case _:java::util::List => 'type ' + o\\n\" +\n                                \"            case 2 => 'value'\\n\" +\n                                \"            case x:String => 'define ' + x\\n\" +\n                                \"            case _ => 'default'\"\n                        , \"TestSimplePatternMatching\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(\"type [1, 2, 3]\", method.invoke(null, Arrays.asList(1, 2, 3)));\n                assertEquals(\"value\", method.invoke(null, 2));\n                assertEquals(\"define test\", method.invoke(null, \"test\"));\n                assertEquals(\"default\", method.invoke(null, 1));\n        }\n\n        @Test\n        public void testDestructPatternMatching() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDestructPatternMatching\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o) = o match\\n\" +\n                                \"            case A(a,b,c) => [a,b,c]\\n\" +\n                                \"            case B(a,b:Integer) => [a,b]\\n\" +\n                                \"        def getClassA = type A\\n\" +\n                                \"        def getClassB = type B\\n\" +\n                                \"data class A(a,b,c)\\n\" +\n                                \"data class B(a,b)\"\n                        , \"TestDestructPatternMatching\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                Method getClassA = cls.getMethod(\"getClassA\");\n                Class<?> clsA = (Class<?>) getClassA.invoke(null);\n                assertEquals(Arrays.asList(1, 2, 3), method.invoke(null, clsA.getConstructor(Object.class, Object.class, Object.class).newInstance(1, 2, 3)));\n\n                Method getClassB = cls.getMethod(\"getClassB\");\n                Class<?> clsB = (Class<?>) getClassB.invoke(null);\n                assertEquals(Arrays.asList(1, 2), method.invoke(null, clsB.getConstructor(Object.class, Object.class).newInstance(1, 2)));\n        }\n\n        @Test\n        public void testComplexPatternMatching() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestComplexPatternMatching\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            val beanA = A(1,\\\"a\\\", B([], [\\\"x\\\" : \\\"y\\\"], A(9,8,7)))\\n\" +\n                                \"            beanA match\\n\" +\n                                \"                case A(1,b:String,B(_:java::util::List, c, A(_,_:Integer,d))) =>\\n\" +\n                                \"                    [b,c,d]\\n\" +\n                                \"data class A(a,b,c)\\n\" +\n                                \"data class B(a,b,c)\"\n                        , \"TestComplexPatternMatching\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(\"a\", Collections.singletonMap(\"x\", \"y\"), 7), method.invoke(null));\n        }\n\n        @Test\n        public void testStringRegex() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestStringRegex\\n\" +\n                                \"    static\\n\" +\n                                \"        def method1 = 'abc'.r\\n\" +\n                                \"        def method2 = 'a'.r\"\n                        , \"TestStringRegex\");\n                Method method1 = cls.getMethod(\"method1\");\n                assertEquals(\"abc\", ((Pattern) method1.invoke(null)).pattern());\n                Method method2 = cls.getMethod(\"method2\");\n                assertEquals(\"a\", ((Pattern) method2.invoke(null)).pattern());\n        }\n\n        @Test\n        public void testNumberLiteralCastToBool() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNumberLiteralCastToBool\\n\" +\n                                \"    static\\n\" +\n                                \"        def numberToBool1 = 1 as bool\\n\" +\n                                \"        def numberToBool2 = 1.1 as bool\\n\" +\n                                \"        def numberToBool3 = 1 as Boolean\\n\" +\n                                \"        def numberToBool4 = 1.1 as Boolean\\n\" +\n                                \"        def numberToBool5 = 0 as bool\\n\" +\n                                \"        def numberToBool6 = 0.0 as bool\\n\" +\n                                \"        def numberToBool7 = 0 as Boolean\\n\" +\n                                \"        def numberToBool8 = 0.0 as Boolean\\n\"\n                        , \"TestNumberLiteralCastToBool\");\n                Method method = cls.getMethod(\"numberToBool1\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool2\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool3\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool4\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool5\");\n                assertEquals(false, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool6\");\n                assertEquals(false, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool7\");\n                assertEquals(false, method.invoke(null));\n\n                method = cls.getMethod(\"numberToBool8\");\n                assertEquals(false, method.invoke(null));\n        }\n\n        @Test\n        public void testStringLiteralCastToBool() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestStringLiteralCastToBool\\n\" +\n                                \"    static\\n\" +\n                                \"        def stringToBool1 = 'a' as bool\\n\" +\n                                \"        def stringToBool2 = \\\"a\\\" as bool\\n\" +\n                                \"        def stringToBool3 = \\\"\\\" as bool\\n\" +\n                                \"        def stringToBool4 = 'a' as Boolean\\n\" +\n                                \"        def stringToBool5 = \\\"a\\\" as Boolean\\n\" +\n                                \"        def stringToBool6 = \\\"\\\" as Boolean\"\n                        , \"TestStringLiteralCastToBool\");\n\n                Method method = cls.getMethod(\"stringToBool1\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"stringToBool2\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"stringToBool3\");\n                assertEquals(false, method.invoke(null));\n\n                method = cls.getMethod(\"stringToBool4\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"stringToBool5\");\n                assertEquals(true, method.invoke(null));\n\n                method = cls.getMethod(\"stringToBool6\");\n                assertEquals(false, method.invoke(null));\n        }\n\n        @Test\n        public void testCharCastToNumber() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestCharCastToNumber\\n\" +\n                                \"    static\\n\" +\n                                \"        def method1 = 'a' as int\\n\" +\n                                \"        def method2 = 'a' as Integer\\n\" +\n                                \"        def method3 = 'a' as long\\n\" +\n                                \"        def method4 = 'a' as Long\\n\" +\n                                \"        def method5 = 'a' as float\\n\" +\n                                \"        def method6 = 'a' as Float\\n\" +\n                                \"        def method7 = 'a' as double\\n\" +\n                                \"        def method8 = 'a' as Double\\n\" +\n                                \"        def method9 = 'a' as byte\\n\" +\n                                \"        def method10 = 'a' as Byte\\n\" +\n                                \"        def method11 = 'a' as short\\n\" +\n                                \"        def method12 = 'a' as Short\\n\" +\n                                \"        def method13 = 97 as char\\n\" +\n                                \"        def method14 = 97 as Character\"\n                        , \"TestCharCastToNumber\");\n\n                Method method = cls.getMethod(\"method1\");\n                assertEquals(97, method.invoke(null));\n\n                method = cls.getMethod(\"method2\");\n                assertEquals(97, method.invoke(null));\n\n                method = cls.getMethod(\"method3\");\n                assertEquals(97L, method.invoke(null));\n\n                method = cls.getMethod(\"method4\");\n                assertEquals(97L, method.invoke(null));\n\n                method = cls.getMethod(\"method5\");\n                assertEquals(97f, method.invoke(null));\n\n                method = cls.getMethod(\"method6\");\n                assertEquals(97f, method.invoke(null));\n\n                method = cls.getMethod(\"method7\");\n                assertEquals(97d, method.invoke(null));\n\n                method = cls.getMethod(\"method8\");\n                assertEquals(97d, method.invoke(null));\n\n                method = cls.getMethod(\"method9\");\n                assertEquals((byte) 97, method.invoke(null));\n\n                method = cls.getMethod(\"method10\");\n                assertEquals((byte) 97, method.invoke(null));\n\n                method = cls.getMethod(\"method11\");\n                assertEquals((short) 97, method.invoke(null));\n\n                method = cls.getMethod(\"method12\");\n                assertEquals((short) 97, method.invoke(null));\n\n                method = cls.getMethod(\"method13\");\n                assertEquals('a', method.invoke(null));\n\n                method = cls.getMethod(\"method14\");\n                assertEquals('a', method.invoke(null));\n        }\n\n        @Test\n        public void testImportStaticAnno() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import java::util::Collections._\\n\" +\n                                \"class TestImportStaticAnno\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            list = [1,3,2]\\n\" +\n                                \"            sort(list)\\n\" +\n                                \"            list\"\n                        , \"TestImportStaticAnno\");\n                StaticImports si = cls.getAnnotation(StaticImports.class);\n                assertEquals(2, si.staticImports().length);\n                Method method = cls.getMethod(\"method\");\n                assertEquals(Arrays.asList(1, 2, 3), method.invoke(null));\n        }\n\n        @Test\n        public void testAnnotationType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"annotation TestAnnotationType\\n\" +\n                                \"    a:int = 1\"\n                        , \"TestAnnotationType\");\n                assertTrue(cls.isAnnotation());\n                cls.getMethod(\"a\");\n        }\n\n        @Test\n        public void testDefineAnnotationPresent() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"annotation A\\n\" +\n                                \"    a:int = 1\\n\" +\n                                \"    b:long\\n\" +\n                                \"@A(b=1)\\n\" +\n                                \"class TestDefineAnnotationPresent\\n\"\n                        , \"TestDefineAnnotationPresent\");\n                Annotation[] annotations = cls.getAnnotations();\n                assertEquals(3, annotations.length);\n                Annotation annotation = null;\n                for (Annotation a : annotations) {\n                        if (a.getClass().getInterfaces()[0].getName().equals(\"A\")) {\n                                annotation = a;\n                                break;\n                        }\n                }\n                if (annotation == null) {\n                        fail(\"annotation should not be null\");\n                }\n                Method a = annotation.getClass().getMethod(\"a\");\n                Method b = annotation.getClass().getMethod(\"b\");\n                assertEquals(1, a.invoke(annotation));\n                assertEquals(1L, b.invoke(annotation));\n        }\n\n        @Test\n        public void testPatternMatchingWithIf() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestPatternMatchingWithIf\\n\" +\n                                \"    static\\n\" +\n                                \"        def getClassA = type A\\n\" +\n                                \"        def method(o) = o match\\n\" +\n                                \"            case A(a,b) if a > b => 1\\n\" +\n                                \"            case A(a,b) if a < b => 2\\n\" +\n                                \"            case _ => 3\\n\" +\n                                \"data class A(a,b)\"\n                        , \"TestPatternMatchingWithIf\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                Method getClassA = cls.getMethod(\"getClassA\");\n                Class<?> classA = (Class<?>) getClassA.invoke(null);\n                Constructor<?> cons = classA.getConstructor(Object.class, Object.class);\n\n                Object a1 = cons.newInstance(2, 1);\n                Object a2 = cons.newInstance(1, 2);\n                Object a3 = cons.newInstance(1, 1);\n\n                assertEquals(1, method.invoke(null, a1));\n                assertEquals(2, method.invoke(null, a2));\n                assertEquals(3, method.invoke(null, a3));\n        }\n\n        @Test\n        public void testNullAddString() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestNullAddString\\n\" +\n                                \"    static\\n\" +\n                                \"        def method=null + 'abc'\"\n                        , \"TestNullAddString\");\n                assertEquals(\"nullabc\", cls.getMethod(\"method\").invoke(null));\n\n                cls = retrieveClass(\"\" +\n                                \"class TestNullAddString2\\n\" +\n                                \"    static\\n\" +\n                                \"        def add(i:int)=i\\n\" +\n                                \"        def method1 = .add 'abc'\\n\" +\n                                \"        def method2\\n\" +\n                                \"            o:X = null\\n\" +\n                                \"            o + 'abc'\\n\" +\n                                \"class X\"\n                        , \"TestNullAddString2\");\n                try {\n                        cls.getMethod(\"method1\").invoke(null);\n                        fail();\n                } catch (InvocationTargetException ignore) {\n                        assertTrue(ignore.getTargetException() instanceof LtRuntimeException);\n                }\n                assertEquals(\"nullabc\", cls.getMethod(\"method2\").invoke(null));\n        }\n\n        @Test\n        public void testClone() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestClone\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)=o.clone()\\n\" +\n                                \"        def getX(a)=X(a)\\n\" +\n                                \"data class X(a)\"\n                        , \"TestClone\");\n                Method getX = cls.getMethod(\"getX\", Object.class);\n                Method method = cls.getMethod(\"method\", Object.class);\n                Object x = getX.invoke(null, 1);\n                Object y = method.invoke(null, x);\n                assertFalse(x == y);\n                assertTrue(x.equals(y));\n        }\n\n        @Test\n        public void testSerialize() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import java::io::_\\n\" +\n                                \"class TestSerialize\\n\" +\n                                \"    static\\n\" +\n                                \"        def method\\n\" +\n                                \"            baos = ByteArrayOutputStream()\\n\" +\n                                \"            ObjectOutputStream(baos).writeObject(X(1))\\n\" +\n                                \"            bytes = baos.toByteArray()\\n\" +\n                                \"            lt::LatteObjectOutputStream((type TestSerialize).classLoader, ByteArrayInputStream(bytes)).readObject()\\n\" +\n                                \"data class X(a)\"\n                        , \"TestSerialize\");\n                Method method = cls.getMethod(\"method\");\n                assertEquals(\"X(a=1)\", method.invoke(null).toString());\n        }\n\n        @Test\n        public void testArrayAsArg() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import java::util::_\\n\" +\n                                \"class TestArrayAsArg\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(o)=Arrays.asList(o)\"\n                        , \"TestArrayAsArg\");\n                Method method = cls.getMethod(\"method\", Object.class);\n                assertEquals(Arrays.asList(1, 2, 3), method.invoke(null, (Object) new Object[]{1, 2, 3}));\n        }\n\n        @Test\n        public void testStringIndexAccess() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestStringIndexAccess\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(s:String, index:int)=s[index]\\n\"\n                        , \"TestStringIndexAccess\");\n                Method method = cls.getMethod(\"method\", String.class, int.class);\n                assertEquals('h', method.invoke(null, \"helloworld\", 0));\n                assertEquals('w', method.invoke(null, \"helloworld\", 5));\n        }\n\n        @Test\n        public void testTakeOnlyUsedVariablesInInnerMethods() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestTakeOnlyUsedVariablesInInnerMethods\\n\" +\n                                \"  static\\n\" +\n                                \"    def method(a:int)\\n\" +\n                                \"      b:String = 'abc'\\n\" +\n                                \"      c:double = 4.0\\n\" +\n                                \"      def inner(d:long)\\n\" +\n                                \"        a += 2\\n\" +\n                                \"        return b + 'de'\\n\" +\n                                \"      inner(1 as long) + a\"\n                        , \"TestTakeOnlyUsedVariablesInInnerMethods\");\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(\"abcde5\", method.invoke(null, 3));\n                // only capture two variables\n                cls.getDeclaredMethod(\"inner$Latte$InnerMethod$0\", Pointer.class, Pointer.class, long.class);\n        }\n\n        @Test\n        public void testTakeOnlyUsedVariablesInInnerMethods2() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestTakeOnlyUsedVariablesInInnerMethods\\n\" +\n                                \"    def method(a:int)\\n\" +\n                                \"      b:String = 'abc'\\n\" +\n                                \"      c:double = 4.0\\n\" +\n                                \"      def inner(d:long)\\n\" +\n                                \"        a += 2\\n\" +\n                                \"        return b + 'de'\\n\" +\n                                \"      inner(1 as long) + a\"\n                        , \"TestTakeOnlyUsedVariablesInInnerMethods\");\n                Object inst = cls.newInstance();\n                Method method = cls.getMethod(\"method\", int.class);\n                assertEquals(\"abcde5\", method.invoke(inst, 3));\n                // only capture two variables\n                cls.getDeclaredMethod(\"inner$Latte$InnerMethod$0\", Pointer.class, Pointer.class, long.class);\n        }\n\n        @Test\n        public void testUTF8Variable() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class 测试UTF8变量\\n\" +\n                                \"  static\\n\" +\n                                \"    字段 = 'world'\\n\" +\n                                \"    def 方法()\\n\" +\n                                \"      你好='hello' + \\\" \\\" + 字段\\n\" +\n                                \"      return 你好\"\n                        , \"测试UTF8变量\");\n                Method method = cls.getMethod(\"方法\");\n                assertEquals(\"hello world\", method.invoke(null));\n        }\n\n        @Test\n        public void testSimpleGeneric() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class A<:T:>\\n\" +\n                                \"  def m(t:T):T=t\\n\" +\n                                \"class TestSimpleGeneric\\n\" +\n                                \"  static\\n\" +\n                                \"    def m1()\\n\" +\n                                \"      a = A<:int:>\\n\" +\n                                \"      return a.m(123)\\n\" +\n                                \"    def m2()\\n\" +\n                                \"      a = A<:int:>()\\n\" +\n                                \"      return a.m(789)\\n\" +\n                                \"    def m3() = A<:int:>().m(101)\\n\" +\n                                \"    def t1 = type A<:int:>\\n\" +\n                                \"    def t2 = type A<:Integer:>\\n\"\n                        , \"TestSimpleGeneric\");\n                Method m1 = cls.getMethod(\"m1\");\n                Method m2 = cls.getMethod(\"m2\");\n                Method m3 = cls.getMethod(\"m3\");\n                assertEquals(123, m1.invoke(null));\n                assertEquals(789, m2.invoke(null));\n                assertEquals(101, m3.invoke(null));\n                Method t1 = cls.getMethod(\"t1\");\n                Method t2 = cls.getMethod(\"t2\");\n                Class<?> c1 = (Class<?>) t1.invoke(null);\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\", c1.getName());\n                Method genericMethod1 = c1.getMethod(\"m\", int.class);\n                assertEquals(int.class, genericMethod1.getReturnType());\n                Class<?> c2 = (Class<?>) t2.invoke(null);\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_Integer\", c2.getName());\n                Method genericMethod2 = c2.getMethod(\"m\", Integer.class);\n                assertEquals(Integer.class, genericMethod2.getReturnType());\n        }\n\n        @Test\n        public void testSimpleObjectGeneric() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"object A<:T:>\\n\" +\n                                \"  def m(t:T):T=t\\n\" +\n                                \"class TestSimpleObjectGeneric\\n\" +\n                                \"  static\\n\" +\n                                \"    def m1()\\n\" +\n                                \"      a = A<:int:>\\n\" +\n                                \"      return a.m(123)\\n\" +\n                                \"    def m2 = A<:int:>.m(456)\\n\" +\n                                \"    def t1 = type A<:int:>\\n\" +\n                                \"    def t2 = type A<:Integer:>\\n\"\n                        , \"TestSimpleObjectGeneric\");\n                Method m1 = cls.getMethod(\"m1\");\n                Method m2 = cls.getMethod(\"m2\");\n                assertEquals(123, m1.invoke(null));\n                assertEquals(456, m2.invoke(null));\n                Method t1 = cls.getMethod(\"t1\");\n                Method t2 = cls.getMethod(\"t2\");\n                Class<?> c1 = (Class<?>) t1.invoke(null);\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\", c1.getName());\n                Method genericMethod1 = c1.getMethod(\"m\", int.class);\n                assertEquals(int.class, genericMethod1.getReturnType());\n                Class<?> c2 = (Class<?>) t2.invoke(null);\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_Integer\", c2.getName());\n                Method genericMethod2 = c2.getMethod(\"m\", Integer.class);\n                assertEquals(Integer.class, genericMethod2.getReturnType());\n        }\n\n        @Test\n        public void testSimpleInterfaceGeneric() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"interface A<:T:>\\n\" +\n                                \"  def m(t:T):T\\n\" +\n                                \"class TestSimpleInterfaceGeneric\\n\" +\n                                \"  static\\n\" +\n                                \"    def m1() = type A<:int:>\\n\" +\n                                \"    def m2() = type A<:Integer:>\\n\"\n                        , \"TestSimpleInterfaceGeneric\");\n                Method m1 = cls.getMethod(\"m1\");\n                Method m2 = cls.getMethod(\"m2\");\n                Class<?> aInt = (Class<?>) m1.invoke(null);\n                Class<?> aInteger = (Class<?>) m2.invoke(null);\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\", aInt.getName());\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_Integer\", aInteger.getName());\n                assertEquals(1, aInt.getMethods().length);\n                assertEquals(1, aInteger.getMethods().length);\n                Method aIntM = aInt.getMethod(\"m\", int.class);\n                Method aIntegerM = aInteger.getMethod(\"m\", Integer.class);\n                assertEquals(int.class, aIntM.getReturnType());\n                assertEquals(Integer.class, aIntegerM.getReturnType());\n        }\n\n        @Test\n        public void testMultiGenericParams() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class C<:T,U:>\\n\" +\n                                \"  def m(t:T):U = 123\\n\" +\n                                \"object O<:T,U:>\\n\" +\n                                \"  def m(t:T):U = 123\\n\" +\n                                \"interface I<:T,U:>\\n\" +\n                                \"  def m(t:T):U\\n\" +\n                                \"class TestMultiGenericParams\\n\" +\n                                \"  static\\n\" +\n                                \"    def m = [type C<:String,int:>, type O<:String,int:>, type I<:String,int:>,\\n\" +\n                                \"             C<:String,int:>().m('abc'), O<:String,int:>.m('abc')\\n\" +\n                                \"            ]\\n\"\n                        , \"TestMultiGenericParams\");\n                Method m = cls.getMethod(\"m\");\n                List ls = (List) m.invoke(null);\n                assertEquals(5, ls.size());\n                Class<?> c = (Class<?>) ls.get(0);\n                Class<?> o = (Class<?>) ls.get(1);\n                Class<?> i = (Class<?>) ls.get(2);\n                Object oc = ls.get(3);\n                Object oo = ls.get(4);\n                assertEquals(\"C\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_String\" + Consts.GENERIC_NAME_SPLIT + \"int\", c.getName());\n                assertEquals(\"O\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_String\" + Consts.GENERIC_NAME_SPLIT + \"int\", o.getName());\n                assertEquals(\"I\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_String\" + Consts.GENERIC_NAME_SPLIT + \"int\", i.getName());\n                assertEquals(int.class, c.getMethod(\"m\", String.class).getReturnType());\n                assertEquals(int.class, o.getMethod(\"m\", String.class).getReturnType());\n                assertEquals(int.class, i.getMethod(\"m\", String.class).getReturnType());\n                assertEquals(123, oc);\n                assertEquals(123, oo);\n        }\n\n        @Test\n        public void testApplyGenericWithGeneric() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"interface A<:T,U:>\\n\" +\n                                \"  def m(t:T):U\\n\" +\n                                \"class TestApplyGenericWithGeneric\\n\" +\n                                \"  static\\n\" +\n                                \"    def m = type A<:String, A<:int, double:>:>\\n\"\n                        , \"TestApplyGenericWithGeneric\");\n                Class<?> c = (Class<?>) cls.getMethod(\"m\").invoke(null);\n                assertEquals(\n                        \"A\" + Consts.GENERIC_NAME_SPLIT + \"java_lang_String\" + Consts.GENERIC_NAME_SPLIT\n                                + \"A\" + Consts.GENERIC_NAME_SPLIT + \"int\" + Consts.GENERIC_NAME_SPLIT + \"double\"\n                        , c.getName());\n                Method m = c.getMethod(\"m\", String.class);\n                Class<?> cc = m.getReturnType();\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\" + Consts.GENERIC_NAME_SPLIT + \"double\", cc.getName());\n                assertEquals(double.class, cc.getMethod(\"m\", int.class).getReturnType());\n        }\n\n        @Test\n        public void testGenericInherit() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"interface A<:T,U:>\\n\" +\n                                \"  def m(t:T):U\\n\" +\n                                \"class B<:T:> : A<:T,T:>\\n\" +\n                                \"  def m(t:T):T = t\\n\" +\n                                \"class TestGenericInherit\\n\" +\n                                \"  static\\n\" +\n                                \"    def m(i:int) = B<:int:>().m(i)\\n\"\n                        , \"TestGenericInherit\");\n                assertEquals(1, cls.getMethod(\"m\", int.class).invoke(null, 1));\n        }\n\n        @Test\n        public void testGenericInGeneric() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class A<:T:>\\n\" +\n                                \"class B<:U:>\\n\" +\n                                \"  def m():A<:U:> = null\\n\" +\n                                \"class TestGenericInGeneric\\n\" +\n                                \"  static\\n\" +\n                                \"    def m = type B<:int:>\\n\"\n                        , \"TestGenericInGeneric\");\n                Method m = cls.getMethod(\"m\");\n                Class<?> b = (Class<?>) m.invoke(null);\n                Class<?> a = b.getMethod(\"m\").getReturnType();\n                assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\", a.getName());\n        }\n\n        @Test\n        public void testGenericFirstApplyThenAdd() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class A<:T:>\\n\" +\n                                \"  public i : T\\n\" +\n                                \"class Y : B<:int:>\\n\" + // b<:int:> before A<:U:>\n                                \"class B<:U:> : A<:U:>\\n\" +\n                                \"\\n\" +\n                                \"class TestGenericFirstApplyThenAdd\\n\" +\n                                \"  static\\n\" +\n                                \"    def m = type Y\\n\"\n                        , \"TestGenericFirstApplyThenAdd\");\n                Class<?> y = (Class<?>) cls.getMethod(\"m\").invoke(null);\n                assertEquals(int.class, y.getField(\"i\").getType());\n        }\n\n        @Test\n        public void testHigherKindType() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class Functor<:F, T, U:>\\n\" +\n                                \"  def fmap(f, a:F<:T:>):F<:U:> = null\\n\" +\n                                \"class X<:T:>\\n\" +\n                                \"class TestHigherKindType\\n\" +\n                                \"  static\\n\" +\n                                \"    def m = type Functor<:X, int, double:>\"\n                        , \"TestHigherKindType\");\n                Class<?> f = (Class<?>) cls.getMethod(\"m\").invoke(null);\n                assertEquals(\"Functor\" +\n                        Consts.GENERIC_NAME_SPLIT + \"X\" +\n                        Consts.GENERIC_NAME_SPLIT + \"int\" +\n                        Consts.GENERIC_NAME_SPLIT + \"double\", f.getName());\n                Method[] methods = f.getMethods();\n                Method fmap = null;\n                for (Method m : methods) {\n                        if (m.getName().equals(\"fmap\")) {\n                                fmap = m;\n                                break;\n                        }\n                }\n                assertNotNull(fmap);\n                assertEquals(2, fmap.getParameterTypes().length);\n                assertEquals(Object.class, fmap.getParameterTypes()[0]);\n                Class<?> p1 = fmap.getParameterTypes()[1];\n                assertEquals(\"X\" + Consts.GENERIC_NAME_SPLIT + \"int\", p1.getName());\n                assertEquals(\"X\" + Consts.GENERIC_NAME_SPLIT + \"double\", fmap.getReturnType().getName());\n        }\n\n        @Test\n        public void testDynamicInvokeWithBool() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestDynamicInvokeWithBool\\n\" +\n                                \"  def a(b:bool)=1\\n\" +\n                                \"  def m(o) = o.a(true)\"\n                        , \"TestDynamicInvokeWithBool\");\n                Object o = cls.newInstance();\n                Method m = cls.getMethod(\"m\", Object.class);\n                // it used to cause an exception\n                /*\n                 * lt.compiler.LtBug: should not reach here, from: class java.lang.Boolean\n                 * at lt.runtime.Dynamic.getNumberPrimitiveCastDepth(Dynamic.java:662)\n                 * at lt.runtime.Dynamic.findBestMatch(Dynamic.java:687)\n                 * at lt.runtime.Dynamic.findMethod(Dynamic.java:214)\n                 * at lt.runtime.Dynamic.invoke(Dynamic.java:840)\n                 * at lt.runtime.Dynamic.invoke(Dynamic.java:1093)\n                 * at TestDynamicInvokeWithBool.m(test.lt:3)\n                 */\n                assertEquals(1, m.invoke(o, o));\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestDefineAnnotations.java",
    "content": "package lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.SModifier;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.annotation.Annotation;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.junit.Assert.*;\n\n/**\n * test defined annotations\n */\npublic class TestDefineAnnotations {\n        public static Class<?> retrieveClass(String code, String clsName) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n                Scanner lexicalProcessor = new ScannerSwitcher(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                final Map<String, byte[]> list = codeGenerator.generate();\n\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                byte[] bs = list.get(name);\n                                if (bs == null) throw new ClassNotFoundException(name);\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                return classLoader.loadClass(clsName);\n        }\n\n        private Annotation getAnno(Class<?> cls, String name) {\n                for (Annotation a : cls.getAnnotations())\n                        if (a.annotationType().getName().equals(name)) return a;\n                fail(\"annotation not found\");\n                throw new AssertionError();\n        }\n\n        @Test\n        public void testPrimitives() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"annotation A\\n\" +\n                                \"    i:int=1\\n\" +\n                                \"    l:long=2\\n\" +\n                                \"    f:float=3\\n\" +\n                                \"    d:double=4\\n\" +\n                                \"    aByte:byte=5\\n\" +\n                                \"    aBool:bool=true\\n\" +\n                                \"    aShort:short=6\\n\" +\n                                \"    aChar:char='c'\\n\" +\n                                \"    str:String='xx'\\n\" +\n                                \"    cls:Class=type Object\\n\" +\n                                \"@A\\n\" +\n                                \"class TestPrimitives\"\n                        , \"TestPrimitives\");\n                Annotation annoA = getAnno(cls, \"A\");\n                assertNotNull(annoA);\n                assertEquals(1, annoA.getClass().getMethod(\"i\").invoke(annoA));\n                assertEquals(2L, annoA.getClass().getMethod(\"l\").invoke(annoA));\n                assertEquals(3f, annoA.getClass().getMethod(\"f\").invoke(annoA));\n                assertEquals(4d, annoA.getClass().getMethod(\"d\").invoke(annoA));\n                assertEquals((byte) 5, annoA.getClass().getMethod(\"aByte\").invoke(annoA));\n                assertEquals(true, annoA.getClass().getMethod(\"aBool\").invoke(annoA));\n                assertEquals((short) 6, annoA.getClass().getMethod(\"aShort\").invoke(annoA));\n                assertEquals('c', annoA.getClass().getMethod(\"aChar\").invoke(annoA));\n                assertEquals(\"xx\", annoA.getClass().getMethod(\"str\").invoke(annoA));\n                assertEquals(Object.class, annoA.getClass().getMethod(\"cls\").invoke(annoA));\n        }\n\n        @Test\n        public void testAnno() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"import lt::compiler::_\\n\" +\n                                \"annotation A\\n\" +\n                                \"    a:AnnotationTest=@AnnotationTest\\n\" +\n                                \"@A\\n\" +\n                                \"class TestAnno\"\n                        , \"TestAnno\");\n                Annotation annoA = getAnno(cls, \"A\");\n\n                annoA = (Annotation) annoA.getClass().getMethod(\"a\").invoke(annoA);\n                assertEquals(100f, annoA.getClass().getMethod(\"f\").invoke(annoA));\n                assertEquals(100d, annoA.getClass().getMethod(\"d\").invoke(annoA));\n                assertEquals(SModifier.PUBLIC, annoA.getClass().getMethod(\"e\").invoke(annoA));\n                assertEquals(String.class, annoA.getClass().getMethod(\"cls\").invoke(annoA));\n                assertEquals((byte) 100, annoA.getClass().getMethod(\"b\").invoke(annoA));\n                assertEquals('a', annoA.getClass().getMethod(\"c\").invoke(annoA));\n                assertEquals(100L, annoA.getClass().getMethod(\"l\").invoke(annoA));\n                assertEquals(100, annoA.getClass().getMethod(\"i\").invoke(annoA));\n                assertEquals(true, annoA.getClass().getMethod(\"bo\").invoke(annoA));\n                assertEquals(\"str\", annoA.getClass().getMethod(\"str\").invoke(annoA));\n                assertEquals((short) 100, annoA.getClass().getMethod(\"s\").invoke(annoA));\n                Annotation anno = (Annotation) annoA.getClass().getMethod(\"anno\").invoke(annoA);\n                assertEquals(100, anno.getClass().getMethod(\"i\").invoke(anno));\n                assertEquals(\"a\", anno.getClass().getMethod(\"str\").invoke(anno));\n                Class<?>[] clsArr = (Class<?>[]) annoA.getClass().getMethod(\"clsArr\").invoke(annoA);\n                assertArrayEquals(new Class[]{Class.class, String.class}, clsArr);\n                String[] strArr = (String[]) annoA.getClass().getMethod(\"strArr\").invoke(annoA);\n                assertArrayEquals(new String[]{\"a\", \"b\"}, strArr);\n        }\n\n        @Test\n        public void testArrayPrimitives() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"annotation A\\n\" +\n                                \"    i:[]int = [1,2,3]\\n\" +\n                                \"    l:[]long = [1,2,3]\\n\" +\n                                \"    f:[]float = [1,2,3]\\n\" +\n                                \"    d:[]double = [1,2,3]\\n\" +\n                                \"    aByte:[]byte = [1,2,3]\\n\" +\n                                \"    aShort:[]short = [1,2,3]\\n\" +\n                                \"    aChar:[]char = ['a','b','c']\\n\" +\n                                \"    aBool:[]bool = [true,false,true]\\n\" +\n                                \"    str:[]String = ['xx', 'yy', 'zz']\\n\" +\n                                \"    cls:[]Class = [type Object, type Integer]\\n\" +\n                                \"@A\\n\" +\n                                \"class TestArrayPrimitives\"\n                        , \"TestArrayPrimitives\");\n                Annotation annoA = getAnno(cls, \"A\");\n                float[] f = (float[]) annoA.getClass().getMethod(\"f\").invoke(annoA);\n                byte[] aByte = (byte[]) annoA.getClass().getMethod(\"aByte\").invoke(annoA);\n                double[] d = (double[]) annoA.getClass().getMethod(\"d\").invoke(annoA);\n                short[] aShort = (short[]) annoA.getClass().getMethod(\"aShort\").invoke(annoA);\n                Class<?>[] clsX = (Class<?>[]) annoA.getClass().getMethod(\"cls\").invoke(annoA);\n                String[] str = (String[]) annoA.getClass().getMethod(\"str\").invoke(annoA);\n                char[] aChar = (char[]) annoA.getClass().getMethod(\"aChar\").invoke(annoA);\n                long[] l = (long[]) annoA.getClass().getMethod(\"l\").invoke(annoA);\n                boolean[] aBool = (boolean[]) annoA.getClass().getMethod(\"aBool\").invoke(annoA);\n                int[] i = (int[]) annoA.getClass().getMethod(\"i\").invoke(annoA);\n\n                assertArrayEquals(new float[]{1f, 2f, 3f}, f, 0);\n                assertArrayEquals(new byte[]{1, 2, 3}, aByte);\n                assertArrayEquals(new double[]{1d, 2d, 3d}, d, 0);\n                assertArrayEquals(new short[]{1, 2, 3}, aShort);\n                assertArrayEquals(new Class[]{Object.class, Integer.class}, clsX);\n                assertArrayEquals(new String[]{\"xx\", \"yy\", \"zz\"}, str);\n                assertArrayEquals(new char[]{'a', 'b', 'c'}, aChar);\n                assertArrayEquals(new long[]{1, 2, 3}, l);\n                assertArrayEquals(new boolean[]{true, false, true}, aBool);\n                assertArrayEquals(new int[]{1, 2, 3}, i);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestDemo.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function0;\nimport lt.lang.function.Function1;\nimport lt.repl.ScriptCompiler;\nimport org.junit.Test;\n\nimport java.io.*;\nimport java.lang.reflect.*;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * test demo\n */\npublic class TestDemo {\n        private Map<String, byte[]> generate(BufferedReader br, String fileName) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n\n                IndentScanner lexicalProcessor = new IndentScanner(fileName, br, new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(fileName, syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                return codeGenerator.generate();\n        }\n\n        @Test\n        public void testLiteral() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/literals.lts\");\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"class literals\\n\");\n                BufferedReader br = new BufferedReader(new InputStreamReader(is));\n                String line;\n                while ((line = br.readLine()) != null) {\n                        sb.append(\"    \").append(line).append(\"\\n\");\n                }\n\n                Map<String, byte[]> map = generate(new BufferedReader(new StringReader(sb.toString())), \"literals.lts\");\n                final byte[] bs = map.get(\"literals\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                Class<?> cls = classLoader.loadClass(\"literals\");\n                Object o = cls.newInstance();\n                int count = 0;\n\n                // i_am_string\n                Field i_am_string = cls.getDeclaredField(\"i_am_string\");\n                i_am_string.setAccessible(true);\n                assertEquals(\"a string\", i_am_string.get(o));\n                ++count;\n\n                // or_in_this_form\n                Field or_in_this_form = cls.getDeclaredField(\"or_in_this_form\");\n                or_in_this_form.setAccessible(true);\n                assertEquals(\"also a string\", or_in_this_form.get(o));\n                ++count;\n\n                // i_am_a_number\n                Field i_am_a_number = cls.getDeclaredField(\"i_am_a_number\");\n                i_am_a_number.setAccessible(true);\n                assertEquals(1, i_am_a_number.get(o));\n                ++count;\n\n                // or_float_number\n                Field or_float_number = cls.getDeclaredField(\"or_float_number\");\n                or_float_number.setAccessible(true);\n                assertEquals(1.2, or_float_number.get(o));\n                ++count;\n\n                // json\n                Field json = cls.getDeclaredField(\"json\");\n                json.setAccessible(true);\n                assertEquals(new LinkedHashMap<Object, Object>() {{\n                        put('a', 'b');\n                }}, json.get(o));\n                ++count;\n\n                // list\n                Field list = cls.getDeclaredField(\"list\");\n                list.setAccessible(true);\n                assertEquals(Arrays.asList(1, 2, 3), list.get(o));\n                ++count;\n\n                // i_am_bool\n                Field i_am_bool = cls.getDeclaredField(\"i_am_bool\");\n                i_am_bool.setAccessible(true);\n                assertEquals(true, i_am_bool.getBoolean(o));\n                ++count;\n\n                // i_am_bool_too\n                Field i_am_bool_too = cls.getDeclaredField(\"i_am_bool_too\");\n                i_am_bool_too.setAccessible(true);\n                assertEquals(true, i_am_bool_too.getBoolean(o));\n                ++count;\n\n                // i_am_bool_false\n                Field i_am_bool_false = cls.getDeclaredField(\"i_am_bool_false\");\n                i_am_bool_false.setAccessible(true);\n                assertEquals(false, i_am_bool_false.getBoolean(o));\n                ++count;\n\n                // i_am_also_bool_false\n                Field i_am_also_bool_false = cls.getDeclaredField(\"i_am_also_bool_false\");\n                i_am_also_bool_false.setAccessible(true);\n                assertEquals(false, i_am_also_bool_false.getBoolean(o));\n                ++count;\n\n                // i_am_char\n                Field i_am_char = cls.getDeclaredField(\"i_am_char\");\n                i_am_char.setAccessible(true);\n                assertEquals('c', i_am_char.getChar(o));\n                ++count;\n\n                // i_am_String\n                Field i_am_String = cls.getDeclaredField(\"i_am_String\");\n                i_am_String.setAccessible(true);\n                assertEquals(\"i am a java.lang.String\", i_am_String.get(o));\n                ++count;\n\n                // i_am_int\n                Field i_am_int = cls.getDeclaredField(\"i_am_int\");\n                i_am_int.setAccessible(true);\n                assertEquals(1, i_am_int.getInt(o));\n                ++count;\n\n                // i_am_double\n                Field i_am_double = cls.getDeclaredField(\"i_am_double\");\n                i_am_double.setAccessible(true);\n                assertEquals(1.2, i_am_double.getDouble(o), 0);\n                ++count;\n\n                // i_am_float\n                Field i_am_float = cls.getDeclaredField(\"i_am_float\");\n                i_am_float.setAccessible(true);\n                assertEquals(1.0f, i_am_float.getFloat(o), 0);\n                ++count;\n\n                // i_am_long\n                Field i_am_long = cls.getDeclaredField(\"i_am_long\");\n                i_am_long.setAccessible(true);\n                assertEquals(1L, i_am_long.getLong(o));\n                ++count;\n\n                // i_am_short\n                Field i_am_short = cls.getDeclaredField(\"i_am_short\");\n                i_am_short.setAccessible(true);\n                assertEquals((short) 1, i_am_short.getShort(o));\n                ++count;\n\n                // i_am_byte\n                Field i_am_byte = cls.getDeclaredField(\"i_am_byte\");\n                i_am_byte.setAccessible(true);\n                assertEquals((byte) 1, i_am_byte.getByte(o));\n                ++count;\n\n                // this_var_is_int\n                Field this_var_is_int = cls.getDeclaredField(\"this_var_is_int\");\n                this_var_is_int.setAccessible(true);\n                assertEquals(1, this_var_is_int.getInt(o));\n                ++count;\n\n                // this_var_is_short\n                Field this_var_is_short = cls.getDeclaredField(\"this_var_is_short\");\n                this_var_is_short.setAccessible(true);\n                assertEquals((short) 1, this_var_is_short.getShort(o));\n                ++count;\n\n                // this_var_is_Integer\n                Field this_var_is_Integer = cls.getDeclaredField(\"this_var_is_Integer\");\n                this_var_is_Integer.setAccessible(true);\n                assertEquals(1, this_var_is_Integer.get(o));\n                ++count;\n\n                // default_value_of_number\n                Field default_value_of_number = cls.getDeclaredField(\"default_value_of_number\");\n                default_value_of_number.setAccessible(true);\n                assertEquals(1, default_value_of_number.get(o));\n                ++count;\n\n                // default_value_of_float_number\n                Field default_value_of_float_number = cls.getDeclaredField(\"default_value_of_float_number\");\n                default_value_of_float_number.setAccessible(true);\n                assertEquals(1.2D, default_value_of_float_number.get(o));\n                ++count;\n\n                // default_value_of_char_string\n                Field default_value_of_char_string = cls.getDeclaredField(\"default_value_of_char_string\");\n                default_value_of_char_string.setAccessible(true);\n                assertEquals('c', default_value_of_char_string.get(o));\n                ++count;\n\n                // default_value_of_string_1\n                Field default_value_of_string_1 = cls.getDeclaredField(\"default_value_of_string_1\");\n                default_value_of_string_1.setAccessible(true);\n                assertEquals(\"s\", default_value_of_string_1.get(o));\n                ++count;\n\n                // default_value_of_string_2\n                Field default_value_of_string_2 = cls.getDeclaredField(\"default_value_of_string_2\");\n                default_value_of_string_2.setAccessible(true);\n                assertEquals(\"length is greater than 1\", default_value_of_string_2.get(o));\n                ++count;\n\n                // default_value_of_string_3\n                Field default_value_of_string_3 = cls.getDeclaredField(\"default_value_of_string_3\");\n                default_value_of_string_3.setAccessible(true);\n                assertEquals(\"\", default_value_of_string_3.get(o));\n                ++count;\n\n                assertEquals(count, cls.getDeclaredFields().length);\n        }\n\n        @Test\n        public void testLtFileStructure() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/ltFileStructure.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"ltFileStructure.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                // lt.demo.I_Am_A_Class\n                Class<?> I_Am_A_Class = classLoader.loadClass(\"lt.demo.I_Am_A_Class\");\n                assertEquals(2, I_Am_A_Class.getDeclaredFields().length); // one field\n                assertEquals(1, I_Am_A_Class.getDeclaredConstructors().length); // one constructor\n                assertEquals(1, I_Am_A_Class.getDeclaredMethods().length); // one method\n                assertEquals(Object.class, I_Am_A_Class.getSuperclass()); // extends Object\n                assertEquals(0, I_Am_A_Class.getInterfaces().length); // 0 interfaces\n                Object I_Am_A_Class_o = I_Am_A_Class.newInstance();\n\n                Field i_am_field = I_Am_A_Class.getDeclaredField(\"i_am_field\");\n                assertEquals(int.class, i_am_field.getType()); // int i_am_field\n                i_am_field.setAccessible(true);\n                assertEquals(0, i_am_field.getInt(I_Am_A_Class_o)); // it's 0\n\n                Field list = I_Am_A_Class.getDeclaredField(\"list\");\n                assertEquals(List.class, list.getType());\n                list.setAccessible(true);\n                assertNull(list.get(I_Am_A_Class_o));\n\n                Method i_am_a_method = I_Am_A_Class.getDeclaredMethod(\"i_am_a_method\");\n                assertEquals(List.class, i_am_a_method.getReturnType()); // java.util.List i_am_a_method()\n                assertEquals(Collections.EMPTY_LIST, i_am_a_method.invoke(I_Am_A_Class_o));\n                assertEquals(Collections.EMPTY_LIST, list.get(I_Am_A_Class_o));\n                // the field is emptyList, the list in method is not a local variable\n\n                // lt.demo.I_Am_An_Interface\n                Class<?> I_Am_An_Interface = classLoader.loadClass(\"lt.demo.I_Am_An_Interface\");\n                assertTrue(I_Am_An_Interface.isInterface());\n        }\n\n        @Test\n        public void testStatements() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/statements.lts\");\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"class statements\\n\");\n                BufferedReader br = new BufferedReader(new InputStreamReader(is));\n                String line;\n                while ((line = br.readLine()) != null) {\n                        sb.append(\"    \").append(line).append(\"\\n\");\n                }\n\n                Map<String, byte[]> map = generate(new BufferedReader(new StringReader(sb.toString())), \"statements.lts\");\n                final byte[] bs = map.get(\"statements\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                Class<?> cls = classLoader.loadClass(\"statements\");\n                Object o = cls.newInstance();\n\n                // arr\n                Field arr = cls.getDeclaredField(\"arr\");\n                arr.setAccessible(true);\n                assertEquals(Arrays.asList(1, 2, 3), arr.get(o));\n\n                // res0\n                Field res0 = cls.getDeclaredField(\"res0\");\n                res0.setAccessible(true);\n                assertEquals(6, res0.get(o));\n\n                // res1\n                Field res1 = cls.getDeclaredField(\"res1\");\n                res1.setAccessible(true);\n                assertEquals(6, res1.get(o));\n\n                // index\n                Field index = cls.getDeclaredField(\"index\");\n                index.setAccessible(true);\n                assertEquals(3, index.get(o));\n\n                // method_if_elseif_else\n                Method method_if_elseif_else = cls.getDeclaredMethod(\"method_if_elseif_else\", Object.class, Object.class);\n                /*\n                 * if a\n                 *     <1\n                 * elseif b\n                 *     <2\n                 * else\n                 *     <3\n                 */\n                // a=true\n                assertEquals(1, method_if_elseif_else.invoke(o, true, false));\n                assertEquals(1, method_if_elseif_else.invoke(o, true, true));\n                // a=false and b=true\n                assertEquals(2, method_if_elseif_else.invoke(o, false, true));\n                // a=false and b=false\n                assertEquals(3, method_if_elseif_else.invoke(o, false, false));\n\n                // method_try_catch_finally\n                Method method_try_catch_finally = cls.getDeclaredMethod(\"method_try_catch_finally\", Object.class);\n                // no exception, then a=1 and finally ++a , a==2\n                // RuntimeException, then a=2 and finally ++a , a==3\n                // Error, Exception, then a=3 and finally ++a , a==4\n                // Throwable, then a=4 and finally ++a , a==5\n                assertEquals(2, method_try_catch_finally.invoke(o, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                        }\n                }));\n                assertEquals(3, method_try_catch_finally.invoke(o, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new RuntimeException();\n                        }\n                }));\n                assertEquals(4, method_try_catch_finally.invoke(o, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Error();\n                        }\n                }));\n                assertEquals(4, method_try_catch_finally.invoke(o, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Exception();\n                        }\n                }));\n                assertEquals(5, method_try_catch_finally.invoke(o, (I) new I() {\n                        @Override\n                        public void apply() throws Throwable {\n                                throw new Throwable();\n                        }\n                }));\n\n                // res2\n                Field res2 = cls.getDeclaredField(\"res2\");\n                res2.setAccessible(true);\n                assertEquals(\"abc\", res2.get(o));\n\n                // variable1\n                Field variable1 = cls.getDeclaredField(\"variable1\");\n                variable1.setAccessible(true);\n                assertEquals(1, variable1.get(o));\n\n                // variable2\n                Field variable2 = cls.getDeclaredField(\"variable2\");\n                variable2.setAccessible(true);\n                assertEquals(1, variable2.getInt(o));\n\n                // variable3\n                Field variable3 = cls.getDeclaredField(\"variable3\");\n                variable3.setAccessible(true);\n                assertEquals(0, variable3.getInt(o));\n\n                // res3\n                Field res3 = cls.getDeclaredField(\"res3\");\n                res3.setAccessible(true);\n                assertEquals(1, res3.get(o));\n\n                // res4\n                Field res4 = cls.getDeclaredField(\"res4\");\n                res4.setAccessible(true);\n                assertEquals(Object.class, res4.get(o).getClass());\n\n                // list1\n                Field list1 = cls.getDeclaredField(\"list1\");\n                list1.setAccessible(true);\n                assertEquals(Collections.singletonList(1), list1.get(o));\n\n                // list2\n                Field list2 = cls.getDeclaredField(\"list2\");\n                list2.setAccessible(true);\n                assertEquals(Collections.EMPTY_LIST, list2.get(o));\n\n                // res5\n                Field res5 = cls.getDeclaredField(\"res5\");\n                res5.setAccessible(true);\n                assertTrue(res5.get(o) == list1.get(o));\n\n                // list3\n                Field list3 = cls.getDeclaredField(\"list3\");\n                list3.setAccessible(true);\n                assertEquals(Arrays.asList(2, 2, 3), list3.get(o));\n\n                // res6\n                Field res6 = cls.getDeclaredField(\"res6\");\n                res6.setAccessible(true);\n                assertEquals(1, res6.get(o));\n\n                // map\n                Field Fmap = cls.getDeclaredField(\"map\");\n                Fmap.setAccessible(true);\n                assertEquals(new LinkedHashMap<Object, Object>() {{\n                        put(\"a\", \"b\");\n                }}, Fmap.get(o));\n        }\n\n        interface I {\n                @SuppressWarnings(\"unused\")\n                void apply() throws Throwable;\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testAdvanced() throws Throwable {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/advanced.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"advanced.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                Class<?> TestInnerMethod = classLoader.loadClass(\"TestInnerMethod\");\n                Method outer = TestInnerMethod.getDeclaredMethod(\"outer\");\n                assertEquals(1, outer.invoke(TestInnerMethod.newInstance()));\n\n                Class<?> TestProcedure = classLoader.loadClass(\"TestProcedure\");\n                Method method = TestProcedure.getDeclaredMethod(\"method\");\n                assertEquals(1, method.invoke(TestProcedure.newInstance()));\n\n                Class<?> Func = classLoader.loadClass(\"Func\");\n                assertEquals(1, Func.getDeclaredMethods().length);\n                Method apply = Func.getDeclaredMethod(\"apply\", Object.class);\n                assertTrue(Modifier.isAbstract(apply.getModifiers()));\n\n                Class<?> TestLambda = classLoader.loadClass(\"TestLambda\");\n                Object o = TestLambda.newInstance();\n                Field func1F = TestLambda.getDeclaredField(\"func1\");\n                Field func2F = TestLambda.getDeclaredField(\"func2\");\n                Field func3F = TestLambda.getDeclaredField(\"func3\");\n\n                Object func1 = func1F.get(o);\n                assertTrue(Func.isInstance(func1));\n                Function1 func2 = (Function1) func2F.get(o);\n                Function1 func3 = (Function1) func3F.get(o);\n\n                assertEquals(2, apply.invoke(func1, 1));\n                assertEquals(2, func2.apply(1));\n                assertEquals(2, func3.apply(1));\n        }\n\n        @Test\n        public void testOperator() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/operator.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"operator.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                Class<?> Num = classLoader.loadClass(\"Num\");\n                Constructor<?> con = Num.getConstructor(Object.class);\n\n                assertEquals(con.newInstance(1), con.newInstance(1));\n                assertEquals(con.newInstance(2), con.newInstance(2));\n                assertNotEquals(con.newInstance(3), con.newInstance(1));\n\n                Class<?> TestNum = classLoader.loadClass(\"TestNum\");\n                Method testAdd = TestNum.getMethod(\"testAdd\");\n                assertEquals(con.newInstance(2), testAdd.invoke(null));\n\n                Method testSubtract = TestNum.getMethod(\"testSubtract\");\n                assertEquals(con.newInstance(-1), testSubtract.invoke(null));\n\n                Method testMultiply = TestNum.getMethod(\"testMultiply\");\n                assertEquals(con.newInstance(12), testMultiply.invoke(null));\n\n                Method testDivide = TestNum.getMethod(\"testDivide\");\n                assertEquals(con.newInstance(5), testDivide.invoke(null));\n\n                Method testRemainder = TestNum.getMethod(\"testRemainder\");\n                assertEquals(con.newInstance(2), testRemainder.invoke(null));\n\n                Method testShiftLeft = TestNum.getMethod(\"testShiftLeft\");\n                assertEquals(con.newInstance(4), testShiftLeft.invoke(null));\n\n                Method testShiftRight = TestNum.getMethod(\"testShiftRight\");\n                assertEquals(con.newInstance(1), testShiftRight.invoke(null));\n\n                Method testUnsignedShiftRight = TestNum.getMethod(\"testUnsignedShiftRight\");\n                assertEquals(con.newInstance(2), testUnsignedShiftRight.invoke(null));\n\n                Method testEqual = TestNum.getMethod(\"testEqual\");\n                assertEquals(true, testEqual.invoke(null));\n\n                Method testNotEqual = TestNum.getMethod(\"testNotEqual\");\n                assertEquals(true, testNotEqual.invoke(null));\n\n                Method testEquals = TestNum.getMethod(\"testEquals\");\n                assertEquals(true, testEquals.invoke(null));\n\n                Method testContains = TestNum.getMethod(\"testContains\");\n                try {\n                        testContains.invoke(null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getCause() instanceof UnsupportedOperationException);\n                        assertEquals(\"contains\", e.getCause().getMessage());\n                }\n\n                Method testGt = TestNum.getMethod(\"testGt\");\n                assertEquals(true, testGt.invoke(null));\n\n                Method testGe = TestNum.getMethod(\"testGe\");\n                assertEquals(true, testGe.invoke(null));\n\n                Method testLt = TestNum.getMethod(\"testLt\");\n                assertEquals(true, testLt.invoke(null));\n\n                Method testLe = TestNum.getMethod(\"testLe\");\n                assertEquals(true, testLe.invoke(null));\n\n                Method testAnd = TestNum.getMethod(\"testAnd\");\n                assertEquals(con.newInstance(0), testAnd.invoke(null));\n\n                Method testXor = TestNum.getMethod(\"testXor\");\n                assertEquals(con.newInstance(3), testXor.invoke(null));\n\n                Method testOr = TestNum.getMethod(\"testOr\");\n                assertEquals(con.newInstance(3), testOr.invoke(null));\n\n                try {\n                        Method testLogicNot = TestNum.getMethod(\"testLogicNot\");\n                        testLogicNot.invoke(null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getCause() instanceof UnsupportedOperationException);\n                        assertEquals(\"logicNot\", e.getCause().getMessage());\n                }\n\n                Method testNot = TestNum.getMethod(\"testNot\");\n                assertEquals(con.newInstance(-2), testNot.invoke(null));\n\n                Method testNegate = TestNum.getMethod(\"testNegate\");\n                assertEquals(con.newInstance(-1), testNegate.invoke(null));\n\n\n                try {\n                        Method testConcat = TestNum.getMethod(\"testConcat\");\n                        testConcat.invoke(null);\n                        fail();\n                } catch (InvocationTargetException e) {\n                        assertTrue(e.getCause() instanceof UnsupportedOperationException);\n                        assertEquals(\"concat\", e.getCause().getMessage());\n                }\n        }\n\n        @Test\n        @SuppressWarnings(\"unchecked\")\n        public void testTypeDef() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/typeDef.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"typeDef.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                // I_Have_Params\n                Class<?> I_Am_A_Class = classLoader.loadClass(\"I_Am_A_Class\");\n                assertEquals(0, I_Am_A_Class.getDeclaredFields().length);\n                assertEquals(0, I_Am_A_Class.getDeclaredMethods().length);\n                assertEquals(1, I_Am_A_Class.getDeclaredConstructors().length);\n\n                // I_Have_Params\n                Class<?> I_Have_Params = classLoader.loadClass(\"I_Have_Params\");\n                assertEquals(2, I_Have_Params.getDeclaredFields().length);\n                assertEquals(0, I_Have_Params.getDeclaredMethods().length);\n                assertEquals(1, I_Have_Params.getDeclaredConstructors().length);\n\n                Constructor<?> I_Have_Params_new = I_Have_Params.getConstructor(int.class, Object.class);\n\n                Field I_Have_Params_param1 = I_Have_Params.getDeclaredField(\"param1\");\n                I_Have_Params_param1.setAccessible(true);\n                assertEquals(int.class, I_Have_Params_param1.getType());\n                Field I_Have_Params_param2 = I_Have_Params.getDeclaredField(\"param2\");\n                I_Have_Params_param2.setAccessible(true);\n                assertEquals(Object.class, I_Have_Params_param2.getType());\n\n                Object I_Have_Params_o = I_Have_Params_new.newInstance(1, \"a\");\n                assertEquals(1, I_Have_Params_param1.get(I_Have_Params_o));\n                assertEquals(\"a\", I_Have_Params_param2.get(I_Have_Params_o));\n\n                // I_Have_Params_too\n                Class<?> I_Have_Params_too = classLoader.loadClass(\"I_Have_Params_too\");\n                assertEquals(2, I_Have_Params_too.getDeclaredFields().length);\n                assertEquals(0, I_Have_Params_too.getDeclaredMethods().length);\n                assertEquals(1, I_Have_Params_too.getDeclaredConstructors().length);\n\n                Constructor<?> I_Have_Params_too_new = I_Have_Params_too.getConstructor(int.class, Object.class);\n\n                Field I_Have_Params_too_param1 = I_Have_Params_too.getDeclaredField(\"param1\");\n                I_Have_Params_too_param1.setAccessible(true);\n                assertEquals(int.class, I_Have_Params_too_param1.getType());\n                Field I_Have_Params_too_param2 = I_Have_Params_too.getDeclaredField(\"param2\");\n                I_Have_Params_too_param2.setAccessible(true);\n                assertEquals(Object.class, I_Have_Params_too_param2.getType());\n\n                Object I_Have_Params_too_o = I_Have_Params_too_new.newInstance(1, \"a\");\n                assertEquals(1, I_Have_Params_too_param1.get(I_Have_Params_too_o));\n                assertEquals(\"a\", I_Have_Params_too_param2.get(I_Have_Params_too_o));\n\n                // I_Have_Parent\n                Class<?> I_Have_Parent = classLoader.loadClass(\"I_Have_Parent\");\n                assertEquals(0, I_Have_Parent.getDeclaredFields().length);\n                assertEquals(0, I_Have_Parent.getDeclaredMethods().length);\n                assertEquals(1, I_Have_Parent.getDeclaredConstructors().length);\n                assertEquals(I_Am_A_Class, I_Have_Parent.getSuperclass());\n\n                // I_Have_Parent_And_Parent_Have_Args\n                Class<?> I_Have_Parent_And_Parent_Have_Args = classLoader.loadClass(\"I_Have_Parent_And_Parent_Have_Args\");\n                assertEquals(0, I_Have_Parent_And_Parent_Have_Args.getDeclaredFields().length);\n                assertEquals(0, I_Have_Parent_And_Parent_Have_Args.getDeclaredMethods().length);\n                assertEquals(1, I_Have_Parent_And_Parent_Have_Args.getConstructors().length);\n                Object I_Have_Parent_And_Parent_Have_Args_o = I_Have_Parent_And_Parent_Have_Args.newInstance();\n                assertEquals(1, I_Have_Params_param1.get(I_Have_Parent_And_Parent_Have_Args_o));\n                assertEquals(\"2\", I_Have_Params_param2.get(I_Have_Parent_And_Parent_Have_Args_o));\n\n                // I_Have_Interfaces\n                Class<?> I_Have_Interfaces = classLoader.loadClass(\"I_Have_Interfaces\");\n                assertEquals(List.class, I_Have_Interfaces.getInterfaces()[0]);\n                assertEquals(Serializable.class, I_Have_Interfaces.getInterfaces()[1]);\n                assertEquals(2, I_Have_Interfaces.getInterfaces().length);\n\n                // I_Have_Both_Class_And_Interface\n                Class<?> I_Have_Both_Class_And_Interface = classLoader.loadClass(\"I_Have_Both_Class_And_Interface\");\n                assertEquals(List.class, I_Have_Both_Class_And_Interface.getInterfaces()[0]);\n                assertEquals(1, I_Have_Both_Class_And_Interface.getInterfaces().length);\n                assertEquals(I_Am_A_Class, I_Have_Both_Class_And_Interface.getSuperclass());\n\n                // My_Constructor_Is_Private_But_Type_Is_Still_Public\n                Class<?> My_Constructor_Is_Private_But_Type_Is_Still_Public = classLoader.loadClass(\"My_Constructor_Is_Private_But_Type_Is_Still_Public\");\n                assertTrue(Modifier.isPublic(My_Constructor_Is_Private_But_Type_Is_Still_Public.getModifiers()));\n                assertTrue(Modifier.isPrivate(My_Constructor_Is_Private_But_Type_Is_Still_Public.getDeclaredConstructors()[0].getModifiers()));\n\n                // I_Have_Fields\n                Class<?> I_Have_Fields = classLoader.loadClass(\"I_Have_Fields\");\n                Field I_Have_Fields_i_am_field = I_Have_Fields.getDeclaredField(\"i_am_field\");\n                I_Have_Fields_i_am_field.setAccessible(true);\n                Field I_Have_Fields_i_am_a_field_with_init_value = I_Have_Fields.getDeclaredField(\"i_am_a_field_with_init_value\");\n                I_Have_Fields_i_am_a_field_with_init_value.setAccessible(true);\n                assertEquals(int.class, I_Have_Fields_i_am_field.getType());\n                assertEquals(Object.class, I_Have_Fields_i_am_a_field_with_init_value.getType());\n\n                Object I_Have_Fields_o = I_Have_Fields.newInstance();\n                assertEquals(0, I_Have_Fields_i_am_field.get(I_Have_Fields_o));\n                assertEquals(\"init value\", I_Have_Fields_i_am_a_field_with_init_value.get(I_Have_Fields_o));\n\n                // I_Have_Methods\n                Class<?> I_Have_Methods = classLoader.loadClass(\"I_Have_Methods\");\n                Object I_Have_Methods_o = I_Have_Methods.newInstance();\n\n                Method i_am_a_simple_method = I_Have_Methods.getDeclaredMethod(\"i_am_a_simple_method\");\n                assertEquals(Object.class, i_am_a_simple_method.getReturnType());\n\n                Method i_am_a_method_with_return_type_spec = I_Have_Methods.getDeclaredMethod(\"i_am_a_method_with_return_type_spec\");\n                assertEquals(void.class, i_am_a_method_with_return_type_spec.getReturnType());\n\n                Method i_am_a_method_with_only_one_statement = I_Have_Methods.getDeclaredMethod(\"i_am_a_method_with_only_one_statement\");\n                assertEquals(Object.class, i_am_a_method_with_only_one_statement.getReturnType());\n                assertEquals(\"this object will be returned\", i_am_a_method_with_only_one_statement.invoke(I_Have_Methods_o));\n\n                Method i_am_a_method_with_only_one_statement_with_return_type = I_Have_Methods.getDeclaredMethod(\"i_am_a_method_with_only_one_statement_with_return_type\");\n                assertEquals(String.class, i_am_a_method_with_only_one_statement_with_return_type.getReturnType());\n                assertEquals(\"this string will be returned\", i_am_a_method_with_only_one_statement_with_return_type.invoke(I_Have_Methods_o));\n\n                Method i_am_a_method_with_no_statements = I_Have_Methods.getDeclaredMethod(\"i_am_a_method_with_no_statements\");\n                assertEquals(Object.class, i_am_a_method_with_no_statements.getReturnType());\n\n                Method i_have_parameters = I_Have_Methods.getDeclaredMethod(\"i_have_parameters\", Object.class);\n                assertEquals(Object.class, i_have_parameters.getReturnType());\n\n                // I_Have_Statements\n                Class<?> I_Have_Statements = classLoader.loadClass(\"I_Have_Statements\");\n                Field I_Have_Statements_list = I_Have_Statements.getDeclaredField(\"list\");\n                I_Have_Statements_list.setAccessible(true);\n                Object I_Have_Statements_o = I_Have_Statements.newInstance();\n                assertEquals(Collections.singletonList(1), I_Have_Statements_list.get(I_Have_Statements_o));\n\n                // I_Have_Static\n                Class<?> I_Have_Static = classLoader.loadClass(\"I_Have_Static\");\n                Field I_Have_Static_field = I_Have_Static.getDeclaredField(\"field\");\n                assertTrue(Modifier.isStatic(I_Have_Static_field.getModifiers()));\n                Method I_Have_Static_method = I_Have_Static.getDeclaredMethod(\"method\");\n                assertTrue(Modifier.isStatic(I_Have_Static_method.getModifiers()));\n                Field I_Have_Static_list = I_Have_Static.getDeclaredField(\"list\");\n                I_Have_Static_list.setAccessible(true);\n                assertTrue(Modifier.isStatic(I_Have_Static_list.getModifiers()));\n                assertEquals(Arrays.asList(1, 2), I_Have_Static_list.get(null));\n                Field I_Have_Static_field2 = I_Have_Static.getDeclaredField(\"field2\");\n                assertTrue(Modifier.isStatic(I_Have_Static_field2.getModifiers()));\n                Method I_Have_Static_method2 = I_Have_Static.getDeclaredMethod(\"method2\");\n                assertTrue(Modifier.isStatic(I_Have_Static_method2.getModifiers()));\n\n                // data class\n                Class<?> DataClass = classLoader.loadClass(\"DataClass\");\n                assertEquals(DataClass.newInstance(), DataClass.newInstance());\n                assertEquals(\"DataClass()\", DataClass.newInstance().toString());\n\n                // DataClassWithFields\n                Class<?> DataClassWithFields = classLoader.loadClass(\"DataClassWithFields\");\n                DataClassWithFields.getDeclaredField(\"id\");\n                DataClassWithFields.getDeclaredField(\"name\");\n\n                // DataClassWithMethods\n                Class<?> DataClassWithMethods = classLoader.loadClass(\"DataClassWithMethods\");\n                Method i_am_a_method_in_data_class = DataClassWithMethods.getMethod(\"i_am_a_method_in_data_class\");\n                assertEquals(\"1\", i_am_a_method_in_data_class.invoke(DataClassWithMethods.newInstance()));\n\n                // I_Am_An_Interface\n                Class<?> I_Am_An_Interface = classLoader.loadClass(\"I_Am_An_Interface\");\n                assertTrue(I_Am_An_Interface.isInterface());\n\n                // Interface_Have_Fields\n                Class<?> Interface_Have_Fields = classLoader.loadClass(\"Interface_Have_Fields\");\n                assertTrue(Interface_Have_Fields.isInterface());\n                Field Interface_Have_Fields_field = Interface_Have_Fields.getField(\"field\");\n                assertEquals(Modifier.PUBLIC | Modifier.STATIC | Modifier.FINAL, Interface_Have_Fields_field.getModifiers());\n                assertEquals(1, Interface_Have_Fields_field.get(null));\n\n                // Interface_Have_Methods\n                Class<?> Interface_Have_Methods = classLoader.loadClass(\"Interface_Have_Methods\");\n                assertTrue(Interface_Have_Methods.isInterface());\n                Method i_am_an_abstract_method = Interface_Have_Methods.getMethod(\"i_am_an_abstract_method\");\n                assertTrue(Modifier.isAbstract(i_am_an_abstract_method.getModifiers()));\n                // assertTrue(i_am_a_default_method.isDefault());\n                // it's not supported now\n\n                // TesterForInterface_Have_Methods\n                Class<?> TesterForInterface_Have_Methods = classLoader.loadClass(\"TesterForInterface_Have_Methods\");\n                assertEquals(Interface_Have_Methods, TesterForInterface_Have_Methods.getInterfaces()[0]);\n                Object TesterForInterface_Have_Methods_o = TesterForInterface_Have_Methods.newInstance();\n                assertEquals(\"abs method impl\", i_am_an_abstract_method.invoke(TesterForInterface_Have_Methods_o));\n\n                // I_Am_A_Function\n                Class<?> I_Am_A_Function = classLoader.loadClass(\"I_Am_A_Function\");\n                assertEquals(\"I_Am_A_Function\", I_Am_A_Function.getName());\n                assertEquals(Function0.class, I_Am_A_Function.getInterfaces()[0]);\n                Function0 f0 = (Function0) I_Am_A_Function.newInstance();\n                assertEquals(1, f0.apply());\n\n                // I_Am_A_Function_With_One_Param\n                Class<?> I_Am_A_Function_With_One_Param = classLoader.loadClass(\"I_Am_A_Function_With_One_Param\");\n                assertEquals(Function1.class, I_Am_A_Function_With_One_Param.getInterfaces()[0]);\n                Function1 f1 = (Function1) I_Am_A_Function_With_One_Param.newInstance();\n                assertEquals(1, f1.apply(2));\n\n                // I_Am_A_Function_With_Super_Type\n                Class<?> I_Am_A_Function_With_Super_Type = classLoader.loadClass(\"I_Am_A_Function_With_Super_Type\");\n                assertEquals(Function1.class, I_Am_A_Function_With_Super_Type.getInterfaces()[0]);\n                @SuppressWarnings(\"unchecked\")\n                Function1<Object, Object> ff = (Function1<Object, Object>) I_Am_A_Function_With_Super_Type.newInstance();\n                assertEquals(1, ff.apply(0));\n        }\n\n        @Test\n        public void testFunCompile() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/fun.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"fun.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                Class<?> TestStdCout = classLoader.loadClass(\"TestStdCout\");\n                TestStdCout.newInstance();\n        }\n\n        @Test\n        public void testRational() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/examples/rational.lt\");\n\n                final Map<String, byte[]> map = generate(new BufferedReader(new InputStreamReader(is)), \"rational.lt\");\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, map.get(name), 0, map.get(name).length);\n                        }\n                };\n\n                Class<?> Rational = classLoader.loadClass(\"lt.demo.examples.Rational\");\n                Constructor<?> con = Rational.getConstructor(int.class, int.class);\n                Constructor<?> con2 = Rational.getConstructor(int.class);\n\n                Object r_1_2 = con.newInstance(1, 2);\n                assertEquals(\"1/2\", r_1_2.toString());\n\n                Object r_4_2 = con.newInstance(4, 2);\n                assertEquals(\"2\", r_4_2.toString());\n\n                assertEquals(\"2\", con2.newInstance(2).toString());\n\n                Object r_neg1_2 = con.newInstance(-1, 2);\n                assertEquals(\"-1/2\", r_neg1_2.toString());\n\n                Object r_neg4_2 = con.newInstance(-4, 2);\n                assertEquals(\"-2\", r_neg4_2.toString());\n\n                Object r_1_4 = con.newInstance(1, 4);\n\n                assertEquals(r_1_2, con.newInstance(2, 4));\n                assertNotEquals(r_1_2, new Object());\n                assertNotEquals(r_1_2, r_neg1_2);\n                assertNotEquals(r_1_2, r_1_4);\n\n                assertEquals(3, r_1_2.hashCode());\n                assertEquals(3, r_4_2.hashCode());\n                assertEquals(1, r_neg1_2.hashCode());\n                assertEquals(-1, r_neg4_2.hashCode());\n                assertEquals(5, r_1_4.hashCode());\n\n                Method add = Rational.getMethod(\"add\", Rational);\n                assertEquals(con.newInstance(5, 2), add.invoke(r_1_2, r_4_2));\n\n                Method subtract = Rational.getMethod(\"subtract\", Rational);\n                assertEquals(con.newInstance(-3, 2), subtract.invoke(r_1_2, r_4_2));\n\n                Method multiply = Rational.getMethod(\"multiply\", Rational);\n                assertEquals(con.newInstance(1, 1), multiply.invoke(r_1_2, r_4_2));\n\n                Method divide = Rational.getMethod(\"divide\", Rational);\n                assertEquals(con.newInstance(1, 4), divide.invoke(r_1_2, r_4_2));\n\n                Class<?> TestRational = classLoader.loadClass(\"lt.demo.examples.TestRational\");\n                assertEquals(con.newInstance(5, 2), TestRational.getMethod(\"testAdd\", Rational, Rational).invoke(null, r_1_2, r_4_2));\n                assertEquals(con.newInstance(-3, 2), TestRational.getMethod(\"testSubtract\", Rational, Rational).invoke(null, r_1_2, r_4_2));\n                assertEquals(con.newInstance(1, 1), TestRational.getMethod(\"testMultiply\", Rational, Rational).invoke(null, r_1_2, r_4_2));\n                assertEquals(con.newInstance(1, 4), TestRational.getMethod(\"testDivide\", Rational, Rational).invoke(null, r_1_2, r_4_2));\n                assertEquals(false, TestRational.getMethod(\"testEquals\", Rational, Rational).invoke(null, r_1_2, r_neg1_2));\n                assertEquals(true, TestRational.getMethod(\"testEquals\", Rational, Rational).invoke(null, r_1_2, con.newInstance(1, 2)));\n        }\n\n\n        @Test\n        public void testList_Map() throws Exception {\n                InputStream is = TestDemo.class.getResourceAsStream(\"/lang-demo/list-map.lts\");\n                StringBuilder sb = new StringBuilder();\n                sb.append(\"import java::util::_\\nclass list_map\\n\");\n                BufferedReader br = new BufferedReader(new InputStreamReader(is));\n                String line;\n                while ((line = br.readLine()) != null) {\n                        sb.append(\"    \").append(line).append(\"\\n\");\n                }\n\n                final Map<String, byte[]> byteMap = generate(new BufferedReader(new StringReader(sb.toString())), \"list-map.lts\");\n\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                byte[] bs = byteMap.get(name);\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                Class<?> cls = classLoader.loadClass(\"list_map\");\n                Object o = cls.newInstance();\n                // ls\n                Field ls = cls.getDeclaredField(\"ls\");\n                ls.setAccessible(true);\n                assertEquals(Arrays.asList(\"z\", \"y\", \"x\"), ls.get(o));\n                // list\n                Field list = cls.getDeclaredField(\"list\");\n                list.setAccessible(true);\n                assertEquals(Arrays.asList(\"u\", \"v\", \"w\", \"b\", \"a\"), list.get(o));\n                // concatRes\n                Field concatRes = cls.getDeclaredField(\"concatRes\");\n                concatRes.setAccessible(true);\n                assertEquals(Arrays.asList(\"a\", \"b\", \"z\", \"y\", \"x\"), concatRes.get(o));\n                // str\n                Field str = cls.getDeclaredField(\"str\");\n                str.setAccessible(true);\n                assertEquals(\"a,b,w,v,u\", str.get(o));\n                // str2\n                Field str2 = cls.getDeclaredField(\"str2\");\n                str2.setAccessible(true);\n                assertEquals(\"u,v,w,b,a\", str2.get(o));\n                // list2\n                Field list2 = cls.getDeclaredField(\"list2\");\n                list2.setAccessible(true);\n                assertEquals(Arrays.asList(\"r\", \"s\", \"t\", \"v\", \"w\", \"b\", \"a\"), list2.get(o));\n                // shiftResult\n                Field shiftResult = cls.getDeclaredField(\"shiftResult\");\n                shiftResult.setAccessible(true);\n                assertEquals(\"u\", shiftResult.get(o));\n                // sliceResult1\n                Field sliceResult1 = cls.getDeclaredField(\"sliceResult1\");\n                sliceResult1.setAccessible(true);\n                assertEquals(Arrays.asList(\"w\", \"b\"), sliceResult1.get(o));\n                // sliceResult2\n                Field sliceResult2 = cls.getDeclaredField(\"sliceResult2\");\n                sliceResult2.setAccessible(true);\n                assertEquals(Arrays.asList(\"w\", \"b\", \"a\"), sliceResult2.get(o));\n                // lengthResult\n                Field lengthResult = cls.getDeclaredField(\"lengthResult\");\n                lengthResult.setAccessible(true);\n                assertEquals(7, lengthResult.get(o));\n                // m\n                Field m = cls.getDeclaredField(\"m\");\n                m.setAccessible(true);\n                Map<String, Integer> jm = new LinkedHashMap<String, Integer>();\n                jm.put(\"a\", 1);\n                jm.put(\"b\", 2);\n                assertEquals(jm, m.get(o));\n                // map\n                Field map = cls.getDeclaredField(\"map\");\n                map.setAccessible(true);\n                jm.clear();\n                jm.put(\"c\", 3);\n                jm.put(\"d\", 4);\n                assertEquals(jm, map.get(o));\n                // map2\n                Field map2 = cls.getDeclaredField(\"map2\");\n                map2.setAccessible(true);\n                jm.clear();\n                jm.put(\"a\", 1);\n                jm.put(\"b\", 2);\n                jm.put(\"c\", 3);\n                jm.put(\"d\", 4);\n                assertEquals(jm, map2.get(o));\n                // a_res\n                Field a_res = cls.getDeclaredField(\"a_res\");\n                a_res.setAccessible(true);\n                assertEquals(1, a_res.get(o));\n                // b_res\n                Field b_res = cls.getDeclaredField(\"b_res\");\n                b_res.setAccessible(true);\n                assertEquals(2, b_res.get(o));\n                // c_res\n                Field c_res = cls.getDeclaredField(\"c_res\");\n                c_res.setAccessible(true);\n                assertEquals(3, c_res.get(o));\n        }\n\n        @Test\n        public void testScriptPass_Literals() throws Throwable {\n                ScriptCompiler sc = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n                sc.compile(\"literals.lts\", new InputStreamReader(TestDemo.class.getResourceAsStream(\"/lang-demo/literals.lts\"))).run();\n        }\n\n        @Test\n        public void testScriptPass_Statements() throws Throwable {\n                ScriptCompiler sc = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n                sc.compile(\"statements.lts\", new InputStreamReader(TestDemo.class.getResourceAsStream(\"/lang-demo/statements.lts\"))).run();\n        }\n\n        @Test\n        public void testScriptPass_List_map() throws Throwable {\n                ScriptCompiler sc = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n                sc.compile(\"list-map.lts\", new InputStreamReader(TestDemo.class.getResourceAsStream(\"/lang-demo/list-map.lts\"))).run();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestDotPackage.java",
    "content": "package lt.compiler.cases;\n\nimport lt.compiler.cases.anno.TestFieldAnno;\nimport lt.repl.Compiler;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.script.ScriptEngine;\nimport javax.script.ScriptEngineManager;\n\nimport java.util.HashMap;\n\nimport static org.junit.Assert.*;\n\n/**\n * test dot package\n */\npublic class TestDotPackage {\n        private ScriptEngine scriptEngine;\n\n        private Class<?> compile(String className, final String... codes) throws Exception {\n                Compiler compiler = new Compiler(Thread.currentThread().getContextClassLoader());\n                ClassLoader cl = compiler.compile(new HashMap<String, String>() {{\n                        int i = 0;\n                        for (String code : codes) {\n                                put(\"f\" + (i++), code);\n                        }\n                }});\n                return cl.loadClass(className);\n        }\n\n        @Before\n        public void setUp() throws Exception {\n                scriptEngine = new ScriptEngineManager().getEngineByName(\"Latte-lang\");\n        }\n\n        @Test\n        public void testGetType() throws Exception {\n                scriptEngine.eval(\"c = type java.lang.Object\");\n                assertEquals(Object.class, scriptEngine.get(\"c\"));\n        }\n\n        @Test\n        public void testGetTypeLong() throws Exception {\n                scriptEngine.eval(\"c = type lt.compiler.cases.anno.TestFieldAnno\");\n                assertEquals(TestFieldAnno.class, scriptEngine.get(\"c\"));\n        }\n\n        @Test\n        public void testAccess() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package x::y::z::a::b::c\\n\" +\n                                \"class X {\\n\" +\n                                \"    static\\n\" +\n                                \"        a = 100\\n\" +\n                                \"}\",\n                        \"\" +\n                                \"class R {\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = x.y.z.a.b.c.X.a\\n\" +\n                                \"}\"\n                );\n                assertEquals(100, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testInvoke() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package a::b::c::d::e\\n\" +\n                                \"class X {\\n\" +\n                                \"    static\\n\" +\n                                \"        def a = 200\\n\" +\n                                \"}\",\n                        \"\" +\n                                \"class R {\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = a.b.c.d.e.X.a()\\n\" +\n                                \"}\"\n                );\n                assertEquals(200, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testNew() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package m::n::o::p::q\\n\" +\n                                \"class X\\n\" +\n                                \"    public f = 123\",\n                        \"\" +\n                                \"class R\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = m.n.o.p.q.X().f\"\n                );\n                assertEquals(123, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testPackageName() throws Exception {\n                Class<?> R = compile(\"x.y.z.m.n.o.p.q.R\", \"\" +\n                        \"package x.y.z.m.n.o.p.q\\n\" +\n                        \"class R\"\n                );\n                assertEquals(\"x.y.z.m.n.o.p.q.R\", R.getName());\n        }\n\n        @Test\n        public void testImport() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package a.b.c.d.e.f\\n\" +\n                                \"class X\\n\" +\n                                \"    static\\n\" +\n                                \"        a = 1\",\n                        \"\" +\n                                \"import a.b.c.d.e.f._\\n\" +\n                                \"class R\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = X.a\"\n                );\n                assertEquals(1, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testImportStatic() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package a.b.c.d.e.f\\n\" +\n                                \"class X\\n\" +\n                                \"    static\\n\" +\n                                \"        a = 2\",\n                        \"\" +\n                                \"import a.b.c.d.e.f.X._\\n\" +\n                                \"class R\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = a\"\n                );\n                assertEquals(2, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testImportShort() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"package a\\n\" +\n                                \"class X\\n\" +\n                                \"    static\\n\" +\n                                \"        a = 3\",\n                        \"\" +\n                                \"import a._\\n\" +\n                                \"class R\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = X.a\"\n                );\n                assertEquals(3, R.getMethod(\"m\").invoke(null));\n        }\n\n        @Test\n        public void testImportStaticShort() throws Exception {\n                Class<?> R = compile(\"R\", \"\" +\n                                \"class X\\n\" +\n                                \"    static\\n\" +\n                                \"        a = 4\",\n                        \"\" +\n                                \"import X._\\n\" +\n                                \"class R\\n\" +\n                                \"    static\\n\" +\n                                \"        def m = a\");\n                assertEquals(4, R.getMethod(\"m\").invoke(null));\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestLambdaGen.java",
    "content": "package lt.compiler.cases;\n\nimport lt.compiler.functionalInterfaces.*;\nimport lt.lang.Pointer;\nimport lt.lang.function.Function0;\nimport lt.lang.function.Function1;\nimport lt.repl.Compiler;\nimport lt.repl.scripting.CL;\nimport lt.runtime.LambdaGen;\nimport org.junit.Assert;\nimport org.junit.Test;\n\nimport java.lang.reflect.Method;\nimport java.util.Map;\n\nimport static org.junit.Assert.*;\n\n/**\n * test lambda generator\n */\npublic class TestLambdaGen {\n        @Test\n        public void testNoParamReturnUnit() throws Exception {\n                final Pointer<String> p = new Pointer<String>(false, false);\n                final Pointer<Object> selfPointer = new Pointer<Object>(false, false);\n                Function0<Object> f = new Function0<Object>() {\n                        public Object self;\n\n                        @Override\n                        public Object apply() throws Exception {\n                                try {\n                                        p.set(\"hello\");\n                                        selfPointer.set(this.self);\n                                } catch (Throwable throwable) {\n                                        throw new AssertionError(throwable);\n                                }\n                                return null;\n                        }\n                };\n                Map.Entry<String, byte[]> res = LambdaGen.gen(f, NoParamReturnUnit.class);\n                String clsName = res.getKey();\n                byte[] bytes = res.getValue();\n                CL cl = new CL(Thread.currentThread().getContextClassLoader());\n                cl.addByteCodes(clsName, bytes);\n                @SuppressWarnings(\"unchecked\")\n                Class<NoParamReturnUnit> resCls = (Class<NoParamReturnUnit>) cl.loadClass(clsName);\n                NoParamReturnUnit o = resCls.getConstructor(Function0.class).newInstance(f);\n                o.x();\n\n                assertEquals(\"hello\", p.get());\n                assertTrue(selfPointer.get() instanceof NoParamReturnUnit);\n        }\n\n        @Test\n        public void testPrimitiveInReturnUnit() throws Exception {\n                final Pointer<Object> p = new Pointer<Object>(false, false);\n                final Pointer<Object> selfPointer = new Pointer<Object>(false, false);\n                Function1<Object, Object> f = new Function1<Object, Object>() {\n                        public Object self;\n\n                        @Override\n                        public Object apply(Object o) throws Exception {\n                                try {\n                                        selfPointer.set(this.self);\n                                        p.set(o);\n                                } catch (Throwable throwable) {\n                                        throw new AssertionError(throwable);\n                                }\n                                return null;\n                        }\n                };\n                Class<?>[] cases = new Class[]{\n                        IntParamReturnUnit.class,\n                        LongParamReturnUnit.class,\n                        FloatParamReturnUnit.class,\n                        DoubleParamReturnUnit.class,\n                        ByteParamReturnUnit.class,\n                        BoolParamReturnUnit.class,\n                        ShortParamReturnUnit.class,\n                        CharParamReturnUnit.class\n                };\n                for (Class<?> c : cases) {\n                        Method x = c.getMethods()[0];\n                        Class<?> param = x.getParameterTypes()[0];\n                        Object inputArg = generatePrimitive(param);\n                        Map.Entry<String, byte[]> res = LambdaGen.gen(f, c);\n                        String clsName = res.getKey();\n                        byte[] bytes = res.getValue();\n                        CL cl = new CL(Thread.currentThread().getContextClassLoader());\n                        cl.addByteCodes(clsName, bytes);\n                        @SuppressWarnings(\"unchecked\")\n                        Class<?> resCls = cl.loadClass(clsName);\n                        Object theObj = resCls.getConstructor(Function1.class).newInstance(f);\n                        x.invoke(theObj, inputArg);\n\n                        assertEquals(inputArg, p.get());\n                        assertTrue(c.isInstance(selfPointer.get()));\n                }\n        }\n\n        @Test\n        public void testIntParamReturnInt() throws Exception {\n                final Pointer<Object> selfPointer = new Pointer<Object>(false, false);\n                Function1<Object, Object> f = new Function1<Object, Object>() {\n                        public Object self;\n\n                        @Override\n                        public Object apply(Object o) throws Exception {\n                                try {\n                                        selfPointer.set(this.self);\n                                } catch (Throwable throwable) {\n                                        throw new AssertionError(throwable);\n                                }\n                                return o;\n                        }\n                };\n                Map.Entry<String, byte[]> res = LambdaGen.gen(f, IntParamReturnInt.class);\n                String clsName = res.getKey();\n                byte[] bytes = res.getValue();\n                CL cl = new CL(Thread.currentThread().getContextClassLoader());\n                cl.addByteCodes(clsName, bytes);\n                @SuppressWarnings(\"unchecked\")\n                Class<IntParamReturnInt> resCls = (Class<IntParamReturnInt>) cl.loadClass(clsName);\n                IntParamReturnInt o = resCls.getConstructor(Function1.class).newInstance(f);\n\n                assertEquals(22, o.x(22));\n                assertTrue(selfPointer.get() instanceof IntParamReturnInt);\n        }\n\n        @Test\n        public void testNoParamReturnPrimitive() throws Exception {\n                Class<?>[] cases = new Class[]{\n                        NoParamReturnInt.class,\n                        NoParamReturnFloat.class,\n                        NoParamReturnLong.class,\n                        NoParamReturnDouble.class,\n                        NoParamReturnByte.class,\n                        NoParamReturnBool.class,\n                        NoParamReturnShort.class,\n                        NoParamReturnChar.class\n                };\n                for (Class<?> c : cases) {\n                        final Pointer<Object> selfPointer = new Pointer<Object>(false, false);\n\n                        Method x = c.getMethods()[0];\n                        final Class<?> returnType = x.getReturnType();\n                        Function0<Object> f = new Function0<Object>() {\n                                public Object self;\n\n                                @Override\n                                public Object apply() throws Exception {\n                                        try {\n                                                selfPointer.set(this.self);\n                                        } catch (Throwable throwable) {\n                                                throw new AssertionError(throwable);\n                                        }\n\n                                        return generatePrimitive(returnType);\n                                }\n                        };\n                        Map.Entry<String, byte[]> res = LambdaGen.gen(f, c);\n                        String clsName = res.getKey();\n                        byte[] bytes = res.getValue();\n                        CL cl = new CL(Thread.currentThread().getContextClassLoader());\n                        cl.addByteCodes(clsName, bytes);\n                        @SuppressWarnings(\"unchecked\")\n                        Class<?> resCls = cl.loadClass(clsName);\n                        Object theObj = resCls.getConstructor(Function0.class).newInstance(f);\n\n                        assertEquals(generatePrimitive(returnType), x.invoke(theObj));\n                        assertTrue(c.isInstance(selfPointer.get()));\n                }\n        }\n\n        private Object generatePrimitive(Class<?> param) {\n                Object inputArg;\n                if (param == int.class) {\n                        inputArg = 22;\n                } else if (param == float.class) {\n                        inputArg = 33f;\n                } else if (param == double.class) {\n                        inputArg = 44.0;\n                } else if (param == long.class) {\n                        inputArg = 55L;\n                } else if (param == byte.class) {\n                        inputArg = (byte) 66;\n                } else if (param == char.class) {\n                        inputArg = (char) 77;\n                } else if (param == short.class) {\n                        inputArg = (short) 88;\n                } else if (param == boolean.class) {\n                        inputArg = true;\n                } else {\n                        fail(\"should not reach here\");\n                        return null;\n                }\n                return inputArg;\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestLang.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.runtime.LtRuntime;\nimport lt.util.RangeList;\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.Collections;\n\nimport static org.junit.Assert.*;\n\n/**\n * lang\n */\npublic class TestLang {\n        @Test\n        public void testRangeListSize() throws Exception {\n                RangeList list = new RangeList(1, 4, true);\n                assertEquals(4, list.size());\n        }\n\n        @Test\n        public void testRangeListGet() throws Exception {\n                RangeList list = new RangeList(1, 4, true);\n                assertEquals(2, list.get(1));\n        }\n\n        @Test\n        public void testRangeListEquals() throws Exception {\n                RangeList list = new RangeList(1, 4, true);\n                assertEquals(Arrays.asList(1, 2, 3, 4), list);\n        }\n\n        @Test\n        public void testRangeList1_1() throws Exception {\n                RangeList list = new RangeList(1, 1, true);\n                assertEquals(Collections.singletonList(1), list);\n\n                RangeList list2 = new RangeList(1, 1, false);\n                assertEquals(Collections.emptyList(), list2);\n        }\n\n        @Test\n        public void testRequire() throws Throwable {\n                Object o1 = LtRuntime.require(this.getClass(), \"cp:test_require2.lts\");\n                Object o2 = LtRuntime.require(this.getClass(), \"cp:test_require2.lts\");\n                assertTrue(o1 == o2);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestOptimizePointer.java",
    "content": "package lt.compiler.cases;\n\nimport lt.dependencies.asm.ClassReader;\nimport lt.dependencies.asm.ClassVisitor;\nimport lt.dependencies.asm.MethodVisitor;\nimport lt.dependencies.asm.Opcodes;\nimport lt.lang.Pointer;\nimport org.junit.Test;\n\nimport java.util.Arrays;\n\nimport static lt.compiler.cases.TestCodeGen.retrieveClass;\nimport static lt.compiler.cases.TestCodeGen.retrieveByteCode;\n\nimport static org.junit.Assert.*;\n\n/**\n * test optimize pointer\n */\npublic class TestOptimizePointer {\n        @Test\n        public void testPrimitivePass() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class TestPrimitive\\n\" +\n                                \"  def f_int(i:int)=null\\n\" +\n                                \"  def f_float(f:float)=null\\n\" +\n                                \"  def f_double(d:double)=null\\n\" +\n                                \"  def f_long(l:long)=null\\n\" +\n                                \"  def f_bool(b:bool)=null\\n\" +\n                                \"  def f_char(c:char)=null\\n\" +\n                                \"  def f_byte(b:byte)=null\\n\" +\n                                \"  def f_short(s:short)=null\\n\"\n                        , \"TestPrimitive\");\n                for (Class<?> c : Arrays.asList(\n                        int.class, float.class, double.class, long.class,\n                        boolean.class, char.class, byte.class, short.class\n                )) {\n                        if (c == boolean.class) {\n                                cls.getMethod(\"f_bool\", c);\n                        } else {\n                                cls.getMethod(\"f_\" + c.getName(), c);\n                        }\n                }\n        }\n\n        private void _testByteCodeNoMethod(byte[] bytes, int methodCount) {\n                ClassReader cr = new ClassReader(bytes);\n                final Pointer<Integer> count = new Pointer<Integer>(false, false);\n                try {\n                        count.set(0);\n                } catch (Throwable throwable) {\n                        throwable.printStackTrace();\n                        fail(\"error\");\n                }\n                cr.accept(new ClassVisitor(Opcodes.ASM5) {\n                        @Override\n                        public MethodVisitor visitMethod(int access, String name, String desc, String signature, String[] exceptions) {\n                                if (name.contains(\"$\")) {\n                                        return null;\n                                }\n                                if (!name.equals(\"<init>\") && !name.equals(\"<clinit>\")) {\n                                        try {\n                                                count.set(count.get() + 1);\n                                        } catch (Throwable throwable) {\n                                                throwable.printStackTrace();\n                                                fail(\"error\");\n                                        }\n                                }\n                                return new MethodVisitor(Opcodes.ASM5) {\n                                        @Override\n                                        public void visitMethodInsn(int opcode, String owner, String name, String desc, boolean itf) {\n                                                if (!name.equals(\"<init>\") && !owner.contains(\"$Latte$Lambda$\")) {\n                                                        fail();\n                                                }\n                                        }\n                                };\n                        }\n                }, 0);\n                int i_count = count.get();\n                assertEquals(methodCount, i_count);\n        }\n\n        @Test\n        public void testByteCode() throws Exception {\n                byte[] bytes = retrieveByteCode(\"\" +\n                        \"class TestByteCodeInt\\n\" +\n                        \"  def f_int(i:int):int=i\\n\" +\n                        \"  def f_float(f:float):float=f\\n\" +\n                        \"  def f_double(d:double):double=d\\n\" +\n                        \"  def f_long(l:long):long=l\\n\" +\n                        \"  def f_bool(b:bool):bool=b\\n\" +\n                        \"  def f_char(c:char):char=c\\n\" +\n                        \"  def f_byte(b:byte):byte=b\\n\" +\n                        \"  def f_short(s:short):short=s\\n\" +\n                        \"  def f_string(s:String):String=s\\n\")\n                        .get(\"TestByteCodeInt\");\n                _testByteCodeNoMethod(bytes, 9);\n        }\n\n        @Test\n        public void testByteCodeWithLambda() throws Exception {\n                byte[] bytes = retrieveByteCode(\"\" +\n                        \"class TestByteCodeWithLambda\\n\" +\n                        \"  def f_int(i:int)=()->1\\n\" +\n                        \"  def f_long(l:long)=()->1 as long\\n\" +\n                        \"  def f_string(s:String)=()->''\\n\")\n                        .get(\"TestByteCodeWithLambda\");\n                _testByteCodeNoMethod(bytes, 3);\n        }\n\n        @Test\n        public void testByteCodeWithInnerMethod() throws Exception {\n                byte[] bytes = retrieveByteCode(\"\" +\n                        \"class TestByteCodeWithInnerMethod\\n\" +\n                        \"  def f_int(i:int)\\n\" +\n                        \"    def x=1\\n\" +\n                        \"    null\\n\" +\n                        \"  def f_long(l:long)\\n\" +\n                        \"    def y=2\\n\" +\n                        \"    null\\n\" +\n                        \"  def f_string(s:String)\\n\" +\n                        \"    def z=3\\n\" +\n                        \"    null\")\n                        .get(\"TestByteCodeWithInnerMethod\");\n                _testByteCodeNoMethod(bytes, 3);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestParser.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.ElementStartNode;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.def.*;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.OneVariableOperation;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.operation.UnaryOneVariableOperation;\nimport lt.compiler.syntactic.pre.Import;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * test SyntacticProcessor\n */\npublic class TestParser {\n        private static List<Statement> parse(String stmt) throws IOException, SyntaxException {\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(stmt), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Parser syntacticProcessor = new Parser(root, new ErrorManager(true));\n\n                return syntacticProcessor.parse();\n        }\n\n        private static List<Statement> parseBrace(String stmt) throws IOException, SyntaxException {\n                BraceScanner processor = new BraceScanner(\"test\", new StringReader(stmt), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Parser syntacticProcessor = new Parser(root, new ErrorManager(true));\n\n                return syntacticProcessor.parse();\n        }\n\n        @Test\n        public void testOperatorInSamePriority() throws Exception {\n                List<Statement> statements = parse(\"1+2-3+4\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"+\", one, two, LineCol.SYNTHETIC);\n\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"-\", tvo1, three, LineCol.SYNTHETIC);\n\n                NumberLiteral four = new NumberLiteral(\"4\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo3 = new TwoVariableOperation(\"+\", tvo2, four, LineCol.SYNTHETIC);\n\n                assertEquals(tvo3, s);\n        }\n\n        @Test\n        public void testOperatorInDifferentPriorities() throws Exception {\n                List<Statement> statements = parse(\"1+2*3+4\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                NumberLiteral four = new NumberLiteral(\"4\", LineCol.SYNTHETIC);\n\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"*\", two, three, LineCol.SYNTHETIC);\n\n\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"+\", one, tvo1, LineCol.SYNTHETIC);\n\n\n                TwoVariableOperation tvo3 = new TwoVariableOperation(\"+\", tvo2, four, LineCol.SYNTHETIC);\n\n                assertEquals(tvo3, s);\n        }\n\n        @Test\n        public void test1Plus2() throws Exception {\n                List<Statement> statements = parse(\"1+2\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"+\", one, two, LineCol.SYNTHETIC);\n\n                assertEquals(tvo1, s);\n        }\n\n        @Test\n        public void test1Plus2Multi3() throws Exception {\n                List<Statement> statements = parse(\"1+2*3\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"*\", two, three, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"+\", one, tvo1, LineCol.SYNTHETIC);\n\n                assertEquals(tvo2, s);\n        }\n\n        @Test\n        public void test1Plus2Multi3Div4() throws Exception {\n                List<Statement> statements = parse(\"1+2*3/4\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                NumberLiteral four = new NumberLiteral(\"4\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"*\", two, three, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"/\", tvo1, four, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo3 = new TwoVariableOperation(\"+\", one, tvo2, LineCol.SYNTHETIC);\n\n                assertEquals(tvo3, s);\n        }\n\n        @Test\n        public void test1Plus2Multi3Div4Minus5() throws Exception {\n                List<Statement> statements = parse(\"1+2*3/4-5\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                NumberLiteral four = new NumberLiteral(\"4\", LineCol.SYNTHETIC);\n                NumberLiteral five = new NumberLiteral(\"5\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"*\", two, three, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"/\", tvo1, four, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo3 = new TwoVariableOperation(\"+\", one, tvo2, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo4 = new TwoVariableOperation(\"-\", tvo3, five, LineCol.SYNTHETIC);\n\n                assertEquals(tvo4, s);\n        }\n\n        @Test\n        public void testPar1Plus2ParMulti3() throws Exception {\n                List<Statement> statements = parse(\"(1+2)*3\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"+\", one, two, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"*\", tvo1, three, LineCol.SYNTHETIC);\n\n                assertEquals(tvo2, s);\n        }\n\n        @Test\n        public void test2VarOperatorFinal() throws Exception {\n                List<Statement> statements = parse(\"1*3/(4+5)*6-(7/8+9)-10-15\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                NumberLiteral four = new NumberLiteral(\"4\", LineCol.SYNTHETIC);\n                NumberLiteral five = new NumberLiteral(\"5\", LineCol.SYNTHETIC);\n                NumberLiteral six = new NumberLiteral(\"6\", LineCol.SYNTHETIC);\n                NumberLiteral seven = new NumberLiteral(\"7\", LineCol.SYNTHETIC);\n                NumberLiteral eight = new NumberLiteral(\"8\", LineCol.SYNTHETIC);\n                NumberLiteral nine = new NumberLiteral(\"9\", LineCol.SYNTHETIC);\n                NumberLiteral ten = new NumberLiteral(\"10\", LineCol.SYNTHETIC);\n                NumberLiteral fifteen = new NumberLiteral(\"15\", LineCol.SYNTHETIC);\n\n                TwoVariableOperation oneMULthree = new TwoVariableOperation(\"*\", one, three, LineCol.SYNTHETIC);\n                TwoVariableOperation fourPLUSfive = new TwoVariableOperation(\"+\", four, five, LineCol.SYNTHETIC);\n                TwoVariableOperation DIV1 = new TwoVariableOperation(\"/\", oneMULthree, fourPLUSfive, LineCol.SYNTHETIC);\n                TwoVariableOperation MUL1 = new TwoVariableOperation(\"*\", DIV1, six, LineCol.SYNTHETIC);\n                TwoVariableOperation sevenDIVIDEeight = new TwoVariableOperation(\"/\", seven, eight, LineCol.SYNTHETIC);\n                TwoVariableOperation DIVPLUSnine = new TwoVariableOperation(\"+\", sevenDIVIDEeight, nine, LineCol.SYNTHETIC);\n                TwoVariableOperation MINUS1 = new TwoVariableOperation(\"-\", MUL1, DIVPLUSnine, LineCol.SYNTHETIC);\n                TwoVariableOperation MINUS10 = new TwoVariableOperation(\"-\", MINUS1, ten, LineCol.SYNTHETIC);\n                TwoVariableOperation MINUS15 = new TwoVariableOperation(\"-\", MINUS10, fifteen, LineCol.SYNTHETIC);\n\n                assertEquals(MINUS15, s);\n        }\n\n        @Test\n        public void testOperators() throws Exception {\n                List<Statement> statements = parse(\"+1++ -3^!true+2+\\\"abc\\\"\");\n\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                OneVariableOperation postPlusPlus = new OneVariableOperation(\"++\", one, LineCol.SYNTHETIC);\n                UnaryOneVariableOperation plusOne = new UnaryOneVariableOperation(\"+\", postPlusPlus, LineCol.SYNTHETIC);\n                NumberLiteral three = new NumberLiteral(\"3\", LineCol.SYNTHETIC);\n                TwoVariableOperation minus = new TwoVariableOperation(\"-\", plusOne, three, LineCol.SYNTHETIC);\n\n                BoolLiteral tr = new BoolLiteral(\"true\", LineCol.SYNTHETIC);\n                UnaryOneVariableOperation not = new UnaryOneVariableOperation(\"!\", tr, LineCol.SYNTHETIC);\n\n                NumberLiteral two = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                TwoVariableOperation plusTwo = new TwoVariableOperation(\"+\", not, two, LineCol.SYNTHETIC);\n                StringLiteral abc = new StringLiteral(\"\\\"abc\\\"\", LineCol.SYNTHETIC);\n                TwoVariableOperation plusABC = new TwoVariableOperation(\"+\", plusTwo, abc, LineCol.SYNTHETIC);\n\n                TwoVariableOperation xor = new TwoVariableOperation(\"^\", minus, plusABC, LineCol.SYNTHETIC);\n\n                assertEquals(xor, s);\n        }\n\n        @Test\n        public void testPost1VarWithOperatorPriority() throws Exception {\n                List<Statement> statements = parse(\"1+1++ *1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                NumberLiteral n1 = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral n2 = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral n3 = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n\n                OneVariableOperation ovo = new OneVariableOperation(\"++\", n2, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo1 = new TwoVariableOperation(\"*\", ovo, n3, LineCol.SYNTHETIC);\n                TwoVariableOperation tvo2 = new TwoVariableOperation(\"+\", n1, tvo1, LineCol.SYNTHETIC);\n\n                assertEquals(tvo2, s);\n        }\n\n        @Test\n        public void testPackage() throws Exception {\n                List<Statement> statements = parse(\"java::lang::Integer\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                AST.PackageRef pkg = new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC);\n                AST.Access a = new AST.Access(pkg, \"Integer\", LineCol.SYNTHETIC);\n\n                assertEquals(a, s);\n        }\n\n        @Test\n        public void testPkgAccess() throws Exception {\n                List<Statement> statements = parse(\"java::lang::String.cls\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                AST.PackageRef pkg = new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(pkg, \"String\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access, \"cls\", LineCol.SYNTHETIC);\n\n                assertEquals(access2, s);\n        }\n\n        @Test\n        public void testInvocation() throws Exception {\n                List<Statement> statements = parse(\"java::lang::String.valueOf(true)\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                AST.PackageRef pkg = new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(pkg, \"String\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access, \"valueOf\", LineCol.SYNTHETIC);\n\n                AST.Invocation invocation = new AST.Invocation(access2,\n                        Collections.<Expression>singletonList(\n                                new BoolLiteral(\"true\", LineCol.SYNTHETIC)),\n                        false, LineCol.SYNTHETIC);\n\n                assertEquals(invocation, s);\n        }\n\n        @Test\n        public void testInvocationNoArg() throws Exception {\n                List<Statement> statements = parse(\"method()\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                AST.Invocation invocation = new AST.Invocation(new AST.Access(null, \"method\", LineCol.SYNTHETIC), Collections.<Expression>emptyList(), false, LineCol.SYNTHETIC);\n\n                assertEquals(invocation, s);\n        }\n\n        @Test\n        public void testVariableWithInitValue() throws Exception {\n                List<Statement> statements = parse(\"i=1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                NumberLiteral n = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                v.setInit(n);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_FullName() throws Exception {\n                List<Statement> statements = parse(\"i:java::lang::Integer\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.PackageRef pkg = new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(pkg, \"Integer\", LineCol.SYNTHETIC);\n                v.setType(access);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_SimpleName() throws Exception {\n                List<Statement> statements = parse(\"i:Integer\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(null, \"Integer\", LineCol.SYNTHETIC);\n                v.setType(access);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_FullName_Inner() throws Exception {\n                List<Statement> statements = parse(\"i:myPackage::ClassName.Inner\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.PackageRef pkg = new AST.PackageRef(\"myPackage\", LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(pkg, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_SimpleName_Inner() throws Exception {\n                List<Statement> statements = parse(\"i:ClassName.Inner\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(null, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_FullName_Init() throws Exception {\n                List<Statement> statements = parse(\"i:java::lang::Integer=1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.PackageRef pkg = new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(pkg, \"Integer\", LineCol.SYNTHETIC);\n                v.setType(access);\n\n                NumberLiteral n = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                v.setInit(n);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_SimpleName_Init() throws Exception {\n                List<Statement> statements = parse(\"i:Integer=1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access = new AST.Access(null, \"Integer\", LineCol.SYNTHETIC);\n                v.setType(access);\n\n                NumberLiteral n = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                v.setInit(n);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_FullName_Inner_Init() throws Exception {\n                List<Statement> statements = parse(\"i:myPackage::ClassName.Inner=1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.PackageRef pkg = new AST.PackageRef(\"myPackage\", LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(pkg, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                NumberLiteral n = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                v.setInit(n);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_SimpleName_Inner_Init() throws Exception {\n                List<Statement> statements = parse(\"i:ClassName.Inner=1\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(null, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                NumberLiteral n = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                v.setInit(n);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testVariableWithInitType_SimpleName_Inner_Init_Operator() throws Exception {\n                List<Statement> statements = parse(\"i:ClassName.Inner=1+2\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(null, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                NumberLiteral n1 = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral n2 = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                TwoVariableOperation o = new TwoVariableOperation(\"+\", n1, n2, LineCol.SYNTHETIC);\n                v.setInit(o);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testModifier() throws Exception {\n                List<Statement> statements = parse(\"val i:ClassName.Inner=1+2\");\n                assertEquals(1, statements.size());\n\n                Statement s = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", new HashSet<Modifier>(Collections.singletonList(new Modifier(Modifier.Available.VAL, LineCol.SYNTHETIC))), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                AST.Access access1 = new AST.Access(null, \"ClassName\", LineCol.SYNTHETIC);\n                AST.Access access2 = new AST.Access(access1, \"Inner\", LineCol.SYNTHETIC);\n                v.setType(access2);\n\n                NumberLiteral n1 = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                NumberLiteral n2 = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                TwoVariableOperation o = new TwoVariableOperation(\"+\", n1, n2, LineCol.SYNTHETIC);\n                v.setInit(o);\n\n                assertEquals(v, s);\n        }\n\n        @Test\n        public void testAssign() throws Exception {\n                List<Statement> statements = parse(\"i=1\\ni=2\");\n                assertEquals(2, statements.size());\n\n                Statement s = statements.get(1);\n\n                AST.Access access = new AST.Access(null, \"i\", LineCol.SYNTHETIC);\n                NumberLiteral n = new NumberLiteral(\"2\", LineCol.SYNTHETIC);\n                AST.Assignment ass = new AST.Assignment(access, \"=\", n, LineCol.SYNTHETIC);\n\n                assertEquals(ass, s);\n        }\n\n        @Test\n        public void testMethodNormal_NoParam() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"def method()\\n\" +\n                                \"    a=false\"\n                );\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new BoolLiteral(\"false\", LineCol.SYNTHETIC));\n\n                MethodDef methodDef = new MethodDef(\"method\",\n                        Collections.singleton(\n                                new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)\n                        ),\n                        null,\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testMethodType_NoParam() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"method():Integer\\n\" +\n                                \"    a=false\"\n                );\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new BoolLiteral(\"false\", LineCol.SYNTHETIC));\n\n                MethodDef methodDef = new MethodDef(\"method\",\n                        Collections.<Modifier>emptySet(),\n                        new AST.Access(null, \"Integer\", LineCol.SYNTHETIC),\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testMethodType_NoParam_NoStmt() throws Exception {\n                List<Statement> list = parse(\"method():Integer\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                MethodDef methodDef = new MethodDef(\"method\",\n                        Collections.<Modifier>emptySet(),\n                        new AST.Access(null, \"Integer\", LineCol.SYNTHETIC),\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testMethodEmpty_NoParam() throws Exception {\n                List<Statement> list = parse(\"method()=...\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                MethodDef methodDef = new MethodDef(\"method\",\n                        Collections.<Modifier>emptySet(),\n                        null,\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testMethodOne_Stmt_NoParam() throws Exception {\n                List<Statement> list = parse(\"method()=123\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                MethodDef methodDef = new MethodDef(\"method\",\n                        Collections.<Modifier>emptySet(),\n                        null,\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(\n                                new AST.Return(new NumberLiteral(\"123\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testMethodGeneral() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"abstract method(a,b:Character):Integer\\n\" +\n                                \"    a=false\"\n                );\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n                VariableDef a = new VariableDef(\"a\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                VariableDef b = new VariableDef(\"b\", new HashSet<Modifier>(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                b.setType(new AST.Access(null, \"Character\", LineCol.SYNTHETIC));\n                List<VariableDef> vars = Arrays.asList(a, b);\n\n                AST.Assignment assignment = new AST.Assignment(new AST.Access(null, \"a\", LineCol.SYNTHETIC), \"=\", new BoolLiteral(\"false\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n\n                MethodDef methodDef = new MethodDef(\n                        \"method\",\n                        new HashSet<Modifier>(Collections.singletonList(new Modifier(Modifier.Available.ABSTRACT, LineCol.SYNTHETIC))),\n                        new AST.Access(null, \"Integer\", LineCol.SYNTHETIC),\n                        vars,\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(assignment),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(methodDef, stmt);\n        }\n\n        @Test\n        public void testReturn() throws Exception {\n                List<Statement> list = parse(\"return i+1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.Access access = new AST.Access(null, \"i\", LineCol.SYNTHETIC);\n                NumberLiteral one = new NumberLiteral(\"1\", LineCol.SYNTHETIC);\n                TwoVariableOperation tvo = new TwoVariableOperation(\"+\", access, one, LineCol.SYNTHETIC);\n                AST.Return r = new AST.Return(tvo, LineCol.SYNTHETIC);\n\n                assertEquals(r, stmt);\n        }\n\n        @Test\n        public void testReturnVoid() throws Exception {\n                List<Statement> list = parse(\"return \");\n                assertEquals(1, list.size());\n\n                assertNull(((AST.Return) list.get(0)).exp);\n        }\n\n        @Test\n        public void testJavaName() throws Exception {\n                try {\n                        parse(\"val=1\");\n                        fail();\n                } catch (Exception ignore) {\n                }\n                List<Statement> list = parse(\"`val`=1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"val\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                List<Statement> list = parse(\"if true\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.If iff = new AST.If(Collections.singletonList(new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC)), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Collections.singletonList(new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC)), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_Elseif() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif boolval\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"boolval\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_Elseif_Body() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif boolval\\n\" +\n                        \"    a=2\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"boolval\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v2), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_Elseif_Body_Else() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif boolval\\n\" +\n                        \"    a=2\\n\" +\n                        \"else\\n\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"boolval\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v2), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(null, Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_Elseif_Body_Else_Body() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif boolval\\n\" +\n                        \"    a=2\\n\" +\n                        \"else\\n\" +\n                        \"    a=3\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n\n                VariableDef v3 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v3.setInit(new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"boolval\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v2), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(null, Collections.<Statement>singletonList(v3), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_2_Elseif_Body_Else_Body__1() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif bool1\\n\" +\n                        \"    a=2\\n\" +\n                        \"elseif bool2\\n\" +\n                        \"else\\n\" +\n                        \"    a=3\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n\n                VariableDef v4 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v4.setInit(new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"bool1\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v2), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"bool2\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(null, Collections.<Statement>singletonList(v4), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_2_Elseif_Else_Body() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif bool1\\n\" +\n                        \"elseif bool2\\n\" +\n                        \"else\\n\" +\n                        \"    a=3\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v4 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v4.setInit(new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"bool1\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"bool2\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(null, Collections.<Statement>singletonList(v4), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testIf_Body_Elseif_Else_Body() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"if true\\n\" +\n                        \"    a=1\\n\" +\n                        \"elseif bool2\\n\" +\n                        \"else\\n\" +\n                        \"    a=3\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v4 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v4.setInit(new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n                AST.If iff = new AST.If(Arrays.asList(\n                        new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v1), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(new AST.Access(null, \"bool2\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new AST.If.IfPair(null, Collections.<Statement>singletonList(v4), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(iff, stmt);\n        }\n\n        @Test\n        public void testFor1() throws Exception {\n                List<Statement> list = parse(\"for i in ite\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.For f = new AST.For(\"i\", new AST.Access(null, \"ite\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(f, stmt);\n        }\n\n        @Test\n        public void testFor2() throws Exception {\n                List<Statement> list = parse(\"for i in ite\\n    a=1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.For f = new AST.For(\"i\", new AST.Access(null, \"ite\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n                assertEquals(f, stmt);\n        }\n\n        @Test\n        public void testLambda_NO_PARAM() throws Exception {\n                List<Statement> list = parse(\"()->1+1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.Lambda l = new AST.Lambda(\n                        Collections.<VariableDef>emptyList(),\n                        Collections.<Statement>singletonList(\n                                new TwoVariableOperation(\"+\",\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(l, stmt);\n        }\n\n        @Test\n        public void testLambda_2_PARAM() throws Exception {\n                List<Statement> list = parse(\"(a,b)->a+b\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.Lambda l = new AST.Lambda(\n                        Arrays.asList(\n                                new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC),\n                                new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                        ),\n                        Collections.<Statement>singletonList(\n                                new TwoVariableOperation(\"+\",\n                                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                        new AST.Access(null, \"b\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(l, stmt);\n        }\n\n        @Test\n        public void testLambda_in_method_invocation() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"method(\\n\" +\n                                \"    (a)->a+1\\n\" +\n                                \"    1\" +\n                                \")\"\n                );\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.Invocation invocation = new AST.Invocation(new AST.Access(null, \"method\", LineCol.SYNTHETIC), Arrays.asList(\n                        new AST.Lambda(Collections.singletonList(new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)), Collections.<Statement>singletonList(\n                                new TwoVariableOperation(\n                                        \"+\",\n                                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        LineCol.SYNTHETIC)), LineCol.SYNTHETIC),\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC)\n                ), false, LineCol.SYNTHETIC);\n\n                assertEquals(invocation, stmt);\n        }\n\n        @Test\n        public void testLambda_only_name() throws Exception {\n                List<Statement> list = parse(\"a->a+1\");\n\n                assertEquals(1, list.size());\n                Statement stmt = list.get(0);\n\n                AST.Lambda l = new AST.Lambda(\n                        Collections.singletonList(\n                                new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                        ),\n                        Collections.<Statement>singletonList(\n                                new TwoVariableOperation(\"+\",\n                                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(l, stmt);\n        }\n\n        @Test\n        public void testStatic1() throws Exception {\n                List<Statement> list = parse(\"static a=1\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.StaticScope st = new AST.StaticScope(Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(st, stmt);\n        }\n\n        @Test\n        public void testStatic2() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"static\\n\" +\n                        \"    a=1\\n\" +\n                        \"    b=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                VariableDef v2 = new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n\n                AST.StaticScope st = new AST.StaticScope(Arrays.<Statement>asList(v1, v2), LineCol.SYNTHETIC);\n\n                assertEquals(st, stmt);\n        }\n\n        @Test\n        public void testClass_NonArg() throws Exception {\n                List<Statement> list = parse(\"class C:Type(),Type2\\n    a=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                ClassDef def = new ClassDef(\"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<VariableDef>emptyList(), new AST.Invocation(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), Collections.<Expression>emptyList(), false, LineCol.SYNTHETIC), Collections.singletonList(new AST.Access(null, \"Type2\", LineCol.SYNTHETIC)), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testClass_Arg() throws Exception {\n                List<Statement> list = parse(\"class C(arg):Type(),Type2\\n    a=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                ClassDef def = new ClassDef(\"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.singletonList(\n                        new VariableDef(\"arg\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                ), new AST.Invocation(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), Collections.<Expression>emptyList(), false, LineCol.SYNTHETIC), Collections.singletonList(new AST.Access(null, \"Type2\", LineCol.SYNTHETIC)), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testClass_Arg_SuperInvocation() throws Exception {\n                List<Statement> list = parse(\"class C(arg):Type(arg),Type2\\n    a=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                ClassDef def = new ClassDef(\"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.singletonList(\n                        new VariableDef(\"arg\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                ), new AST.Invocation(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), Collections.<Expression>singletonList(new AST.Access(null, \"arg\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC), Collections.singletonList(new AST.Access(null, \"Type2\", LineCol.SYNTHETIC)), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testClass_Arg_SuperInvocation_Modifiers() throws Exception {\n                List<Statement> list = parse(\"abstract class C(arg):Type(arg),Type2\\n    a=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                ClassDef def = new ClassDef(\"C\", Collections.<AST.Access>emptyList(), new HashSet<Modifier>(Collections.singletonList(\n                        new Modifier(Modifier.Available.ABSTRACT, LineCol.SYNTHETIC)\n                )), Collections.singletonList(\n                        new VariableDef(\"arg\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                ), new AST.Invocation(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), Collections.<Expression>singletonList(new AST.Access(null, \"arg\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC), Collections.singletonList(new AST.Access(null, \"Type2\", LineCol.SYNTHETIC)), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(v), LineCol.SYNTHETIC);\n\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testInterface_simple() throws Exception {\n                List<Statement> list = parse(\"interface A\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                InterfaceDef def = new InterfaceDef(\"A\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<AST.Access>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testInterface_super_interfaces() throws Exception {\n                List<Statement> list = parse(\"interface A:B,C\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                InterfaceDef def = new InterfaceDef(\"A\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                        Arrays.asList(\n                                new AST.Access(null, \"B\", LineCol.SYNTHETIC),\n                                new AST.Access(null, \"C\", LineCol.SYNTHETIC)\n                        ), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testInterface_super_interfaces_stmt() throws Exception {\n                List<Statement> list = parse(\"interface A:B,C\\n    method()=...\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                InterfaceDef def = new InterfaceDef(\"A\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                        Arrays.asList(\n                                new AST.Access(null, \"B\", LineCol.SYNTHETIC),\n                                new AST.Access(null, \"C\", LineCol.SYNTHETIC)\n                        ), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(\n                        new MethodDef(\"method\", Collections.<Modifier>emptySet(), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testInterface_super_interfaces_stmt_modifiers() throws Exception {\n                List<Statement> list = parse(\"protected interface A:B,C\\n    method()=...\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                InterfaceDef def = new InterfaceDef(\"A\", Collections.<AST.Access>emptyList(),\n                        new HashSet<Modifier>(Collections.singletonList(\n                                new Modifier(Modifier.Available.PROTECTED, LineCol.SYNTHETIC)\n                        )), Arrays.asList(\n                        new AST.Access(null, \"B\", LineCol.SYNTHETIC),\n                        new AST.Access(null, \"C\", LineCol.SYNTHETIC)\n                ), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(\n                        new MethodDef(\"method\", Collections.<Modifier>emptySet(), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(def, stmt);\n        }\n\n        @Test\n        public void testTryAll() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"try\\n\" +\n                                \"    a=1\\n\" +\n                                \"catch e\\n\" +\n                                \"    if e is type Exception or e is type Throwable\\n\" +\n                                \"        a=2\\n\" +\n                                \"    elseif e is type RuntimeException\\n\" +\n                                \"        a=3\\n\" +\n                                \"finally\\n\" +\n                                \"    a=4\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n\n                VariableDef v3 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v3.setInit(new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n\n                VariableDef v4 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v4.setInit(new NumberLiteral(\"4\", LineCol.SYNTHETIC));\n\n                AST.Try t = new AST.Try(Collections.<Statement>singletonList(v1), \"e\", Collections.<Statement>singletonList(\n                        new AST.If(\n                                Arrays.asList(\n                                        new AST.If.IfPair(\n                                                new TwoVariableOperation(\"or\",\n                                                        new TwoVariableOperation(\"is\",\n                                                                new AST.Access(\n                                                                        null, \"e\", LineCol.SYNTHETIC),\n                                                                new AST.TypeOf(\n                                                                        new AST.Access(null, \"Exception\", LineCol.SYNTHETIC),\n                                                                        LineCol.SYNTHETIC\n                                                                ),\n                                                                LineCol.SYNTHETIC),\n                                                        new TwoVariableOperation(\"is\",\n                                                                new AST.Access(\n                                                                        null, \"e\", LineCol.SYNTHETIC),\n                                                                new AST.TypeOf(\n                                                                        new AST.Access(null, \"Throwable\", LineCol.SYNTHETIC),\n                                                                        LineCol.SYNTHETIC\n                                                                ),\n                                                                LineCol.SYNTHETIC),\n                                                        LineCol.SYNTHETIC\n                                                ),\n                                                Collections.<Statement>singletonList(v2),\n                                                LineCol.SYNTHETIC\n                                        ),\n                                        new AST.If.IfPair(\n                                                new TwoVariableOperation(\"is\",\n                                                        new AST.Access(\n                                                                null, \"e\", LineCol.SYNTHETIC),\n                                                        new AST.TypeOf(\n                                                                new AST.Access(null, \"RuntimeException\", LineCol.SYNTHETIC),\n                                                                LineCol.SYNTHETIC\n                                                        ),\n                                                        LineCol.SYNTHETIC),\n                                                Collections.<Statement>singletonList(v3),\n                                                LineCol.SYNTHETIC\n                                        )\n                                ),\n                                LineCol.SYNTHETIC\n                        )\n                ), Collections.<Statement>singletonList(v4), LineCol.SYNTHETIC);\n\n                assertEquals(t, stmt);\n        }\n\n        @Test\n        public void testTryOneCatchNoProcess() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"try\\n\" +\n                                \"    a=1\\n\" +\n                                \"catch e\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                AST.Try t = new AST.Try(Collections.<Statement>singletonList(v1), \"e\", Collections.<Statement>emptyList(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n\n                assertEquals(t, stmt);\n        }\n\n        @Test\n        public void testTryFinally() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"try\\n\" +\n                                \"    a=1\\n\" +\n                                \"finally\\n\" +\n                                \"    a=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                VariableDef v2 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n\n                AST.Try t = new AST.Try(Collections.<Statement>singletonList(v1), null, Collections.<Statement>emptyList(),\n                        Collections.<Statement>singletonList(v2),\n                        LineCol.SYNTHETIC);\n                assertEquals(t, stmt);\n        }\n\n        @Test\n        public void testThrow() throws Exception {\n                List<Statement> list = parse(\"throw e\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                AST.Throw t = new AST.Throw(new AST.Access(null, \"e\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(t, stmt);\n        }\n\n        @Test\n        public void testAnnoVariable() throws Exception {\n                List<Statement> list = parse(\"@Anno(abc=1)\\ni=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                VariableDef v = new VariableDef(\n                        \"i\",\n                        Collections.<Modifier>emptySet(),\n                        new HashSet<AST.Anno>(Collections.singletonList(\n                                new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.singletonList(\n                                        new AST.Assignment(new AST.Access(null, \"abc\", LineCol.SYNTHETIC), \"=\", new NumberLiteral(\"1\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                                ), LineCol.SYNTHETIC)\n                        )),\n                        LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testAnnoInterface() throws Exception {\n                List<Statement> list = parse(\"@Anno\\ninterface I\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                InterfaceDef i = new InterfaceDef(\"I\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<AST.Access>emptyList(),\n                        new HashSet<AST.Anno>(Collections.singletonList(\n                                new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                        )),\n                        Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testAnnoClass() throws Exception {\n                List<Statement> list = parse(\"@Anno\\nclass C\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                ClassDef c = new ClassDef(\n                        \"C\",\n                        Collections.<AST.Access>emptyList(),\n                        Collections.<Modifier>emptySet(),\n                        Collections.<VariableDef>emptyList(),\n                        null,\n                        Collections.<AST.Access>emptyList(),\n                        new HashSet<AST.Anno>(Collections.singletonList(\n                                new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                        )),\n                        Collections.<Statement>emptyList(),\n                        LineCol.SYNTHETIC);\n                assertEquals(c, stmt);\n        }\n\n        @Test\n        public void testAnnoMethod() throws Exception {\n                List<Statement> list = parse(\"@Anno\\nmethod()=...\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                MethodDef m = new MethodDef(\n                        \"method\",\n                        Collections.<Modifier>emptySet(),\n                        null,\n                        Collections.<VariableDef>emptyList(),\n                        new HashSet<AST.Anno>(Collections.singletonList(\n                                new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                        )),\n                        Collections.<Statement>emptyList(),\n                        LineCol.SYNTHETIC);\n                assertEquals(m, stmt);\n        }\n\n        @Test\n        public void testArrayExp() throws Exception {\n                List<Statement> list = parse(\"[1,2]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.ArrayExp arr = new AST.ArrayExp(Arrays.<Expression>asList(\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(arr, stmt);\n        }\n\n        @Test\n        public void testArrayExp0() throws Exception {\n                List<Statement> list = parse(\"[]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.ArrayExp arr = new AST.ArrayExp(Collections.<Expression>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(arr, stmt);\n        }\n\n        @Test\n        public void testIndexAccess1() throws Exception {\n                List<Statement> list = parse(\"array[1]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Index index = new AST.Index(new AST.Access(null, \"array\", LineCol.SYNTHETIC), Collections.<Expression>singletonList(\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(index, stmt);\n        }\n\n        @Test\n        public void testIndexAccess2() throws Exception {\n                List<Statement> list = parse(\"array[1,2]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Index index = new AST.Index(new AST.Access(null, \"array\", LineCol.SYNTHETIC), Arrays.<Expression>asList(\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(index, stmt);\n        }\n\n        @Test\n        public void testIndexAccess0() throws Exception {\n                List<Statement> list = parse(\"array[]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Index index = new AST.Index(new AST.Access(null, \"array\", LineCol.SYNTHETIC), Collections.<Expression>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(index, stmt);\n        }\n\n        @Test\n        public void testMap() throws Exception {\n                List<Statement> list = parse(\"[a:b]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), new AST.Access(null, \"b\", LineCol.SYNTHETIC));\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, stmt);\n        }\n\n        @Test\n        public void testMap_two_key() throws Exception {\n                List<Statement> list = parse(\"[a:b,c:d]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), new AST.Access(null, \"b\", LineCol.SYNTHETIC));\n                map.put(new AST.Access(null, \"c\", LineCol.SYNTHETIC), new AST.Access(null, \"d\", LineCol.SYNTHETIC));\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, stmt);\n        }\n\n        @Test\n        public void testMap_in_map() throws Exception {\n                List<Statement> list = parse(\n                        \"[a:[b:c]]\"\n                );\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n\n                LinkedHashMap<Expression, Expression> inside_map = new LinkedHashMap<Expression, Expression>();\n                inside_map.put(new AST.Access(null, \"b\", LineCol.SYNTHETIC), new AST.Access(null, \"c\", LineCol.SYNTHETIC));\n                AST.MapExp inside = new AST.MapExp(inside_map, LineCol.SYNTHETIC);\n\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), inside);\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, stmt);\n        }\n\n        @Test\n        public void testMap_assign() throws Exception {\n                List<Statement> list = parse(\"map=[a:b]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), new AST.Access(null, \"b\", LineCol.SYNTHETIC));\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n\n                VariableDef v = new VariableDef(\"map\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(mapExp);\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testMap_in_map_assign() throws Exception {\n                List<Statement> list = parse(\n                        \"map=[a:[b:c]]\"\n                );\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n\n                LinkedHashMap<Expression, Expression> inside_map = new LinkedHashMap<Expression, Expression>();\n                inside_map.put(new AST.Access(null, \"b\", LineCol.SYNTHETIC), new AST.Access(null, \"c\", LineCol.SYNTHETIC));\n                AST.MapExp inside = new AST.MapExp(inside_map, LineCol.SYNTHETIC);\n\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), inside);\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n\n                VariableDef v = new VariableDef(\"map\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(mapExp);\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testMap_in_map_pretty() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"[\\n\" +\n                                \"    a:[\\n\" +\n                                \"        b:c\\n\" +\n                                \"    ]\\n\" +\n                                \"]\"\n                );\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n\n                LinkedHashMap<Expression, Expression> inside_map = new LinkedHashMap<Expression, Expression>();\n                inside_map.put(new AST.Access(null, \"b\", LineCol.SYNTHETIC), new AST.Access(null, \"c\", LineCol.SYNTHETIC));\n                AST.MapExp inside = new AST.MapExp(inside_map, LineCol.SYNTHETIC);\n\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC), inside);\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, stmt);\n        }\n\n        @Test\n        public void testPkgDeclare1() throws Exception {\n                List<Statement> list = parse(\"package lt\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                PackageDeclare p = new PackageDeclare(new AST.PackageRef(\"lt\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(p, stmt);\n        }\n\n        @Test\n        public void testPkgDeclare2() throws Exception {\n                List<Statement> list = parse(\"package lt::lang::util\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                PackageDeclare p = new PackageDeclare(new AST.PackageRef(\"lt::lang::util\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(p, stmt);\n        }\n\n        @Test\n        public void testImportPackageAll() throws Exception {\n                List<Statement> list = parse(\"import lt::lang::_\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), null, true, false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportClass() throws Exception {\n                List<Statement> list = parse(\"import lt::lang::Cls\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), \"Cls\", LineCol.SYNTHETIC), false\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportClassAll() throws Exception {\n                List<Statement> list = parse(\"import lt::lang::Cls._\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), \"Cls\", LineCol.SYNTHETIC), true\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportInnerClass() throws Exception {\n                List<Statement> list = parse(\"import lt::lang::Cls.Inner\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.Access(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), \"Cls\", LineCol.SYNTHETIC), \"Inner\", LineCol.SYNTHETIC), false\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportInnerClassAll() throws Exception {\n                List<Statement> list = parse(\"import lt::lang::Cls.Inner._\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.Access(new AST.PackageRef(\"lt::lang\", LineCol.SYNTHETIC), \"Cls\", LineCol.SYNTHETIC), \"Inner\", LineCol.SYNTHETIC), true\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportClassAllNoPKG() throws Exception {\n                List<Statement> list = parse(\"import Cls._\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(null, \"Cls\", LineCol.SYNTHETIC), true\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportInnerClassAllNoPKG() throws Exception {\n                List<Statement> list = parse(\"import Cls.Inner._\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.Access(null, \"Cls\", LineCol.SYNTHETIC), \"Inner\", LineCol.SYNTHETIC), true\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testImportInnerClassNoPKG() throws Exception {\n                List<Statement> list = parse(\"import Cls.Inner\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                Import i = new Import(null, new AST.Access(new AST.Access(null, \"Cls\", LineCol.SYNTHETIC), \"Inner\", LineCol.SYNTHETIC), false\n                        , false, LineCol.SYNTHETIC);\n                assertEquals(i, stmt);\n        }\n\n        @Test\n        public void testWhile() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"while true\\n\" +\n                        \"    1\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.While w = new AST.While(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC)\n                ), false, LineCol.SYNTHETIC);\n                assertEquals(w, stmt);\n        }\n\n        @Test\n        public void testDoWhile() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"do\\n\" +\n                        \"    1\\n\" +\n                        \"while true\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.While w = new AST.While(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>singletonList(\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC)\n                ), true, LineCol.SYNTHETIC);\n                assertEquals(w, stmt);\n        }\n\n        @Test\n        public void testAnnoArray() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"@Anno(a=[1,2])\\n\" +\n                        \"i=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), new HashSet<AST.Anno>(Collections.singletonList(\n                        new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.singletonList(\n                                new AST.Assignment(new AST.Access(null, \"a\", LineCol.SYNTHETIC), \"=\", new AST.ArrayExp(Arrays.<Expression>asList(\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                                ), LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC)\n                )), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testAnnoNoAssign() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"@Anno([1,2])\\n\" +\n                        \"i=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), new HashSet<AST.Anno>(Collections.singletonList(\n                        new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.singletonList(\n                                new AST.Assignment(new AST.Access(null, \"value\", LineCol.SYNTHETIC), \"=\", new AST.ArrayExp(Arrays.<Expression>asList(\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                                ), LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC)\n                )), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testClosure() throws Exception {\n                List<Statement> list = parse(\"(return 1)\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Procedure procedure = new AST.Procedure(Collections.<Statement>singletonList(\n                        new AST.Return(new NumberLiteral(\"1\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(procedure, stmt);\n        }\n\n        @Test\n        public void testClosureMultipleLine() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"(\\n\" +\n                        \"    i=1\\n\" +\n                        \"    return i\\n\" +\n                        \")\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.Procedure procedure = new AST.Procedure(Arrays.asList(\n                        v,\n                        new AST.Return(new AST.Access(null, \"i\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(procedure, stmt);\n        }\n\n        @Test\n        public void testSync() throws Exception {\n                List<Statement> list = parse(\"synchronized(lock)\\n    i=1\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                AST.Synchronized s = new AST.Synchronized(Collections.<Expression>singletonList(\n                        new AST.Access(null, \"lock\", LineCol.SYNTHETIC)\n                ), Collections.<Statement>singletonList(\n                        v\n                ), LineCol.SYNTHETIC);\n                assertEquals(s, stmt);\n        }\n\n        @Test\n        public void testArrayType() throws Exception {\n                List<Statement> list = parse(\"i:[]Type\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC));\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void test2ArrayType() throws Exception {\n                List<Statement> list = parse(\"i:[][]Type\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(new AST.Access(new AST.Access(null, \"Type\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC));\n                assertEquals(v, stmt);\n        }\n\n        @Test\n        public void testTypeOf() throws Exception {\n                List<Statement> list = parse(\"type int\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.TypeOf typeOf = new AST.TypeOf(new AST.Access(null, \"int\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(typeOf, stmt);\n        }\n\n        @Test\n        public void testIn() throws Exception {\n                List<Statement> list = parse(\"1 in [1,2]\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                TwoVariableOperation tvo = new TwoVariableOperation(\"in\",\n                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                        new AST.ArrayExp(Arrays.<Expression>asList(\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC)\n                        , LineCol.SYNTHETIC);\n                assertEquals(tvo, stmt);\n        }\n\n        @Test\n        public void testAbstractClass() throws Exception {\n                List<Statement> list = parse(\"abstract class AbsCls(id,name)\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                ClassDef c = new ClassDef(\n                        \"AbsCls\",\n                        Collections.<AST.Access>emptyList(),\n                        new HashSet<Modifier>(Collections.singletonList(new Modifier(Modifier.Available.ABSTRACT, LineCol.SYNTHETIC))),\n                        Arrays.asList(\n                                new VariableDef(\"id\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC),\n                                new VariableDef(\"name\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                        ),\n                        null,\n                        Collections.<AST.Access>emptyList(),\n                        Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(c, stmt);\n        }\n\n        @Test\n        public void testPass() throws Exception {\n                List<Statement> list = parse(\"def method()\\n    ...\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                MethodDef m = new MethodDef(\"method\", Collections.singleton(\n                        new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)\n                ), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(\n                        new AST.Pass(LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(m, stmt);\n        }\n\n        @Test\n        public void testNull() throws Exception {\n                List<Statement> list = parse(\"null\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Null n = new AST.Null(LineCol.SYNTHETIC);\n                assertEquals(n, stmt);\n        }\n\n        @Test\n        public void testAsType() throws Exception {\n                List<Statement> list = parse(\"1 as java::lang::List\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.AsType asType = new AST.AsType(new NumberLiteral(\"1\", LineCol.SYNTHETIC), new AST.Access(new AST.PackageRef(\"java::lang\", LineCol.SYNTHETIC), \"List\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(asType, stmt);\n        }\n\n        @Test\n        public void testUnaryInc() throws Exception {\n                List<Statement> list = parse(\"++i\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                UnaryOneVariableOperation ovo = new UnaryOneVariableOperation(\"++\", new AST.Access(null, \"i\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(ovo, stmt);\n        }\n\n        @Test\n        public void testOperatorLikeInvocation() throws Exception {\n                List<Statement> list = parse(\"a op b\\na op\");\n\n                assertEquals(2, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Invocation invocation = new AST.Invocation(new AST.Access(new AST.Access(null, \"a\", LineCol.SYNTHETIC), \"op\", LineCol.SYNTHETIC), Collections.<Expression>singletonList(new AST.Access(null, \"b\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC);\n                assertEquals(invocation, stmt);\n\n                stmt = list.get(1);\n                assertEquals(new AST.Access(new AST.Access(null, \"a\", LineCol.SYNTHETIC), \"op\", LineCol.SYNTHETIC), stmt);\n        }\n\n        @Test\n        public void testOperatorLikeInvocation2() throws Exception {\n                List<Statement> list = parse(\"db select a, b, c from user\");\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                AST.Invocation invocation = new AST.Invocation(\n                        new AST.Access(\n                                new AST.Invocation(\n                                        new AST.Access(\n                                                new AST.Access(null, \"db\", null),\n                                                \"select\",\n                                                null),\n                                        Arrays.<Expression>asList(\n                                                new AST.Access(null, \"a\", null),\n                                                new AST.Access(null, \"b\", null),\n                                                new AST.Access(null, \"c\", null)\n                                        ),\n                                        false, null\n                                ),\n                                \"from\",\n                                null\n                        ),\n                        Collections.<Expression>singletonList(new AST.Access(null, \"user\", null)),\n                        false, null\n                );\n                assertEquals(invocation, stmt);\n        }\n\n        @Test\n        public void testInvokeWithName() throws Exception {\n                List<Statement> list = parse(\"test(a=1, b=2)\");\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                VariableDef v1 = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v1.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                VariableDef v2 = new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v2.setInit(new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                AST.Invocation invocation = new AST.Invocation(\n                        new AST.Access(\n                                null, \"test\", null\n                        ),\n                        Arrays.<Expression>asList(\n                                v1, v2\n                        ),\n                        true, null\n                );\n                assertEquals(invocation, stmt);\n        }\n\n        @Test\n        public void testDataClass() throws Exception {\n                List<Statement> list = parse(\"data class User\");\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                assertEquals(\n                        new ClassDef(\"User\",\n                                Collections.<AST.Access>emptyList(),\n                                Collections.singleton(new Modifier(Modifier.Available.DATA, LineCol.SYNTHETIC)),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        stmt\n                );\n        }\n\n        @Test\n        public void testAssignOp() throws Exception {\n                List<Statement> list = parse(\"a:=1\");\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n                assertEquals(\n                        new TwoVariableOperation(\n                                \":=\",\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        stmt\n                );\n        }\n\n        @Test\n        public void testAnnotationAsValue() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"@Anno(a=@Anno)\\n\" +\n                        \"val a\");\n                assertEquals(1, list.size());\n                assertEquals(\n                        new VariableDef(\"a\", Collections.singleton(new Modifier(Modifier.Available.VAL, LineCol.SYNTHETIC)),\n                                Collections.singleton(new AST.Anno(\n                                        new AST.Access(null, \"Anno\", LineCol.SYNTHETIC),\n                                        Collections.singletonList(\n                                                new AST.Assignment(\n                                                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                                        \"=\",\n                                                        new AST.AnnoExpression(\n                                                                new AST.Anno(\n                                                                        new AST.Access(null, \"Anno\", LineCol.SYNTHETIC),\n                                                                        Collections.<AST.Assignment>emptyList(),\n                                                                        LineCol.SYNTHETIC\n                                                                )\n                                                        ),\n                                                        LineCol.SYNTHETIC\n                                                )\n                                        ),\n                                        LineCol.SYNTHETIC\n                                )), LineCol.SYNTHETIC)\n                        , list.get(0));\n        }\n\n        @Test\n        public void testFun() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"fun F(o):java::util::function::Function\\n\" +\n                        \"    return o\");\n                assertEquals(\n                        Collections.singletonList(\n                                new FunDef(\n                                        \"F\",\n                                        Collections.singletonList(\n                                                new VariableDef(\n                                                        \"o\", Collections.<Modifier>emptySet(),\n                                                        Collections.<AST.Anno>emptySet(),\n                                                        LineCol.SYNTHETIC\n                                                )\n                                        ),\n                                        new AST.Access(\n                                                new AST.PackageRef(\n                                                        \"java::util::function\",\n                                                        LineCol.SYNTHETIC\n                                                ),\n                                                \"Function\",\n                                                LineCol.SYNTHETIC\n                                        ),\n                                        Collections.<AST.Anno>emptySet(),\n                                        Collections.<Statement>singletonList(\n                                                new AST.Return(\n                                                        new AST.Access(null, \"o\", LineCol.SYNTHETIC),\n                                                        LineCol.SYNTHETIC\n                                                )\n                                        ),\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        list\n                );\n        }\n\n        @Test\n        public void testVar() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"var a\\n\" +\n                        \"var b = 1\\n\" +\n                        \"class X(var a, var b)\");\n\n                VariableDef b = new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                b.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                assertEquals(\n                        Arrays.asList(\n                                new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC),\n                                b,\n                                new ClassDef(\"X\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                        Arrays.asList(\n                                                new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC),\n                                                new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                        ), null, Collections.<AST.Access>emptyList(), Collections.<AST.Anno>emptySet(),\n                                        Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                        ), list);\n        }\n\n        @Test\n        public void testNew() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"new X()\\n\" +\n                        \"new X\");\n                AST.New aNew = new AST.New(\n                        new AST.Invocation(\n                                new AST.Access(null, \"X\", LineCol.SYNTHETIC),\n                                Collections.<Expression>emptyList(),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        LineCol.SYNTHETIC\n                );\n                assertEquals(aNew, list.get(0));\n                assertEquals(aNew, list.get(1));\n        }\n\n        @Test\n        public void testGeneratorSpec() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"#lt::generator::js\\n\" +\n                        \"#lt::generator::js\\n\" +\n                        \"    a=1\\n\" +\n                        \"(\\n\" +\n                        \"    #lt::generator::js\\n\" +\n                        \"        a=1).charAt(0)\");\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                AST.GeneratorSpec gs2 = new AST.GeneratorSpec(\n                        new AST.Access(new AST.PackageRef(\"lt::generator\", LineCol.SYNTHETIC), \"js\", LineCol.SYNTHETIC),\n                        Collections.<Statement>singletonList(v),\n                        LineCol.SYNTHETIC\n                );\n                assertEquals(\n                        Arrays.asList(\n                                new AST.GeneratorSpec(\n                                        new AST.Access(new AST.PackageRef(\"lt::generator\", LineCol.SYNTHETIC), \"js\", LineCol.SYNTHETIC),\n                                        Collections.<Statement>emptyList(),\n                                        LineCol.SYNTHETIC\n                                ), gs2,\n                                new AST.Invocation(new AST.Access(\n                                        gs2, \"charAt\", LineCol.SYNTHETIC),\n                                        Collections.<Expression>singletonList(new NumberLiteral(\"0\", LineCol.SYNTHETIC)),\n                                        false, LineCol.SYNTHETIC)\n                        ),\n                        list\n                );\n        }\n\n        @Test\n        public void testInternalSyntaxLambda() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"(\\n\" +\n                        \"    (redisLock(o))\\n\" +\n                        \"        println(it)\\n\" +\n                        \").test()\");\n                AST.Invocation redisLock = new AST.Invocation(new AST.Access(null, \"redisLock\", LineCol.SYNTHETIC),\n                        Collections.<Expression>singletonList(new AST.Access(null, \"o\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC);\n                AST.Lambda lambda = new AST.Lambda(Collections.singletonList(\n                        new VariableDef(\"it\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                ), Collections.<Statement>singletonList(\n                        new AST.Invocation(new AST.Access(null, \"println\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(new AST.Access(null, \"it\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                AST.Invocation invokeLambda = new AST.Invocation(redisLock, Collections.<Expression>singletonList(lambda), false, LineCol.SYNTHETIC);\n                AST.Invocation test = new AST.Invocation(new AST.Access(invokeLambda, \"test\", LineCol.SYNTHETIC),\n                        Collections.<Expression>emptyList(), false, LineCol.SYNTHETIC);\n                assertEquals(Collections.singletonList(test), stmts);\n        }\n\n        @Test\n        public void testSqlGeneratorSyntax() throws Exception {\n                // pass\n                parse(\"\" +\n                        \"sql = select(#sql#[user.id, user.name, user.pwd]).\\n\" +\n                        \"from('user').\\n\" +\n                        \"join('user_role').`as`('ur').on(#sql#ur.user_id == user.id).\\n\" +\n                        \"join('role').on(#sql#role.id == ur.user_id).\\n\" +\n                        \"where(#sql#user.id > 10 and user.name not 'cass')\");\n        }\n\n        @Test\n        public void testArrayTypeMap() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"['a':1, 'b':2]\\n\" +\n                        \"[\\n\" +\n                        \"    'a': 1\\n\" +\n                        \"    'b': 2\\n\" +\n                        \"]\\n\" +\n                        \"[\\n\" +\n                        \"    'a':1,\\n\" +\n                        \"    'b':2\\n\" +\n                        \"]\\n\" +\n                        \"['a':1\\n\" +\n                        \"    'b':2]\"\n                );\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new StringLiteral(\"'a'\", LineCol.SYNTHETIC), new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                map.put(new StringLiteral(\"'b'\", LineCol.SYNTHETIC), new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                assertEquals(Arrays.asList(\n                        new AST.MapExp(map, LineCol.SYNTHETIC),\n                        new AST.MapExp(map, LineCol.SYNTHETIC),\n                        new AST.MapExp(map, LineCol.SYNTHETIC),\n                        new AST.MapExp(map, LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testDefNoPar() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"def m\\n\" +\n                        \"def n\\n\" +\n                        \"    ...\\n\" +\n                        \"def o:int\\n\" +\n                        \"def p:int\\n\" +\n                        \"    ...\\n\" +\n                        \"def q=1\\n\" +\n                        \"def r:int=1\");\n                assertEquals(Arrays.asList(\n                        new MethodDef(\"m\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new MethodDef(\"n\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)), LineCol.SYNTHETIC),\n                        new MethodDef(\"o\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), new AST.Access(null, \"int\", LineCol.SYNTHETIC), Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new MethodDef(\"p\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), new AST.Access(null, \"int\", LineCol.SYNTHETIC), Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)), LineCol.SYNTHETIC),\n                        new MethodDef(\"q\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)), LineCol.SYNTHETIC),\n                        new MethodDef(\"r\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)), new AST.Access(null, \"int\", LineCol.SYNTHETIC), Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)), LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testObject() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"object Test1\\n\" +\n                        \"object Test2:Object\\n\" +\n                        \"object Test3:ArrayList([])\\n\" +\n                        \"object Test4:ArrayList([]),List\"\n                );\n                assertEquals(Arrays.asList(\n                        new ObjectDef(\"Test1\", Collections.<AST.Access>emptyList(), null, Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new ObjectDef(\"Test2\", Collections.<AST.Access>emptyList(), null, Collections.singletonList(new AST.Access(null, \"Object\", LineCol.SYNTHETIC)), Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new ObjectDef(\"Test3\", Collections.<AST.Access>emptyList(), new AST.Invocation(\n                                new AST.Access(null, \"ArrayList\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(new AST.ArrayExp(Collections.<Expression>emptyList(), LineCol.SYNTHETIC)),\n                                false, LineCol.SYNTHETIC\n                        ), Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                        new ObjectDef(\"Test4\", Collections.<AST.Access>emptyList(), new AST.Invocation(\n                                new AST.Access(null, \"ArrayList\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(new AST.ArrayExp(Collections.<Expression>emptyList(), LineCol.SYNTHETIC)),\n                                false, LineCol.SYNTHETIC\n                        ), Collections.singletonList(\n                                new AST.Access(null, \"List\", LineCol.SYNTHETIC)\n                        ), Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testImportImplicit() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"import implicit xx\\n\" +\n                        \"import implicit yy::zz\\n\" +\n                        \"import implicit aa.bb\\n\" +\n                        \"import implicit cc::dd.ee\"\n                );\n                assertEquals(Arrays.asList(\n                        new Import(null, new AST.Access(null, \"xx\", LineCol.SYNTHETIC), false, true, LineCol.SYNTHETIC),\n                        new Import(null,\n                                new AST.Access(new AST.PackageRef(\"yy\", LineCol.SYNTHETIC), \"zz\", LineCol.SYNTHETIC),\n                                false, true, LineCol.SYNTHETIC),\n                        new Import(null,\n                                new AST.Access(new AST.Access(null, \"aa\", LineCol.SYNTHETIC), \"bb\", LineCol.SYNTHETIC),\n                                false, true, LineCol.SYNTHETIC),\n                        new Import(null,\n                                new AST.Access(\n                                        new AST.Access(\n                                                new AST.PackageRef(\"cc\", LineCol.SYNTHETIC), \"dd\", LineCol.SYNTHETIC),\n                                        \"ee\", LineCol.SYNTHETIC),\n                                false, true, LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testDestruct() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"List(a,b) <- [1,2]\\n\" +\n                        \"B() <- 123\\n\" +\n                        // \"C <- 456\\n\" + it's not supported now\n                        \"D(d, _) <- 789\\n\" +\n                        \"() <- 101\\n\" +\n                        \"(e,f) <- 102\\n\" +\n                        \"(g,_) <- 103\\n\" +\n                        \"var (h,_) <- 104\\n\" +\n                        \"val (i,j) <- 105\\n\" +\n                        \"@Anno\\n(k,l) <- 106\"\n                );\n                assertEquals(Arrays.asList(\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        new AST.Access(null, \"List\", LineCol.SYNTHETIC),\n                                        Arrays.<AST.Pattern>asList(\n                                                new AST.Pattern_Define(\"a\", null),\n                                                new AST.Pattern_Define(\"b\", null))),\n                                new AST.ArrayExp(Arrays.<Expression>asList(\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                                ), LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        new AST.Access(null, \"B\", LineCol.SYNTHETIC),\n                                        Collections.<AST.Pattern>emptyList()\n                                ),\n                                new NumberLiteral(\"123\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        /*\n                        it's not supported now\n                        new AST.Destruct(\n                                Collections.emptySet(),\n                                new AST.Pattern_Destruct(\n                                        new AST.Access(null, \"C\", LineCol.SYNTHETIC),\n                                        Collections.emptyList()\n                                ),\n                                new NumberLiteral(\"456\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        */\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        new AST.Access(null, \"D\", LineCol.SYNTHETIC),\n                                        Arrays.asList(\n                                                new AST.Pattern_Define(\"d\", null),\n                                                AST.Pattern_Default.get()\n                                        )\n                                ),\n                                new NumberLiteral(\"789\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Collections.<AST.Pattern>emptyList()\n                                ),\n                                new NumberLiteral(\"101\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Arrays.<AST.Pattern>asList(\n                                                new AST.Pattern_Define(\"e\", null),\n                                                new AST.Pattern_Define(\"f\", null)\n                                        )\n                                ),\n                                new NumberLiteral(\"102\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Arrays.asList(\n                                                new AST.Pattern_Define(\"g\", null),\n                                                AST.Pattern_Default.get()\n                                        )\n                                ),\n                                new NumberLiteral(\"103\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.singleton(\n                                        new Modifier(Modifier.Available.VAR, LineCol.SYNTHETIC)\n                                ),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Arrays.asList(\n                                                new AST.Pattern_Define(\"h\", null),\n                                                AST.Pattern_Default.get()\n                                        )\n                                ),\n                                new NumberLiteral(\"104\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.singleton(\n                                        new Modifier(Modifier.Available.VAL, LineCol.SYNTHETIC)\n                                ),\n                                Collections.<AST.Anno>emptySet(),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Arrays.<AST.Pattern>asList(\n                                                new AST.Pattern_Define(\"i\", null),\n                                                new AST.Pattern_Define(\"j\", null)\n                                        )\n                                ),\n                                new NumberLiteral(\"105\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Destruct(\n                                Collections.<Modifier>emptySet(),\n                                Collections.singleton(\n                                        new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC),\n                                                Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                                ),\n                                new AST.Pattern_Destruct(\n                                        null,\n                                        Arrays.<AST.Pattern>asList(\n                                                new AST.Pattern_Define(\"k\", null),\n                                                new AST.Pattern_Define(\"l\", null)\n                                        )\n                                ),\n                                new NumberLiteral(\"106\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testDestructingEq() throws Exception {\n                List<Statement> stmts1 = parse(\"\" +\n                        \"var (h,_) <- 104\\n\" +\n                        \"val (i,j) <- 105\\n\" +\n                        \"@Anno\\n(k,l) <- 106\");\n\n                List<Statement> stmts2 = parse(\"\" +\n                        \"var (h,_) = 104\\n\" +\n                        \"val (i,j) = 105\\n\" +\n                        \"@Anno\\n(k,l) = 106\");\n\n                assertEquals(stmts1, stmts2);\n        }\n\n        @Test\n        public void testSimplePatterns() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"a = 1\\n\" +\n                        \"list match\\n\" +\n                        \"    case _      => ...\\n\" +\n                        \"    case x      => ...\\n\" +\n                        \"    case a      => ...\\n\" +\n                        \"    case true   => ...\\n\" +\n                        \"    case 123    => ...\\n\" +\n                        \"    case 'abc'  => ...\\n\" +\n                        \"    case _:List => ...\\n\"\n                );\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                LinkedHashMap<AST.PatternCondition, List<Statement>> linkedHashMap = new LinkedHashMap<AST.PatternCondition, List<Statement>>();\n                List<Statement> stmt = Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC));\n                linkedHashMap.put(new AST.PatternCondition(AST.Pattern_Default.get(), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Define(\"x\", null), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Value(new AST.Access(null, \"a\", LineCol.SYNTHETIC)), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Value(new BoolLiteral(\"true\", LineCol.SYNTHETIC)), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Value(new NumberLiteral(\"123\", LineCol.SYNTHETIC)), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Value(new StringLiteral(\"'abc'\", LineCol.SYNTHETIC)), null), stmt);\n                linkedHashMap.put(new AST.PatternCondition(new AST.Pattern_Type(new AST.Access(null, \"List\", LineCol.SYNTHETIC)), null), stmt);\n                assertEquals(\n                        Arrays.asList(\n                                v,\n                                new AST.PatternMatching(\n                                        new AST.Access(null, \"list\", LineCol.SYNTHETIC),\n                                        linkedHashMap,\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        stmts\n                );\n        }\n\n        @Test\n        public void testPatternDestructing() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"a = 1\\n\" +\n                        \"list match\\n\" +\n                        \"    case List(a,b,c) => ...\\n\" +\n                        \"    case A(x) => ...\\n\" +\n                        \"    case B(1) => ...\\n\" +\n                        \"    case C(_, _:X) => ...\\n\" +\n                        \"    case D(x:L) => ...\\n\" +\n                        \"    case E() => ...\\n\" +\n                        \"    case F(x) if x > 10 => ...\"\n                );\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                LinkedHashMap<AST.PatternCondition, List<Statement>> map = new LinkedHashMap<AST.PatternCondition, List<Statement>>();\n                List<Statement> stmt = Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC));\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"List\", LineCol.SYNTHETIC),\n                                Arrays.asList(\n                                        new AST.Pattern_Value(new AST.Access(null, \"a\", LineCol.SYNTHETIC)),\n                                        new AST.Pattern_Define(\"b\", null),\n                                        new AST.Pattern_Define(\"c\", null)\n                                )\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"A\", LineCol.SYNTHETIC),\n                                Collections.<AST.Pattern>singletonList(\n                                        new AST.Pattern_Define(\"x\", null)\n                                )\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"B\", LineCol.SYNTHETIC),\n                                Collections.<AST.Pattern>singletonList(\n                                        new AST.Pattern_Value(new NumberLiteral(\"1\", LineCol.SYNTHETIC))\n                                )\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"C\", LineCol.SYNTHETIC),\n                                Arrays.asList(\n                                        AST.Pattern_Default.get(),\n                                        new AST.Pattern_Type(new AST.Access(null, \"X\", LineCol.SYNTHETIC))\n                                )\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"D\", LineCol.SYNTHETIC),\n                                Collections.<AST.Pattern>singletonList(\n                                        new AST.Pattern_Define(\"x\", new AST.Access(null, \"L\", LineCol.SYNTHETIC))\n                                )\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"E\", LineCol.SYNTHETIC),\n                                Collections.<AST.Pattern>emptyList()\n                        ), null), stmt);\n                map.put(new AST.PatternCondition(\n                        new AST.Pattern_Destruct(\n                                new AST.Access(null, \"F\", LineCol.SYNTHETIC),\n                                Collections.<AST.Pattern>singletonList(\n                                        new AST.Pattern_Define(\"x\", null)\n                                )\n                        ),\n                        new TwoVariableOperation(\">\",\n                                new AST.Access(null, \"x\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"10\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)), stmt);\n\n                assertEquals(Arrays.asList(\n                        v,\n                        new AST.PatternMatching(\n                                new AST.Access(null, \"list\", LineCol.SYNTHETIC),\n                                map, LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testSimplePatterns_Brace() throws Exception {\n                assertEquals(\n                        parse(\"\" +\n                                \"a = 1\\n\" +\n                                \"list match\\n\" +\n                                \"    case _      => ...\\n\" +\n                                \"    case x      => ...\\n\" +\n                                \"    case a      => ...\\n\" +\n                                \"    case true   => ...\\n\" +\n                                \"    case 123    => ...\\n\" +\n                                \"    case 'abc'  => ...\\n\" +\n                                \"    case _:List => ...\"\n                        ),\n                        parseBrace(\"\" +\n                                \"a = 1\\n\" +\n                                \"list match {\\n\" +\n                                \"    case _      => ...\\n\" +\n                                \"    case x      => ...\\n\" +\n                                \"    case a      => {...}\\n\" +\n                                \"    case true   => ...\\n\" +\n                                \"    case 123    => ...\\n\" +\n                                \"    case 'abc'  => ...\\n\" +\n                                \"    case _:List => ...\\n\" +\n                                \"}\"\n                        )\n                );\n        }\n\n        @Test\n        public void testDotStartInvocation() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \".a 1\\n\" +\n                        \".a .b 1\\n\" +\n                        \".a .b .c\\n\" +\n                        \".a + .b // it's a(+b())\\n\" +\n                        \".a 1,2,3\\n\" +\n                        \".a .b 1,2,3\");\n                assertEquals(Arrays.asList(\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new AST.Invocation(\n                                                new AST.Access(null, \"b\", LineCol.SYNTHETIC),\n                                                Collections.<Expression>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)),\n                                                false,\n                                                LineCol.SYNTHETIC\n                                        )\n                                ),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new AST.Invocation(\n                                                new AST.Access(null, \"b\", LineCol.SYNTHETIC),\n                                                Collections.<Expression>singletonList(\n                                                        new AST.Invocation(\n                                                                new AST.Access(null, \"c\", LineCol.SYNTHETIC),\n                                                                Collections.<Expression>emptyList(),\n                                                                false,\n                                                                LineCol.SYNTHETIC\n                                                        )\n                                                ),\n                                                false,\n                                                LineCol.SYNTHETIC\n                                        )\n                                ),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new UnaryOneVariableOperation(\"+\",\n                                                new AST.Invocation(\n                                                        new AST.Access(null, \"b\", LineCol.SYNTHETIC),\n\n                                                        Collections.<Expression>emptyList(),\n                                                        false,\n                                                        LineCol.SYNTHETIC\n                                                ),\n                                                LineCol.SYNTHETIC)\n                                ),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Arrays.<Expression>asList(\n                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                                        new NumberLiteral(\"3\", LineCol.SYNTHETIC)\n                                ),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        new AST.Invocation(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new AST.Invocation(\n                                                new AST.Access(null, \"b\", LineCol.SYNTHETIC),\n                                                Arrays.<Expression>asList(\n                                                        new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                                                        new NumberLiteral(\"3\", LineCol.SYNTHETIC)\n                                                ),\n                                                false,\n                                                LineCol.SYNTHETIC\n                                        )\n                                ),\n                                false,\n                                LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testAnnotationDef() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"annotation A\\n\" +\n                        \"    a = 1\\n\" +\n                        \"@Retention(RetentionPolicy.RUNTIME)\\n\" +\n                        \"@Target(ElementType.TYPE)\\n\" +\n                        \"annotation B\\n\"\n                );\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                assertEquals(Arrays.asList(\n                        new AnnotationDef(\n                                \"A\",\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>singletonList(v),\n                                LineCol.SYNTHETIC\n                        ),\n                        new AnnotationDef(\n                                \"B\",\n                                new HashSet<AST.Anno>(\n                                        Arrays.asList(\n                                                new AST.Anno(\n                                                        new AST.Access(null, \"Retention\", LineCol.SYNTHETIC),\n                                                        Collections.singletonList(\n                                                                new AST.Assignment(\n                                                                        new AST.Access(null, \"value\", LineCol.SYNTHETIC),\n                                                                        \"=\",\n                                                                        new AST.Access(new AST.Access(null, \"RetentionPolicy\", LineCol.SYNTHETIC), \"RUNTIME\", LineCol.SYNTHETIC),\n                                                                        LineCol.SYNTHETIC\n                                                                )\n                                                        ),\n                                                        LineCol.SYNTHETIC\n                                                ),\n                                                new AST.Anno(\n                                                        new AST.Access(null, \"Target\", LineCol.SYNTHETIC),\n                                                        Collections.singletonList(\n                                                                new AST.Assignment(\n                                                                        new AST.Access(null, \"value\", LineCol.SYNTHETIC),\n                                                                        \"=\",\n                                                                        new AST.Access(new AST.Access(null, \"ElementType\", LineCol.SYNTHETIC), \"TYPE\", LineCol.SYNTHETIC),\n                                                                        LineCol.SYNTHETIC\n                                                                )\n                                                        ),\n                                                        LineCol.SYNTHETIC\n                                                )\n                                        )\n                                ),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testEmptyProcedure() throws Exception {\n                List<Statement> stmts = parse(\"()\");\n                assertEquals(Collections.singletonList(\n                        new AST.Procedure(Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testClassGeneric() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"class A<:T:>\\n\" +\n                        \"class B<:T,U:>\\n\" +\n                        \"class C<:T:> : A<:X:>\\n\" +\n                        \"class D<:T:>(a)\\n\" +\n                        \"class E<:T:> : A<:X:>, B<:X,Y:>\\n\" +\n                        \"class F<:T:> : A<:X:>()\\n\");\n                AST.Access cExtends = new AST.Access(null, \"A\", LineCol.SYNTHETIC);\n                cExtends.generics.add(new AST.Access(null, \"X\", LineCol.SYNTHETIC));\n                AST.Access eExtends = new AST.Access(null, \"B\", LineCol.SYNTHETIC);\n                eExtends.generics.add(new AST.Access(null, \"X\", LineCol.SYNTHETIC));\n                eExtends.generics.add(new AST.Access(null, \"Y\", LineCol.SYNTHETIC));\n                assertEquals(Arrays.asList(\n                        new ClassDef(\n                                \"A\",\n                                Collections.singletonList(new AST.Access(null, \"T\", LineCol.SYNTHETIC)),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"B\",\n                                Arrays.asList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC),\n                                        new AST.Access(null, \"U\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"C\",\n                                Collections.singletonList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.singletonList(cExtends),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"D\",\n                                Collections.singletonList(new AST.Access(null, \"T\", LineCol.SYNTHETIC)),\n                                Collections.<Modifier>emptySet(),\n                                Collections.singletonList(\n                                        new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                ),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"E\",\n                                Collections.singletonList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Arrays.asList(\n                                        cExtends,\n                                        eExtends\n                                ),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"F\",\n                                Collections.singletonList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                new AST.Invocation(cExtends, Collections.<Expression>emptyList(), false, LineCol.SYNTHETIC),\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testInterfaceGeneric() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"interface A<:T:>\\n\" +\n                        \"interface B<:T,U:>\\n\" +\n                        \"interface C<:T:> : A<:X:>\"\n                );\n                AST.Access cExtends = new AST.Access(null, \"A\", LineCol.SYNTHETIC);\n                cExtends.generics.add(new AST.Access(null, \"X\", LineCol.SYNTHETIC));\n                assertEquals(Arrays.asList(\n                        new InterfaceDef(\n                                \"A\",\n                                Collections.singletonList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new InterfaceDef(\n                                \"B\",\n                                Arrays.asList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC),\n                                        new AST.Access(null, \"U\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new InterfaceDef(\n                                \"C\",\n                                Collections.singletonList(\n                                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<Modifier>emptySet(),\n                                Collections.singletonList(cExtends),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        )\n                ), stmts);\n        }\n\n        @Test\n        public void testGenericObject() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"object O<:T:>\");\n                assertEquals(Collections.singletonList(\n                        new ObjectDef(\"O\",\n                                Collections.singletonList(new AST.Access(null, \"T\", LineCol.SYNTHETIC)),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<Modifier>emptySet(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC)\n                ), stmts);\n        }\n\n        @Test\n        public void testUseAnnotationWithGeneric() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"@Anno<:X:>\\n\" +\n                        \"class A\\n\" +\n                        \"@Anno<:Y:>(1)\\n\" +\n                        \"class B\\n\" +\n                        \"@Anno<:Z:>(a='b')\\n\" +\n                        \"class C\\n\");\n                assertEquals(3, stmts.size());\n                ClassDef a = (ClassDef) stmts.get(0);\n                ClassDef b = (ClassDef) stmts.get(1);\n                ClassDef c = (ClassDef) stmts.get(2);\n                assertEquals(1, a.annos.size());\n                assertEquals(1, b.annos.size());\n                assertEquals(1, c.annos.size());\n                AST.Anno aa = a.annos.iterator().next();\n                AST.Anno ba = b.annos.iterator().next();\n                AST.Anno ca = c.annos.iterator().next();\n                assertEquals(1, aa.anno.generics.size());\n                assertEquals(1, ba.anno.generics.size());\n                assertEquals(1, ca.anno.generics.size());\n                assertEquals(new AST.Access(null, \"X\", LineCol.SYNTHETIC), aa.anno.generics.get(0));\n                assertEquals(new AST.Access(null, \"Y\", LineCol.SYNTHETIC), ba.anno.generics.get(0));\n                assertEquals(new AST.Access(null, \"Z\", LineCol.SYNTHETIC), ca.anno.generics.get(0));\n        }\n\n        @Test\n        public void testGenericAccess() throws Exception {\n                List<Statement> stmts = parse(\"\" +\n                        \"a.b.A<:T, U:>\"\n                );\n                AST.Access access = (AST.Access) stmts.get(0);\n                AST.Access expected = new AST.Access(\n                        new AST.Access(\n                                new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                \"b\", LineCol.SYNTHETIC), \"A\", LineCol.SYNTHETIC);\n                expected.generics.add(\n                        new AST.Access(null, \"T\", LineCol.SYNTHETIC)\n                );\n                expected.generics.add(\n                        new AST.Access(null, \"U\", LineCol.SYNTHETIC)\n                );\n                assertEquals(expected, access);\n        }\n\n        @Test\n        public void testTypeArray() throws Exception {\n                List<Statement> stmts = parse(\"type []A<:T:>\");\n                AST.Access a = new AST.Access(null, \"A\", LineCol.SYNTHETIC);\n                a.generics.add(new AST.Access(null, \"T\", LineCol.SYNTHETIC));\n                assertEquals(Collections.singletonList(\n                        new AST.TypeOf(new AST.Access(a, \"[]\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                ), stmts);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestParserMix.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.ElementStartNode;\nimport lt.compiler.syntactic.*;\nimport lt.compiler.syntactic.def.MethodDef;\nimport lt.compiler.syntactic.def.VariableDef;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.pre.Modifier;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * mix test of Syntactic processor results\n */\npublic class TestParserMix {\n        private static List<Statement> parse(String stmt) throws IOException, SyntaxException {\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(stmt), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Parser syntacticProcessor = new Parser(root, new ErrorManager(true));\n\n                return syntacticProcessor.parse();\n        }\n\n        @Test\n        public void test2VarOperatorAndAccessAndPar() throws Exception {\n                List<Statement> statements = parse(\"list * (1+2)\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(\n                        \"*\",\n                        new AST.Access(null, \"list\", LineCol.SYNTHETIC),\n                        new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC);\n                assertEquals(tvo, statement);\n        }\n\n        @Test\n        public void testAnnotationOnWrongPosition() throws Exception {\n                try {\n                        parse(\"\" +\n                                \"@Anno()\\n\" +\n                                \"1+1\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testModifierOnWrongPosition() throws Exception {\n                try {\n                        parse(\"pri 1\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testAccessDotAndOperator1() throws Exception {\n                List<Statement> statements = parse(\"1+a.b.c+2\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(\n                        \"+\",\n                        new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new AST.Access(new AST.Access(new AST.Access(null, \"a\", LineCol.SYNTHETIC), \"b\", LineCol.SYNTHETIC), \"c\", LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC);\n                assertEquals(tvo, statement);\n        }\n\n        @Test\n        public void testAccessDotAndOperator2() throws Exception {\n                List<Statement> statements = parse(\"1+list.get(0)+2\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(\n                        \"+\",\n                        new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new AST.Invocation(new AST.Access(new AST.Access(null, \"list\", LineCol.SYNTHETIC), \"get\", LineCol.SYNTHETIC),\n                                        Collections.<Expression>singletonList(new NumberLiteral(\"0\", LineCol.SYNTHETIC)), false, LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC);\n                assertEquals(tvo, statement);\n        }\n\n        @Test\n        public void testClosureAndOperator() throws Exception {\n                List<Statement> statements = parse(\"\" +\n                        \"1+(\\n\" +\n                        \"    if i==1\\n\" +\n                        \"        return 5\\n\" +\n                        \"    return 2\\n\" +\n                        \")+2\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(\n                        \"+\",\n                        new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new AST.Procedure(Arrays.asList(\n                                        new AST.If(Collections.singletonList(new AST.If.IfPair(new TwoVariableOperation(\n                                                \"==\",\n                                                new AST.Access(null, \"i\", LineCol.SYNTHETIC),\n                                                new NumberLiteral(\"1\", LineCol.SYNTHETIC)\n                                                , LineCol.SYNTHETIC),\n                                                Collections.<Statement>singletonList(\n                                                        new AST.Return(new NumberLiteral(\"5\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                                                ), LineCol.SYNTHETIC))\n                                                , LineCol.SYNTHETIC),\n                                        new AST.Return(new NumberLiteral(\"2\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                                ), LineCol.SYNTHETIC),\n                                LineCol.SYNTHETIC),\n                        new NumberLiteral(\"2\", LineCol.SYNTHETIC),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(tvo, statement);\n        }\n\n        @Test\n        public void testMethodMultipleAnnotation() throws Exception {\n                List<Statement> statements = parse(\"\" +\n                        \"@Anno\\n\" +\n                        \"public method(\\n\" +\n                        \"    @Anno1\\n\" +\n                        \"    arg0\\n\" +\n                        \"    @Anno2\\n\" +\n                        \"    arg1\" +\n                        \"):Unit\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                MethodDef m = new MethodDef(\n                        \"method\",\n                        new HashSet<Modifier>(Collections.singletonList(\n                                new Modifier(Modifier.Available.PUBLIC, LineCol.SYNTHETIC)\n                        )),\n                        new AST.Access(null, \"Unit\", LineCol.SYNTHETIC),\n                        Arrays.asList(\n                                new VariableDef(\"arg0\", Collections.<Modifier>emptySet(), new HashSet<AST.Anno>(Collections.singletonList(\n                                        new AST.Anno(new AST.Access(null, \"Anno1\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                                )), LineCol.SYNTHETIC),\n                                new VariableDef(\"arg1\", Collections.<Modifier>emptySet(), new HashSet<AST.Anno>(Collections.singletonList(\n                                        new AST.Anno(new AST.Access(null, \"Anno2\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                                )), LineCol.SYNTHETIC)\n                        ),\n                        new HashSet<AST.Anno>(Collections.singletonList(\n                                new AST.Anno(new AST.Access(null, \"Anno\", LineCol.SYNTHETIC), Collections.<AST.Assignment>emptyList(), LineCol.SYNTHETIC)\n                        )),\n                        Collections.<Statement>emptyList(),\n                        LineCol.SYNTHETIC);\n\n                assertEquals(m, statement);\n        }\n\n        @Test\n        public void testMethodDefInitVal() throws Exception {\n                try {\n                        parse(\"method(arg0,arg1=1,arg2)=0\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testMethodDefInitValPass() throws Exception {\n                try {\n                        parse(\"method(arg0,arg1=1,arg2=2)=0\");\n                } catch (SyntaxException ignore) {\n                        fail();\n                }\n        }\n\n        @Test\n        public void testClassDefInitVal() throws Exception {\n                try {\n                        parse(\"class C(arg0,arg1=1,arg2)\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testClassDefInitValPass() throws Exception {\n                try {\n                        parse(\"class C(arg0,arg1=1,arg2=2)\");\n                } catch (SyntaxException ignore) {\n                        fail();\n                }\n        }\n\n        @Test\n        public void testMultipleLines() throws Exception {\n                List<Statement> statements = parse(\"\" +\n                        \"3+\\n\" +\n                        \"2\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                TwoVariableOperation tvo = new TwoVariableOperation(\"+\", new NumberLiteral(\"3\", LineCol.SYNTHETIC), new NumberLiteral(\"2\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(tvo, statement);\n        }\n\n        @Test\n        public void testPrimitive() throws Exception {\n                List<Statement> statements = parse(\"i:int\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(null, \"int\", LineCol.SYNTHETIC));\n                assertEquals(v, statement);\n        }\n\n        @Test\n        public void testPrimitiveAssign() throws Exception {\n                List<Statement> statements = parse(\"i:bool=yes\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(null, \"bool\", LineCol.SYNTHETIC));\n                v.setInit(new BoolLiteral(\"yes\", LineCol.SYNTHETIC));\n                assertEquals(v, statement);\n        }\n\n        @Test\n        public void testMethodPrimitive() throws Exception {\n                List<Statement> statements = parse(\"method():int\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                MethodDef m = new MethodDef(\"method\", Collections.<Modifier>emptySet(), new AST.Access(null, \"int\", LineCol.SYNTHETIC), Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC);\n                assertEquals(m, statement);\n        }\n\n        @Test\n        public void testMapList() throws Exception {\n                List<Statement> statements = parse(\"[a:[1,2]]\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                        new AST.ArrayExp(Arrays.<Expression>asList(\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC));\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, statement);\n        }\n\n        @Test\n        public void testListMap() throws Exception {\n                List<Statement> statements = parse(\"[['a':b],['c':d]]\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                LinkedHashMap<Expression, Expression> map1 = new LinkedHashMap<Expression, Expression>();\n                map1.put(new StringLiteral(\"'a'\", LineCol.SYNTHETIC), new AST.Access(null, \"b\", LineCol.SYNTHETIC));\n                LinkedHashMap<Expression, Expression> map2 = new LinkedHashMap<Expression, Expression>();\n                map2.put(new StringLiteral(\"'c'\", LineCol.SYNTHETIC), new AST.Access(null, \"d\", LineCol.SYNTHETIC));\n                AST.ArrayExp arrayExp = new AST.ArrayExp(Arrays.<Expression>asList(\n                        new AST.MapExp(map1, LineCol.SYNTHETIC),\n                        new AST.MapExp(map2, LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(arrayExp, statement);\n        }\n\n        @Test\n        public void testMapWithListAndOther() throws Exception {\n                List<Statement> statements = parse(\"[a:[1,2],b:c]\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                LinkedHashMap<Expression, Expression> map = new LinkedHashMap<Expression, Expression>();\n                map.put(new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                        new AST.ArrayExp(Arrays.<Expression>asList(\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC));\n                map.put(new AST.Access(null, \"b\", LineCol.SYNTHETIC),\n                        new AST.Access(null, \"c\", LineCol.SYNTHETIC));\n                AST.MapExp mapExp = new AST.MapExp(map, LineCol.SYNTHETIC);\n                assertEquals(mapExp, statement);\n        }\n\n        @Test\n        public void testListWithMapAndOther() throws Exception {\n                List<Statement> statements = parse(\"[a,['c':d]]\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                LinkedHashMap<Expression, Expression> map2 = new LinkedHashMap<Expression, Expression>();\n                map2.put(new StringLiteral(\"'c'\", LineCol.SYNTHETIC), new AST.Access(null, \"d\", LineCol.SYNTHETIC));\n                AST.ArrayExp arrayExp = new AST.ArrayExp(Arrays.asList(\n                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                        new AST.MapExp(map2, LineCol.SYNTHETIC)\n                ), LineCol.SYNTHETIC);\n                assertEquals(arrayExp, statement);\n        }\n\n        @Test\n        public void testArrayPrimitive() throws Exception {\n                List<Statement> statements = parse(\"i:[]int\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(new AST.Access(null, \"int\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC));\n                assertEquals(v, statement);\n        }\n\n        @Test\n        public void testArrayPkgClass() throws Exception {\n                List<Statement> statements = parse(\"i:[]java::util::List\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                VariableDef v = new VariableDef(\"i\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setType(new AST.Access(new AST.Access(new AST.PackageRef(\"java::util\", LineCol.SYNTHETIC), \"List\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC));\n                assertEquals(v, statement);\n        }\n\n        @Test\n        public void testTypeOfArray() throws Exception {\n                List<Statement> statements = parse(\"type []int\");\n                assertEquals(1, statements.size());\n                Statement statement = statements.get(0);\n\n                AST.TypeOf typeOf = new AST.TypeOf(new AST.Access(new AST.Access(null, \"int\", LineCol.SYNTHETIC), \"[]\", LineCol.SYNTHETIC), LineCol.SYNTHETIC);\n                assertEquals(typeOf, statement);\n        }\n\n        @Test\n        public void testIndexAssign() throws Exception {\n                List<Statement> list = parse(\"a[1]=2\");\n\n                assertEquals(1, list.size());\n\n                Statement stmt = list.get(0);\n\n                assertEquals(\n                        new AST.Assignment(\n                                new AST.Access(new AST.Index(new AST.Access(null, \"a\", LineCol.SYNTHETIC), Collections.<Expression>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)), LineCol.SYNTHETIC), null, LineCol.SYNTHETIC),\n                                \"=\",\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC)\n                                , LineCol.SYNTHETIC)\n                        ,\n                        stmt\n                );\n        }\n\n        @Test\n        public void testStaticStatement() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"static method():Unit\\n\" +\n                        \"static field=1\\n\" +\n                        \"static System.out.println('hello world')\");\n\n                assertEquals(3, list.size());\n\n                Statement stmt0 = list.get(0);\n                Statement stmt1 = list.get(1);\n                Statement stmt2 = list.get(2);\n\n                assertTrue(stmt0 instanceof AST.StaticScope);\n                assertTrue(stmt1 instanceof AST.StaticScope);\n                assertTrue(stmt2 instanceof AST.StaticScope);\n\n                stmt0 = ((AST.StaticScope) stmt0).statements.get(0);\n                stmt1 = ((AST.StaticScope) stmt1).statements.get(0);\n                stmt2 = ((AST.StaticScope) stmt2).statements.get(0);\n\n                assertTrue(stmt0 instanceof MethodDef);\n                assertTrue(stmt1 instanceof VariableDef);\n                assertTrue(stmt2 instanceof AST.Invocation);\n        }\n\n        @Test\n        public void testMap_OperatorLikeInvocation() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"[\\n\" +\n                        \"    'a':a op b\\n\" +\n                        \"    a op b:'b'\\n\" +\n                        \"    'a':a op\\n\" +\n                        \"    a op:'b'\\n\" +\n                        \"]\");\n\n                assertEquals(1, list.size());\n                AST.MapExp mapExp = new AST.MapExp(new LinkedHashMap<Expression, Expression>() {\n                        {\n                                put(new StringLiteral(\"'a'\", null), new AST.Invocation(\n                                        new AST.Access(new AST.Access(null, \"a\", null), \"op\", null),\n                                        Collections.<Expression>singletonList(new AST.Access(null, \"b\", null)),\n                                        false, null\n                                ));\n                                put(new AST.Invocation(\n                                        new AST.Access(new AST.Access(null, \"a\", null), \"op\", null),\n                                        Collections.<Expression>singletonList(new AST.Access(null, \"b\", null)),\n                                        false, null\n                                ), new StringLiteral(\"'b'\", null));\n                                put(new StringLiteral(\"'a'\", null), new AST.Access(new AST.Access(null, \"a\", null), \"op\", null));\n                                put(new AST.Access(new AST.Access(null, \"a\", null), \"op\", null), new StringLiteral(\"'b'\", null));\n                        }\n                }, null);\n                assertEquals(mapExp, list.get(0));\n        }\n\n        @Test\n        public void testOperatorLikeInvocationWithTwoVarOp() throws Exception {\n                List<Statement> list = parse(\"a op b + 1 op 2 op\");\n                assertEquals(1, list.size());\n\n                // ((a op (b+1)) op 2) op\n                AST.Access access = new AST.Access(\n                        new AST.Invocation(\n                                new AST.Access(\n                                        new AST.Invocation(\n                                                new AST.Access(\n                                                        new AST.Access(null, \"a\", null),\n                                                        \"op\",\n                                                        null\n                                                ),\n                                                Collections.<Expression>singletonList(\n                                                        new TwoVariableOperation(\n                                                                \"+\",\n                                                                new AST.Access(\n                                                                        null,\n                                                                        \"b\",\n                                                                        null\n                                                                ),\n                                                                new NumberLiteral(\"1\", null),\n                                                                null\n                                                        )\n                                                ),\n                                                false, null\n                                        ),\n                                        \"op\",\n                                        null\n                                ),\n                                Collections.<Expression>singletonList(new NumberLiteral(\"2\", null)),\n                                false, null\n                        ),\n                        \"op\",\n                        null\n                );\n\n                assertEquals(access, list.get(0));\n        }\n\n        @Test\n        public void testMapIndexAccess() throws Exception {\n                List<Statement> list = parse(\n                        \"\" +\n                                \"[\\n\" +\n                                \"    'USER' : session['USER']\\n\" +\n                                \"]\"\n                );\n                assertEquals(\n                        Collections.singletonList(\n                                new AST.MapExp(new LinkedHashMap<Expression, Expression>() {{\n                                        put(new StringLiteral(\"'USER'\", LineCol.SYNTHETIC),\n                                                new AST.Index(\n                                                        new AST.Access(null, \"session\", LineCol.SYNTHETIC),\n                                                        Collections.<Expression>singletonList(\n                                                                new StringLiteral(\"'USER'\", LineCol.SYNTHETIC)\n                                                        ), LineCol.SYNTHETIC\n                                                ));\n                                }}, LineCol.SYNTHETIC)\n                        ),\n                        list\n                );\n        }\n\n        @Test\n        public void testManyInternalSyntax() throws Exception {\n                List<Statement> list = parse(\"\" +\n                        \"a\\n\" +\n                        \"    b\\n\" +\n                        \"c\\n\" +\n                        \"    d\"\n                );\n                assertEquals(Arrays.asList(\n                        new AST.Invocation(new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new AST.Lambda(\n                                                Collections.singletonList(new VariableDef(\"it\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)),\n                                                Collections.<Statement>singletonList(new AST.Access(null, \"b\", LineCol.SYNTHETIC)), LineCol.SYNTHETIC\n                                        )\n                                ), false, LineCol.SYNTHETIC),\n                        new AST.Invocation(new AST.Access(null, \"c\", LineCol.SYNTHETIC),\n                                Collections.<Expression>singletonList(\n                                        new AST.Lambda(\n                                                Collections.singletonList(new VariableDef(\"it\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)),\n                                                Collections.<Statement>singletonList(new AST.Access(null, \"d\", LineCol.SYNTHETIC)), LineCol.SYNTHETIC\n                                        )\n                                ), false, LineCol.SYNTHETIC)\n                ), list);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestPrimitiveOperators.java",
    "content": "package lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.Properties;\nimport lt.compiler.Scanner;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.function.Function1;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.reflect.Method;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * primitive operators\n */\npublic class TestPrimitiveOperators {\n        @SuppressWarnings(\"unchecked\")\n        public List<Function1<Object, Number>> numberFuncs = Arrays.asList(\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.intValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.longValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.floatValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.doubleValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.byteValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.shortValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number n) throws Exception {\n                                return (char) n.intValue();\n                        }\n                }\n        );\n        @SuppressWarnings(\"unchecked\")\n        public List<Function1<Object, Number>> integerFuncs = Arrays.asList(\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.intValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.longValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.byteValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number number) throws Exception {\n                                return number.shortValue();\n                        }\n                },\n                new Function1<Object, Number>() {\n                        @Override\n                        public Object apply(Number n) throws Exception {\n                                return (char) n.intValue();\n                        }\n                }\n        );\n\n        public static Class<?> retrieveClass(String code, String clsName) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n                Scanner lexicalProcessor = new ScannerSwitcher(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                final Map<String, byte[]> list = codeGenerator.generate();\n\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                byte[] bs = list.get(name);\n                                if (bs == null) throw new ClassNotFoundException(name);\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                return classLoader.loadClass(clsName);\n        }\n\n        private void testAddSubtractMultiplyDivide(Number a, Number b, Number r, Method method) throws Exception {\n                int countDouble = 0;\n                int countFloat = 0;\n                int countLong = 0;\n                int countInt = 0;\n\n                for (Function1<Object, Number> f1 : numberFuncs) {\n                        Object aa = f1.apply(a);\n                        for (Function1<Object, Number> f2 : numberFuncs) {\n                                Object bb = f2.apply(b);\n                                Object rr = method.invoke(null, aa, bb);\n\n                                if (aa instanceof Double || bb instanceof Double) {\n                                        ++countDouble;\n                                        assertEquals(r.doubleValue(), rr);\n                                } else if (aa instanceof Float || bb instanceof Float) {\n                                        ++countFloat;\n                                        assertEquals(r.floatValue(), rr);\n                                } else if (aa instanceof Long || bb instanceof Long) {\n                                        ++countLong;\n                                        assertEquals(r.longValue(), rr);\n                                } else {\n                                        ++countInt;\n                                        assertEquals(r.intValue(), rr);\n                                }\n                        }\n                }\n\n                assertEquals(11, countFloat);\n                assertEquals(9, countLong);\n                assertEquals(16, countInt);\n                assertEquals(13, countDouble);\n        }\n\n        @Test\n        public void testAdd() throws Exception {\n                Class<?> add = retrieveClass(\"\" +\n                                \"class TestAdd\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a + b\"\n                        , \"TestAdd\");\n                Method method = add.getMethod(\"method\", Object.class, Object.class);\n\n                testAddSubtractMultiplyDivide(1, 8, 9, method);\n        }\n\n        @Test\n        public void testSubtract() throws Exception {\n                Class<?> subtract = retrieveClass(\"\" +\n                                \"class TestSubtract\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a - b\"\n                        , \"TestSubtract\");\n                Method method = subtract.getMethod(\"method\", Object.class, Object.class);\n\n                testAddSubtractMultiplyDivide(1, 8, -7, method);\n        }\n\n        @Test\n        public void testMultiply() throws Exception {\n                Class<?> multiply = retrieveClass(\"\" +\n                                \"class TestMultiply\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a * b\"\n                        , \"TestMultiply\");\n                Method method = multiply.getMethod(\"method\", Object.class, Object.class);\n\n                testAddSubtractMultiplyDivide(4, 3, 12, method);\n        }\n\n        @Test\n        public void testDivide() throws Exception {\n                Class<?> divide = retrieveClass(\"\" +\n                                \"class TestDivide\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a / b\"\n                        , \"TestDivide\");\n                Method method = divide.getMethod(\"method\", Object.class, Object.class);\n\n                testAddSubtractMultiplyDivide(4, 3, 4d / 3d, method);\n        }\n\n        private void testShift(Number a, Number b, int by, int s, int c, int i, long l, Method method) throws Exception {\n                for (Function1<Object, Number> f1 : integerFuncs) {\n                        Object aa = f1.apply(a);\n                        for (Function1<Object, Number> f2 : integerFuncs) {\n                                Object bb = f2.apply(b);\n                                Object rr = method.invoke(null, aa, bb);\n\n                                if (aa instanceof Long) {\n                                        assertEquals(l, rr);\n                                } else if (aa instanceof Integer) {\n                                        assertEquals(i, rr);\n                                } else if (aa instanceof Character) {\n                                        assertEquals(c, rr);\n                                } else if (aa instanceof Short) {\n                                        assertEquals(s, rr);\n                                } else if (aa instanceof Byte) {\n                                        assertEquals(by, rr);\n                                } else {\n                                        fail();\n                                }\n                        }\n                }\n        }\n\n        @Test\n        public void testShiftLeft() throws Exception {\n                Class<?> shiftLeft = retrieveClass(\"\" +\n                                \"class TestShiftLeft\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a << b\"\n                        , \"TestShiftLeft\");\n                Method method = shiftLeft.getMethod(\"method\", Object.class, Object.class);\n\n                testShift(3, 5, ((byte) 3) << 5, ((short) 3) << 5, ((char) 3) << 5, (3 << 5), 3L << 5, method);\n        }\n\n        @Test\n        public void testShiftRight() throws Exception {\n                Class<?> shiftRight = retrieveClass(\"\" +\n                                \"class TestShiftRight\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a >> b\"\n                        , \"TestShiftRight\");\n                Method method = shiftRight.getMethod(\"method\", Object.class, Object.class);\n\n                testShift(-123, 2, ((byte) -123) >> 2, ((short) -123) >> 2, ((char) -123) >> 2, -123 >> 2, -123L >> 2, method);\n        }\n\n        @Test\n        public void testUnsignedShiftRight() throws Exception {\n                Class<?> unsignedShiftRight = retrieveClass(\"\" +\n                                \"class TestUnsignedShiftRight\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a >>> b\"\n                        , \"TestUnsignedShiftRight\");\n                Method method = unsignedShiftRight.getMethod(\"method\", Object.class, Object.class);\n\n                testShift(-123, 2, ((byte) -123) >>> 2, ((short) -123) >>> 2, ((char) -123) >>> 2, -123 >>> 2, -123L >>> 2, method);\n        }\n\n        private void testLogic(Number a, Number b, Number r, int rci, long rcl, Method method) throws Exception {\n                int countLong = 0;\n                int countInt = 0;\n\n                for (Function1<Object, Number> f1 : integerFuncs) {\n                        Object aa = f1.apply(a);\n                        for (Function1<Object, Number> f2 : integerFuncs) {\n                                Object bb = f2.apply(b);\n                                Object rr = method.invoke(null, aa, bb);\n\n                                if (aa instanceof Long || bb instanceof Long) {\n                                        ++countLong;\n                                        if (aa instanceof Character) {\n                                                assertEquals(rcl, rr);\n                                        } else {\n                                                assertEquals(r.longValue(), rr);\n                                        }\n                                } else {\n                                        ++countInt;\n                                        if (aa instanceof Character) {\n                                                assertEquals(rci, rr);\n                                        } else {\n                                                assertEquals(r.intValue(), rr);\n                                        }\n                                }\n                        }\n                }\n\n                assertEquals(9, countLong);\n                assertEquals(16, countInt);\n        }\n\n        private void testBoolOps(Number a, boolean b, boolean res, Method method) throws Exception {\n                for (Function1<Object, Number> f : numberFuncs) {\n                        Object aa = f.apply(a);\n                        Object rr1 = method.invoke(null, aa, b);\n                        Object rr2 = method.invoke(null, b, aa);\n                        assertEquals(res, rr1);\n                        assertEquals(res, rr2);\n                }\n        }\n\n        @Test\n        public void testAnd() throws Exception {\n                Class<?> and = retrieveClass(\"\" +\n                                \"class TestAnd\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a & b\"\n                        , \"TestAnd\");\n                Method method = and.getMethod(\"method\", Object.class, Object.class);\n\n                testLogic(-123, 4, -123 & 4, ((char) -123) & 4, ((char) -123) & 4L, method);\n                testBoolOps(3, true, true, method);\n                testBoolOps(3, false, false, method);\n                testBoolOps(0, true, false, method);\n                testBoolOps(0, false, false, method);\n        }\n\n        @Test\n        public void testOr() throws Exception {\n                Class<?> or = retrieveClass(\"\" +\n                                \"class TestOr\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a | b\"\n                        , \"TestOr\");\n                Method method = or.getMethod(\"method\", Object.class, Object.class);\n\n                testLogic(-123, 2, -123 | 2, ((char) -123) | 2, ((char) -123) | 2L, method);\n                testBoolOps(3, true, true, method);\n                testBoolOps(3, false, true, method);\n                testBoolOps(0, true, true, method);\n                testBoolOps(0, false, false, method);\n        }\n\n        @Test\n        public void testXor() throws Exception {\n                Class<?> xor = retrieveClass(\"\" +\n                                \"class TestXor\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a ^ b\"\n                        , \"TestXor\");\n                Method method = xor.getMethod(\"method\", Object.class, Object.class);\n\n                testLogic(-123, 2, -123 ^ 2, ((char) -123) ^ 2, ((char) -123) ^ 2L, method);\n        }\n\n        @Test\n        public void testRemainder() throws Exception {\n                Class<?> remainder = retrieveClass(\"\" +\n                                \"class TestRemainder\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a % b\"\n                        , \"TestRemainder\");\n                Method method = remainder.getMethod(\"method\", Object.class, Object.class);\n\n                testLogic(4, 3, 1, 1, 1L, method);\n        }\n\n        @Test\n        public void testNegate() throws Exception {\n                Class<?> negate = retrieveClass(\"\" +\n                                \"class TestNegate\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a)= -a\"\n                        , \"TestNegate\");\n                Method method = negate.getMethod(\"method\", Object.class);\n\n                Number a = 3;\n                Number r = -3;\n                for (Function1<Object, Number> f : numberFuncs) {\n                        Object aa = f.apply(a);\n                        Object rr = method.invoke(null, aa);\n                        if (aa instanceof Double) {\n                                assertEquals(r.doubleValue(), rr);\n                        } else if (aa instanceof Float) {\n                                assertEquals(r.floatValue(), rr);\n                        } else if (aa instanceof Long) {\n                                assertEquals(r.longValue(), rr);\n                        } else {\n                                assertEquals(r.intValue(), rr);\n                        }\n                }\n        }\n\n        @Test\n        public void testNot() throws Exception {\n                Class<?> not = retrieveClass(\"\" +\n                                \"class TestNot\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a)= ~a\"\n                        , \"TestNot\");\n                Method method = not.getMethod(\"method\", Object.class);\n\n                Number a = 3;\n                for (Function1<Object, Number> f : integerFuncs) {\n                        Object aa = f.apply(a);\n                        Object rr = method.invoke(null, aa);\n                        if (aa instanceof Long) {\n                                assertEquals(~3L, rr);\n                        } else {\n                                assertEquals(~3, rr);\n                        }\n                }\n        }\n\n        private void testBoolRes(Number a, Number b, boolean res, Method method) throws Exception {\n                for (Function1<Object, Number> f1 : numberFuncs) {\n                        Object aa = f1.apply(a);\n                        for (Function1<Object, Number> f2 : numberFuncs) {\n                                Object bb = f2.apply(b);\n                                Object rr = method.invoke(null, aa, bb);\n                                assertEquals(res, rr);\n                        }\n                }\n        }\n\n        @Test\n        public void testGt() throws Exception {\n                Class<?> gt = retrieveClass(\"\" +\n                                \"class TestGt\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a > b\"\n                        , \"TestGt\");\n                Method method = gt.getMethod(\"method\", Object.class, Object.class);\n\n                testBoolRes(3, 5, false, method);\n                testBoolRes(3, 2, true, method);\n                testBoolRes(3, 3, false, method);\n        }\n\n        @Test\n        public void testGe() throws Exception {\n                Class<?> ge = retrieveClass(\"\" +\n                                \"class TestGe\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a >= b\"\n                        , \"TestGe\");\n                Method method = ge.getMethod(\"method\", Object.class, Object.class);\n\n                testBoolRes(3, 5, false, method);\n                testBoolRes(3, 2, true, method);\n                testBoolRes(3, 3, true, method);\n        }\n\n        @Test\n        public void testLt() throws Exception {\n                Class<?> lt = retrieveClass(\"\" +\n                                \"class TestLt\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a < b\"\n                        , \"TestLt\");\n                Method method = lt.getMethod(\"method\", Object.class, Object.class);\n\n                testBoolRes(3, 5, true, method);\n                testBoolRes(3, 2, false, method);\n                testBoolRes(3, 3, false, method);\n        }\n\n        @Test\n        public void testLe() throws Exception {\n                Class<?> le = retrieveClass(\"\" +\n                                \"class TestLe\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a <= b\"\n                        , \"TestLe\");\n                Method method = le.getMethod(\"method\", Object.class, Object.class);\n\n                testBoolRes(3, 5, true, method);\n                testBoolRes(3, 2, false, method);\n                testBoolRes(3, 3, true, method);\n        }\n\n        private void testBoolRes(Number a, boolean res, Method method) throws Exception {\n                for (Function1<Object, Number> f1 : numberFuncs) {\n                        Object aa = f1.apply(a);\n                        Object rr = method.invoke(null, aa);\n                        assertEquals(res, rr);\n                }\n        }\n\n        @Test\n        public void testLogicNot() throws Exception {\n                Class<?> logicNot = retrieveClass(\"\" +\n                                \"class TestLe\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a)= !a\"\n                        , \"TestLe\");\n                Method method = logicNot.getMethod(\"method\", Object.class);\n\n                testBoolRes(2, false, method);\n                testBoolRes(0, true, method);\n                assertEquals(false, method.invoke(null, true));\n                assertEquals(true, method.invoke(null, false));\n        }\n\n        @Test\n        public void testStringObject() throws Exception {\n                Class<?> str = retrieveClass(\"\" +\n                                \"class TestStringObject\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a, b)= a + b\"\n                        , \"TestStringObject\");\n                Method method = str.getMethod(\"method\", Object.class, Object.class);\n\n                assertEquals(\"abc\", method.invoke(null, \"a\", \"bc\"));\n                assertEquals(\"abc\", method.invoke(null, \"ab\", \"c\"));\n                assertEquals(\"atrue\", method.invoke(null, \"a\", true));\n                assertEquals(\"truea\", method.invoke(null, true, \"a\"));\n                String x = method.invoke(null, new Object(), \"a\").toString();\n                assertTrue(x.startsWith(\"java.lang.Object@\") && x.endsWith(\"a\"));\n        }\n\n        @Test\n        public void testPow() throws Exception {\n                Class<?> pow = retrieveClass(\"\" +\n                                \"class TestPow\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a,b) = a ^^ b\"\n                        , \"TestPow\");\n                double result = Math.pow(3, 4);\n                Method method = pow.getMethod(\"method\", Object.class, Object.class);\n                for (Function1<Object, Number> f1 : numberFuncs) {\n                        Object a = f1.apply(3);\n                        for (Function1<Object, Number> f2 : numberFuncs) {\n                                Object b = f2.apply(4);\n                                assertEquals(result, method.invoke(null, a, b));\n                        }\n                }\n        }\n\n        @Test\n        public void testImplicitCastWhenInvokingMethods() throws Exception {\n                Class<?> c = retrieveClass(\"\" +\n                                \"class TestImplicitCastWhenInvokingMethods\\n\" +\n                                \"    static\\n\" +\n                                \"        private i(i:int)=i\\n\" +\n                                \"        private l(l:long)=l\\n\" +\n                                \"        private f(f:float)=f\\n\" +\n                                \"        private d(d:double)=d\\n\" +\n                                \"        b2i(b:byte)=i(b)\\n\" +\n                                \"        b2l(b:byte)=l(b)\\n\" +\n                                \"        b2f(b:byte)=f(b)\\n\" +\n                                \"        b2d(b:byte)=d(b)\\n\" +\n                                \"        s2i(b:short)=i(b)\\n\" +\n                                \"        s2l(b:short)=l(b)\\n\" +\n                                \"        s2f(b:short)=f(b)\\n\" +\n                                \"        s2d(b:short)=d(b)\\n\" +\n                                \"        c2i(b:char)=i(b)\\n\" +\n                                \"        c2l(b:char)=l(b)\\n\" +\n                                \"        c2f(b:char)=f(b)\\n\" +\n                                \"        c2d(b:char)=d(b)\\n\" +\n                                \"        i2l(b:int)=l(b)\\n\" +\n                                \"        i2f(b:int)=f(b)\\n\" +\n                                \"        i2d(b:int)=d(b)\\n\" +\n                                \"        l2f(b:long)=f(b)\\n\" +\n                                \"        l2d(b:long)=d(b)\\n\" +\n                                \"        f2d(b:float)=d(b)\\n\"\n                        , \"TestImplicitCastWhenInvokingMethods\");\n                for (Class<?> from : Arrays.<Class<?>>asList(\n                        byte.class, short.class, char.class,\n                        int.class, long.class, float.class\n                )) {\n                        for (Class<?> to : Arrays.<Class<?>>asList(int.class, long.class, float.class, double.class)) {\n                                if (from == to) {\n                                        continue;\n                                }\n                                if (from == long.class && to == int.class) {\n                                        continue;\n                                } else if (from == float.class && (to == int.class || to == long.class)) {\n                                        continue;\n                                }\n\n                                Method x = c.getMethod(from.getName().charAt(0) + \"2\" + to.getName().charAt(0), from);\n                                Object input = produce(from);\n                                Object output = produce(to);\n\n                                Object res = x.invoke(null, input);\n                                assertEquals(output, res);\n                        }\n                }\n        }\n\n        private Object produce(Class<?> t) {\n                if (t == byte.class) {\n                        return (byte) 1;\n                } else if (t == short.class) {\n                        return (short) 1;\n                } else if (t == char.class) {\n                        return (char) 1;\n                } else if (t == int.class) {\n                        return 1;\n                } else if (t == long.class) {\n                        return 1L;\n                } else if (t == float.class) {\n                        return 1f;\n                } else if (t == double.class) {\n                        return 1d;\n                } else throw new RuntimeException();\n        }\n\n        @Test\n        public void testOverwritten() throws Exception {\n                Class<?> c = retrieveClass(\"\" +\n                                \"class TestOverwritten1\\n\" +\n                                \"  static\\n\" +\n                                \"    private x(i:int)=i\\n\" +\n                                \"    private x(f:float)=f\\n\" +\n                                \"    private x(l:long)=l\\n\" +\n                                \"    private x(d:double)=d\\n\" +\n                                \"    def method_byte(o:byte)=x(o)\\n\" +\n                                \"    def method_short(o:short)=x(o)\\n\" +\n                                \"    def method_char(o:char)=x(o)\\n\" +\n                                \"    def method_int(o:int)=x(o)\"\n                        , \"TestOverwritten1\");\n                for (Class<?> t : Arrays.<Class<?>>asList(byte.class, short.class, char.class, int.class)) {\n                        Method method = c.getMethod(\"method_\" + t.getName(), t);\n                        Object input = produce(t);\n                        Object output = produce(int.class);\n\n                        Object result = method.invoke(null, input);\n                        assertEquals(\"input \" + t + \", output: int, result \" + result.getClass(), output, result);\n                }\n\n                c = retrieveClass(\"\" +\n                                \"class TestOverwritten2\\n\" +\n                                \"  static\\n\" +\n                                \"    private x(f:float)=f\\n\" +\n                                \"    private x(l:long)=l\\n\" +\n                                \"    private x(d:double)=d\\n\" +\n                                \"    def method_byte(o:byte)=x(o)\\n\" +\n                                \"    def method_short(o:short)=x(o)\\n\" +\n                                \"    def method_char(o:char)=x(o)\\n\" +\n                                \"    def method_int(o:int)=x(o)\"\n                        , \"TestOverwritten2\");\n                for (Class<?> t : Arrays.<Class<?>>asList(byte.class, short.class, char.class, int.class)) {\n                        Method method = c.getMethod(\"method_\" + t.getName(), t);\n                        Object input = produce(t);\n                        Object output = produce(long.class);\n\n                        Object result = method.invoke(null, input);\n                        assertEquals(\"input \" + t + \", output: long, result \" + result.getClass(), output, result);\n                }\n\n                c = retrieveClass(\"\" +\n                                \"class TestOverwritten3\\n\" +\n                                \"  static\\n\" +\n                                \"    private x(f:float)=f\\n\" +\n                                \"    private x(d:double)=d\\n\" +\n                                \"    def method_byte(o:byte)=x(o)\\n\" +\n                                \"    def method_short(o:short)=x(o)\\n\" +\n                                \"    def method_char(o:char)=x(o)\\n\" +\n                                \"    def method_int(o:int)=x(o)\"\n                        , \"TestOverwritten3\");\n                for (Class<?> t : Arrays.<Class<?>>asList(byte.class, short.class, char.class, int.class)) {\n                        Method method = c.getMethod(\"method_\" + t.getName(), t);\n                        Object input = produce(t);\n                        Object output = produce(float.class);\n\n                        Object result = method.invoke(null, input);\n                        assertEquals(\"input \" + t + \", output: float, result \" + result.getClass(), output, result);\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestScanner.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.ErrorManager;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.*;\nimport org.junit.Test;\n\nimport java.io.StringReader;\n\nimport static org.junit.Assert.*;\n\n/**\n * test\n */\npublic class TestScanner {\n        @Test\n        public void testPkg() throws Exception {\n                // package lt.test\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"package lt::test\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"package\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"lt\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"test\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testImport() throws Exception {\n                // import packageName._\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"\" +\n                        \"import Package::name::_\\n\" +\n                        \"import Package::name::Test\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"import\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"Package\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"name\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"_\", TokenType.VALID_NAME);\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"import\", TokenType.KEY);\n                args.previous = new Element(args, \"Package\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"name\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                new Element(args, \"Test\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testCls1() throws Exception {\n                // class ClassName\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"class ClassName\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                new Element(args, \"ClassName\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testCls2() throws Exception {\n                // class ClassName(arg1:Type1,arg2:Type2)\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"class ClassName(arg1,arg2=value2)\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"ClassName\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"arg1\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n\n                args.previous = new Element(args, \"arg2\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"value2\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testVariable3() throws Exception {\n                // val value:Type = 1\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"val value = 1\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"value\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testMethod1() throws Exception {\n                //val trim(input)\n                //    <input.trim()\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"\" +\n                        \"val trim(input)\\n\" +\n                        \"    return input.trim()\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testMethod2() throws Exception {\n                // voidMethod(input)=0\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"voidMethod(input)=0\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"voidMethod\", TokenType.VALID_NAME);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"0\", TokenType.NUMBER);\n\n                args.previous = null;\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testModifiers() throws Exception {\n                //pub val abs class X\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"public val abstract class X\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"public\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                args.previous = new Element(args, \"abstract\", TokenType.MODIFIER);\n                args.previous = new Element(args, \"class\", TokenType.KEY);\n                args.previous = new Element(args, \"X\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                //if true\n                //    <\"hello world\"\n                //elseif false\n                //    <\"hello\"\n                //else\n                //    <\"world\"\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"if true\\n\" +\n                                \"    return \\\"hello world\\\"\\n\" +\n                                \"elseif false\\n\" +\n                                \"    return \\\"hello\\\"\\n\" +\n                                \"else\\n\" +\n                                \"    return \\\"world\\\"\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"if\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"elseif\", TokenType.KEY);\n                args.previous = new Element(args, \"false\", TokenType.BOOL);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"else\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello world\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"world\\\"\", TokenType.STRING);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testFor1() throws Exception {\n                //for i @ iterable\n                //    i\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"for i in iterable\\n\" +\n                                \"    i\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"for\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"in\", TokenType.KEY);\n                args.previous = new Element(args, \"iterable\", TokenType.VALID_NAME);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                startNode.setLinkedNode(new Element(args, \"i\", TokenType.VALID_NAME));\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile1() throws Exception {\n                //while true\n                //    i+=1\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"while true\\n\" +\n                                \"    i+=1\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile2() throws Exception {\n                // do\n                //     i+=1\n                // while true\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"do\\n\" +\n                                \"    i+=1\\n\" +\n                                \"while true\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"do\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testTry() throws Exception {\n                //try\n                //    throw e\n                //catch e\n                //    SomeException,AnotherException\n                //        throw RuntimeException(e)\n                //    OtherException\n                //finally\n                //    <ret\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"try\\n\" +\n                                \"    throw e\\n\" +\n                                \"catch e\\n\" +\n                                \"    SomeException,AnotherException\\n\" +\n                                \"        throw RuntimeException(e)\\n\" +\n                                \"    OtherException\\n\" +\n                                \"finally\\n\" +\n                                \"    return ret\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"try\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"catch\", TokenType.KEY);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"finally\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(4));\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"SomeException\", TokenType.VALID_NAME);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"AnotherException\", TokenType.VALID_NAME);\n                ElementStartNode startNode1_1 = new ElementStartNode(args, new Indent(8));\n                args.previous = startNode1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"OtherException\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1_1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"RuntimeException\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode1_1_1 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode1_1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode1_1_1.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"ret\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testLambda() throws Exception {\n                //list.stream().filter(\n                //    (e)->\n                //        e>10\n                //)\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"list.stream().filter(\\n    (e)->e>10)\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"list\", TokenType.VALID_NAME);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"stream\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"filter\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(4));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                startNode1.setLinkedNode(args.previous);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"->\", TokenType.SYMBOL);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode2.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \">\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"10\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testOperators() throws Exception {\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"1+2\\n\" +\n                                \"3-4\\n\" +\n                                \"5*6\\n\" +\n                                \"7/8\\n\" +\n                                \"9%10\\n\" +\n                                \"i+=11\\n\" +\n                                \"i-=12\\n\" +\n                                \"i*=13\\n\" +\n                                \"i/=14\\n\" +\n                                \"i%=15\\n\" +\n                                \"i++\\n\" +\n                                \"i--\\n\" +\n                                \"++i\\n\" +\n                                \"--i\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"2\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"3\", TokenType.NUMBER);\n                args.previous = new Element(args, \"-\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"4\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"5\", TokenType.NUMBER);\n                args.previous = new Element(args, \"*\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"6\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"7\", TokenType.NUMBER);\n                args.previous = new Element(args, \"/\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"8\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"9\", TokenType.NUMBER);\n                args.previous = new Element(args, \"%\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"10\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"11\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"-=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"12\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"*=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"13\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"/=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"14\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"%=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"15\", TokenType.NUMBER);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"++\", TokenType.SYMBOL);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"--\", TokenType.SYMBOL);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"++\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n\n                args.previous = new Element(args, \"--\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testSpacesAtTheFront() throws Exception {\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"  import package::name::_\"\n                ), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n                Node n = root.getLinkedNode();\n                assertTrue(n instanceof Element);\n                Element e = (Element) n;\n                assertEquals(1, e.getLineCol().line);\n                assertEquals(3, e.getLineCol().column);\n        }\n\n        @Test\n        public void testIndent() throws Exception {\n                Properties properties = new Properties();\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        // the statements is copied from testIf\n                        // but changed indentation to 2\n                        \"\" +\n                                \"if true\\n\" +\n                                \"  return \\\"hello world\\\"\\n\" +\n                                \"elseif false\\n\" +\n                                \"  return \\\"hello\\\"\\n\" +\n                                \"else\\n\" +\n                                \"  return \\\"world\\\"\"), properties, new ErrorManager(true));\n                processor.scan();\n        }\n\n        @Test\n        public void testMultipleLineComment() throws Exception {\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"a=1/**/\\n\" + // inline comment 1\n                                \"a/**/=2\\n\" + // inline comment 2\n                                \"a/* a */=3\\n\" + // inline comment 3\n                                \"a=4/* a */\\n\" + // inline comment 4\n                                \"a/*\\n\" +\n                                \"*/=5\\n\" +// multiple line 1\n                                \"/*\\n\" +\n                                \"*/a=6\\n\" + // multiple line 2\n                                \"/*\\n\" +\n                                \"a\\n\" +\n                                \"*/a=7\" + // multiple line 3\n                                \"\"),\n                        new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                Element e = new Element(args, \"a\", TokenType.VALID_NAME);\n                root2.setLinkedNode(e);\n                args.previous = e;\n\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n                for (int i = 2; i <= 7; ++i) {\n                        args.previous = new EndingNode(args, EndingNode.WEAK);\n                        args.previous = new Element(args, \"a\", TokenType.VALID_NAME);\n                        args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                        args.previous = new Element(args, \"\" + i, TokenType.NUMBER);\n                }\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testUTF8Words() throws Exception {\n                IndentScanner scanner = new IndentScanner(\"test\", new StringReader(\"\" +\n                        \"\" +\n                        \"你好='hello'\"),\n                        new Properties(), new ErrorManager(true));\n                ElementStartNode root = scanner.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                Element e = new Element(args, \"你好\", TokenType.VALID_NAME);\n                root2.setLinkedNode(e);\n                args.previous = e;\n\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"'hello'\", TokenType.STRING);\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testPairIndent() throws Exception {\n                IndentScanner scanner = new IndentScanner(\"test\", new StringReader(\"\" +\n                        \"\" +\n                        \"a = [1,\\n\" +\n                        \"  2,3,[\\n\" +\n                        \"    4,5\\n\" +\n                        \"   ]\\n\" + // more indent\n                        \"]\\n\" + // same as root indent\n                        \"b = [\\n\" +\n                        \"]\\n\" + // FLEX indent\n                        \"\"),\n                        new Properties(), new ErrorManager(true));\n                ElementStartNode root = scanner.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                Element e = new Element(args, \"a\", TokenType.VALID_NAME);\n                root2.setLinkedNode(e);\n                args.previous = e;\n\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"[\", TokenType.SYMBOL);\n                ElementStartNode startLine1 = new ElementStartNode(args, new Indent(2));\n                args.previous = startLine1;\n                args.previous = new EndingNode(args, EndingNode.SYNTHETIC);\n                args.previous = new Element(args, \"]\", TokenType.SYMBOL);\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"b\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"[\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"]\", TokenType.SYMBOL);\n\n                args.previous = null;\n                e = new Element(args, \"1\", TokenType.NUMBER);\n                startLine1.setLinkedNode(e);\n                args.previous = e;\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"2\", TokenType.NUMBER);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"3\", TokenType.NUMBER);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"[\", TokenType.SYMBOL);\n                ElementStartNode startLine2 = new ElementStartNode(args, new Indent(4));\n                args.previous = startLine2;\n                args.previous = new EndingNode(args, EndingNode.SYNTHETIC);\n                args.previous = new Element(args, \"]\", TokenType.SYMBOL);\n\n                args.previous = null;\n                e = new Element(args, \"4\", TokenType.NUMBER);\n                args.previous = e;\n                startLine2.setLinkedNode(e);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"5\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestScannerLayerControl.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.ErrorManager;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.*;\nimport org.junit.Test;\n\nimport java.io.StringReader;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * test\n */\npublic class TestScannerLayerControl {\n        @Test\n        public void testPkg() throws Exception {\n                // package lt.test\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"package lt::test\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"package\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"lt\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"::\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"test\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testMethod1() throws Exception {\n                //val trim(input)\n                //    <input.trim()\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\"\" +\n                        \"val trim(input) {return input.trim()}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"val\", TokenType.MODIFIER);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"input\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \".\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"trim\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                //if true\n                //    <\"hello world\"\n                //elseif false\n                //    <\"hello\"\n                //else\n                //    <\"world\"\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"if true {return \\\"hello world\\\"} elseif false {return \\\"hello\\\"} else {return \\\"world\\\"}\"),\n                        new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"if\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"elseif\", TokenType.KEY);\n                args.previous = new Element(args, \"false\", TokenType.BOOL);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"else\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello world\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"hello\\\"\", TokenType.STRING);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"\\\"world\\\"\", TokenType.STRING);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testFor1() throws Exception {\n                //for i @ iterable\n                //    i\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"for i in iterable {i}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"for\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"in\", TokenType.KEY);\n                args.previous = new Element(args, \"iterable\", TokenType.VALID_NAME);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                startNode.setLinkedNode(new Element(args, \"i\", TokenType.VALID_NAME));\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile1() throws Exception {\n                //while true\n                //    i+=1\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"while true {i+=1}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testWhile2() throws Exception {\n                // do\n                //     i+=1\n                // while true\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"do {i+=1} while true\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"do\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"while\", TokenType.KEY);\n                args.previous = new Element(args, \"true\", TokenType.BOOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"i\", TokenType.VALID_NAME);\n                startNode.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"+=\", TokenType.SYMBOL);\n                args.previous = new Element(args, \"1\", TokenType.NUMBER);\n\n                assertEquals(root2, root);\n        }\n\n        @Test\n        public void testTry() throws Exception {\n                // the syntax is not used\n                // but the test remains\n                //try\n                //    throw e\n                //catch e\n                //    SomeException,AnotherException\n                //        throw RuntimeException(e)\n                //    OtherException\n                //finally\n                //    return ret\n                IndentScanner processor = new IndentScanner(\"test\", new StringReader(\n                        \"\" +\n                                \"try \" +\n                                /**/\"{throw e} \" +\n                                \"catch e \" +\n                                /**/\"{SomeException,AnotherException \" +\n                                /* ** */\"{throw RuntimeException(e)} \" +\n                                /**/\"OtherException } \" +\n                                \"finally \" +\n                                /**/\"{return ret}\"), new Properties(), new ErrorManager(true));\n                ElementStartNode root = processor.scan();\n\n                Args args = new Args();\n                ElementStartNode root2 = new ElementStartNode(args, new Indent(0));\n                args.previous = new Element(args, \"try\", TokenType.KEY);\n                root2.setLinkedNode(args.previous);\n                ElementStartNode startNode1 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"catch\", TokenType.KEY);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                ElementStartNode startNode2 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode2;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"finally\", TokenType.KEY);\n                ElementStartNode startNode3 = new ElementStartNode(args, new Indent(-1));\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"SomeException\", TokenType.VALID_NAME);\n                startNode2.setLinkedNode(args.previous);\n                args.previous = new EndingNode(args, EndingNode.STRONG);\n                args.previous = new Element(args, \"AnotherException\", TokenType.VALID_NAME);\n                ElementStartNode startNode1_1 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \"OtherException\", TokenType.VALID_NAME);\n\n                args.previous = null;\n                args.previous = new Element(args, \"throw\", TokenType.KEY);\n                startNode1_1.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"RuntimeException\", TokenType.VALID_NAME);\n                args.previous = new Element(args, \"(\", TokenType.SYMBOL);\n                ElementStartNode startNode1_1_1 = new ElementStartNode(args, new Indent(-1));\n                args.previous = startNode1_1_1;\n                args.previous = new EndingNode(args, EndingNode.WEAK);\n                args.previous = new Element(args, \")\", TokenType.SYMBOL);\n\n                args.previous = null;\n                args.previous = new Element(args, \"e\", TokenType.VALID_NAME);\n                startNode1_1_1.setLinkedNode(args.previous);\n\n                args.previous = null;\n                args.previous = new Element(args, \"return\", TokenType.KEY);\n                startNode3.setLinkedNode(args.previous);\n                args.previous = new Element(args, \"ret\", TokenType.VALID_NAME);\n\n                assertEquals(root2, root);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestScannerSwitcher.java",
    "content": "package lt.compiler.cases;\n\nimport lt.compiler.ErrorManager;\nimport lt.compiler.Properties;\nimport lt.compiler.ScannerSwitcher;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\nimport java.io.StringReader;\n\n/**\n * test scanner switcher\n */\npublic class TestScannerSwitcher {\n        @Test\n        public void test1() throws Exception {\n                ScannerSwitcher s1 = new ScannerSwitcher(\"test\", new StringReader(\n                        \"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"class A(a, public b):B(a) {\\n\" +\n                                \"protected x=1\\n\" +\n                                \"}\"\n                ), new Properties(), new ErrorManager(true));\n                ScannerSwitcher s2 = new ScannerSwitcher(\"test\", new StringReader(\n                        \"\" +\n                                \"class A(a, public b):B(a)\\n\" +\n                                \"    protected x=1\"\n                ), new Properties(), new ErrorManager(true));\n                assertTrue(s1.scan().equalsIgnoreIndent(s2.scan()));\n        }\n\n        @Test\n        public void testMap() throws Exception {\n                ScannerSwitcher s1 = new ScannerSwitcher(\"test\", new StringReader(\n                        \"\" +\n                                \"/// :scanner-brace\\n\" +\n                                \"[\\\"a\\\":1\\n\" +\n                                \"\\\"b\\\":2,\\\"c\\\":3\\n\" +\n                                \"\\\"d\\\":4]\"\n                ), new Properties(), new ErrorManager(true));\n                ScannerSwitcher s2 = new ScannerSwitcher(\"test\", new StringReader(\n                        \"\" +\n                                \"[\\n\" +\n                                \"    \\\"a\\\":1\\n\" +\n                                \"    \\\"b\\\":2,\\n\" +\n                                \"    \\\"c\\\":3\\n\" +\n                                \"    \\\"d\\\":4\\n\" +\n                                \"]\"\n                ), new Properties(), new ErrorManager(true));\n\n                assertTrue(s1.scan().equalsIgnoreIndent(s2.scan()));\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestSemantic.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases;\n\nimport lt.compiler.*;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.lexical.ElementStartNode;\nimport lt.compiler.semantic.*;\nimport lt.compiler.semantic.builtin.*;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.util.LocalVariables;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.reflect.InvocationTargetException;\nimport java.lang.reflect.Method;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * semantic\n */\npublic class TestSemantic {\n        private Set<STypeDef> parse(Map<String, String> fileMap) throws IOException, SyntaxException {\n                ErrorManager err = new ErrorManager(true);\n\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                for (String fileName : fileMap.keySet()) {\n                        IndentScanner lexicalProcessor = new IndentScanner(\"test\", new StringReader(fileMap.get(fileName)), new Properties(), err);\n                        ElementStartNode root = lexicalProcessor.scan();\n                        Parser syntacticProcessor = new Parser(root, err);\n                        List<Statement> stmts = syntacticProcessor.parse();\n                        map.put(fileName, stmts);\n                }\n                SemanticProcessor semanticProcessor = new SemanticProcessor(map, Thread.currentThread().getContextClassLoader(), err);\n                return semanticProcessor.parse();\n        }\n\n        @Test\n        public void testClass() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(\"test.A\", classDef.fullName());\n        }\n\n        @Test\n        public void testFun() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"fun A(o):lt::lang::function::Function1\\n\" +\n                        \"    return o\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(\"test.A\", classDef.fullName());\n                assertEquals(1, classDef.constructors().size());\n                assertTrue(classDef.constructors().get(0).getParameters().isEmpty());\n                assertEquals(1, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                assertEquals(\"apply\", method.name());\n                assertEquals(1, method.getParameters().size());\n                assertEquals(2, method.statements().size());\n                assertTrue(method.statements().get(1) instanceof Ins.TReturn);\n                Ins.TReturn r = (Ins.TReturn) method.statements().get(1);\n                assertEquals(Ins.TReturn.AReturn, r.returnIns());\n                assertTrue(r.value() instanceof Ins.CheckCast);\n                assertTrue(((Ins.CheckCast) r.value()).theValueToCheck() instanceof Ins.InvokeVirtual);\n        }\n\n        @Test\n        public void testClassExtends() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import java::util::_\\n\" +\n                        \"class A:ArrayList\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(\"test.A\", classDef.fullName());\n                assertTrue(classDef.modifiers().contains(SModifier.PUBLIC));\n                assertEquals(\"java.util.ArrayList\", classDef.parent().fullName());\n        }\n\n        @Test\n        public void testClassImplements() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import java::util::_\\n\" +\n                        \"abstract class A:List\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(\"test.A\", classDef.fullName());\n                assertEquals(1, classDef.superInterfaces().size());\n                assertTrue(classDef.modifiers().contains(SModifier.PUBLIC) && classDef.modifiers().contains(SModifier.ABSTRACT));\n                assertEquals(\"java.util.List\", classDef.superInterfaces().get(0).fullName());\n        }\n\n        @Test\n        public void testArrayType() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    arr:[]String\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                assertEquals(\"test.A\", classDef.fullName());\n                assertEquals(1, classDef.fields().size());\n\n                SFieldDef f = classDef.fields().get(0);\n                assertEquals(\"arr\", f.name());\n                assertEquals(\"[Ljava.lang.String;\", f.type().fullName());\n        }\n\n        @Test\n        public void testArrayType2Dimension() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    arr:[][]String\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                assertEquals(\"test.A\", classDef.fullName());\n                assertEquals(1, classDef.fields().size());\n\n                SFieldDef f = classDef.fields().get(0);\n                assertEquals(\"arr\", f.name());\n                assertEquals(\"[[Ljava.lang.String;\", f.type().fullName());\n        }\n\n        @Test\n        public void testClassNotFound() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A:B\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testCircularInheritance_2_Classes() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A:B\\n\" +\n                        \"class B:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testCircularInheritance_3_Classes() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A:B\\n\" +\n                        \"class B:C\\n\" +\n                        \"class C:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testCircularInheritance_2_Interfaces() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"interface A:B\\n\" +\n                        \"interface B:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testCircularInheritance_3_Interfaces() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"interface A:B\\n\" +\n                        \"interface B:C\\n\" +\n                        \"interface C:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testNotOverridden() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A:java::util::List\\n\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testNotOverridden2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"interface A\\n\" +\n                        \"    method()=...\\n\" +\n                        \"class B:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testNotOverriddenFromClass() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"abs class A\\n\" +\n                        \"    abs method():Unit\\n\" +\n                        \"class B:A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testImport() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import java::awt::_\\n\" +\n                        \"import java::util::List\\n\" +\n                        \"import java::util::Collections._\\n\" +\n                        \"class A(ls:List)\\n\" +\n                        \"    emptyList()\\n\" +\n                        \"    EMPTY_LIST\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SParameter p = classDef.constructors().get(0).getParameters().get(0);\n                assertEquals(\"java.util.List\", p.type().fullName());\n\n                Instruction i1 = classDef.constructors().get(0).statements().get(1 + 1);\n                Instruction i2 = classDef.constructors().get(0).statements().get(2 + 1);\n\n                assertTrue(i1 instanceof Ins.InvokeStatic);\n                assertTrue(i2 instanceof Ins.GetStatic);\n\n                assertEquals(\"emptyList\", ((SMethodDef) ((Ins.InvokeStatic) i1).invokable()).name());\n                assertEquals(\"EMPTY_LIST\", ((Ins.GetStatic) i2).field().name());\n\n                assertEquals(\"java.util.Collections\", ((Ins.InvokeStatic) i1).invokable().declaringType().fullName());\n                assertEquals(\"java.util.Collections\", ((Ins.GetStatic) i2).field().declaringType().fullName());\n        }\n\n        @Test\n        public void testAnno() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"@MyAnno(str='',i=1)\\n\" +\n                        \"class A\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(\"test.A\", classDef.fullName());\n                assertTrue(classDef.modifiers().contains(SModifier.PUBLIC));\n                assertEquals(3, classDef.annos().size()); // @MyAnno and @ImplicitImports\n\n                SAnno anno = classDef.annos().get(0);\n                assertEquals(2, anno.type().annoFields().size());\n                for (SAnnoField f : anno.type().annoFields()) {\n                        if (f.name().equals(\"i\")) {\n                                assertEquals(new IntValue(100), f.defaultValue());\n                        }\n                }\n        }\n\n        @Test\n        public void testAnnoAll() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"@AnnotationTest(str='\\\\t\\\\n')\\n\" +\n                        \"class A\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(3, classDef.annos().size()); // @AnnotationTest, @ImplicitImports\n\n                SAnno anno = classDef.annos().get(0);\n                SAnnoDef annoDef = anno.type();\n                assertEquals(14, annoDef.annoFields().size());\n\n                for (SAnnoField f : anno.values().keySet()) {\n                        Value v = anno.values().get(f);\n                        if (f.name().equals(\"str\")) {\n                                assertEquals(new StringConstantValue(\"\\t\\n\"), v);\n                        }\n                }\n\n                for (SAnnoField f : annoDef.annoFields()) {\n                        if (f.name().equals(\"clsArr\")) {\n                                Value v = f.defaultValue();\n                                assertTrue(v instanceof SArrayValue);\n                                SArrayValue arr = (SArrayValue) v;\n                                assertEquals(1, arr.dimension());\n                                assertEquals(2, arr.length());\n                                assertEquals(\"java.lang.Class\", arr.type().type().fullName());\n                                Value[] values = arr.values();\n                                assertTrue(values[0] instanceof Ins.GetClass);\n                                assertTrue(values[1] instanceof Ins.GetClass);\n\n                                assertEquals(\"java.lang.Class\", ((Ins.GetClass) values[0]).targetType().fullName());\n                                assertEquals(\"java.lang.String\", ((Ins.GetClass) values[1]).targetType().fullName());\n                        } else if (f.name().equals(\"strArr\")) {\n                                Value v = f.defaultValue();\n                                assertTrue(v instanceof SArrayValue);\n                                SArrayValue arr = (SArrayValue) v;\n                                assertEquals(1, arr.dimension());\n                                assertEquals(2, arr.length());\n                                assertEquals(\"java.lang.String\", arr.type().type().fullName());\n                                Value[] values = arr.values();\n                                assertTrue(values[0] instanceof StringConstantValue);\n                                assertTrue(values[1] instanceof StringConstantValue);\n\n                                assertEquals(\"a\", new String(((StringConstantValue) values[0]).getByte()));\n                                assertEquals(\"b\", new String(((StringConstantValue) values[1]).getByte()));\n                        } else if (f.name().equals(\"e\")) {\n                                Value v = f.defaultValue();\n                                assertTrue(v instanceof EnumValue);\n                                assertEquals(\"lt.compiler.semantic.SModifier\", v.type().fullName());\n                                assertEquals(\"PUBLIC\", ((EnumValue) v).enumStr());\n                        } else if (f.name().equals(\"cls\")) {\n                                Value v = f.defaultValue();\n                                assertTrue(v instanceof Ins.GetClass);\n                                assertEquals(\"java.lang.Class\", v.type().fullName());\n                                assertEquals(\"java.lang.String\", ((Ins.GetClass) v).targetType().fullName());\n                        } else if (f.name().equals(\"str\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new StringConstantValue(\"str\"), v);\n                        } else if (f.name().equals(\"i\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new IntValue(100), v);\n                        } else if (f.name().equals(\"l\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new LongValue(100), v);\n                        } else if (f.name().equals(\"s\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new ShortValue((short) 100), v);\n                        } else if (f.name().equals(\"b\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new ByteValue((byte) 100), v);\n                        } else if (f.name().equals(\"bo\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new BoolValue(true), v);\n                        } else if (f.name().equals(\"c\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new CharValue('a'), v);\n                        } else if (f.name().equals(\"f\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new FloatValue(100), v);\n                        } else if (f.name().equals(\"d\")) {\n                                Value v = f.defaultValue();\n                                assertEquals(new DoubleValue(100), v);\n                        } else if (f.name().equals(\"anno\")) {\n                                Value v = f.defaultValue();\n                                assertTrue(v instanceof SAnno);\n                                SAnno a = (SAnno) v;\n                                for (SAnnoField ff : a.values().keySet()) {\n                                        Value ffv = a.values().get(ff);\n                                        if (ff.name().equals(\"str\")) {\n                                                assertEquals(new StringConstantValue(\"a\"), ffv);\n                                        } else if (ff.name().equals(\"i\")) {\n                                                assertEquals(new IntValue(100), ffv);\n                                        }\n                                }\n                        }\n                }\n        }\n\n        @Test\n        public void testConstructorParamInitValue() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a,b:int=1,c:int=2)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(3, classDef.constructors().size());\n\n                SConstructorDef lastConstructor = null;\n                for (SConstructorDef con : classDef.constructors()) {\n                        if (null == lastConstructor) assertEquals(3, con.getParameters().size());\n                        else assertEquals(lastConstructor.getParameters().size() - 1, con.getParameters().size());\n\n                        if (null != lastConstructor) {\n                                Ins.InvokeSpecial invokeSpecial = (Ins.InvokeSpecial) con.statements().get(0);\n                                assertEquals(lastConstructor, invokeSpecial.invokable()); // invoke last constructor\n                                assertEquals(invokeSpecial.invokable().getParameters().size(), invokeSpecial.arguments().size()); // param size\n                                Ins.TLoad tLoad = (Ins.TLoad) invokeSpecial.arguments().get(0);\n                                int index = LocalVariables.calculateIndexForLocalVariable(tLoad.value(), tLoad.getScope(), false);\n                                assertEquals(1, index);\n                                if (invokeSpecial.arguments().size() == 2) {\n                                        assertEquals(new IntValue(1), invokeSpecial.arguments().get(1));\n                                }\n                                if (invokeSpecial.arguments().size() == 3) {\n                                        tLoad = (Ins.TLoad) invokeSpecial.arguments().get(1);\n                                        index = LocalVariables.calculateIndexForLocalVariable(tLoad.value(), tLoad.getScope(), false);\n                                        assertEquals(2, index);\n                                        assertEquals(new IntValue(2), invokeSpecial.arguments().get(2));\n                                }\n                        }\n\n                        lastConstructor = con;\n                }\n        }\n\n        @Test\n        public void testMethodParamInitValue() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method(a,b:int=1,c:double=2)=pass\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(3, classDef.methods().size());\n\n                SMethodDef lastMethod = null;\n                for (SMethodDef m : classDef.methods()) {\n                        if (null == lastMethod) assertEquals(3, m.getParameters().size());\n                        else assertEquals(lastMethod.getParameters().size() - 1, m.getParameters().size());\n\n                        if (null != lastMethod) {\n                                // it's return\n                                // get the returned value\n                                // the returned value should be invokeVirtual\n                                Ins.InvokeVirtual invokeVirtual = ((Ins.InvokeVirtual) (\n                                        (Ins.TReturn) m.statements().get(0)).value()\n                                );\n                                assertEquals(lastMethod, invokeVirtual.invokable()); // invoke last method\n                                assertEquals(invokeVirtual.invokable().getParameters().size(), invokeVirtual.arguments().size()); // param size\n                                Ins.TLoad tLoad = (Ins.TLoad) invokeVirtual.arguments().get(0);\n                                int index = LocalVariables.calculateIndexForLocalVariable(tLoad.value(), tLoad.getScope(), false);\n                                assertEquals(1, index);\n\n                                assertTrue(invokeVirtual.arguments().size() == 2 || invokeVirtual.arguments().size() == 3);\n                                if (invokeVirtual.arguments().size() == 2) {\n                                        assertEquals(new IntValue(1), invokeVirtual.arguments().get(1));\n                                }\n                                if (invokeVirtual.arguments().size() == 3) {\n                                        tLoad = (Ins.TLoad) invokeVirtual.arguments().get(1);\n                                        index = LocalVariables.calculateIndexForLocalVariable(tLoad.value(), tLoad.getScope(), false);\n                                        assertEquals(2, index);\n                                        assertEquals(new DoubleValue(2), invokeVirtual.arguments().get(2));\n                                }\n                        }\n\n                        lastMethod = m;\n                }\n        }\n\n        @Test\n        public void testMethodInvoke_$null_methodName$() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method()=pass\\n\" +\n                        \"    method() // invoke\"); // invoke\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(1, classDef.methods().size());\n\n                assertEquals(\"method\", classDef.methods().get(0).name());\n                assertEquals(0, classDef.methods().get(0).getParameters().size());\n\n                SMethodDef methodDef = classDef.methods().get(0);\n\n                assertEquals(2, classDef.constructors().get(0).statements().size());\n                assertTrue(classDef.constructors().get(0).statements().get(1) instanceof Ins.InvokeVirtual);\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) classDef.constructors().get(0).statements().get(1);\n\n                assertTrue(methodDef == invokeVirtual.invokable());\n        }\n\n        @Test\n        public void testMethodInvoke_$this_methodName$() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method()=pass\\n\" +\n                        \"    this.method() // invoke this\"); // invoke this\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(1, classDef.methods().size());\n\n                assertEquals(\"method\", classDef.methods().get(0).name());\n                assertEquals(0, classDef.methods().get(0).getParameters().size());\n\n                SMethodDef methodDef = classDef.methods().get(0);\n\n                assertEquals(2, classDef.constructors().get(0).statements().size());\n                assertTrue(classDef.constructors().get(0).statements().get(1) instanceof Ins.InvokeVirtual);\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) classDef.constructors().get(0).statements().get(1);\n\n                assertTrue(methodDef == invokeVirtual.invokable());\n        }\n\n        @Test\n        public void testMethodInvoke_$superClass_$this_methodName$$() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    Object.this.hashCode() // invoke special\"); // invoke special\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                assertEquals(2, classDef.constructors().get(0).statements().size());\n                assertTrue(classDef.constructors().get(0).statements().get(1) instanceof Ins.InvokeSpecial);\n                Ins.InvokeSpecial invokeSpecial = (Ins.InvokeSpecial) classDef.constructors().get(0).statements().get(1);\n                assertEquals(\"hashCode\", ((SMethodDef) invokeSpecial.invokable()).name());\n        }\n\n        @Test\n        public void testMethodInvoke_$null_methodName$but_method_is_static() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        method()=...\\n\" +\n                        \"    method() // invoke static\"); // invoke static\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(1, classDef.methods().size());\n\n                assertEquals(\"method\", classDef.methods().get(0).name());\n                assertEquals(0, classDef.methods().get(0).getParameters().size());\n\n                SMethodDef methodDef = classDef.methods().get(0);\n                assertTrue(methodDef.modifiers().contains(SModifier.STATIC));\n\n                assertEquals(2, classDef.constructors().get(0).statements().size());\n                assertTrue(classDef.constructors().get(0).statements().get(1) instanceof Ins.InvokeStatic);\n                Ins.InvokeStatic invokeVirtual = (Ins.InvokeStatic) classDef.constructors().get(0).statements().get(1);\n\n                assertTrue(methodDef == invokeVirtual.invokable());\n        }\n\n        @Test\n        public void testMethodInvoke_$Type_methodName$() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        method()=...\\n\" +\n                        \"    A.method() // invoke static\"); // invoke static\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(1, classDef.methods().size());\n\n                assertEquals(\"method\", classDef.methods().get(0).name());\n                assertEquals(0, classDef.methods().get(0).getParameters().size());\n\n                SMethodDef methodDef = classDef.methods().get(0);\n                assertTrue(methodDef.modifiers().contains(SModifier.STATIC));\n\n                assertEquals(2, classDef.constructors().get(0).statements().size());\n                assertTrue(classDef.constructors().get(0).statements().get(1) instanceof Ins.InvokeStatic);\n                Ins.InvokeStatic invokeVirtual = (Ins.InvokeStatic) classDef.constructors().get(0).statements().get(1);\n\n                assertTrue(methodDef == invokeVirtual.invokable());\n        }\n\n        @Test\n        public void testMethodInvoke_$value_methodName$() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    Integer(1).toString()\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeVirtual);\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) ins;\n                SInvokable sInvokable = invokeVirtual.invokable();\n                assertTrue(sInvokable instanceof SMethodDef);\n                SMethodDef sMethodDef = (SMethodDef) sInvokable;\n                assertEquals(\"toString\", sMethodDef.name());\n        }\n\n        private static Value parseValueFromExpression(SemanticProcessor processor, Expression exp, STypeDef requiredType, SemanticScope scope) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n                Method parseValueFromExpression = processor.getClass().getDeclaredMethod(\"parseValueFromExpression\", Expression.class, STypeDef.class, SemanticScope.class);\n                parseValueFromExpression.setAccessible(true);\n                return (Value) parseValueFromExpression.invoke(processor, exp, requiredType, scope);\n        }\n\n        private static STypeDef getTypeWithName(SemanticProcessor processor, String className, LineCol lineCol) throws NoSuchMethodException, InvocationTargetException, IllegalAccessException {\n                Method getTypeWithName = processor.getClass().getDeclaredMethod(\"getTypeWithName\", String.class, LineCol.class);\n                getTypeWithName.setAccessible(true);\n                return (STypeDef) getTypeWithName.invoke(processor, className, lineCol);\n        }\n\n        @Test\n        public void testVariableWithNoLimit() throws Exception {\n                SemanticProcessor processor = new SemanticProcessor(new HashMap<String, List<Statement>>(), Thread.currentThread().getContextClassLoader(), new ErrorManager(true));\n                processor.parse();\n\n                assertEquals(new IntValue(1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new DoubleValue(1.2), parseValueFromExpression(processor, new NumberLiteral(\"1.2\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new CharValue('c'), parseValueFromExpression(processor, new StringLiteral(\"'c'\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new StringConstantValue(\"s\"), parseValueFromExpression(processor, new StringLiteral(\"\\\"s\\\"\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new StringConstantValue(\"str\"), parseValueFromExpression(processor, new StringLiteral(\"\\\"str\\\"\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new StringConstantValue(\"str\"), parseValueFromExpression(processor, new StringLiteral(\"'str'\", LineCol.SYNTHETIC), null, null));\n                assertEquals(new BoolValue(true), parseValueFromExpression(processor, new BoolLiteral(\"true\", LineCol.SYNTHETIC), null, null));\n        }\n\n        @Test\n        public void testPrimitiveVariableWithLimit() throws Exception {\n                SemanticProcessor processor = new SemanticProcessor(new HashMap<String, List<Statement>>(), Thread.currentThread().getContextClassLoader(), new ErrorManager(true));\n                processor.parse();\n\n                assertEquals(new CharValue('c'), parseValueFromExpression(processor, new StringLiteral(\"\\\"c\\\"\", LineCol.SYNTHETIC), CharTypeDef.get(), null));\n                assertEquals(new IntValue(1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), IntTypeDef.get(), null));\n                assertEquals(new ShortValue((short) 1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), ShortTypeDef.get(), null));\n                assertEquals(new ByteValue((byte) 1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), ByteTypeDef.get(), null));\n                assertEquals(new LongValue(1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), LongTypeDef.get(), null));\n                assertEquals(new FloatValue(1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), FloatTypeDef.get(), null));\n                assertEquals(new DoubleValue(1), parseValueFromExpression(processor, new NumberLiteral(\"1\", LineCol.SYNTHETIC), DoubleTypeDef.get(), null));\n\n                assertEquals(new FloatValue(1.2f), parseValueFromExpression(processor, new NumberLiteral(\"1.2\", LineCol.SYNTHETIC), FloatTypeDef.get(), null));\n                assertEquals(new DoubleValue(1.2), parseValueFromExpression(processor, new NumberLiteral(\"1.2\", LineCol.SYNTHETIC), DoubleTypeDef.get(), null));\n        }\n\n        @Test\n        public void testCharAndString() throws Exception {\n                SemanticProcessor processor = new SemanticProcessor(new HashMap<String, List<Statement>>(), Thread.currentThread().getContextClassLoader(), new ErrorManager(true));\n                processor.parse();\n\n                STypeDef charSequenceType = getTypeWithName(processor, \"java.lang.CharSequence\", LineCol.SYNTHETIC);\n                assertEquals(new StringConstantValue(\"s\"), parseValueFromExpression(processor, new StringLiteral(\"'s'\", LineCol.SYNTHETIC), charSequenceType, null));\n\n                STypeDef objectType = getTypeWithName(processor, \"java.lang.Object\", LineCol.SYNTHETIC);\n                Value v = parseValueFromExpression(processor, new StringLiteral(\"'c'\", LineCol.SYNTHETIC), objectType, null);\n                assertTrue(v instanceof Ins.InvokeStatic);\n                assertEquals(\"java.lang.Character\", v.type().fullName());\n                assertEquals(new CharValue('c'), ((Ins.InvokeStatic) v).arguments().get(0));\n\n                Value v2 = parseValueFromExpression(processor, new StringLiteral(\"\\\"s\\\"\", LineCol.SYNTHETIC), objectType, null);\n                assertEquals(new StringConstantValue(\"s\"), v2);\n        }\n\n        @Test\n        public void testInvokeConstructor() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    Object()\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n\n                assertTrue(ins instanceof Ins.New);\n                Ins.New aNew = (Ins.New) ins;\n                assertEquals(\"java.lang.Object\", aNew.constructor().declaringType().fullName());\n        }\n\n        @Test\n        public void testMethodBestMatch1() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method(i:Integer)=pass\\n\" +\n                        \"    method(i:Object)=pass\\n\" +\n                        \"    method(Integer(1))\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(2, classDef.methods().size());\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeVirtual);\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) ins;\n\n                assertEquals(\"java.lang.Integer\", invokeVirtual.invokable().getParameters().get(0).type().fullName());\n        }\n\n        @Test\n        public void testMethodBestMatch2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method(i:Integer,j:Integer)=pass\\n\" +\n                        \"    method(i:Object,j:Number)=pass\\n\" +\n                        \"    method(Integer(1),Integer(1))\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(2, classDef.methods().size());\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeVirtual);\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) ins;\n\n                assertEquals(\"java.lang.Integer\", invokeVirtual.invokable().getParameters().get(0).type().fullName());\n                assertEquals(\"java.lang.Integer\", invokeVirtual.invokable().getParameters().get(1).type().fullName());\n        }\n\n        @Test\n        public void testMethodBestMatch3() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method(i:Integer,j:Object)=pass\\n\" +\n                        \"    method(i:Object,j:Number)=pass\\n\" +\n                        \"    method(Integer(1),Integer(1))\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testArgAutoCast() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    Long(1)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.New);\n                Ins.New aNew = (Ins.New) ins;\n\n                Value v = aNew.args().get(0);\n                assertTrue(v instanceof Ins.Cast);\n                Ins.Cast c = (Ins.Cast) v;\n\n                assertEquals(Ins.Cast.CAST_INT_TO_LONG, c.castMode());\n                assertEquals(new IntValue(1), c.value());\n        }\n\n        @Test\n        public void testAsType_parsed_into_short_and_the_value_would_be_ignored() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    1 as short\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                assertEquals(1, classDef.constructors().get(0).statements().size());\n        }\n\n        @Test\n        public void testAsType() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    Short(1 as short)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.New);\n                Ins.New aNew = (Ins.New) ins;\n\n                assertEquals(new ShortValue((short) 1), aNew.args().get(0));\n        }\n\n        @Test\n        public void testLocalField() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(i)\\n\" +\n                        \"    i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1 + 1);\n                assertTrue(ins instanceof Ins.GetField);\n                Ins.GetField getField = (Ins.GetField) ins;\n                assertEquals(\"i\", getField.field().name());\n        }\n\n        @Test\n        public void testGetField() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    i:Object\\n\" +\n                        \"    i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.GetField);\n                Ins.GetField getField = (Ins.GetField) ins;\n                assertEquals(\"i\", getField.field().name());\n        }\n\n        @Test\n        public void testGetStatic() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        i:Object\\n\" +\n                        \"    i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.GetStatic);\n                Ins.GetStatic getStatic = (Ins.GetStatic) ins;\n                assertEquals(\"i\", getStatic.field().name());\n        }\n\n        @Test\n        public void testGetStaticWithType() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        i:Object\\n\" +\n                        \"    A.i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.GetStatic);\n                Ins.GetStatic getStatic = (Ins.GetStatic) ins;\n                assertEquals(\"i\", getStatic.field().name());\n        }\n\n        @Test\n        public void testSuperThisField1() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    protected i:int\\n\" +\n                        \"class B:A\\n\" +\n                        \"    protected i:String\\n\" +\n                        \"    i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(2, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                if (classDef.fullName().equals(\"test.A\")) {\n                        classDef = (SClassDef) it.next();\n                }\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.GetField);\n                Ins.GetField getField = (Ins.GetField) ins;\n                assertEquals(\"i\", getField.field().name());\n\n                assertEquals(classDef, getField.field().declaringType());\n        }\n\n        @Test\n        public void testSuperThisField2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    protected i:int\\n\" +\n                        \"class B:A\\n\" +\n                        \"    protected i:String\\n\" +\n                        \"    A.this.i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(2, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                if (classDef.fullName().equals(\"test.A\")) {\n                        classDef = (SClassDef) it.next();\n                }\n\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.GetField);\n                Ins.GetField getField = (Ins.GetField) ins;\n                assertEquals(\"i\", getField.field().name());\n\n                assertEquals(\"test.A\", getField.field().declaringType().fullName());\n        }\n\n        @Test\n        public void testArrayLength() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    i:[]int\\n\" +\n                        \"    i.length\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.ArrayLength);\n                Ins.ArrayLength arrayLength = (Ins.ArrayLength) ins;\n                assertTrue(arrayLength.arrayValue() instanceof Ins.GetField);\n                Ins.GetField gf = (Ins.GetField) arrayLength.arrayValue();\n                assertEquals(\"i\", gf.field().name());\n        }\n\n        @Test\n        public void testIndex() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    i:[]int\\n\" +\n                        \"    i[0]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.TALoad);\n                Ins.TALoad TALoad = (Ins.TALoad) ins;\n                assertTrue(TALoad.arr() instanceof Ins.GetField);\n                assertEquals(\"i\", ((Ins.GetField) TALoad.arr()).field().name());\n                assertEquals(new IntValue(0), TALoad.index());\n                assertEquals(Ins.TALoad.Iaload, TALoad.mode());\n        }\n\n        @Test\n        public void testIndexGet() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import java::util::_\\n\" +\n                        \"class A\\n\" +\n                        \"    i:List\\n\" +\n                        \"    i[0]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeInterface);\n                Ins.InvokeInterface invokeInterface = (Ins.InvokeInterface) ins;\n                assertTrue(invokeInterface.invokable() instanceof SMethodDef);\n                assertEquals(\"get\", ((SMethodDef) invokeInterface.invokable()).name());\n                assertEquals(new IntValue(0), invokeInterface.arguments().get(0));\n        }\n\n        @Test\n        public void testIndexGetDynamic() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    i:Object\\n\" +\n                        \"    i[0]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeStatic);\n                Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) ins;\n                assertEquals(\"get\", ((StringConstantValue) invokeStatic.arguments().get(5)).getStr());\n                assertTrue(invokeStatic.arguments().get(1) instanceof Ins.GetField); // i\n                // Integer.valueOf(0)\n                Ins.ANewArray arr = ((Ins.ANewArray) invokeStatic.arguments().get(7));\n                assertEquals(new IntValue(0), ((Ins.InvokeStatic) arr.initValues().get(0)).arguments().get(0)); // [0]\n        }\n\n        @Test\n        public void testIndexAllPrimitiveTest() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    intArr:[]int\\n\" +\n                        \"    boolArr:[]bool\\n\" +\n                        \"    byteArr:[]byte\\n\" +\n                        \"    shortArr:[]short\\n\" +\n                        \"    longArr:[]long\\n\" +\n                        \"    floatArr:[]float\\n\" +\n                        \"    doubleArr:[]double\\n\" +\n                        \"    objArr:[]Object\\n\" +\n                        \"    arrArr:[][]int\\n\" +\n\n                        \"    intArr[0]\\n\" +\n                        \"    boolArr[0]\\n\" +\n                        \"    byteArr[0]\\n\" +\n                        \"    shortArr[0]\\n\" +\n                        \"    longArr[0]\\n\" +\n                        \"    floatArr[0]\\n\" +\n                        \"    doubleArr[0]\\n\" +\n                        \"    objArr[0]\\n\" +\n                        \"    arrArr[0]\\n\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                List<Instruction> instructions = classDef.constructors().get(0).statements();\n                Ins.TALoad intArr = (Ins.TALoad) instructions.get(1);\n                Ins.TALoad boolArr = (Ins.TALoad) instructions.get(2);\n                Ins.TALoad byteArr = (Ins.TALoad) instructions.get(3);\n                Ins.TALoad shortArr = (Ins.TALoad) instructions.get(4);\n                Ins.TALoad longArr = (Ins.TALoad) instructions.get(5);\n                Ins.TALoad floatArr = (Ins.TALoad) instructions.get(6);\n                Ins.TALoad doubleArr = (Ins.TALoad) instructions.get(7);\n                Ins.TALoad objArr = (Ins.TALoad) instructions.get(8);\n                Ins.TALoad arrArr = (Ins.TALoad) instructions.get(9);\n\n                assertEquals(Ins.TALoad.Iaload, intArr.mode());\n                assertEquals(Ins.TALoad.Baload, boolArr.mode());\n                assertEquals(Ins.TALoad.Baload, byteArr.mode());\n                assertEquals(Ins.TALoad.Saload, shortArr.mode());\n                assertEquals(Ins.TALoad.Laload, longArr.mode());\n                assertEquals(Ins.TALoad.Faload, floatArr.mode());\n                assertEquals(Ins.TALoad.Daload, doubleArr.mode());\n                assertEquals(Ins.TALoad.Aaload, objArr.mode());\n                assertEquals(Ins.TALoad.Aaload, arrArr.mode());\n        }\n\n        @Test\n        public void testMethod() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method(i):Unit\\n\" +\n                        \"        i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(1, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                assertEquals(2, method.statements().size());\n                Instruction ins = method.statements().get(1);\n                assertTrue(ins instanceof Ins.CheckCast);\n                Ins.CheckCast checkCast = (Ins.CheckCast) ins;\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) checkCast.theValueToCheck();\n                SMethodDef pointer_get = (SMethodDef) invokeVirtual.invokable();\n                assertEquals(\"get\", pointer_get.name());\n                assertEquals(\"lt.lang.Pointer\", pointer_get.declaringType().fullName());\n        }\n\n        @Test\n        public void testStaticMethod() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        method(i):Unit\\n\" +\n                        \"            i\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(1, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                assertEquals(2, method.statements().size());\n                Instruction ins = method.statements().get(1);\n                assertTrue(ins instanceof Ins.CheckCast);\n                Ins.CheckCast checkCast = (Ins.CheckCast) ins;\n                Ins.InvokeVirtual invokeVirtual = (Ins.InvokeVirtual) checkCast.theValueToCheck();\n                SMethodDef pointer_get = (SMethodDef) invokeVirtual.invokable();\n                assertEquals(\"get\", pointer_get.name());\n                assertEquals(\"lt.lang.Pointer\", pointer_get.declaringType().fullName());\n        }\n\n        @Test\n        public void testStatic() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        a:Object\\n\" +\n                        \"        a\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.staticStatements().get(0);\n                assertTrue(ins instanceof Ins.GetStatic);\n                Ins.GetStatic getStatic = (Ins.GetStatic) ins;\n                assertEquals(\"a\", getStatic.field().name());\n        }\n\n        @Test\n        public void testVariableDef() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    def method()\\n\" +\n                        \"        a=1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(1, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                assertEquals(1, method.statements().size());\n\n                Instruction ins = ((ValuePack) ((Ins.TReturn) method.statements().get(0)).value()).instructions().get(0); // ValuePack(TStore,TLoad)\n                assertTrue(ins instanceof Ins.TStore);\n                Ins.TStore TStore = (Ins.TStore) ins;\n\n                int index = LocalVariables.calculateIndexForLocalVariable(TStore.leftValue(), TStore.getScope(), false);\n                assertEquals(1, index);\n                assertTrue(TStore.newValue() instanceof Ins.New);\n                Ins.New pointer_new = (Ins.New) TStore.newValue();\n                assertEquals(\"lt.lang.Pointer\", pointer_new.constructor().declaringType().fullName());\n        }\n\n        @Test\n        public void testVariableDefPutField() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a=1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(1, classDef.constructors().size());\n                SConstructorDef constructor = classDef.constructors().get(0);\n                assertEquals(2, constructor.statements().size());\n\n                Instruction ins = ((ValuePack) constructor.statements().get(1)).instructions().get(0);\n                assertTrue(ins instanceof Ins.PutField);\n                Ins.PutField putField = (Ins.PutField) ins;\n\n                assertTrue(putField.obj() instanceof Ins.This);\n\n                assertTrue(putField.value() instanceof Ins.InvokeStatic);\n                Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) putField.value();\n                assertEquals(new IntValue(1), invokeStatic.arguments().get(0));\n        }\n\n        @Test\n        public void testVariableDefPutStatic() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        a=1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(1, classDef.staticStatements().size());\n\n                Instruction ins = ((ValuePack) classDef.staticStatements().get(0)).instructions().get(0);\n                assertTrue(ins instanceof Ins.PutStatic);\n                Ins.PutStatic putStatic = (Ins.PutStatic) ins;\n\n                assertTrue(putStatic.value() instanceof Ins.InvokeStatic);\n                Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) putStatic.value();\n                assertEquals(new IntValue(1), invokeStatic.arguments().get(0));\n        }\n\n        private void testTwoVarOp(String code, Value a, int op, Value b) throws IOException, SyntaxException {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    \" + code);\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n\n                Instruction instruction = classDef.constructors().get(0).statements().get(1);\n                assertTrue(instruction instanceof Ins.TwoVarOp);\n                Ins.TwoVarOp tvo = (Ins.TwoVarOp) instruction;\n                assertEquals(op, tvo.op());\n                assertEquals(a, tvo.a());\n                assertEquals(b, tvo.b());\n        }\n\n        @Test\n        public void testTwoVarOpInt() throws Exception {\n                testTwoVarOp(\"1+2\", new IntValue(1), Ins.TwoVarOp.Iadd, new IntValue(2));\n                testTwoVarOp(\"1-2\", new IntValue(1), Ins.TwoVarOp.Isub, new IntValue(2));\n                testTwoVarOp(\"1*2\", new IntValue(1), Ins.TwoVarOp.Imul, new IntValue(2));\n                testTwoVarOp(\"1/2\", new IntValue(1), Ins.TwoVarOp.Idiv, new IntValue(2));\n                testTwoVarOp(\"1%2\", new IntValue(1), Ins.TwoVarOp.Irem, new IntValue(2));\n                testTwoVarOp(\"1<<2\", new IntValue(1), Ins.TwoVarOp.Ishl, new IntValue(2));\n                testTwoVarOp(\"1>>2\", new IntValue(1), Ins.TwoVarOp.Ishr, new IntValue(2));\n                testTwoVarOp(\"1>>>2\", new IntValue(1), Ins.TwoVarOp.Iushr, new IntValue(2));\n                testTwoVarOp(\"1|2\", new IntValue(1), Ins.TwoVarOp.Ior, new IntValue(2));\n                testTwoVarOp(\"1&2\", new IntValue(1), Ins.TwoVarOp.Iand, new IntValue(2));\n                testTwoVarOp(\"1^2\", new IntValue(1), Ins.TwoVarOp.Ixor, new IntValue(2));\n        }\n\n        @Test\n        public void testTwoVarOpLong() throws Exception {\n                testTwoVarOp(\"1 as long + 2 as long\", new LongValue(1), Ins.TwoVarOp.Ladd, new LongValue(2));\n                testTwoVarOp(\"1 as long - 2 as long\", new LongValue(1), Ins.TwoVarOp.Lsub, new LongValue(2));\n                testTwoVarOp(\"1 as long * 2 as long\", new LongValue(1), Ins.TwoVarOp.Lmul, new LongValue(2));\n                testTwoVarOp(\"1 as long / 2 as long\", new LongValue(1), Ins.TwoVarOp.Ldiv, new LongValue(2));\n                testTwoVarOp(\"1 as long % 2 as long\", new LongValue(1), Ins.TwoVarOp.Lrem, new LongValue(2));\n                testTwoVarOp(\"1 as long << 2 as long\", new LongValue(1), Ins.TwoVarOp.Lshl, new LongValue(2));\n                testTwoVarOp(\"1 as long >> 2 as long\", new LongValue(1), Ins.TwoVarOp.Lshr, new LongValue(2));\n                testTwoVarOp(\"1 as long >>> 2 as long\", new LongValue(1), Ins.TwoVarOp.Lushr, new LongValue(2));\n                testTwoVarOp(\"1 as long | 2 as long\", new LongValue(1), Ins.TwoVarOp.Lor, new LongValue(2));\n                testTwoVarOp(\"1 as long & 2 as long\", new LongValue(1), Ins.TwoVarOp.Land, new LongValue(2));\n                testTwoVarOp(\"1 as long ^ 2 as long\", new LongValue(1), Ins.TwoVarOp.Lxor, new LongValue(2));\n        }\n\n        @Test\n        public void testTwoVarOpDouble() throws Exception {\n                testTwoVarOp(\"1.0+2.0\", new DoubleValue(1), Ins.TwoVarOp.Dadd, new DoubleValue(2));\n                testTwoVarOp(\"1.0-2.0\", new DoubleValue(1), Ins.TwoVarOp.Dsub, new DoubleValue(2));\n                testTwoVarOp(\"1.0*2.0\", new DoubleValue(1), Ins.TwoVarOp.Dmul, new DoubleValue(2));\n                testTwoVarOp(\"1.0/2.0\", new DoubleValue(1), Ins.TwoVarOp.Ddiv, new DoubleValue(2));\n                testTwoVarOp(\"1.0%2.0\", new DoubleValue(1), Ins.TwoVarOp.Drem, new DoubleValue(2));\n        }\n\n        @Test\n        public void testTwoVarOpFloat() throws Exception {\n                testTwoVarOp(\"1 as float + 2 as float\", new FloatValue(1), Ins.TwoVarOp.Fadd, new FloatValue(2));\n                testTwoVarOp(\"1 as float - 2 as float\", new FloatValue(1), Ins.TwoVarOp.Fsub, new FloatValue(2));\n                testTwoVarOp(\"1 as float * 2 as float\", new FloatValue(1), Ins.TwoVarOp.Fmul, new FloatValue(2));\n                testTwoVarOp(\"1 as float / 2 as float\", new FloatValue(1), Ins.TwoVarOp.Fdiv, new FloatValue(2));\n                testTwoVarOp(\"1 as float % 2 as float\", new FloatValue(1), Ins.TwoVarOp.Frem, new FloatValue(2));\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    def method()\\n\" +\n                        \"        if true\\n\" +\n                        \"            return 1\\n\" +\n                        \"        elseif false\\n\" +\n                        \"            return 2\\n\" +\n                        \"        elseif true\\n\" +\n                        \"            return 3\\n\" +\n                        \"        else\\n\" +\n                        \"            return 4\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SMethodDef method = classDef.methods().get(0);\n\n                Instruction i1 = method.statements().get(0); // true ifNe goto nop1\n                Instruction i2 = method.statements().get(1); // return 1\n                Instruction i3 = method.statements().get(2); // goto nop\n                Instruction i4 = method.statements().get(3); // nop1\n\n                Instruction i5 = method.statements().get(4); // false ifNe goto nop2\n                Instruction i6 = method.statements().get(5); // return 2\n                Instruction i7 = method.statements().get(6); // goto nop\n                Instruction i8 = method.statements().get(7); // nop2\n\n                Instruction i9 = method.statements().get(8); // true ifNe goto nop3\n                Instruction i10 = method.statements().get(9); // return 3\n                Instruction i11 = method.statements().get(10); // goto nop\n                Instruction i12 = method.statements().get(11); // nop3\n\n                Instruction i13 = method.statements().get(12); // return 4\n\n                Instruction i14 = method.statements().get(13); // nop\n\n                assertEquals(14, method.statements().size());\n\n                assertTrue(i1 instanceof Ins.IfEq);\n                assertEquals(i4, ((Ins.IfEq) i1).gotoIns());\n                assertTrue(i5 instanceof Ins.IfEq);\n                assertEquals(i8, ((Ins.IfEq) i5).gotoIns());\n                assertTrue(i9 instanceof Ins.IfEq);\n                assertEquals(i12, ((Ins.IfEq) i9).gotoIns());\n\n                assertTrue(i3 instanceof Ins.Goto);\n                assertEquals(i14, ((Ins.Goto) i3).gotoIns());\n                assertTrue(i7 instanceof Ins.Goto);\n                assertEquals(i14, ((Ins.Goto) i7).gotoIns());\n                assertTrue(i11 instanceof Ins.Goto);\n                assertEquals(i14, ((Ins.Goto) i11).gotoIns());\n\n                assertTrue(i2 instanceof Ins.TReturn);\n                assertTrue(i4 instanceof Ins.Nop);\n\n                assertTrue(i6 instanceof Ins.TReturn);\n                assertTrue(i8 instanceof Ins.Nop);\n\n                assertTrue(i10 instanceof Ins.TReturn);\n                assertTrue(i12 instanceof Ins.Nop);\n\n                assertTrue(i13 instanceof Ins.TReturn);\n\n                assertTrue(i14 instanceof Ins.Nop);\n        }\n\n        @Test\n        public void testWhile() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    while true\\n\" +\n                        \"        a=1\\n\" +\n                        \"    a=2\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1); // if eq true\n                Instruction i2 = ((ValuePack) con.statements().get(2)).instructions().get(0); // ValuePack(PutField,GetField)\n                Instruction i3 = con.statements().get(3); // nop ----- for continue\n                Instruction i4 = con.statements().get(4); // goto\n                Instruction i5 = con.statements().get(5); // Nop\n                Instruction i6 = ((ValuePack) con.statements().get(6)).instructions().get(0); // ValuePack(PutField,GetField)\n\n                assertTrue(i1 instanceof Ins.IfEq);\n                assertTrue(i2 instanceof Ins.PutField);\n                assertTrue(i3 instanceof Ins.Nop);\n                assertTrue(i4 instanceof Ins.Goto);\n                assertTrue(i5 instanceof Ins.Nop);\n                assertTrue(i6 instanceof Ins.PutField);\n\n                assertEquals(i5, ((Ins.IfEq) i1).gotoIns());\n                assertEquals(i1, ((Ins.Goto) i4).gotoIns());\n        }\n\n        @Test\n        public void testDoWhile() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    do\\n\" +\n                        \"        a=1\\n\" +\n                        \"    while true\\n\" +\n                        \"    a=2\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                ValuePack gotoHere = (ValuePack) con.statements().get(1);\n\n                Instruction i1 = ((ValuePack) con.statements().get(1)).instructions().get(0); // ValuePack(PutField,GetField)\n                Instruction i2 = con.statements().get(2); // nop ------ for continue\n                Instruction i3 = con.statements().get(3); // IfNe\n                Instruction i4 = con.statements().get(4); // nop ------ for break\n                Instruction i5 = ((ValuePack) con.statements().get(5)).instructions().get(0); // ValuePack(PutField,GetField)\n\n                assertTrue(i1 instanceof Ins.PutField);\n                assertTrue(i2 instanceof Ins.Nop);\n                assertTrue(i3 instanceof Ins.IfNe);\n                assertTrue(i4 instanceof Ins.Nop);\n                assertTrue(i5 instanceof Ins.PutField);\n\n                assertEquals(gotoHere, ((Ins.IfNe) i3).gotoIns());\n        }\n\n        @Test\n        public void testFor() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(ls)\\n\" +\n                        \"    for i in ls\\n\" +\n                        \"        a=1\\n\" +\n                        \"    a=2\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1 + 1); // TStore aload invokestatic tstore\n                Instruction i2 = con.statements().get(2 + 1); // IfEq aload invokevirtual(hasNext) ifeq\n                Instruction i3 = con.statements().get(3 + 1); // TStore aload invokevirtual(next) tstore\n                Instruction i4 = ((ValuePack) con.statements().get(4 + 1)).instructions().get(0); // ValuePack(PutField,GetField)\n                Instruction i5 = con.statements().get(5 + 1); // nop ----- for continue\n                Instruction i6 = con.statements().get(6 + 1); // Goto\n                Instruction i7 = con.statements().get(7 + 1); // Nop\n                Instruction i8 = ((ValuePack) con.statements().get(8 + 1)).instructions().get(0); // ValuePack(PutField,GetField)\n\n                assertTrue(i1 instanceof Ins.TStore);\n                assertTrue(i2 instanceof Ins.IfEq);\n                assertTrue(i3 instanceof Ins.TStore);\n                assertTrue(i4 instanceof Ins.PutField);\n                assertTrue(i5 instanceof Ins.Nop);\n                assertTrue(i6 instanceof Ins.Goto);\n                assertTrue(i7 instanceof Ins.Nop);\n                assertTrue(i8 instanceof Ins.PutField);\n\n                assertEquals(i7, ((Ins.IfEq) i2).gotoIns());\n                assertEquals(i2, ((Ins.Goto) i6).gotoIns());\n        }\n\n        @Test\n        public void testThrow() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    throw RuntimeException()\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1);\n                assertTrue(i1 instanceof Ins.AThrow);\n                assertTrue(((Ins.AThrow) i1).exception() instanceof Ins.New);\n        }\n\n        @Test\n        public void testTryCatch() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    try\\n\" +\n                        \"        throw RuntimeException()\\n\" +\n                        \"    catch e\\n\" +\n                        \"        if e is type RuntimeException or e is type Exception\\n\" +\n                        \"            e.printStackTrace()\\n\" +\n                        \"        elseif e is type Error\\n\" +\n                        \"            e.printStackTrace()\\n\" +\n                        \"        elseif e is type Throwable\\n\" +\n                        \"            e.printStackTrace()\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1); // throw\n                Instruction i2 = con.statements().get(2); // goto nopX\n                Instruction i3 = con.statements().get(3); // exStore\n                Instruction i4 = con.statements().get(4); // TStore\n                Instruction i5 = con.statements().get(5); // if eq to (nop1)7\n                Instruction i6 = con.statements().get(6); // InvokeDynamic\n                Instruction i7 = con.statements().get(7); // goto nop\n                Instruction i8 = con.statements().get(8); // nop1\n                Instruction i9 = con.statements().get(9); // if eq to (nop2)11\n                Instruction i10 = con.statements().get(10); // InvokeDynamic\n                Instruction i11 = con.statements().get(11); // goto nop\n                Instruction i12 = con.statements().get(12); // nop2\n                Instruction i13 = con.statements().get(13); // if eq to (nop3)15\n                Instruction i14 = con.statements().get(14); // InvokeDynamic\n                Instruction i15 = con.statements().get(15); // goto nop\n                Instruction i16 = con.statements().get(16); // nop3\n                Instruction i17 = con.statements().get(17); // nop\n                Instruction i18 = con.statements().get(18); // goto nopX\n                Instruction i19 = con.statements().get(19); // exStore\n                Instruction i20 = con.statements().get(20); // aThrow\n                Instruction i21 = con.statements().get(21); // nopX\n\n                assertEquals(22, con.statements().size());\n\n                assertTrue(i1 instanceof Ins.AThrow);\n                assertTrue(i2 instanceof Ins.Goto);\n                assertTrue(i3 instanceof Ins.ExStore);\n                assertTrue(i4 instanceof Ins.TStore);\n                assertTrue(i5 instanceof Ins.IfEq);\n                assertTrue(i6 instanceof Ins.InvokeStatic);\n                assertTrue(i7 instanceof Ins.Goto);\n                assertTrue(i8 instanceof Ins.Nop);\n                assertTrue(i9 instanceof Ins.IfEq);\n                assertTrue(i10 instanceof Ins.InvokeStatic);\n                assertTrue(i11 instanceof Ins.Goto);\n                assertTrue(i12 instanceof Ins.Nop);\n                assertTrue(i13 instanceof Ins.IfEq);\n                assertTrue(i14 instanceof Ins.InvokeStatic);\n                assertTrue(i15 instanceof Ins.Goto);\n                assertTrue(i16 instanceof Ins.Nop);\n                assertTrue(i17 instanceof Ins.Nop);\n                assertTrue(i18 instanceof Ins.Goto);\n                assertTrue(i19 instanceof Ins.ExStore);\n                assertTrue(i20 instanceof Ins.AThrow);\n                assertTrue(i21 instanceof Ins.Nop);\n\n                assertEquals(i8, ((Ins.IfEq) i5).gotoIns());\n                assertEquals(i12, ((Ins.IfEq) i9).gotoIns());\n                assertEquals(i16, ((Ins.IfEq) i13).gotoIns());\n\n                assertEquals(i21, ((Ins.Goto) i2).gotoIns());\n                assertEquals(i17, ((Ins.Goto) i7).gotoIns());\n                assertEquals(i17, ((Ins.Goto) i11).gotoIns());\n                assertEquals(i17, ((Ins.Goto) i15).gotoIns());\n                assertEquals(i21, ((Ins.Goto) i18).gotoIns());\n\n                ExceptionTable tbl0 = con.exceptionTables().get(0); // 1-2 to 3 Throwable\n                ExceptionTable tbl1 = con.exceptionTables().get(1); // 3-18 to 19 any\n\n                assertEquals(2, con.exceptionTables().size());\n\n                assertEquals(i1, tbl0.getFrom());\n                assertEquals(i2, tbl0.getTo());\n                assertEquals(i3, tbl0.getTarget());\n                assertEquals(\"java.lang.Throwable\", tbl0.getType().fullName());\n\n                assertEquals(i3, tbl1.getFrom());\n                assertEquals(i18, tbl1.getTo());\n                assertEquals(i19, tbl1.getTarget());\n                assertNull(tbl1.getType());\n        }\n\n        @Test\n        public void testUnaryInc() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a:int)\\n\" +\n                        \"    ++a\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1 + 1);\n                assertTrue(i1 instanceof ValuePack);\n                assertTrue(((ValuePack) i1).instructions().get(1) instanceof Ins.PutField);\n                assertTrue(((ValuePack) i1).instructions().get(2) instanceof Ins.TLoad);\n                assertTrue(((Ins.PutField) ((ValuePack) i1).instructions().get(1)).value() instanceof Ins.TLoad);\n        }\n\n        @Test\n        public void testSelfInc() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a:int)\\n\" +\n                        \"    a++\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i = con.statements().get(1 + 1);\n                assertTrue(i instanceof ValuePack);\n                ValuePack valuePack = (ValuePack) i;\n\n                Instruction i0 = valuePack.instructions().get(0); // GetField\n                Instruction i1 = valuePack.instructions().get(1); // ValuePack\n                Instruction i2 = valuePack.instructions().get(2); // pop\n\n                assertTrue(i0 instanceof Ins.GetField);\n                assertTrue(i1 instanceof ValuePack);\n                assertTrue(i2 instanceof Ins.Pop);\n        }\n\n        @Test\n        public void testArrayAssign() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a:[]int)\\n\" +\n                        \"    a[1]=10\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i = con.statements().get(1 + 1);\n                assertTrue(i instanceof ValuePack);\n                ValuePack valuePack = (ValuePack) i;\n\n                Instruction i0 = valuePack.instructions().get(1); // IAStore\n                Instruction i1 = valuePack.instructions().get(2); // IALoad\n\n                assertTrue(i0 instanceof Ins.TAStore);\n                assertTrue(i1 instanceof Ins.TLoad);\n\n                Ins.TAStore TAStore = (Ins.TAStore) i0;\n                assertEquals(Ins.TAStore.IASTORE, TAStore.mode());\n        }\n\n        @Test\n        public void testIndexAccessAssignInvoke() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import java::util::_\\n\" +\n                        \"class A(a:List)\\n\" +\n                        \"    a[1]=10\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i = con.statements().get(1 + 1);\n                assertTrue(i instanceof ValuePack);\n                ValuePack valuePack = (ValuePack) i;\n\n                Instruction i0 = valuePack.instructions().get(1); // InvokeDynamic\n                Instruction i1 = valuePack.instructions().get(2); // InvokeInterface\n\n                assertTrue(i0 instanceof Ins.InvokeInterface);\n                assertTrue(i1 instanceof Ins.TLoad);\n\n                Ins.InvokeInterface in0 = (Ins.InvokeInterface) i0;\n                assertEquals(\"set\", ((SMethodDef) in0.invokable()).name());\n                assertEquals(2, in0.arguments().size());\n                assertTrue(in0.arguments().get(0) instanceof IntValue);\n                assertTrue(in0.arguments().get(1) instanceof Ins.InvokeStatic);\n        }\n\n        @Test\n        public void testIndexAccessAssignInvoke2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a)\\n\" +\n                        \"    a[1]=10\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i = con.statements().get(1 + 1);\n                assertTrue(i instanceof ValuePack);\n                ValuePack valuePack = (ValuePack) i;\n\n                Instruction i0 = valuePack.instructions().get(1); // InvokeDynamic\n                Instruction i1 = valuePack.instructions().get(2); // InvokeDynamic\n\n                assertTrue(i0 instanceof Ins.InvokeStatic);\n                assertTrue(i1 instanceof Ins.TLoad);\n\n                Ins.InvokeStatic in0 = (Ins.InvokeStatic) i0;\n                assertEquals(\"set\", ((StringConstantValue) in0.arguments().get(5)).getStr());\n                assertEquals(9, in0.arguments().size());\n                assertTrue(in0.arguments().get(0) instanceof Ins.GetClass);\n                assertTrue(in0.arguments().get(1) instanceof Ins.GetField);\n                assertEquals(NullValue.get(), in0.arguments().get(3));\n                // Integer.valueOf(1)\n                assertTrue(\n                        ((Ins.InvokeStatic)\n                                ((Ins.ANewArray)\n                                        in0.arguments().get(7)).initValues().get(0)).arguments().get(0)\n                                instanceof IntValue);\n                // Integer.valueOf(?)\n                assertTrue(((Ins.InvokeStatic)\n                        ((Ins.ANewArray)\n                                in0.arguments().get(7)).initValues().get(1)).arguments().get(0)\n                        instanceof Ins.TLoad);\n        }\n\n        @Test\n        public void testNewArray() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a:[]int=[10,20]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Ins.PutField putField = (Ins.PutField) ((ValuePack) con.statements().get(1)).instructions().get(0);\n                Ins.NewArray newArray = (Ins.NewArray) putField.value();\n                assertEquals(2, newArray.count().getValue());\n                assertEquals(Ins.NewArray.NewIntArray, newArray.mode());\n\n                assertEquals(10, ((IntValue) newArray.initValues().get(0)).getValue());\n                assertEquals(20, ((IntValue) newArray.initValues().get(1)).getValue());\n        }\n\n        @Test\n        public void testANewArray() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a:[]Object=[10,20]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Ins.PutField putField = (Ins.PutField) ((ValuePack) con.statements().get(1)).instructions().get(0);\n                Ins.ANewArray newArray = (Ins.ANewArray) putField.value();\n                assertEquals(2, newArray.count().getValue());\n                assertEquals(\"java.lang.Object\", newArray.componentType().fullName());\n\n                assertTrue(newArray.initValues().get(0) instanceof Ins.InvokeStatic);\n                assertTrue(newArray.initValues().get(1) instanceof Ins.InvokeStatic);\n        }\n\n        @Test\n        public void testNewList() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a=[10,20]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Ins.PutField putField = (Ins.PutField) ((ValuePack) con.statements().get(1)).instructions().get(0);\n                Ins.NewList newList = (Ins.NewList) putField.value();\n                assertEquals(\"java.util.LinkedList\", newList.type().fullName());\n\n                assertTrue(newList.initValues().get(0) instanceof Ins.InvokeStatic);\n                assertTrue(newList.initValues().get(1) instanceof Ins.InvokeStatic);\n        }\n\n        @Test\n        public void testNewMap() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a=[\\n\" +\n                        \"        \\\"a\\\":1\\n\" +\n                        \"        \\\"b\\\":2\\n\" +\n                        \"        \\\"c\\\":3\\n\" +\n                        \"        \\\"d\\\":4\\n\" +\n                        \"    ]\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Ins.PutField putField = (Ins.PutField) ((ValuePack) con.statements().get(1)).instructions().get(0);\n                Ins.NewMap newMap = (Ins.NewMap) putField.value();\n\n                Iterator<Map.Entry<Value, Value>> entries = newMap.initValues().entrySet().iterator();\n                Map.Entry<Value, Value> entry = entries.next();\n                assertEquals(\"a\", ((StringConstantValue) entry.getKey()).getStr());\n                assertTrue(entry.getValue() instanceof Ins.InvokeStatic);\n\n                entry = entries.next();\n                assertEquals(\"b\", ((StringConstantValue) entry.getKey()).getStr());\n                assertTrue(entry.getValue() instanceof Ins.InvokeStatic);\n\n                entry = entries.next();\n                assertEquals(\"c\", ((StringConstantValue) entry.getKey()).getStr());\n                assertTrue(entry.getValue() instanceof Ins.InvokeStatic);\n\n                entry = entries.next();\n                assertEquals(\"d\", ((StringConstantValue) entry.getKey()).getStr());\n                assertTrue(entry.getValue() instanceof Ins.InvokeStatic);\n        }\n\n        @Test\n        public void testSync() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a,b)\\n\" +\n                        \"    synchronized(a,b)\\n\" +\n                        \"        a=2\\n\" +\n                        \"        b=3\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1 + 2); // monitor enter\n                Instruction i2 = con.statements().get(2 + 2); // monitor enter\n                Instruction i3 = con.statements().get(3 + 2); // ValuePack(PutField,GetField)\n                Instruction i4 = con.statements().get(4 + 2); // ValuePack(PutField,GetField)\n                Instruction i5 = con.statements().get(5 + 2); // monitor exit\n                Instruction i6 = con.statements().get(6 + 2); // monitor exit\n                Instruction i7 = con.statements().get(7 + 2); // goto\n                Instruction i8 = con.statements().get(8 + 2); // astore\n                Instruction i9 = con.statements().get(9 + 2); // monitor exit\n                Instruction i10 = con.statements().get(10 + 2); // monitor exit\n                Instruction i11 = con.statements().get(11 + 2); // athrow\n\n                assertTrue(i1 instanceof Ins.MonitorEnter);\n                assertTrue(i2 instanceof Ins.MonitorEnter);\n                assertTrue(i3 instanceof ValuePack);\n                assertTrue(i4 instanceof ValuePack);\n                assertTrue(i5 instanceof Ins.MonitorExit);\n                assertTrue(i6 instanceof Ins.MonitorExit);\n                assertTrue(i7 instanceof Ins.Goto);\n                assertTrue(i8 instanceof Ins.ExStore);\n                assertTrue(i9 instanceof Ins.MonitorExit);\n                assertTrue(i10 instanceof Ins.MonitorExit);\n                assertTrue(i11 instanceof Ins.AThrow);\n\n                ValuePack p3 = (ValuePack) i3;\n                ValuePack p4 = (ValuePack) i4;\n\n                Instruction i30 = p3.instructions().get(1); // 0 is TStore and 1 is PutField and 2 is TLoad\n                assertTrue(i30 instanceof Ins.PutField);\n                Instruction i40 = p4.instructions().get(1);\n                assertTrue(i40 instanceof Ins.PutField);\n        }\n\n        @Test\n        public void testSyncReturn() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a,b)\\n\" +\n                        \"    synchronized(a,b)\\n\" +\n                        \"        a=2\\n\" +\n                        \"        b=3\\n\" +\n                        \"        return \");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1 + 2); // monitor enter\n                Instruction i2 = con.statements().get(2 + 2); // monitor enter\n                Instruction i3 = con.statements().get(3 + 2); // ValuePack(PutField,GetField)\n                Instruction i4 = con.statements().get(4 + 2); // ValuePack(PutField,GetField)\n                Instruction i5 = con.statements().get(5 + 2); // monitor exit\n                Instruction i6 = con.statements().get(6 + 2); // monitor exit\n                Instruction i7 = con.statements().get(7 + 2); // TReturn\n                Instruction i8 = con.statements().get(8 + 2); // monitor exit\n                Instruction i9 = con.statements().get(9 + 2); // monitor exit\n                Instruction i10 = con.statements().get(10 + 2); // goto\n                Instruction i11 = con.statements().get(11 + 2); // astore\n                Instruction i12 = con.statements().get(12 + 2); // monitor exit\n                Instruction i13 = con.statements().get(13 + 2); // monitor exit\n                Instruction i14 = con.statements().get(14 + 2); // athrow\n\n                assertTrue(i1 instanceof Ins.MonitorEnter);\n                assertTrue(i2 instanceof Ins.MonitorEnter);\n                assertTrue(i3 instanceof ValuePack);\n                assertTrue(i4 instanceof ValuePack);\n                assertTrue(i5 instanceof Ins.MonitorExit);\n                assertTrue(i6 instanceof Ins.MonitorExit);\n                assertTrue(i7 instanceof Ins.TReturn);\n                assertTrue(i8 instanceof Ins.MonitorExit);\n                assertTrue(i9 instanceof Ins.MonitorExit);\n                assertTrue(i10 instanceof Ins.Goto);\n                assertTrue(i11 instanceof Ins.ExStore);\n                assertTrue(i12 instanceof Ins.MonitorExit);\n                assertTrue(i13 instanceof Ins.MonitorExit);\n                assertTrue(i14 instanceof Ins.AThrow);\n\n                ValuePack p3 = (ValuePack) i3;\n                ValuePack p4 = (ValuePack) i4;\n\n                Instruction i30 = p3.instructions().get(1);\n                assertTrue(i30 instanceof Ins.PutField);\n                Instruction i40 = p4.instructions().get(1);\n                assertTrue(i40 instanceof Ins.PutField);\n        }\n\n        @Test\n        public void testTryCatchFinally() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    try\\n\" +\n                        \"        System.out.println('hello')\\n\" +\n                        \"    catch e\\n\" +\n                        \"        if e is type RuntimeException\\n\" +\n                        \"            e.printStackTrace()\\n\" +\n                        \"    finally\\n\" +\n                        \"        System.out.println(' world')\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1); // InvokeVirtual\n                Instruction i2 = con.statements().get(2); // goto (normal finally)\n                Instruction i3 = con.statements().get(3); // exStore\n                Instruction i4 = con.statements().get(4); // Tstore\n                Instruction i5 = con.statements().get(5); // ifEq nop\n                Instruction i6 = con.statements().get(6); // InvokeDynamic\n                Instruction i7 = con.statements().get(7); // goto nop1\n                Instruction i8 = con.statements().get(8); // nop\n                Instruction i9 = con.statements().get(9); // nop1\n                Instruction i10 = con.statements().get(10); // goto (normal finally)\n                Instruction i11 = con.statements().get(11); // exStore\n                Instruction i12 = con.statements().get(12); // invokeVirtual\n                Instruction i13 = con.statements().get(13); // aThrow\n                Instruction i14 = con.statements().get(14); // invokeVirtual (normal finally)\n                assertEquals(15, con.statements().size());\n\n                assertTrue(((ValueAnotherType) i1).value() instanceof Ins.InvokeVirtual);\n                assertTrue(i2 instanceof Ins.Goto);\n                assertTrue(i3 instanceof Ins.ExStore);\n                assertTrue(i4 instanceof Ins.TStore);\n                assertTrue(i5 instanceof Ins.IfEq);\n                assertTrue(i6 instanceof Ins.InvokeStatic);\n                assertTrue(i7 instanceof Ins.Goto);\n                assertTrue(i8 instanceof Ins.Nop);\n                assertTrue(i9 instanceof Ins.Nop);\n                assertTrue(i10 instanceof Ins.Goto);\n                assertTrue(i11 instanceof Ins.ExStore);\n                assertTrue(((ValueAnotherType) i12).value() instanceof Ins.InvokeVirtual);\n                assertTrue(i13 instanceof Ins.AThrow);\n                assertTrue(((ValueAnotherType) i14).value() instanceof Ins.InvokeVirtual);\n\n                assertEquals(i14, ((Ins.Goto) i2).gotoIns());\n                assertEquals(i8, ((Ins.IfEq) i5).gotoIns());\n                assertEquals(i9, ((Ins.Goto) i7).gotoIns());\n                assertEquals(i14, ((Ins.Goto) i10).gotoIns());\n\n                ExceptionTable tbl0 = con.exceptionTables().get(0); // 1-2 goto 3  Throwable\n                ExceptionTable tbl1 = con.exceptionTables().get(1); // 3-10 goto 11  any\n                assertEquals(2, con.exceptionTables().size());\n\n                assertEquals(i1, tbl0.getFrom());\n                assertEquals(i2, tbl0.getTo());\n                assertEquals(i3, tbl0.getTarget());\n                assertEquals(\"java.lang.Throwable\", tbl0.getType().fullName());\n\n                assertEquals(i3, tbl1.getFrom());\n                assertEquals(i10, tbl1.getTo());\n                assertEquals(i11, tbl1.getTarget());\n                assertNull(tbl1.getType());\n        }\n\n        @Test\n        public void testReturnFinally() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    def method()\\n\" +\n                        \"        try\\n\" +\n                        \"            return 1\\n\" +\n                        \"        catch e\\n\" +\n                        \"            return 2\\n\" +\n                        \"        finally\\n\" +\n                        \"            1+1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SMethodDef met = classDef.methods().get(0);\n\n                Instruction i0 = met.statements().get(0); // Nop\n                Instruction i1 = met.statements().get(1); // AStore (store 1)\n                Instruction i2 = met.statements().get(2); // IAdd (finally)\n                Instruction i3 = met.statements().get(3); // AReturn (load 1)\n                Instruction i4 = met.statements().get(4); // goto (normal finally)\n                Instruction i5 = met.statements().get(5); // exStore\n                Instruction i6 = met.statements().get(6); // TStore\n                Instruction i7 = met.statements().get(7); // AStore (store 2)\n                Instruction i8 = met.statements().get(8); // IAdd (finally)\n                Instruction i9 = met.statements().get(9); // AReturn (load 2)\n                Instruction i10 = met.statements().get(10); // goto (normal finally)\n                Instruction i11 = met.statements().get(11); // exStore\n                Instruction i12 = met.statements().get(12); // IAdd\n                Instruction i13 = met.statements().get(13); // AThrow\n                Instruction i14 = met.statements().get(14); // IAdd (normal finally)\n\n                assertEquals(15, met.statements().size());\n\n                assertTrue(i0 instanceof Ins.Nop);\n                assertTrue(i1 instanceof Ins.TStore);\n                assertTrue(i2 instanceof Ins.TwoVarOp);\n                assertTrue(i3 instanceof Ins.TReturn);\n                assertTrue(i4 instanceof Ins.Goto);\n                assertTrue(i5 instanceof Ins.ExStore);\n                assertTrue(i6 instanceof Ins.TStore);\n                assertTrue(i7 instanceof Ins.TStore);\n                assertTrue(i8 instanceof Ins.TwoVarOp);\n                assertTrue(i9 instanceof Ins.TReturn);\n                assertTrue(i10 instanceof Ins.Goto);\n                assertTrue(i11 instanceof Ins.ExStore);\n                assertTrue(i12 instanceof Ins.TwoVarOp);\n                assertTrue(i13 instanceof Ins.AThrow);\n                assertTrue(i14 instanceof Ins.TwoVarOp);\n\n                assertEquals(i14, ((Ins.Goto) i4).gotoIns());\n                assertEquals(i14, ((Ins.Goto) i10).gotoIns());\n\n                ExceptionTable tbl0 = met.exceptionTables().get(0); // 0-2 to 5 Throwable\n                ExceptionTable tbl1 = met.exceptionTables().get(1); // 5-8 to 11 any\n\n                assertEquals(2, met.exceptionTables().size());\n\n                assertEquals(i0, tbl0.getFrom());\n                assertEquals(i2, tbl0.getTo());\n                assertEquals(i5, tbl0.getTarget());\n                assertEquals(\"java.lang.Throwable\", tbl0.getType().fullName());\n\n                assertEquals(i5, tbl1.getFrom());\n                assertEquals(i8, tbl1.getTo());\n                assertEquals(i11, tbl1.getTarget());\n                assertNull(tbl1.getType());\n        }\n\n        @Test\n        public void testConstructorField() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(a,b)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SConstructorDef con = classDef.constructors().get(0);\n\n                Instruction i1 = con.statements().get(1);\n                Instruction i2 = con.statements().get(2);\n\n                assertTrue(i1 instanceof Ins.PutField);\n                assertTrue(i2 instanceof Ins.PutField);\n\n                assertEquals(2, classDef.fields().size());\n                assertEquals(\"a\", classDef.fields().get(0).name());\n                assertEquals(\"b\", classDef.fields().get(1).name());\n        }\n\n        @Test\n        public void testInnerMethod1() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    def method()\\n\" +\n                        \"        inner():Unit\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(2, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                SMethodDef innerMethod = classDef.methods().get(1);\n\n                assertEquals(\"method\", method.name());\n                assertEquals(\"inner$Latte$InnerMethod$0\", innerMethod.name());\n                assertEquals(0, innerMethod.getParameters().size());\n        }\n\n        @Test\n        public void testInnerMethod2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    def method()\\n\" +\n                        \"        i:int=1\\n\" +\n                        \"        inner():Unit\\n\" +\n                        \"        j=2\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                assertEquals(2, classDef.methods().size());\n                SMethodDef method = classDef.methods().get(0);\n                SMethodDef innerMethod = classDef.methods().get(1);\n\n                assertEquals(\"method\", method.name());\n                assertEquals(\"inner$Latte$InnerMethod$0\", innerMethod.name());\n\n                assertEquals(1, innerMethod.getParameters().size());\n                assertTrue(innerMethod.getParameters().get(0).type().fullName().equals(\"lt.lang.Pointer\"));\n                assertEquals(\"i\", innerMethod.getParameters().get(0).name());\n        }\n\n        @Test\n        public void testProcedure1() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method():int\\n\" +\n                        \"        return (return 1)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SMethodDef method = classDef.methods().get(0);\n                Instruction i0 = method.statements().get(0);\n\n                assertTrue(i0 instanceof Ins.TReturn);\n                assertTrue(((Ins.TReturn) i0).value() instanceof Ins.InvokeWithCapture);\n                Ins.InvokeWithCapture invokeWithCapture = (Ins.InvokeWithCapture) ((Ins.TReturn) i0).value();\n\n                assertFalse(invokeWithCapture.isStatic());\n                assertTrue(invokeWithCapture.invokable() instanceof SMethodDef);\n                assertEquals(\"procedure$0$Latte$InnerMethod$0\", ((SMethodDef) invokeWithCapture.invokable()).name());\n\n                assertEquals(new IntValue(1), ((Ins.TReturn) invokeWithCapture.invokable().statements().get(0)).value());\n        }\n\n        @Test\n        public void testProcedure2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    i:int=(return 1)\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction i1 = ((ValuePack) classDef.constructors().get(0).statements().get(1)).instructions().get(0);\n\n                assertTrue(i1 instanceof Ins.PutField);\n                assertTrue(((Ins.PutField) i1).value() instanceof Ins.InvokeWithCapture);\n                Ins.InvokeWithCapture invokeWithCapture = (Ins.InvokeWithCapture) ((Ins.PutField) i1).value();\n                assertFalse(invokeWithCapture.isStatic());\n\n                assertTrue(invokeWithCapture.invokable() instanceof SMethodDef);\n                assertEquals(\"procedure$0$Latte$InnerMethod$0\", ((SMethodDef) invokeWithCapture.invokable()).name());\n\n                assertEquals(new IntValue(1), ((Ins.TReturn) invokeWithCapture.invokable().statements().get(0)).value());\n        }\n\n        @Test\n        public void testLambda1() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::lang::function::_\\n\" +\n                        \"class A\\n\" +\n                        \"    func:Function1=(o)->\\n\" +\n                        \"        return 1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(2, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                if (!classDef.fullName().equals(\"test.A\")) classDef = (SClassDef) it.next();\n                Instruction i1 = ((ValuePack) classDef.constructors().get(0).statements().get(1)).instructions().get(0);\n\n                assertTrue(i1 instanceof Ins.PutField);\n                Value v = ((Ins.PutField) i1).value();\n                assertTrue(v instanceof Ins.New);\n                Ins.New aNew = (Ins.New) v;\n                assertEquals(\"test.A$Latte$Lambda$0\", aNew.constructor().declaringType().fullName());\n                assertEquals(2, aNew.args().size());\n        }\n\n        @Test\n        public void testLambda2() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::lang::function::_\\n\" +\n                        \"class A(a)\\n\" +\n                        \"    func:Function1=(o)->\\n\" +\n                        \"        return 1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(2, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                if (!classDef.fullName().equals(\"test.A\")) classDef = (SClassDef) it.next();\n                Instruction i1 = ((ValuePack) classDef.constructors().get(0).statements().get(1 + 1)).instructions().get(0);\n\n                assertTrue(i1 instanceof Ins.PutField);\n                Value v = ((Ins.PutField) i1).value();\n                assertTrue(v instanceof Ins.New);\n                Ins.New aNew = (Ins.New) v;\n                assertEquals(\"test.A$Latte$Lambda$0\", aNew.constructor().declaringType().fullName());\n                assertEquals(2, aNew.args().size());\n        }\n\n        @Test\n        public void testLambda3() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"class A(a)\\n\" +\n                        \"    func:TestLambdaFunc=(o)->\\n\" +\n                        \"        return 1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(2, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SClassDef testA = null;\n                SClassDef lambda = null;\n                if (classDef.fullName().equals(\"test.A\")) {\n                        testA = classDef;\n                } else {\n                        lambda = classDef;\n                }\n                classDef = (SClassDef) it.next();\n                if (classDef.fullName().equals(\"test.A\")) {\n                        testA = classDef;\n                } else {\n                        lambda = classDef;\n                }\n\n                // test.A\n                assert testA != null;\n                Instruction i1 = ((ValuePack) testA.constructors().get(0).statements().get(1 + 1)).instructions().get(0);\n\n                assertTrue(i1 instanceof Ins.PutField);\n                Value v = ((Ins.PutField) i1).value();\n                assertTrue(v instanceof Ins.New);\n                Ins.New aNew = (Ins.New) v;\n                assertEquals(2, aNew.args().size());\n\n                // lambda\n                assert lambda != null;\n                assertEquals(\"o\", lambda.fields().get(0).name());\n                assertEquals(\"local\", lambda.fields().get(1).name());\n\n                i1 = lambda.constructors().get(0).statements().get(1); // put field\n                Instruction i2 = lambda.constructors().get(0).statements().get(2); // put field\n                Instruction i3 = lambda.constructors().get(0).statements().get(3); // put field\n                assertTrue(i1 instanceof Ins.PutField);\n                assertTrue(i2 instanceof Ins.PutField);\n                assertTrue(i3 instanceof Ins.PutField);\n\n                assertEquals(\"apply\", lambda.methods().get(0).name());\n                assertEquals(1, lambda.methods().get(0).getParameters().size());\n                Ins.TReturn i0 = (Ins.TReturn) lambda.methods().get(0).statements().get(0); // return\n\n                assertTrue(i0.value() instanceof Ins.InvokeWithCapture);\n\n        }\n\n        @Test\n        public void testType() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    o=type A\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n\n                Value v = ((Ins.PutField) ((ValuePack) classDef.constructors().get(0).statements().get(1)).instructions().get(0)).value();\n                assertTrue(v instanceof Ins.GetClass);\n                assertEquals(classDef, ((Ins.GetClass) v).targetType());\n        }\n\n        @Test\n        public void testAssignValFieldFail() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    val i=1\\n\" +\n                        \"    i=2\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(4, e.lineCol.line);\n                        assertEquals(6, e.lineCol.column);\n                }\n        }\n\n        @Test\n        public void testAssignValSParamFail() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(val i)\\n\" +\n                        \"    i=2\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(3, e.lineCol.line);\n                        assertEquals(6, e.lineCol.column);\n                }\n        }\n\n        @Test\n        public void testAssignValLocalFail() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    method()\\n\" +\n                        \"        val i=2\\n\" +\n                        \"        i=1\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(5, e.lineCol.line);\n                        assertEquals(9, e.lineCol.column);\n                }\n        }\n\n        @Test\n        public void testTestFunctionalCheck() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"@FunctionalAbstractClass\\n\" +\n                        \"abstract class A\\n\" +\n                        \"    abstract method()=...\");\n                parse(map);\n\n                map.clear();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"@FunctionalInterface\\n\" +\n                        \"interface A\\n\" +\n                        \"    method()=...\");\n                parse(map);\n\n                map.clear();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"@FunctionalAbstractClass\\n\" +\n                        \"abs class A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(3, e.lineCol.line);\n                        assertEquals(5, e.lineCol.column);\n                }\n\n                map.clear();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"@FunctionalInterface\\n\" +\n                        \"interface A\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(3, e.lineCol.line);\n                        assertEquals(1, e.lineCol.column);\n                }\n        }\n\n        @Test\n        public void testOverrideCheck() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    @Override\\n\" +\n                        \"    toString():String='abc'\");\n                parse(map);\n\n                map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    @Override\\n\" +\n                        \"    toStringX():String='abc'\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException e) {\n                        assertEquals(4, e.lineCol.line);\n                        assertEquals(5, e.lineCol.column);\n                }\n        }\n\n        @Test\n        public void testAssignOp() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a:=1\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                Instruction ins = classDef.constructors().get(0).statements().get(1);\n                assertTrue(ins instanceof Ins.InvokeStatic);\n                assertEquals(\"assign\", ((StringConstantValue) ((Ins.InvokeStatic) ins).arguments().get(5)).getStr());\n        }\n\n        @Test\n        public void testAnnotationAnnotation() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"import lt::compiler::_\\n\" +\n                        \"@AnnoAnno(myAnno=@MyAnno(str='a'))\\n\" +\n                        \"class A\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                Iterator<STypeDef> it = set.iterator();\n\n                SClassDef classDef = (SClassDef) it.next();\n                SAnno anno = classDef.annos().get(0);\n                Map.Entry<SAnnoField, Value> entry = anno.values().entrySet().iterator().next();\n                assertEquals(\"myAnno\", entry.getKey().name());\n                assertTrue(entry.getValue() instanceof SAnno);\n                SAnno value = (SAnno) entry.getValue();\n                Map.Entry<SAnnoField, Value> entry2 = value.values().entrySet().iterator().next();\n                assertEquals(\"str\", entry2.getKey().name());\n                assertEquals(\"a\", ((StringConstantValue) entry2.getValue()).getStr());\n        }\n\n        @Test\n        public void testAccessType() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    static\\n\" +\n                        \"        a=1\\n\" +\n                        \"    b = 2\\n\" +\n                        \"    A + 1\\n\" +\n                        \"    A() + 1\\n\" +\n                        \"    A.a + 1\\n\" +\n                        \"    A().b + 1\\n\" +\n                        \"    a + 1\\n\" +\n                        \"    A.toString\");\n                Set<STypeDef> set = parse(map);\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                SConstructorDef cons = classDef.constructors().get(0);\n\n                Ins.InvokeStatic i2 = (Ins.InvokeStatic) cons.statements().get(2);\n                Ins.InvokeStatic i3 = (Ins.InvokeStatic) cons.statements().get(3);\n                Ins.InvokeStatic i4 = (Ins.InvokeStatic) cons.statements().get(4);\n                Ins.InvokeStatic i5 = (Ins.InvokeStatic) cons.statements().get(5);\n                Ins.InvokeStatic i6 = (Ins.InvokeStatic) cons.statements().get(6);\n                Ins.InvokeStatic i7 = (Ins.InvokeStatic) cons.statements().get(7);\n\n                assertTrue(i2.arguments().get(1) instanceof Ins.New);\n                assertTrue(i3.arguments().get(1) instanceof Ins.New);\n                assertTrue(i4.arguments().get(1) instanceof Ins.GetStatic);\n                assertTrue(i5.arguments().get(1) instanceof Ins.GetField);\n                assertTrue(i6.arguments().get(1) instanceof Ins.GetStatic);\n                assertTrue(i7.arguments().get(0) instanceof Ins.New);\n        }\n\n        @Test\n        public void testNew() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A(x:int=1)\\n\" +\n                        \"    a = new A\\n\" +\n                        \"    b = new A(2)\\n\" +\n                        \"    something:Object = 1\\n\" +\n                        \"    c = new A(something)\");\n                Set<STypeDef> set = parse(map);\n\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                SConstructorDef cons = classDef.constructors().get(0);\n\n                ValuePack valuePack1 = (ValuePack) cons.statements().get(2);\n                ValuePack valuePack2 = (ValuePack) cons.statements().get(3);\n                ValuePack valuePack3 = (ValuePack) cons.statements().get(5);\n\n                Ins.PutField p1 = (Ins.PutField) valuePack1.instructions().get(0);\n                Ins.PutField p2 = (Ins.PutField) valuePack2.instructions().get(0);\n                Ins.PutField p3 = (Ins.PutField) valuePack3.instructions().get(0);\n\n                assertTrue(p1.value() instanceof Ins.New);\n                assertEquals(0, ((Ins.New) p1.value()).args().size());\n                assertTrue(p2.value() instanceof Ins.New);\n                assertEquals(1, ((Ins.New) p2.value()).args().size());\n                assertTrue(p3.value() instanceof Ins.InvokeStatic);\n                assertEquals(1, ((Ins.ANewArray) (((Ins.InvokeStatic) p3.value()).arguments().get(3))).initValues().size());\n        }\n\n        @Test\n        public void testGeneratorSpec() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a = #js\\n\" +\n                        \"        a=1\");\n                Set<STypeDef> set = parse(map);\n\n                assertEquals(1, set.size());\n\n                SClassDef classDef = (SClassDef) set.iterator().next();\n                SConstructorDef cons = classDef.constructors().get(0);\n\n                ValuePack valuePack1 = (ValuePack) cons.statements().get(1);\n                Ins.PutField p1 = (Ins.PutField) valuePack1.instructions().get(0);\n                assertTrue(p1.value() instanceof StringConstantValue);\n                String str = ((StringConstantValue) p1.value()).getStr();\n                assertEquals(\"var a = 1;\", str);\n        }\n\n        @Test\n        public void testFunctionalObject() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a = ()->1\\n\" +\n                        \"    a()\");\n                Set<STypeDef> set = parse(map);\n                Iterator<STypeDef> it = set.iterator();\n\n                assertEquals(2, set.size());\n\n                SClassDef classDef = (SClassDef) it.next();\n                if (!classDef.fullName().equals(\"test.A\")) classDef = (SClassDef) it.next();\n                SConstructorDef cons = classDef.constructors().get(0);\n\n                Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) cons.statements().get(2);\n                Ins.ANewArray arr = (Ins.ANewArray) invokeStatic.arguments().get(7);\n                assertEquals(0, arr.initValues().size());\n                Ins.GetField getField = (Ins.GetField) invokeStatic.arguments().get(3);\n                assertEquals(\"a\", getField.field().name());\n        }\n\n        @Test\n        public void testInvokingAnything() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    a = ()->()-> 1\\n\" +\n                        \"    a()()\");\n                Set<STypeDef> set = parse(map);\n                Iterator<STypeDef> it = set.iterator();\n\n                assertEquals(3, set.size());\n\n                SClassDef classDef = (SClassDef) it.next();\n                while (!classDef.fullName().equals(\"test.A\")) classDef = (SClassDef) it.next();\n                SConstructorDef cons = classDef.constructors().get(0);\n\n                Ins.InvokeStatic invokeStatic = (Ins.InvokeStatic) cons.statements().get(2);\n                Ins.ANewArray arr = (Ins.ANewArray) invokeStatic.arguments().get(2);\n                assertEquals(0, arr.initValues().size());\n                Ins.InvokeStatic invokeStatic2 = (Ins.InvokeStatic) invokeStatic.arguments().get(0);\n                Ins.GetField getField = (Ins.GetField) invokeStatic2.arguments().get(3);\n                assertEquals(\"a\", getField.field().name());\n        }\n\n        @Test\n        public void testOverrideMethods() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class A\\n\" +\n                        \"    protected abstract method(arg)\\n\" +\n                        \"class B:A\\n\" +\n                        \"    @Override\\n\" +\n                        \"    protected method(arg)=1\\n\" +\n                        \"class C:A\\n\" +\n                        \"    @Override\\n\" +\n                        \"    protected method(arg)=2\");\n                parse(map); // pass compilation\n        }\n\n        @Test\n        public void testImportStaticName() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"package test\\n\" +\n                        \"class Utils\");\n                map.put(\"test2\", \"\" +\n                        \"import test::Utils\\n\" +\n                        \"class X\\n\" +\n                        \"    Utils()\");\n                parse(map); // pass compilation\n        }\n\n        @Test\n        public void testAccessInnerClass() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"import java::util::Map\\n\" +\n                        \"class Test\\n\" +\n                        \"    x = type Map.Entry\");\n\n                Set<STypeDef> set = parse(map);\n                Iterator<STypeDef> it = set.iterator();\n\n                assertEquals(1, set.size());\n                SClassDef Test = (SClassDef) it.next();\n                Instruction ins = Test.constructors().get(0).statements().get(1);\n                ValuePack vp = (ValuePack) ins;\n                Ins.PutField pf = (Ins.PutField) vp.instructions().get(0);\n                Ins.GetClass getClass = (Ins.GetClass) pf.value();\n                STypeDef sTypeDef = getClass.targetType();\n                assertEquals(\"java.util.Map$Entry\", sTypeDef.fullName());\n        }\n\n        @Test\n        public void testInterfaceDefaultMethodFail() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"interface Test\\n\" +\n                        \"    def m = 1\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testInterfaceStaticMethodFail() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"interface Test\\n\" +\n                        \"    static\\n\" +\n                        \"        def m = 1\");\n                try {\n                        parse(map);\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testSAnnoDef() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"annotation A\\n\" +\n                        \"    a:int = 1\");\n                Set<STypeDef> sTypeDefs = parse(map);\n                assertEquals(1, sTypeDefs.size());\n                SAnnoDef sAnnoDef = (SAnnoDef) sTypeDefs.iterator().next();\n                assertEquals(\"A\", sAnnoDef.fullName());\n                assertEquals(1, sAnnoDef.annoFields().size());\n                SAnnoField f = sAnnoDef.annoFields().get(0);\n                assertEquals(\"a\", f.name());\n                assertEquals(IntTypeDef.get(), f.type());\n                assertEquals(new IntValue(1), f.defaultValue());\n        }\n\n        @Test\n        public void testLambdaConstruction() throws Exception {\n                Map<String, String> map = new HashMap<String, String>();\n                map.put(\"test\", \"\" +\n                        \"class A\\n\" +\n                        \"  def method\\n\" +\n                        \"    x = 1\\n\" +\n                        \"    y = 2\\n\" +\n                        \"    a = ()-> x + 1\\n\");\n                Set<STypeDef> sTypeDefs = parse(map);\n                assertEquals(2, sTypeDefs.size());\n                Iterator<STypeDef> it = sTypeDefs.iterator();\n                STypeDef type = it.next();\n                if (!type.fullName().equals(\"A\")) {\n                        type = it.next();\n                }\n                assertEquals(\"A\", type.fullName());\n                SClassDef sClassDef = (SClassDef) type;\n\n                List<SMethodDef> methodDefs = sClassDef.methods();\n                assertEquals(2, methodDefs.size());\n                Iterator<SMethodDef> it2 = methodDefs.iterator();\n                SMethodDef method = it2.next();\n                if (!method.name().equals(\"method\")) {\n                        method = it2.next();\n                }\n                assertEquals(\"method\", method.name());\n                assertEquals(3, method.statements().size());\n                Instruction ins = method.statements().get(2);\n                Ins.TReturn ret = (Ins.TReturn) ins;\n                ValuePack vp = (ValuePack) ret.value();\n                Ins.InvokeVirtual iv = (Ins.InvokeVirtual) vp.instructions().get(1);\n                Ins.New iNew = (Ins.New) iv.arguments().get(0);\n                assertEquals(2, iNew.args().size());\n                Ins.NewMap newMap = (Ins.NewMap) iNew.args().get(1);\n\n                // only capture one argument\n                assertEquals(1, newMap.initValues().size());\n        }\n}"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/TestSynchronized.java",
    "content": "package lt.compiler.cases;\n\nimport lt.RepeatRule;\nimport org.junit.BeforeClass;\nimport org.junit.Rule;\nimport org.junit.Test;\n\nimport java.lang.reflect.Method;\n\nimport static lt.compiler.cases.TestCodeGen.retrieveClass;\nimport static org.junit.Assert.assertTrue;\n\n/**\n * synchronized\n */\npublic class TestSynchronized {\n        @Rule\n        public RepeatRule repeatRule = new RepeatRule();\n        private static Class<?> testSynchronizedCls;\n        private static Class<?> testSynchronizedReturnCls;\n\n        @BeforeClass\n        public static void classSetUp() throws Exception {\n                testSynchronizedCls = retrieveClass(\n                        \"\" +\n                                \"class TestAnnotation\\n\" +\n                                \"    static\\n\" +\n                                \"        method(a,b,c):Unit\\n\" +\n                                \"            synchronized(a,b)\\n\" +\n                                \"                c.i=1\\n\" +\n                                \"                Thread.sleep(200)\\n\" +\n                                \"                a.i+=1\\n\" +\n                                \"                b.i+=2\",\n                        \"TestAnnotation\");\n                testSynchronizedReturnCls = retrieveClass(\n                        \"\" +\n                                \"class TestSynchronizedReturn\\n\" +\n                                \"    static\\n\" +\n                                \"        def method(a,b,c)\\n\" +\n                                \"            synchronized(a,b)\\n\" +\n                                \"                c.i=1\\n\" +\n                                \"                Thread.sleep(200)\\n\" +\n                                \"                a.i+=1\\n\" +\n                                \"                b.i+=2\\n\" +\n                                \"                return 10\",\n                        \"TestSynchronizedReturn\");\n        }\n\n        @Test\n        @RepeatRule.Repeat(times = 20)\n        public void testSynchronized() throws Exception {\n                Class<?> cls = testSynchronizedCls;\n                class Container {\n                        public int i = 0;\n                }\n                final Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n                final Container a = new Container();\n                final Container b = new Container();\n                final Container c = new Container();\n                new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                try {\n                                        method.invoke(null, a, b, c);\n                                } catch (Exception e) {\n                                        e.printStackTrace();\n                                }\n                        }\n                }).start();\n\n                while (c.i == 0) {\n                        Thread.sleep(1);\n                }\n\n                class Result {\n                        boolean pass1 = false;\n                        boolean pass2 = false;\n                }\n                final Result result = new Result();\n\n                Thread t1 = new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                synchronized (a) {\n                                        if (1 == a.i) result.pass1 = true;\n                                }\n                        }\n                });\n                t1.start();\n                Thread t2;\n                t2 = new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                synchronized (b) {\n                                        if (2 == b.i) result.pass2 = true;\n                                }\n                        }\n                });\n                t2.start();\n                t1.join();\n                t2.join();\n                assertTrue(result.pass1);\n                assertTrue(result.pass2);\n        }\n\n        @Test\n        @RepeatRule.Repeat(times = 20)\n        public void testSynchronizedReturn() throws Exception {\n                Class<?> cls = testSynchronizedReturnCls;\n                class Container {\n                        public int i = 0;\n                }\n                final Method method = cls.getMethod(\"method\", Object.class, Object.class, Object.class);\n                final Container a = new Container();\n                final Container b = new Container();\n                final Container c = new Container();\n                class Result {\n                        boolean result = false;\n                        boolean pass1 = false;\n                        boolean pass2 = false;\n                }\n                final Result result = new Result();\n                new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                try {\n                                        Object res = method.invoke(null, a, b, c);\n                                        if (res.equals(10)) result.result = true;\n                                        c.i = 2;\n                                } catch (Exception e) {\n                                        e.printStackTrace();\n                                }\n                        }\n                }).start();\n\n                while (c.i == 0) {\n                        Thread.sleep(1);\n                }\n\n                Thread t1 = new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                synchronized (a) {\n                                        if (1 == a.i) result.pass1 = true;\n                                }\n                        }\n                });\n                t1.start();\n                Thread t2 = new Thread(new Runnable() {\n                        @Override\n                        public void run() {\n                                synchronized (b) {\n                                        if (2 == b.i) result.pass2 = true;\n                                }\n                        }\n                });\n                t2.start();\n                t1.join();\n                t2.join();\n\n                while (c.i == 1) {\n                        Thread.sleep(1);\n                }\n\n                assertTrue(result.result);\n                assertTrue(result.pass1);\n                assertTrue(result.pass2);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/anno/TestConstructorAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases.anno;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test constructor\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.CONSTRUCTOR)\npublic @interface TestConstructorAnno {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/anno/TestFieldAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases.anno;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test field\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.FIELD)\npublic @interface TestFieldAnno {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/anno/TestMethodAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases.anno;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test method\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.METHOD)\npublic @interface TestMethodAnno {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/anno/TestParamAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases.anno;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test parameter\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.PARAMETER)\npublic @interface TestParamAnno {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/cases/anno/TestTypeAnno.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.cases.anno;\n\nimport java.lang.annotation.ElementType;\nimport java.lang.annotation.Retention;\nimport java.lang.annotation.RetentionPolicy;\nimport java.lang.annotation.Target;\n\n/**\n * test type\n */\n@Retention(RetentionPolicy.RUNTIME)\n@Target(ElementType.TYPE)\npublic @interface TestTypeAnno {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/err_rec/TestParserErrorRecovery.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.err_rec;\n\nimport lt.compiler.*;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Expression;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.def.ClassDef;\nimport lt.compiler.syntactic.def.InterfaceDef;\nimport lt.compiler.syntactic.def.MethodDef;\nimport lt.compiler.syntactic.def.VariableDef;\nimport lt.compiler.syntactic.literal.BoolLiteral;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.literal.StringLiteral;\nimport lt.compiler.syntactic.operation.TwoVariableOperation;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.compiler.syntactic.pre.PackageDeclare;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.Arrays;\nimport java.util.Collections;\nimport java.util.LinkedHashMap;\nimport java.util.List;\n\nimport static org.junit.Assert.*;\n\n/**\n * parser error recovery\n */\npublic class TestParserErrorRecovery {\n        private List<Statement> parse(String code, ErrorManager err) throws IOException, SyntaxException {\n                IndentScanner scanner = new IndentScanner(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser parser = new Parser(scanner.scan(), err);\n                return parser.parse();\n        }\n\n        @Test\n        public void testNextNodeNotNull() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"1+,2\"\n                /*         ^Unexpected End */\n                        , err);\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(3, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedEnd, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new TwoVariableOperation(\n                                \"+\",\n                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                new NumberLiteral(\"2\", LineCol.SYNTHETIC), LineCol.SYNTHETIC),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testNextNodeNull() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"1+\"\n                /*         ^Unexpected End */\n                        , err);\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(3, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedEnd, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testTokenNoWhereToPlace() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"if a type Object\\n\" +\n                /*          ^no where to place */\n                                \"    ...\"\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(4, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.If(Collections.singletonList(\n                                new AST.If.IfPair(\n                                        new AST.TypeOf(new AST.Access(null, \"Object\", LineCol.SYNTHETIC), LineCol.SYNTHETIC),\n                                        Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)),\n                                        LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testStaticNoStmt() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"static private\"\n                /*              ^not a statement */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(8, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testSyncNotExp() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"synchronized(a, method():Unit)\\n\" +\n                /*                       ^not an expression */\n                                \"    ...\"\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(17, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.Synchronized(\n                                Collections.<Expression>singletonList(new AST.Access(null, \"a\", LineCol.SYNTHETIC)),\n                                Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)),\n                                LineCol.SYNTHETIC\n                        ),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testWhileEmptyBody() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"while true\"\n                /*       ^not elem start */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(1, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.While(\n                                new BoolLiteral(\"true\", LineCol.SYNTHETIC),\n                                Collections.<Statement>emptyList(),\n                                false,\n                                LineCol.SYNTHETIC\n                        ),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testDoWhileEmptyBody() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"do a\"\n                /*          ^unexpected\n                 *       ^unexpected end\n                 */\n                        , err);\n\n                assertEquals(2, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(4, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, err.errorList.get(1).lineCol.line);\n                assertEquals(1, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedEnd, err.errorList.get(1).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testPkgImportNotAccess() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"import method()\\n\" +\n                /*              ^not access */\n                                \"import method()._\"\n                /*              ^not import static */\n                        , err);\n\n                assertEquals(2, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(8, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n                assertEquals(2, err.errorList.get(1).lineCol.line);\n                assertEquals(8, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testPkgDec() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"package pack cls\\n\" +\n                /*                    ^shouldn't be name */\n                                \"package\\n\" +\n                /*              ^shouldn't be name */\n                                \"    ...\"\n                        , err);\n\n                assertEquals(3, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(14, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, err.errorList.get(1).lineCol.line);\n                assertEquals(1, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(1).type);\n\n                assertEquals(3, err.errorList.get(2).lineCol.line);\n                assertEquals(5, err.errorList.get(2).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(2).type);\n\n                assertEquals(\n                        Arrays.asList(\n                                new PackageDeclare(new AST.PackageRef(\"pack\", LineCol.SYNTHETIC), LineCol.SYNTHETIC),\n                                new PackageDeclare(new AST.PackageRef(\"\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testAnno() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"@[]\\n\" +\n                /*        ^expecting annotation instance */\n                                \"a\"\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(2, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.Access(null, \"a\", LineCol.SYNTHETIC),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testTry() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"try\\n\" +\n                /*       ^invalid try */\n                                \"try\\n\" +\n                                \"    ...\\n\" +\n                                \"catch e fail1\\n\" +\n                /*                    ^unexpected */\n                                \"try\\n\" +\n                                \"    ...\\n\" +\n                                \"finally fail2\"\n                /*               ^unexpected token */\n                        , err);\n\n                assertEquals(3, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(1, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(4, err.errorList.get(1).lineCol.line);\n                assertEquals(9, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(1).type);\n\n                assertEquals(7, err.errorList.get(2).lineCol.line);\n                assertEquals(9, err.errorList.get(2).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(2).type);\n\n                assertEquals(\n                        Arrays.asList(\n                                new AST.Try(\n                                        Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)),\n                                        \"e\",\n                                        Collections.<Statement>emptyList(),\n                                        Collections.<Statement>emptyList(),\n                                        LineCol.SYNTHETIC\n                                ),\n                                new AST.Try(\n                                        Collections.<Statement>singletonList(new AST.Pass(LineCol.SYNTHETIC)),\n                                        null,\n                                        Collections.<Statement>emptyList(),\n                                        Collections.<Statement>emptyList(),\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testInterface() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"interface I:invoke()\\n\" +\n                /*                   ^invalid try */\n                                \"interface :\\n\" +\n                /*                 ^invalid try */\n                                \"interface\\n\" +\n                                \"    ....\"\n                /*           ^invalid try */\n                        , err);\n\n                assertEquals(3, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(13, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(2, err.errorList.get(1).lineCol.line);\n                assertEquals(11, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(1).type);\n\n                assertEquals(4, err.errorList.get(2).lineCol.line);\n                assertEquals(5, err.errorList.get(2).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(2).type);\n\n                assertEquals(\n                        Collections.singletonList(\n                                new InterfaceDef(\n                                        \"I\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(), Collections.<AST.Access>emptyList(),\n                                        Collections.<AST.Anno>emptySet(), Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testClass() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"class C(a=1,b)\\n\" +\n                /*                   ^should have init value */\n                                \"class C(a, method())\\n\" +\n                /*                  ^not variableDef or Access(null,'') */\n                                \"class C*\\n\" +\n                /*              ^unexpected */\n                                \"class C:P1(),P2()\\n\" +\n                /*                    ^multiple Inheritance */\n                                \"class C:a*2\\n\" +\n                /*                ^not invocation nor access */\n                                \"class\\n\" +\n                                \"    ...\"\n                /*           ^unexpected */\n                        , err);\n\n                assertEquals(6, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(13, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(2, err.errorList.get(1).lineCol.line);\n                assertEquals(12, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(1).type);\n\n                assertEquals(3, err.errorList.get(2).lineCol.line);\n                assertEquals(8, err.errorList.get(2).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(2).type);\n\n                assertEquals(4, err.errorList.get(3).lineCol.line);\n                assertEquals(14, err.errorList.get(3).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(3).type);\n\n                assertEquals(5, err.errorList.get(4).lineCol.line);\n                assertEquals(10, err.errorList.get(4).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(4).type);\n\n                assertEquals(7, err.errorList.get(5).lineCol.line);\n                assertEquals(5, err.errorList.get(5).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(5).type);\n\n                VariableDef var_1_a = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                var_1_a.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                assertEquals(Arrays.asList(\n                        new ClassDef(\n                                \"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                Arrays.asList(\n                                        var_1_a,\n                                        new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                ),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                Collections.singletonList(\n                                        new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                ),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                new AST.Invocation(\n                                        new AST.Access(null, \"P1\", LineCol.SYNTHETIC),\n                                        Collections.<Expression>emptyList(),\n                                        false, LineCol.SYNTHETIC\n                                ),\n                                Collections.singletonList(\n                                        new AST.Access(null, \"P2\", LineCol.SYNTHETIC)\n                                ),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        ),\n                        new ClassDef(\n                                \"C\", Collections.<AST.Access>emptyList(), Collections.<Modifier>emptySet(),\n                                Collections.<VariableDef>emptyList(),\n                                null,\n                                Collections.<AST.Access>emptyList(),\n                                Collections.<AST.Anno>emptySet(),\n                                Collections.<Statement>emptyList(),\n                                LineCol.SYNTHETIC\n                        )\n                ), statements);\n        }\n\n        @Test\n        public void testFor() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"for\\n\" +\n                                \"    ...\"\n                /*           ^unexpected */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n\n                assertEquals(2, err.errorList.get(0).lineCol.line);\n                assertEquals(5, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"if true\\n\" +\n                                \"else\\n\" +\n                                \"elseif true\"\n                /*              ^syntax */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n\n                assertEquals(3, err.errorList.get(0).lineCol.line);\n                assertEquals(8, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.If(Arrays.asList(\n                                new AST.If.IfPair(new BoolLiteral(\"true\", LineCol.SYNTHETIC), Collections.<Statement>emptyList(), LineCol.SYNTHETIC),\n                                new AST.If.IfPair(null, Collections.<Statement>emptyList(), LineCol.SYNTHETIC)\n                        ), LineCol.SYNTHETIC),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testMethod() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"method(a=1,b):Unit\\n\" +\n                /*                  ^no init value */\n                                \"method(a=1,method()):Unit\\n\"\n                /*                  ^syntax */\n                        , err);\n\n                assertEquals(2, err.errorList.size());\n\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(12, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(2, err.errorList.get(1).lineCol.line);\n                assertEquals(12, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(1).type);\n\n                VariableDef v = new VariableDef(\"a\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC);\n                v.setInit(new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n\n                assertEquals(\n                        Arrays.asList(\n                                new MethodDef(\n                                        \"method\", Collections.<Modifier>emptySet(),\n                                        new AST.Access(null, \"Unit\", LineCol.SYNTHETIC),\n                                        Arrays.asList(\n                                                v,\n                                                new VariableDef(\"b\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)\n                                        ),\n                                        Collections.<AST.Anno>emptySet(),\n                                        Collections.<Statement>emptyList(),\n                                        LineCol.SYNTHETIC\n                                ),\n                                new MethodDef(\n                                        \"method\", Collections.<Modifier>emptySet(),\n                                        new AST.Access(null, \"Unit\", LineCol.SYNTHETIC),\n                                        Collections.singletonList(v),\n                                        Collections.<AST.Anno>emptySet(),\n                                        Collections.<Statement>emptyList(),\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testAs() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"as 1\"\n                /*                  ^syntax */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(1, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n\n        @Test\n        public void testInvocation() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"method()()\\n\" +\n                /*       ^!!!! it's NO longer a syntax error */\n                                \"method(class C, a)\"\n                /*              ^syntax */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n\n                assertEquals(2, err.errorList.get(0).lineCol.line);\n                assertEquals(8, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(\n                        Arrays.asList(\n                                new AST.Invocation(\n                                        new AST.Invocation(\n                                                new AST.Access(null, \"method\", LineCol.SYNTHETIC),\n                                                Collections.<Expression>emptyList(),\n                                                false, LineCol.SYNTHETIC\n                                        ),\n                                        Collections.<Expression>emptyList(),\n                                        false, LineCol.SYNTHETIC\n                                ),\n                                new AST.Invocation(\n                                        new AST.Access(null, \"method\", LineCol.SYNTHETIC),\n                                        Collections.<Expression>singletonList(new AST.Access(null, \"a\", LineCol.SYNTHETIC)),\n                                        false, LineCol.SYNTHETIC\n                                )\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testMap() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"[\\n\" +\n                                \"    'a':,\\n\" +\n                /*              ^syntax */\n                                \"    'b':2\\n\" +\n                                \"]\\n\" +\n                                \"[\\n\" +\n                                \"    'a':1\\n\" +\n                                \"    'b':class C\\n\" +\n                /*               ^syntax */\n                                \"    'c':3\\n\" +\n                                \"]\"\n                        , err);\n\n                //assertEquals(3, err.errorList.size());\n                assertEquals(2, err.errorList.get(0).lineCol.line);\n                assertEquals(8, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(0).type);\n\n                assertEquals(7, err.errorList.get(2).lineCol.line);\n                assertEquals(9, err.errorList.get(2).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(2).type);\n\n                assertEquals(7, err.errorList.get(5).lineCol.line);\n                assertEquals(15, err.errorList.get(5).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.Syntax, err.errorList.get(5).type);\n\n                assertEquals(\n                        Arrays.asList(\n                                new AST.MapExp(\n                                        new LinkedHashMap<Expression, Expression>() {{\n                                                put(new StringLiteral(\"'b'\", LineCol.SYNTHETIC), new NumberLiteral(\"2\", LineCol.SYNTHETIC));\n                                        }},\n                                        LineCol.SYNTHETIC\n                                ),\n                                new AST.MapExp(\n                                        new LinkedHashMap<Expression, Expression>() {{\n                                                put(new StringLiteral(\"'a'\", LineCol.SYNTHETIC), new NumberLiteral(\"1\", LineCol.SYNTHETIC));\n                                                put(new StringLiteral(\"'c'\", LineCol.SYNTHETIC), new NumberLiteral(\"3\", LineCol.SYNTHETIC));\n                                        }},\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testIndexAndArray() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"arr[1,class C,3]\\n\" +\n                /*              ^unexpected */\n                                \"[1,class C,3]\"\n                /*          ^unexpected */\n                        , err);\n\n                assertEquals(2, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(7, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(2, err.errorList.get(1).lineCol.line);\n                assertEquals(4, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(1).type);\n\n                assertEquals(\n                        Arrays.asList(\n                                new AST.Index(\n                                        new AST.Access(null, \"arr\", LineCol.SYNTHETIC),\n                                        Arrays.<Expression>asList(\n                                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                                new NumberLiteral(\"3\", LineCol.SYNTHETIC)\n                                        ),\n                                        LineCol.SYNTHETIC\n                                ),\n                                new AST.ArrayExp(\n                                        Arrays.<Expression>asList(\n                                                new NumberLiteral(\"1\", LineCol.SYNTHETIC),\n                                                new NumberLiteral(\"3\", LineCol.SYNTHETIC)\n                                        ),\n                                        LineCol.SYNTHETIC\n                                )\n                        ),\n                        statements\n                );\n        }\n\n        @Test\n        public void testLambda() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"(a.b, method(), c)->1\"\n                /*              ^unexpected */\n                        , err);\n\n                assertEquals(2, err.errorList.size());\n                assertEquals(1, err.errorList.get(0).lineCol.line);\n                assertEquals(2, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(1, err.errorList.get(1).lineCol.line);\n                assertEquals(7, err.errorList.get(1).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(1).type);\n\n                assertEquals(1, statements.size());\n                assertEquals(\n                        new AST.Lambda(\n                                Collections.singletonList(new VariableDef(\"c\", Collections.<Modifier>emptySet(), Collections.<AST.Anno>emptySet(), LineCol.SYNTHETIC)),\n                                Collections.<Statement>singletonList(new NumberLiteral(\"1\", LineCol.SYNTHETIC)),\n                                LineCol.SYNTHETIC\n                        ),\n                        statements.get(0)\n                );\n        }\n\n        @Test\n        public void testAccessAssign() throws Exception {\n                ErrorManager err = new ErrorManager(false);\n                err.out = ErrorManager.Out.allNull();\n\n                List<Statement> statements = parse(\"\" +\n                                \"a.\\n\" +\n                                \"    ...\\n\"\n                /*           ^unexpected */\n                        , err);\n\n                assertEquals(1, err.errorList.size());\n                assertEquals(2, err.errorList.get(0).lineCol.line);\n                assertEquals(5, err.errorList.get(0).lineCol.column);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.errorList.get(0).type);\n\n                assertEquals(0, statements.size());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/err_rec/TestScannerErrorRecovery.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.compiler.err_rec;\n\nimport lt.compiler.ErrorManager;\nimport lt.compiler.IndentScanner;\nimport lt.compiler.Properties;\nimport lt.compiler.SyntaxException;\nimport lt.compiler.lexical.Element;\nimport lt.compiler.lexical.ElementStartNode;\nimport lt.compiler.lexical.EndingNode;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\n\nimport static org.junit.Assert.*;\n\n/**\n * error recovery\n */\npublic class TestScannerErrorRecovery {\n        private ElementStartNode scan(String words, ErrorManager errorManager) throws IOException, SyntaxException {\n                IndentScanner scanner = new IndentScanner(\"test.lt\", new StringReader(words), new Properties(), errorManager);\n                return scanner.scan();\n        }\n\n        @Test\n        public void testUnknownToken() throws Exception {\n                ErrorManager manager = new ErrorManager(false);\n                manager.out = ErrorManager.Out.allNull();\n\n                ElementStartNode root = scan(\"\" +\n                        \"a ? = 1\"\n                /*         ^unknown token ? */\n                        , manager);\n\n                assertEquals(1, manager.errorList.size());\n                ErrorManager.CompilingError err = manager.errorList.get(0);\n                assertEquals(ErrorManager.CompilingError.UnknownToken, err.type);\n                assertEquals(1, err.lineCol.line);\n                assertEquals(3, err.lineCol.column);\n\n                Element a = (Element) root.getLinkedNode();\n                Element eq = (Element) a.next();\n                Element one = (Element) eq.next();\n\n                assertEquals(\"a\", a.getContent());\n                assertEquals(\"=\", eq.getContent());\n                assertEquals(\"1\", one.getContent());\n                assertNull(one.next());\n        }\n\n        @Test\n        public void testUnexpectedToken_Pair_End() throws Exception {\n                ErrorManager manager = new ErrorManager(false);\n                manager.out = ErrorManager.Out.allNull();\n\n                ElementStartNode root = scan(\"\" +\n                        \"['id':1}\"\n                /*              ^unknown token ? */\n                        , manager);\n\n                assertEquals(1, manager.errorList.size());\n                ErrorManager.CompilingError err = manager.errorList.get(0);\n                assertEquals(ErrorManager.CompilingError.UnexpectedToken, err.type);\n                assertEquals(1, err.lineCol.line);\n                assertEquals(8, err.lineCol.column);\n\n                Element _b1_ = (Element) root.getLinkedNode();\n                ElementStartNode start = (ElementStartNode) _b1_.next();\n                EndingNode end = (EndingNode) start.next();\n                Element _b2_ = (Element) end.next();\n                assertNull(_b2_.next());\n\n                Element id = (Element) start.getLinkedNode();\n                Element colon = (Element) id.next();\n                Element one = (Element) colon.next();\n                assertNull(one.next());\n\n                assertEquals(\"[\", _b1_.getContent());\n                assertEquals(\"]\", _b2_.getContent());\n                assertEquals(\"'id'\", id.getContent());\n                assertEquals(\":\", colon.getContent());\n                assertEquals(\"1\", one.getContent());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/err_rec/TestSemanticError.java",
    "content": "package lt.compiler.err_rec;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Set;\n\nimport static org.junit.Assert.*;\n\npublic class TestSemanticError {\n        private Set<STypeDef> get(String code) throws IOException, SyntaxException {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner scanner = new IndentScanner(\"test.lt\", new StringReader(code), new Properties(), err);\n                final Parser parser = new Parser(scanner.scan(), err);\n                SemanticProcessor semanticProcessor = new SemanticProcessor(new HashMap<String, List<Statement>>() {{\n                        put(\"test.lt\", parser.parse());\n                }}, Thread.currentThread().getContextClassLoader(), err);\n                return semanticProcessor.parse();\n        }\n\n        @Test\n        public void testFailWhenNoMethod() throws Exception {\n                try {\n                        get(\"\" +\n                                \"package test\\n\" +\n                                \"class A\\n\" +\n                                \"    method()\\n\" +\n                                \"        inner():Unit\");\n                } catch (Throwable t) {\n                        t.printStackTrace();\n                        fail();\n                }\n        }\n\n        @Test\n        public void testImportFail() throws Exception {\n                try {\n                        get(\"import java::xyz::_\");\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n\n        @Test\n        public void testImplicitFail() throws Exception {\n                try {\n                        get(\"\" +\n                                \"@Implicit\\n\" +\n                                \"class X\"\n                        );\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n\n                try {\n                        get(\"\" +\n                                \"@Implicit\\n\" +\n                                \"object X\\n\" +\n                                \"    @Implicit\\n\" +\n                                \"    def m\"\n                        );\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n\n                try {\n                        get(\"\" +\n                                \"@Implicit\\n\" +\n                                \"object X\\n\" +\n                                \"    @Implicit\\n\" +\n                                \"    def m(o):Unit\"\n                        );\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n\n                // implicit\n\n                try {\n                        get(\"\" +\n                                \"implicit object X\\n\" +\n                                \"    implicit def m\"\n                        );\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n\n                try {\n                        get(\"\" +\n                                \"implicit object X\\n\" +\n                                \"    implicit def m(o):Unit\"\n                        );\n                        fail();\n                } catch (SyntaxException ignore) {\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/BoolParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface BoolParamReturnUnit {\n        void x(boolean a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/ByteParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface ByteParamReturnUnit {\n        void x(byte a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/CharParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface CharParamReturnUnit {\n        void x(char a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/DoubleParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface DoubleParamReturnUnit {\n        void x(double a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/FloatParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface FloatParamReturnUnit {\n        void x(float a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/IntParamReturnInt.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface IntParamReturnInt {\n        int x(int a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/IntParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface IntParamReturnUnit {\n        void x(int a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/LongParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface LongParamReturnUnit {\n        void x(long a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnBool.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnBool {\n        boolean x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnByte.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnByte {\n        byte x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnChar.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnChar {\n        char x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnDouble.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnDouble {\n        double x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnFloat.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnFloat {\n        float x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnInt.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnInt {\n        int x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnLong.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnLong {\n        long x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnShort.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnShort {\n        short x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/NoParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface NoParamReturnUnit {\n        void x();\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/compiler/functionalInterfaces/ShortParamReturnUnit.java",
    "content": "package lt.compiler.functionalInterfaces;\n\npublic interface ShortParamReturnUnit {\n        void x(short a);\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/generator/TestJsSupport.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.generator;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.builtin.StringConstantValue;\nimport lt.compiler.syntactic.Statement;\nimport lt.lang.js;\nimport org.junit.Test;\n\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.util.Collections;\nimport java.util.List;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * test js\n */\npublic class TestJsSupport {\n        private String compile(String source) throws IOException, SyntaxException {\n                ErrorManager err = new ErrorManager(true);\n                IndentScanner scanner = new IndentScanner(\"test-js.ltjs\", new StringReader(source), new Properties(), err);\n                Parser parser = new Parser(scanner.scan(), err);\n                js js = new js();\n                js.init(parser.parse(), new SemanticProcessor(Collections.<String, List<Statement>>emptyMap(), ClassLoader.getSystemClassLoader(), err), null, null, err);\n                return ((StringConstantValue) js.generate()).getStr();\n        }\n\n        @Test\n        public void testName() throws Exception {\n                assertEquals(\"\" +\n                                \"var x;\\n\" +\n                                \"var y = 1;\"\n                        ,\n                        compile(\"\" +\n                                \"var x\\n\" +\n                                \"y=1\"));\n        }\n\n        @Test\n        public void testLiteral() throws Exception {\n                assertEquals(\"\" +\n                                \"1;\\n\" +\n                                \"'abc';\\n\" +\n                                \"true;\\n\" +\n                                \"true;\\n\" +\n                                \"false;\\n\" +\n                                \"false;\"\n                        ,\n                        compile(\"\" +\n                                \"1\\n\" +\n                                \"'abc'\\n\" +\n                                \"true\\n\" +\n                                \"yes\\n\" +\n                                \"false\\n\" +\n                                \"no\"));\n        }\n\n        @Test\n        public void testOperator() throws Exception {\n                assertEquals(\"\" +\n                                \"++a;\\n\" +\n                                \"a++;\\n\" +\n                                \"a + b;\"\n                        , compile(\"\" +\n                                \"++a\\n\" +\n                                \"a++\\n\" +\n                                \"a+b\"));\n        }\n\n        @Test\n        public void testAccess() throws Exception {\n                assertEquals(\"\" +\n                                \"a.b;\\n\" +\n                                \"a;\"\n                        ,\n                        compile(\"\" +\n                                \"a.b\\n\" +\n                                \"a\"));\n        }\n\n        @Test\n        public void testArray() throws Exception {\n                assertEquals(\"\" +\n                                \"[1, 2, 3];\"\n                        ,\n                        compile(\"\" +\n                                \"[1,2,3]\"));\n        }\n\n        @Test\n        public void testAssign() throws Exception {\n                assertEquals(\"\" +\n                                \"var a;\\n\" +\n                                \"a = 1;\"\n                        ,\n                        compile(\"\" +\n                                \"var a\\n\" +\n                                \"a=1\"));\n        }\n\n        @Test\n        public void testProcedure() throws Exception {\n                assertEquals(\"\" +\n                                \"(function(){\\n\" +\n                                \"    return 1 + 1;\\n\" +\n                                \"})();\",\n                        compile(\"\" +\n                                \"(return 1+1)\"));\n        }\n\n        @Test\n        public void testIndex() throws Exception {\n                assertEquals(\"\" +\n                                \"a[1];\\n\" +\n                                \"a[1][2];\",\n                        compile(\"\" +\n                                \"a[1]\\n\" +\n                                \"a[1,2]\"));\n        }\n\n        @Test\n        public void testLambda() throws Exception {\n                assertEquals(\"\" +\n                        \"function(x) {\\n\" +\n                        \"    return x + 1;\\n\" +\n                        \"};\", compile(\"x->x+1\"));\n        }\n\n        @Test\n        public void testMap() throws Exception {\n                assertEquals(\"\" +\n                        \"{\\n\" +\n                        \"    'a' : 1,\\n\" +\n                        \"    'b' : 2\\n\" +\n                        \"};\", compile(\"['a':1,'b':2]\"));\n        }\n\n        @Test\n        public void testNew() throws Exception {\n                assertEquals(\"new A();\\nnew A(1);\", compile(\"new A\\nnew A(1)\"));\n        }\n\n        @Test\n        public void testNull() throws Exception {\n                assertEquals(\"null;\", compile(\"null\"));\n        }\n\n        @Test\n        public void testRequire() throws Exception {\n                assertEquals(\"require('xx');\", compile(\"require 'xx'\"));\n        }\n\n        @Test\n        public void testClassDef() throws Exception {\n                assertEquals(\"\" +\n                                \"function A(a, b, c) {\\n\" +\n                                \"    b = b ? b : 1;\\n\" +\n                                \"    c = c ? c : 2;\\n\" +\n                                \"    a + b + c;\\n\" +\n                                \"    this.a = a;\\n\" +\n                                \"    this.b = b;\\n\" +\n                                \"    this.c = c;\\n\" +\n                                \"}\",\n                        compile(\"\" +\n                                \"class A(a,b=1,c=2)\\n\" +\n                                \"    a+b+c\"));\n        }\n\n        @Test\n        public void testFun() throws Exception {\n                assertEquals(\"\" +\n                        \"function F(a) {\\n\" +\n                        \"    return a + 1;\\n\" +\n                        \"}\", compile(\"\" +\n                        \"fun F(a)\\n\" +\n                        \"    return a + 1\"));\n        }\n\n        @Test\n        public void testFor() throws Exception {\n                assertEquals(\"\" +\n                                \"for (var i in x) {\\n\" +\n                                \"    i + 1;\\n\" +\n                                \"}\",\n                        compile(\"for i in x\\n\" +\n                                \"    i + 1\"));\n        }\n\n        @Test\n        public void testIf() throws Exception {\n                assertEquals(\"\" +\n                                \"if (a) {\\n\" +\n                                \"    return 1;\\n\" +\n                                \"} else if (b) {\\n\" +\n                                \"    return 2;\\n\" +\n                                \"} else if (c) {\\n\" +\n                                \"    return 3;\\n\" +\n                                \"} else {\\n\" +\n                                \"    return 4;\\n\" +\n                                \"}\",\n                        compile(\"if a\\n\" +\n                                \"    return 1\\n\" +\n                                \"elseif b\\n\" +\n                                \"    return 2\\n\" +\n                                \"elseif c\\n\" +\n                                \"    return 3\\n\" +\n                                \"else\\n\" +\n                                \"    return 4\"));\n        }\n\n        @Test\n        public void testPass() throws Exception {\n                assertEquals(\"/* pass */;\", compile(\"...\"));\n        }\n\n        @Test\n        public void testThrow() throws Exception {\n                assertEquals(\"throw e;\", compile(\"throw e\"));\n        }\n\n        @Test\n        public void testTry() throws Exception {\n                assertEquals(\"\" +\n                                \"try {\\n\" +\n                                \"    1 + 1;\\n\" +\n                                \"} catch (e) {\\n\" +\n                                \"    2 + 2;\\n\" +\n                                \"} finally {\\n\" +\n                                \"    3 + 3;\\n\" +\n                                \"}\",\n                        compile(\"try\\n\" +\n                                \"    1+1\\n\" +\n                                \"catch e\\n\" +\n                                \"    2+2\\n\" +\n                                \"finally\\n\" +\n                                \"    3+3\"));\n        }\n\n        @Test\n        public void testWhile() throws Exception {\n                assertEquals(\"\" +\n                                \"do {\\n\" +\n                                \"    1 + 1;\\n\" +\n                                \"} while (b);\\n\" +\n                                \"while (b) {\\n\" +\n                                \"    2 + 2;\\n\" +\n                                \"}\",\n                        compile(\"do\\n\" +\n                                \"    1+1\\n\" +\n                                \"while b\\n\" +\n                                \"while b\\n\" +\n                                \"    2 + 2\"));\n        }\n\n        @Test\n        public void testContinue() throws Exception {\n                assertEquals(\"continue;\", compile(\"continue\"));\n        }\n\n        @Test\n        public void testBreak() throws Exception {\n                assertEquals(\"break;\", compile(\"break\"));\n        }\n\n        @Test\n        public void testMethod() throws Exception {\n                assertEquals(\"\" +\n                        \"function method() {\\n\" +\n                        \"    return 1 + 1;\\n\" +\n                        \"}\", compile(\"\" +\n                        \"def method()\\n\" +\n                        \"    return 1 + 1\"));\n\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/TestBugsInEval.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.compiler.*;\nimport lt.compiler.semantic.STypeDef;\nimport lt.compiler.syntactic.Statement;\nimport lt.repl.scripting.Config;\nimport lt.repl.scripting.EvalEntry;\nimport lt.runtime.LtRuntimeException;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.script.ScriptException;\nimport java.io.IOException;\nimport java.io.StringReader;\nimport java.lang.reflect.Constructor;\nimport java.lang.reflect.Field;\nimport java.lang.reflect.InvocationTargetException;\nimport java.util.HashMap;\nimport java.util.List;\nimport java.util.Map;\nimport java.util.Set;\n\nimport static org.junit.Assert.*;\n\n/**\n * bugs caught by eval\n */\npublic class TestBugsInEval {\n        Evaluator evaluator;\n\n        @Before\n        public void setUp() throws Exception {\n                evaluator = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n        }\n\n        private Class<?> retrieveClass(String code, String clsName) throws IOException, SyntaxException, ClassNotFoundException {\n                ErrorManager err = new ErrorManager(true);\n\n                IndentScanner lexicalProcessor = new IndentScanner(\"test.lt\", new StringReader(code), new Properties(), err);\n                Parser syntacticProcessor = new Parser(lexicalProcessor.scan(), err);\n                Map<String, List<Statement>> map = new HashMap<String, List<Statement>>();\n                map.put(\"test.lt\", syntacticProcessor.parse());\n                SemanticProcessor semanticProcessor = new SemanticProcessor(\n                        map,\n                        Thread.currentThread().getContextClassLoader(),\n                        err);\n                Set<STypeDef> types = semanticProcessor.parse();\n\n                CodeGenerator codeGenerator = new CodeGenerator(types, semanticProcessor.getTypes());\n                Map<String, byte[]> list = codeGenerator.generate();\n\n                final byte[] bs = list.get(clsName);\n                ClassLoader classLoader = new ClassLoader() {\n                        @Override\n                        protected Class<?> findClass(String name)\n                                throws ClassNotFoundException {\n                                return defineClass(name, bs, 0, bs.length);\n                        }\n                };\n\n                return classLoader.loadClass(clsName);\n        }\n\n        /**\n         * arr:[]String = [null]<br>\n         * arr[0]='abc'<br>\n         * <pre>\n         * java.lang.VerifyError: Bad type on operand stack in putfield\n         * Exception Details:\n         * Location:\n         * Evaluate.<init>(Ljava/lang/Object;)V @32: putfield\n         * Reason:\n         * Type 'java/lang/Object' (current frame, stack[1]) is not assignable to 'Evaluate' (constant pool 41)\n         * Current Frame:\n         * bci: @32\n         * flags: { }\n         * locals: { 'Evaluate', 'java/lang/Object' }\n         * stack: { 'Evaluate', 'java/lang/Object', 'java/lang/Object' }\n         * Bytecode:\n         * 0x0000000: 2ab7 000e b800 1457 2a2b b500 162a 2b12\n         * 0x0000010: 1712 19ba 0024 0000 2b12 17ba 0027 0000\n         * 0x0000020: b500 292a b400 2957 572a 2bb5 0016 2ab4\n         * 0x0000030: 0016 57b1\n         * </pre><br>\n         * date: 2016-05-09 10:37\n         *\n         * @throws Exception ex\n         */\n        @Test\n        public void test1() throws Exception {\n                evaluator.eval(\"arr:[]String=[null]\");\n                EvalEntry entry = evaluator.eval(\"arr[0]='abc'\");\n                assertEquals(\"res0\", entry.name);\n                assertEquals(\"abc\", entry.result);\n        }\n\n        @Test\n        public void test1_same() throws Exception {\n                Class<?> cls = retrieveClass(\"\" +\n                                \"class Test1(arr)\\n\" +\n                                \"    res0=(arr[0]='abc')\\n\" +\n                                \"    this.arr=arr\"\n                        , \"Test1\");\n                Constructor<?> cons = cls.getConstructor(Object.class);\n                String[] arr = new String[]{null};\n                Object o = cons.newInstance((Object) arr);\n                Field f = cls.getDeclaredField(\"res0\");\n                f.setAccessible(true);\n                assertEquals(\"abc\", f.get(o));\n        }\n\n        /**\n         * class Test<br>\n         * m(a):Unit<br>\n         * t = Test()<br>\n         * t.m(null) ----- error<br>\n         * n=null<br>\n         * t.m(n) ------ ok<br>\n         * Test().m(null) ------- ok<br>\n         * <pre>\n         * java.lang.BootstrapMethodError: java.lang.NoClassDefFoundError: null\n         * at Evaluate.<init>(EVALUATE.lts:1)\n         * at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)\n         * at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)\n         * at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)\n         * at java.lang.reflect.Constructor.newInstance(Constructor.java:422)\n         * at lt.repl.Evaluator.eval(Evaluator.java:225)\n         * at lt.repl.REPL.main(REPL.java:82)\n         * Caused by: java.lang.NoClassDefFoundError: null\n         * ... 7 more\n         * Caused by: java.lang.ClassNotFoundException: null\n         * at lt.repl.Evaluator$3.findClass(Evaluator.java:213)\n         * at java.lang.ClassLoader.loadClass(ClassLoader.java:424)\n         * at java.lang.ClassLoader.loadClass(ClassLoader.java:357)\n         * ... 7 more\n         * </pre><br>\n         * date : 2016-05-09 20:09\n         *\n         * @throws Exception ex\n         */\n        @Test\n        public void test2() throws Exception {\n                evaluator.eval(\"\" +\n                        \"class Test\\n\" +\n                        \"    m(a):Unit\");\n                evaluator.eval(\"t=Test()\");\n                evaluator.eval(\"t.m(null)\");\n        }\n\n        @Test\n        public void testFunctionAdd() throws Exception {\n                Object res = evaluator.eval(\"\" +\n                        \"x = (a,b,c)->a+b+c\\n\" +\n                        \"x(1,2,3)\" +\n                        \"\").result;\n                assertEquals(6, res);\n        }\n\n        @Test\n        public void testEmptyLambda() throws Exception {\n                evaluator.eval(\"()->...\");\n        }\n\n        @Test\n        public void testOpAssign() throws Exception {\n                evaluator.eval(\"i = 1\");\n                Object res = evaluator.eval(\"i <<= 2\").result;\n                assertEquals(4, res);\n        }\n\n        @Test\n        public void testInternalLambdaAndOtherStatements() throws Exception {\n                evaluator.setScannerType(Config.SCANNER_TYPE_BRACE);\n                assertEquals(2, evaluator.eval(\"\" +\n                        \"[1, 2, 3, 4].filter{it > 2}\\n\" +\n                        \"1 + 1\").result);\n        }\n\n        @Test\n        public void testLayerControlSymbolWithoutEnd() throws Exception {\n                Object res = evaluator.eval(\"\" +\n                        \"var count = 0\\n\" +\n                        \"(1 to 10).forEach { count+=it }\\n\" +\n                        \"count\").result;\n                assertEquals(55, res);\n\n        }\n\n        @Test\n        public void testExistingFunction() throws Exception {\n                evaluator.eval(\"\" +\n                        \"fun F(o)\\n\" +\n                        \"    o+1\");\n                Object res = evaluator.eval(\"F(2)\").result;\n                assertEquals(3, res);\n        }\n\n        @Test\n        public void testStringTemplateCast() throws Exception {\n                List list = (List) evaluator.eval(\"\" +\n                        \"class Rational(a,b)\\n\" +\n                        \"    add(that:Rational)=Rational(this.a*that.b + that.a*this.b, this.b*that.b)\\n\" +\n                        \"    toString():String='${a}/${b}'\"\n                ).result;\n                assertEquals(1, list.size());\n                assertEquals(\"Rational\", ((Class) list.get(0)).getName());\n                assertEquals(\"19/28\", evaluator.eval(\"\" +\n                        \"a = Rational(1, 4)\\n\" +\n                        \"b = Rational(3, 7)\\n\" +\n                        \"c = a + b\").result.toString());\n        }\n\n        @Test\n        public void testOverrideReturnTypeMismatch() throws Exception {\n                try {\n                        evaluator.eval(\"\" +\n                                \"class X\\n\" +\n                                \"    toString()='abc'\"\n                        );\n                        fail();\n                } catch (Exception ignore) {\n                }\n                try {\n                        evaluator.eval(\"\" +\n                                \"class X\\n\" +\n                                \"    toString():String='abc'\"\n                        );\n                } catch (Exception ignore) {\n                }\n        }\n\n        @Test\n        public void testMethodParamLongDouble() throws Exception {\n                List list = (List) evaluator.eval(\"\" +\n                        \"class X\\n\" +\n                        \"    def method(a:int, b:long, c:float)=a+b+c\").result;\n                Class<?> X = (Class<?>) list.get(0);\n                Object x = X.newInstance();\n                assertEquals(6f, x.getClass().getMethod(\"method\", int.class, long.class, float.class).invoke(x, 1, 2L, 3F));\n\n                list = (List) evaluator.eval(\"\" +\n                        \"class Y\\n\" +\n                        \"    def method(a:int, b:double, c:float)=a+b+c\").result;\n                X = (Class<?>) list.get(0);\n                x = X.newInstance();\n                assertEquals(6d, x.getClass().getMethod(\"method\", int.class, double.class, float.class).invoke(x, 1, 2d, 3F));\n        }\n\n        @Test\n        public void testMethodDefAssign() throws Exception {\n                evaluator.eval(\"\" +\n                        \"class X\\n\" +\n                        \"    a:int = 1\\n\" +\n                        \"    def method():int = a\\n\" +\n                        \"    private method2():int = a\");\n        }\n\n        @Test\n        public void testCallFunctionalObjectWithCast() throws Exception {\n                Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n                e.eval(\"\" +\n                        \"@FunctionalAbstractClass\\n\" +\n                        \"abstract class X\\n\" +\n                        \"    abstract x(o:B)=...\\n\" +\n                        \"class A : X\\n\" +\n                        \"    x(o:B)=o\\n\" +\n                        \"data class B(i:int)\\n\" +\n                        \"a = A\");\n                Object o = e.eval(\"a([\\\"i\\\": 10])\").result;\n                assertEquals(10, o.getClass().getMethod(\"getI\").invoke(o));\n        }\n\n        @Test\n        public void testForEachCast() throws Exception {\n                Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n                e.setScannerType(Config.SCANNER_TYPE_BRACE);\n                try {\n                        e.eval(\"(1 to 100).forEach(()->{...})\");\n                        fail();\n                } catch (Exception ex) {\n                        // ex: argument type mismatch\n                        Object res = e.eval(\"\" +\n                                \"var res = 0\\n\" +\n                                \"(1 to 100).forEach { res += it }\\n\" +\n                                \"res\").result;\n                        assertEquals(5050, res);\n                }\n        }\n\n        @Test\n        public void testIntegerEqInt() throws Exception {\n                Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n                assertEquals(true,\n                        e.eval(\"\" +\n                                \"val i : Integer = 1\\n\" +\n                                \"i == 1\").result);\n        }\n\n        @Test\n        public void testInPrimitives() throws Exception {\n                Evaluator e = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n                try {\n                        e.eval(\"\" +\n                                \"1 in 2\"\n                        );\n                        fail();\n                } catch (LtRuntimeException ex) {\n                        // pass\n                        return;\n                }\n                fail();\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/TestEvaluator.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport lt.repl.scripting.Config;\nimport lt.repl.scripting.EvalEntry;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.lang.reflect.Method;\nimport java.util.*;\n\nimport static org.junit.Assert.*;\n\n/**\n * test evaluator\n */\npublic class TestEvaluator {\n        private static final ClassPathLoader CLASS_PATH_LOADER = new ClassPathLoader(Thread.currentThread().getContextClassLoader());\n\n        Evaluator evaluator;\n\n        @Before\n        public void setUp() throws Exception {\n                evaluator = new Evaluator(CLASS_PATH_LOADER);\n        }\n\n        @Test\n        public void testSimpleCode() throws Exception {\n                assertEquals(1, evaluator.eval(\"1\").result);\n        }\n\n        @Test\n        public void testSimpleExpression() throws Exception {\n                assertEquals(2, evaluator.eval(\"1+1\").result);\n        }\n\n        @Test\n        public void testMultipleLineExpression() throws Exception {\n                assertEquals(\n                        new LinkedHashMap<Object, Object>() {{\n                                put(\"id\", 1);\n                                put(\"name\", \"cass\");\n                        }},\n                        evaluator.eval(\"\" +\n                                \"[\\n\" +\n                                \"    'id':1\\n\" +\n                                \"    'name':'cass'\\n\" +\n                                \"]\"\n                        ).result);\n        }\n\n        @Test\n        public void testEvaluateTwice() throws Exception {\n                assertEquals(1, evaluator.eval(\"1\").result);\n                assertEquals(2, evaluator.eval(\"1+1\").result);\n        }\n\n        @Test\n        public void testEvaluateTwiceWithMultipleLineExp() throws Exception {\n                assertEquals(\n                        new LinkedHashMap<Object, Object>() {{\n                                put(\"id\", 1);\n                                put(\"name\", \"cass\");\n                        }},\n                        evaluator.eval(\"\" +\n                                \"[\\n\" +\n                                \"    'id':1\\n\" +\n                                \"    'name':'cass'\\n\" +\n                                \"]\"\n                        ).result);\n                assertEquals(2, evaluator.eval(\"1+1\").result);\n        }\n\n        @Test\n        public void testEvaluateThreeTimes() throws Exception {\n                assertEquals(1, evaluator.eval(\"1\").result);\n                assertEquals(2, evaluator.eval(\"1+1\").result);\n                assertEquals(100, evaluator.eval(\"10*10\").result);\n        }\n\n        @Test\n        public void testEvaluateThreeTimesWithMultipleLineExp() throws Exception {\n                assertEquals(\n                        new LinkedHashMap<Object, Object>() {{\n                                put(\"id\", 1);\n                                put(\"name\", \"cass\");\n                        }},\n                        evaluator.eval(\"\" +\n                                \"[\\n\" +\n                                \"    'id':1\\n\" +\n                                \"    'name':'cass'\\n\" +\n                                \"]\"\n                        ).result);\n                assertEquals(2, evaluator.eval(\"1+1\").result);\n                assertEquals(100, evaluator.eval(\"10*10\").result);\n        }\n\n        @Test\n        public void testEvaluateVariableDef() throws Exception {\n                EvalEntry entry = evaluator.eval(\"i=10*10\");\n                assertEquals(\"i\", entry.name);\n                assertEquals(100, entry.result);\n        }\n\n        @Test\n        public void testEvaluateFieldSet() throws Exception {\n                EvalEntry entry = evaluator.eval(\"i=10*10\");\n                assertEquals(\"i\", entry.name);\n                assertEquals(100, entry.result);\n                assertEquals(2, evaluator.eval(\"i=2\").result);\n                assertEquals(2, evaluator.eval(\"i\").result);\n        }\n\n        @Test\n        public void testEvaluateStmt() throws Exception {\n                EvalEntry entry = evaluator.eval(\"method()=1\");\n                assertNull(entry.name);\n                Object o = entry.result;\n                Method m = o.getClass().getDeclaredMethod(\"method\");\n                assertEquals(1, m.invoke(o));\n        }\n\n        @Test\n        public void testEvaluateMethod() throws Exception {\n                evaluator.eval(\"method()=1\");\n                assertEquals(1, evaluator.eval(\"method()\").result);\n        }\n\n        @Test\n        public void testEvaluateClass() throws Exception {\n                @SuppressWarnings(\"unchecked\")\n                java.util.List<Class<?>> list = (java.util.List<Class<?>>) evaluator.eval(\"class User\").result;\n                assertEquals(1, list.size());\n                assertEquals(\"User\", list.get(0).getName());\n        }\n\n        @Test\n        public void testEvaluateClassAndStmt() throws Exception {\n                Object o = evaluator.eval(\"\" +\n                        \"class User\\n\" +\n                        \"User()\").result;\n                assertEquals(\"User\", o.getClass().getName());\n        }\n\n        @Test\n        public void testPrimitiveCast() throws Exception {\n                Evaluator e = evaluator;\n                // int to short\n                assertEquals((short) 1, e.eval(\"int_short:int=1\\nint_short as short\").result);\n                // int to byte\n                assertEquals((byte) 1, e.eval(\"int_byte:int=1\\nint_byte as byte\").result);\n                // int to char\n                assertEquals('a', e.eval(\"int_char:int=97\\nint_char as char\").result);\n                // int to long\n                assertEquals((long) 1, e.eval(\"int_long:int=1\\nint_long as long\").result);\n                // int to float\n                assertEquals((float) 1, e.eval(\"int_float:int=1\\nint_float as float\").result);\n                // int to double\n                assertEquals((double) 1, e.eval(\"int_double:int=1\\nint_double as double\").result);\n                // int to bool\n                assertEquals(true, e.eval(\"int_bool1:int=1\\nint_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"int_bool2:int=0\\nint_bool2 as bool\").result);\n\n                // short to int\n                assertEquals(1, e.eval(\"short_int:short=1\\nshort_int as int\").result);\n                // short to byte\n                assertEquals((byte) 1, e.eval(\"short_byte:short=1\\nshort_byte as byte\").result);\n                // short to char\n                assertEquals('a', e.eval(\"short_char:short=97\\nshort_char as char\").result);\n                // short to long\n                assertEquals((long) 1, e.eval(\"short_long:short=1\\nshort_long as long\").result);\n                // short to float\n                assertEquals((float) 1, e.eval(\"short_float:short=1\\nshort_float as float\").result);\n                // short to double\n                assertEquals((double) 1, e.eval(\"short_double:short=1\\nshort_double as double\").result);\n                // short to bool\n                assertEquals(true, e.eval(\"short_bool1:short=1\\nshort_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"short_bool2:short=0\\nshort_bool2 as bool\").result);\n\n                // byte to int\n                assertEquals(1, e.eval(\"byte_int:byte=1\\nbyte_int as int\").result);\n                // byte to short\n                assertEquals((short) 1, e.eval(\"byte_short:byte=1\\nbyte_short as short\").result);\n                // byte to char\n                assertEquals('a', e.eval(\"byte_char:byte=97\\nbyte_char as char\").result);\n                // byte to long\n                assertEquals((long) 1, e.eval(\"byte_long:byte=1\\nbyte_long as long\").result);\n                // byte to float\n                assertEquals((float) 1, e.eval(\"byte_float:byte=1\\nbyte_float as float\").result);\n                // byte to double\n                assertEquals((double) 1, e.eval(\"byte_double:byte=1\\nbyte_double as double\").result);\n                // byte to bool\n                assertEquals(true, e.eval(\"byte_bool1:byte=1\\nbyte_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"byte_bool2:byte=0\\nbyte_bool2 as bool\").result);\n\n                // char to int\n                assertEquals(97, e.eval(\"char_int:char='a'\\nchar_int as int\").result);\n                // char to short\n                assertEquals((short) 97, e.eval(\"char_short:char='a'\\nchar_short as short\").result);\n                // char to byte\n                assertEquals((byte) 97, e.eval(\"char_byte:char='a'\\nchar_byte as byte\").result);\n                // char to long\n                assertEquals((long) 97, e.eval(\"char_long:char='a'\\nchar_long as long\").result);\n                // char to float\n                assertEquals((float) 97, e.eval(\"char_float:char='a'\\nchar_float as float\").result);\n                // char to double\n                assertEquals((double) 97, e.eval(\"char_double:char='a'\\nchar_double as double\").result);\n                // char to bool\n                assertEquals(true, e.eval(\"char_bool:char='a'\\nchar_bool as bool\").result);\n\n                // long to int\n                assertEquals(1, e.eval(\"long_int:long=1\\nlong_int as int\").result);\n                // long to short\n                assertEquals((short) 1, e.eval(\"long_short:long=1\\nlong_short as short\").result);\n                // long to byte\n                assertEquals((byte) 1, e.eval(\"long_byte:long=1\\nlong_byte as byte\").result);\n                // long to char\n                assertEquals('a', e.eval(\"long_char:long=97\\nlong_char as char\").result);\n                // long to float\n                assertEquals((float) 1, e.eval(\"long_float:long=1\\nlong_float as float\").result);\n                // long to double\n                assertEquals((double) 1, e.eval(\"long_double:long=1\\nlong_double as double\").result);\n                // long to bool\n                assertEquals(true, e.eval(\"long_bool1:long=1\\nlong_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"long_bool2:long=0\\nlong_bool2 as bool\").result);\n\n                // float to int\n                assertEquals(1, e.eval(\"float_int:float=1\\nfloat_int as int\").result);\n                // float to short\n                assertEquals((short) 1, e.eval(\"float_short:float=1\\nfloat_short as short\").result);\n                // float to byte\n                assertEquals((byte) 1, e.eval(\"float_byte:float=1\\nfloat_byte as byte\").result);\n                // float to char\n                assertEquals('a', e.eval(\"float_char:float=97\\nfloat_char as char\").result);\n                // float to long\n                assertEquals((long) 1, e.eval(\"float_long:float=1\\nfloat_long as long\").result);\n                // float to double\n                assertEquals((double) 1, e.eval(\"float_double:float=1\\nfloat_double as double\").result);\n                // float to bool\n                assertEquals(true, e.eval(\"float_bool1:float=1\\nfloat_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"float_bool2:float=0\\nfloat_bool2 as bool\").result);\n\n                // double to int\n                assertEquals(1, e.eval(\"double_int:double=1\\ndouble_int as int\").result);\n                // double to short\n                assertEquals((short) 1, e.eval(\"double_short:double=1\\ndouble_short as short\").result);\n                // double to byte\n                assertEquals((byte) 1, e.eval(\"double_byte:double=1\\ndouble_byte as byte\").result);\n                // double to char\n                assertEquals('a', e.eval(\"double_char:double=97\\ndouble_char as char\").result);\n                // double to long\n                assertEquals((long) 1, e.eval(\"double_long:double=1\\ndouble_long as long\").result);\n                // double to float\n                assertEquals((float) 1, e.eval(\"double_float:double=1\\ndouble_float as float\").result);\n                // double to bool\n                assertEquals(true, e.eval(\"double_bool1:double=1\\ndouble_bool1 as bool\").result);\n                assertEquals(false, e.eval(\"double_bool2:double=0\\ndouble_bool2 as bool\").result);\n\n                // bool cannot be number or char\n        }\n\n        @Test\n        public void testJavaInteroperable() throws Exception {\n                List<Integer> list = new ArrayList<Integer>();\n                list.add(4);\n                list.add(3);\n                list.add(5);\n                evaluator.setScannerType(Config.SCANNER_TYPE_BRACE);\n                evaluator.put(\"list\", list);\n                EvalEntry entry = evaluator.eval(\"\" +\n                        \"import java::util::Collections._\\n\" +\n                        \"list2:List = list\\n\" +\n                        \"sort(list2)\\n\" +\n                        \"list\");\n                List newList = (List) entry.result;\n                assertEquals(Arrays.asList(3, 4, 5), newList);\n        }\n\n        @Test\n        public void testObject() throws Exception {\n                evaluator.eval(\"\" +\n                        \"object O\");\n                Object o = evaluator.eval(\"O\").result;\n                assertEquals(\"O\", o.getClass().getName());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/TestGenericInREPL.java",
    "content": "package lt.repl;\n\nimport lt.compiler.util.Consts;\nimport lt.lang.GenericTemplate;\nimport lt.repl.scripting.EvalEntry;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport java.util.Arrays;\nimport java.util.List;\n\nimport static org.junit.Assert.*;\n\npublic class TestGenericInREPL {\n        Evaluator evaluator;\n\n        @Before\n        public void setUp() throws Exception {\n                evaluator = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n        }\n\n        @SuppressWarnings(\"unchecked\")\n        @Test\n        public void testGetGenericASTFromCompiledClasses() throws Exception {\n                for (String x : Arrays.asList(\"class\", \"interface\", \"object\")) {\n                        evaluator = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\n\n                        EvalEntry entry = evaluator.eval(\"\" +\n                                x + \" A<:T:>\");\n                        List<Class<?>> definedClasses = (List<Class<?>>) entry.result;\n                        assertEquals(1, definedClasses.size());\n                        Class<?> templateA = definedClasses.get(0);\n                        assertEquals(\"A\", templateA.getName());\n                        assertTrue(templateA.isAnnotationPresent(GenericTemplate.class));\n\n                        assertTrue(templateA.getField(Consts.AST_FIELD).get(null) instanceof String);\n\n                        entry = evaluator.eval(\"\" +\n                                \"type A<:int:>\");\n                        Class<?> typeA = (Class<?>) entry.result;\n                        assertEquals(\"A\" + Consts.GENERIC_NAME_SPLIT + \"int\", typeA.getName());\n\n                        if (x.equals(\"class\")) {\n                                assertTrue(typeA.toString().startsWith(\"class\"));\n                        } else if (x.equals(\"interface\")) {\n                                assertTrue(typeA.isInterface());\n                        } else /* if (x.equals(\"object\") */ {\n                                assertTrue(typeA.toString().startsWith(\"class\"));\n                        }\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/TestJsr223.java",
    "content": "package lt.repl;\n\nimport lt.compiler.LineCol;\nimport lt.compiler.syntactic.AST;\nimport lt.compiler.syntactic.Statement;\nimport lt.compiler.syntactic.def.MethodDef;\nimport lt.compiler.syntactic.def.VariableDef;\nimport lt.compiler.syntactic.literal.NumberLiteral;\nimport lt.compiler.syntactic.pre.Modifier;\nimport lt.repl.scripting.CL;\nimport lt.repl.scripting.LatteEngine;\nimport lt.repl.scripting.LatteEngineFactory;\nimport lt.repl.scripting.LatteScope;\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport javax.script.ScriptContext;\nimport javax.script.ScriptEngineManager;\n\nimport java.util.Collections;\nimport java.util.List;\n\nimport static org.junit.Assert.*;\n\n/**\n * test scripting\n */\npublic class TestJsr223 {\n        private LatteEngineFactory factory;\n        private LatteEngine engine;\n        private LatteScope engineScope;\n\n        @Before\n        public void setUp() throws Exception {\n                factory = new LatteEngineFactory();\n                engine = (LatteEngine) new ScriptEngineManager().getEngineByName(\"Latte-lang\");\n                engineScope = (LatteScope) engine.getBindings(ScriptContext.ENGINE_SCOPE);\n        }\n\n        @Test\n        public void testFactoryGetPrintStatement() throws Exception {\n                String res = factory.getOutputStatement(\"hello world\");\n                assertEquals(\"println(\\\"hello world\\\")\", res);\n                res = factory.getOutputStatement(\"\\\"\");\n                assertEquals(\"println(\\\"\\\\\\\"\\\")\", res);\n        }\n\n        @Test\n        public void testFactoryGetMethodInvocation() throws Exception {\n                String res = factory.getMethodCallSyntax(\"a\", \"m\", \"arg1\", \"arg2\");\n                assertEquals(\"a.`m`(arg1,arg2)\", res);\n        }\n\n        @Test\n        public void testScopeAfterEvalNonAssignmentExp() throws Exception {\n                assertEquals(0, engineScope.size());\n                assertEquals(4, engine.eval(\"1 + 3\"));\n                assertEquals(4, engineScope.size());\n                assertEquals(Collections.emptyList(), engineScope.get(\"$latte.scripting.imports\"));\n                assertTrue(engineScope.get(\"$latte.scripting.CL\") instanceof CL);\n                assertEquals(Collections.emptyList(), engineScope.get(\"$latte.scripting.methods\"));\n                assertEquals(0, engineScope.get(\"$latte.scripting.res_count\"));\n        }\n\n        @Test\n        public void testScopeAfterEvalAssignment() throws Exception {\n                assertEquals(4, engine.eval(\"a = 1 + 3\"));\n                assertNull(engineScope.get(\"$latte.scripting.res_count\"));\n                assertEquals(4, engineScope.get(\"a\"));\n        }\n\n        @Test\n        public void testScopeAfterMethodDef() throws Exception {\n                assertNull(engine.eval(\"def method = 1\"));\n                @SuppressWarnings(\"unchecked\")\n                List<MethodDef> methods = (List<MethodDef>) engineScope.get(\"$latte.scripting.methods\");\n                assertEquals(1, methods.size());\n                MethodDef methodDef = methods.get(0);\n                assertEquals(new MethodDef(\"method\", Collections.singleton(new Modifier(Modifier.Available.DEF, LineCol.SYNTHETIC)),\n                        null, Collections.<VariableDef>emptyList(), Collections.<AST.Anno>emptySet(),\n                        Collections.<Statement>singletonList(new AST.Return(new NumberLiteral(\"1\", LineCol.SYNTHETIC), LineCol.SYNTHETIC)),\n                        LineCol.SYNTHETIC), methodDef);\n        }\n\n        @Test\n        public void testBindings() throws Exception {\n                Object a = engineScope.putNew(\"a\", 1, int.class);\n                assertNull(a);\n                assertEquals(1, engineScope.get(\"a\"));\n                try {\n                        engineScope.put(\"a\", 2.1);\n                        fail();\n                } catch (IllegalArgumentException ignore) {\n                        try {\n                                engineScope.put(\"a\", null);\n                                fail();\n                        } catch (NullPointerException ignore2) {\n                        }\n                }\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/TestScript.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.repl;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * script\n */\npublic class TestScript {\n        ScriptCompiler scriptCompiler;\n\n        @Before\n        public void setUp() throws Exception {\n                scriptCompiler = new ScriptCompiler(ClassLoader.getSystemClassLoader());\n        }\n\n        @Test\n        public void testSimpleScript() throws Throwable {\n                ScriptCompiler.Script script = scriptCompiler.compile(\"script\", \"return 1\");\n                assertEquals(1, script.run().getResult());\n        }\n\n        @Test\n        public void testScriptArgs() throws Throwable {\n                ScriptCompiler.Script script = scriptCompiler.compile(\"script\", \"return args\");\n                assertArrayEquals(new String[0], (Object[]) script.run().getResult());\n                String[] args = new String[]{\"a\", \"b\", \"c\"};\n                assertArrayEquals(args, (Object[]) script.run(args).getResult());\n        }\n\n        @Test\n        public void testInternalLambdaBug() throws Throwable {\n                String code = \"\" +\n                        \"[1, 2, 3, 4].\\n\" +\n                        \"filter {it > 2}.\\n\" +\n                        \"map {it + 1}\\n\" +\n                        \"\\n\" +\n                        \"a = 1\\n\" +\n                        \"b = 2\\n\" +\n                        \"val result = (if a>b {1} else {2})\\n\" +\n                        \"return result\";\n                assertEquals(2, scriptCompiler.compile(\"testInternalLambdaBug\", code).run().getResult());\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/lt/repl/VariableTest.java",
    "content": "package lt.repl;\n\nimport org.junit.Before;\nimport org.junit.Test;\n\nimport static org.junit.Assert.*;\n\n/**\n * tests for pointers\n */\npublic class VariableTest {\n        Evaluator evaluator;\n\n        @Before\n        public void setUp() throws Exception {\n                evaluator = new Evaluator(new ClassPathLoader(ClassLoader.getSystemClassLoader()));\n\n        }\n\n        @Test\n        public void testInvoke() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"def method()\\n\" +\n                        \"    i:lt::lang::function::Function0=()->1\\n\" +\n                        \"    return i()\\n\" +\n                        \"method()\"\n                ).result;\n                assertEquals(1, result);\n        }\n\n        @Test\n        public void testAccessField() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"class X(public num)\\n\" +\n                        \"def method()\\n\" +\n                        \"    i:X = X(1)\\n\" +\n                        \"    return i.num\\n\" +\n                        \"method()\"\n                ).result;\n                assertEquals(1, result);\n        }\n\n        @Test\n        public void testAccessMethod() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"data class X(num)\\n\" +\n                        \"def method()\\n\" +\n                        \"    i:X = X(1)\\n\" +\n                        \"    return i.num\\n\" +\n                        \"method()\"\n                ).result;\n                assertEquals(1, result);\n        }\n\n        @Test\n        public void testLambdaChangeValue() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"def method()\\n\" +\n                        \"    i:int = 1\\n\" +\n                        \"    f=()->\\n\" +\n                        \"        i=2\\n\" +\n                        \"    f()\\n\" +\n                        \"    return i\\n\" +\n                        \"method()\").result;\n                assertEquals(2, result);\n        }\n\n        @Test\n        public void testLambdaGetValue() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"def method()\\n\" +\n                        \"    i:int = 1\\n\" +\n                        \"    return (()->i)()\\n\" +\n                        \"method()\"\n                ).result;\n                assertEquals(1, result);\n        }\n\n        @Test\n        public void testArrayPointer() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"def method()\\n\" +\n                        \"    i:[]int = [1,2]\\n\" +\n                        \"    return i[0]\\n\" +\n                        \"method()\").result;\n                assertEquals(1, result);\n        }\n\n        @Test\n        public void test2dArrayPointer() throws Exception {\n                Object result = evaluator.eval(\"\" +\n                        \"def method()\\n\" +\n                        \"    i:[][]int = [[1,2],[3,4]]\\n\" +\n                        \"    return i[1, 0]\\n\" +\n                        \"method()\").result;\n                assertEquals(3, result);\n        }\n}\n"
  },
  {
    "path": "latte-compiler/src/test/java/suite/Suite.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage suite;\n\nimport junit.framework.TestSuite;\nimport lt.compiler.cases.*;\nimport lt.compiler.err_rec.TestParserErrorRecovery;\nimport lt.compiler.err_rec.TestScannerErrorRecovery;\nimport lt.compiler.err_rec.TestSemanticError;\nimport lt.generator.TestJsSupport;\nimport lt.repl.*;\nimport org.junit.runner.RunWith;\n\n/**\n * test suite\n */\n@RunWith(org.junit.runners.Suite.class)\n@org.junit.runners.Suite.SuiteClasses({\n        TestScanner.class,\n        TestParser.class,\n        TestParserMix.class,\n        TestSemantic.class,\n        TestCodeGen.class,\n        TestLang.class,\n        TestDemo.class,\n        TestEvaluator.class,\n        TestBugsInEval.class,\n        TestScannerErrorRecovery.class,\n        TestParserErrorRecovery.class,\n        TestScript.class,\n        TestAnnotations.class,\n        TestJsSupport.class,\n        TestBraceScanner.class,\n        TestScannerSwitcher.class,\n        VariableTest.class,\n        TestScannerLayerControl.class,\n        TestSemanticError.class,\n        TestSynchronized.class,\n        TestPrimitiveOperators.class,\n        TestDefineAnnotations.class,\n        TestJsr223.class,\n        TestDotPackage.class,\n        TestLambdaGen.class,\n        TestGenericInREPL.class\n})\npublic class Suite extends TestSuite {\n}\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/advanced.lt",
    "content": "// advanced features in Latte\n// ============\n// inner method\n// ============\nclass TestInnerMethod\n    def outer()\n        def inner()  // a method defined inside another is `inner method`\n            return 1\n        return inner() // invoke inner method\n// inner methods are private and can only be accessed in the current scope\n// the inner method generates a new private method inside the class,\n// the method name is automatically generated and there's rare chance you would\n// invoke the generated method directly instead of invoking by inner method name\n\n// the inner method have several limitations\n// 1. parameters of inner methods don't have default values\n// 2. inner methods don't have annotations and modifiers\n// 3. inner method cannot be overwritten\n\n// Note That, the inner method can capture local variables,\n// and can change the values `inside` the inner method,\n// but it won't have effect on the outer method variables\n\n// =========\n// procedure\n// =========\nclass TestProcedure\n    def method()\n        return (return 1) // the procedure is surrounded by (),\n              // and there should be at least one statement\n              // or more than one expression in the procedure\n// the procedure allow you to write code anywhere\n// e.g.\n// in java, we use boolValue?exp1:exp2, in Latte, we can use\n// (   if boolValue\n//         return exp1\n//     else\n//         return exp2)\n// the procedure itself is considered as a Value\n// so it can be filled into any position that requires a value\n\n// the procedure is based on inner method\n// it simply creates an inner method with no parameters and invokes it\n\n// ======\n// lambda\n// ======\n// java supports lambda for FunctionalInterfaces\n// Latte not only supports that, but also supports `FunctionalAbstractClasses`\n// a FunctionalAbstractClass means An abstract class with only one unimplemented\n// method and it has a public constructor with no parameters\n// e.g.\n@FunctionalAbstractClass\nabstract class Func\n    abstract apply(o)=...\n// Func is a FunctionalAbstractClass\n// (o)->... creates a subclass\n// and overrides `apply(o)`\n\n// here's how to use\nclass TestLambda\n    public func1:Func=(o)->o+1 // creates an instance of Func and it adds o with 1\n    public func2:lt::lang::function::Function1=(o)->o+1 // specify the type\n    public func3=(o)->o+1      // implicitly use lt::lang::function::Function1\n    // the type of the lambda is lt::lang::function::Function1\n    // there are 27 functions from Function0 to Function26\n    // taking parameters whose sizes range from 0 to 26\n// lambda is based on inner method\n// it creates an inner method and retreive MethodHandle of the method\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/examples/rational.lt",
    "content": "package lt::demo::examples\n\nclass Rational(n:int, d:int=1)\n    if d is 0\n        throw IllegalArgumentException(\"divider cannot be 0\")\n\n    neg= n * d < 0\n    n=Math.abs(n)\n    d=Math.abs(d)\n    g=gcd(n,d)\n    n/=g\n    d/=g\n\n    if neg\n        n=-n\n\n    toString():String = n + (\n        if d==1\n            return \"\"\n        return \"/\" + d)\n\n    equals(o):bool\n        if o is type Rational\n            return o.n==n and o.d==d\n        else\n            return false\n\n    hashCode():int\n        return n+d\n\n    add(o:Rational):Rational = Rational(n*o.d+o.n*d, d*o.d)\n    subtract(o:Rational):Rational = Rational(n*o.d-o.n*d, d*o.d)\n    multiply(o:Rational):Rational = Rational(n*o.n, d*o.d)\n    divide(o:Rational):Rational = Rational(n*o.d, d*o.n)\n\n    static\n        private gcd(a:int, b:int)\n            if b\n                return gcd(b, a % b)\n            else\n                return a\n\nclass TestRational\n    static\n        testAdd(a:Rational, b:Rational)=a + b\n        testSubtract(a:Rational, b:Rational)=a - b\n        testMultiply(a:Rational, b:Rational)=a * b\n        testDivide(a:Rational, b:Rational)=a / b\n        testEquals(a:Rational, b:Rational)= a==b\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/fun.lt",
    "content": "class std\n    static\n        cout:Cout=Cout()\n        endl:String=\"\\n\"\n\nclass Cout\n    shiftLeft(o):Cout\n        System.out.print(o)\n        return this\n\nclass TestStdCout\n    std.cout<<\"a\"<<1<<2<<java::util::Collections.singletonList(1)<<std.endl<<\n    \"b\"\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/list-map.lts",
    "content": "// a demo about how collection works\n\n/*\n * =================\n *       List\n * =================\n */\n\n// JSON Literal\nls = [\"z\",\"y\",\"x\"] // the list is [z,y,x]\n// empty list\nlist = LinkedList()\n\n// add\nlist.add(\"a\")\nlist + \"b\"         // operator binding (add)\n\n// concat\n// concat will NOT modify the current list\nconcatRes = list.concat(\"c\")\nconcatRes = concatRes:::\"d\"   // operator binding (concat)\nconcatRes = list.concat(ls)\n// concatRes is [a,b,z,y,x]\n\n// addAll\nlist.addAll([\"w\",\"v\",\"u\"])\n\n// build a string\nstr = list.join(\",\")\n// str is \"a,b,w,v,u\"\n\n// reverse() DO modifies and returns the list itself\nstr2 = list.reverse().join(\",\")\n// str2 is \"u,v,w,b,a\"\n\nlist2 = LinkedList(list)\nshiftResult = list2.shift()\n// the result is u\n// and list2 will be [v,w,b,a]\n\nsliceResult1 = list2.slice(1,3)\n// the result is [w,b]\n\nsliceResult2 = list2.slice(1)\n// the result is [w,b,a]\n\nlist2.unshift(\"t\")\n// list2 is [t,v,w,b,a]\nlist2.unshift([\"r\",\"s\"])\n// list2 is [r,s,t,v,w,b,a]\n\nlengthResult = list2.length\n// (length is not a field, it's a method with 0 parameters.)\n// length is 7\n\n/*\n * =================\n *        Map\n * =================\n */\n\n// Json Literal\nm = [\n    \"a\" : 1\n    \"b\" : 2\n]             // the map is {a:1, b:2}\n// empty map\nmap = LinkedHashMap()\n\n// put\nmap.put(\"c\",3)\nmap[\"d\"] = 4\n// the map is {c:3, d:4}\n\n// construct a map filled with existing map entries\nmap2 = LinkedHashMap(m)\nmap2.putAll(map)\n// map2 is {a:1, b:2, c:3, d:4}\n\n// get\na_res = map2.get(\"a\")    // a_res is 1\nb_res = map2[\"b\"]        // b_res is 2\nc_res = map2.c           // c_res is 3\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/literals.lts",
    "content": "// there are 5 kinds of literals in Latte\n// string number map array bool regex\n\n// string\ni_am_string = 'a string'\nor_in_this_form = \"also a string\"\n\n// number\ni_am_a_number = 1\nor_float_number = 1.2\n\n// map\njson = [\n    'a':'b'\n]\n// comma at the end can be omitted\n// map literal would be parsed into lt::util::Map\n\n// array\nlist = [1,2,3]\n// array literal can be array or list (lt::util::List)\n\n// bool values could be the following\ni_am_bool : bool = true\ni_am_bool_too : bool = yes\ni_am_bool_false : bool = false\ni_am_also_bool_false : bool = no\n\n// string literal can be java.lang.String or char\ni_am_char : char = 'c'\ni_am_String : String = 'i am a java.lang.String'\n\n// number literal can be int double float long short byte or char\ni_am_int : int = 1\ni_am_double : double = 1.2\ni_am_float : float = 1\ni_am_long : long = 1\ni_am_short : short = 1\ni_am_byte : byte = 1\n// note that float number cannot be parsed into integers, which could result in a compiling error\n\n// eight java primitives still exist in Latte\n// implicit cast would be performed during both compiling and runtime\n// so there's rarely any difference between primitive and boxing types\n\n// note that the type of literal depends on \"required type\"\n// e.g.\nthis_var_is_int : int = 1 // 1 is int\nthis_var_is_short : short = 1 // 1 is short\nthis_var_is_Integer = 1 // actually it invokes Integer.valueOf(1), but the literal means int 1\n\n// sometimes there's no required type, then the literals will be parsed into their \"default type\"\n// e.g.\ndefault_value_of_number = 1 // int (and invokes Integer.valueOf(1))\ndefault_value_of_float_number = 1.2 // double (and invokes Double.valueOf(1.2))\ndefault_value_of_char_string = 'c' // char (and invokes Character.valueOf('c'))\ndefault_value_of_string_1 = \"s\" // java.lang.String\ndefault_value_of_string_2 = 'length is greater than 1' // java.lang.String\ndefault_value_of_string_3 = '' // java.lang.String (length is 0)\n// this is easily understood, if 'c', the length is 1, it would likely to be char\n// but with 0 length or length greater than 1, it can never be char, then it would be considered as String\n// if want to construct a string with length==1, use \"s\"\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/ltFileStructure.lt",
    "content": "// the code starts with namespace declare\npackage lt::demo\n/*\ndeclares that the whole file is in namespace \"lt::demo\"\nnamespaces are java packages\nnamespaces can only appear once, and must at the first effective line of the file\n(lines containing only comments or defines or undefs are not effective lines)\nNOTE THAT scripts cannot have package declaration\n*/\n\n// if there's no declaration of the namespace, the namespace would be \"\"\n\n// then, there can be import commands\nimport java::awt::_               // import all types from java::awt\nimport java::util::List           // import java::util::List\nimport java::util::Collections._  // import all static fields and methods from java::util::Collections\n// there can be 0 or 1 or more imports\n// and \"import\" can appear in any position in the root of the code part\n\n/*\nLatte allows class and interface definition\nif the file is *.lts, the rest part can be type definitions, statements or expressions\nyou can see \"statements.lts\" for more details\nif the file is *.lt, the rest part in root of code can only hold type definitions\nyou can see \"typeDef.lt\" for more details\n*/\nclass I_Am_A_Class\n    /*\n    ; Class Constructing Block\n    ; you can define variables and methods\n    */\n    i_am_field : int          // defines a variable\n    // varialbes in class constructing blocks are considered as Fields in java\n    list : List               // another field\n    // the import checks full name first\n    // so, List matches java::util::List instead of java::awt::List\n\n    i_am_a_method():List      // defines a method\n        // method block\n        // variables in method block are local variables\n        list=emptyList()      // invoke java::util::Collections.emptyList()\n        // and assign to field `list`\n        return list\n\ninterface I_Am_An_Interface\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/operator.lt",
    "content": "/*\nLatte supports operator binding\ne.g. + is bond to add(?)\na + b can be considered as a.add(b)\n\nhere's all operators supported in Latte\n*/\nclass Num(public i)\n    equals(o):bool             // override equals(o)\n        if o is null\n            return false\n        elseif o is type Num\n            return this.i==o.i\n        else\n            return false\n\n    add(o)=Num(i+o)            // bind +\n    subtract(o)=Num(i-o)       // bind -\n    multiply(o)=Num(i*o)       // bind *\n    divide(o)=Num(i/o)         // bind /\n    remainder(o)=Num(i%o)      // bind %\n    shiftLeft(o)=Num(i<<o)     // bind <<\n    shiftRight(o)=Num(i>>o)    // bind >>\n    unsignedShiftRight(o)=Num(i>>>o)// bind >>>\n    eq(o)=i==o                 // bind ==\n    ne(o)=i!=o                 // bind !=\n    def contains(o)            // bind (this in o)\n        throw UnsupportedOperationException('contains')\n    gt(o)=i>o                  // bind >\n    ge(o)=i>=o                 // bind >=\n    lt(o)=i<o                  // bind <\n    le(o)=i<=o                 // bind <=\n    `and`(o)=Num(i&o)          // bind &\n    xor(o)=Num(i^o)            // bind ^\n    `or`(o)=Num(i|o)           // bind |\n    def logicNot()             // bind unary !\n        throw UnsupportedOperationException('logicNot')\n    `not`()=Num(~i)            // bind ~\n    negate()=Num(-i)           // bind -\n    def concat(o)                  // bind :::\n        throw UnsupportedOperationException('concat')\n\n    toString():String=\"Num(\"+i+\")\"\n\nclass TestNum\n    static\n        testAdd()=Num(1)+1           // should be Num(2)\n        testSubtract()=Num(1)-2      // should be Num(-1)\n        testMultiply()=Num(3)*4      // should be Num(12)\n        testDivide()=Num(10)/2       // should be Num(5)\n        testRemainder()=Num(12)%5    // should be Num(2)\n        testShiftLeft()=Num(1)<<2    // should be Num(4)\n        testShiftRight()=Num(4)>>2   // should be Num(1)\n        testUnsignedShiftRight()=Num(8)>>>2 // should be Num(2)\n        testEqual()=Num(1)==1        // should be true\n        testNotEqual()=Num(1)!=2     // should be true\n        testEquals()=Num(1) is Num(1)// should be true\n        testContains()=1 in Num(1)   // should throw exception\n        testGt()=Num(1)>0            // should be true\n        testGe()=Num(1)>=1           // should be true\n        testLt()=Num(1)<2            // should be true\n        testLe()=Num(1)<=1           // should be true\n        testAnd()=Num(1) & 2         // should be Num(0)  (01 & 10)\n        testXor()=Num(1) ^ 2         // should be Num(3)  (01 ^ 10)\n        testOr()=Num(1) | 2          // should be Num(3)  (01 | 10)\n        testLogicNot()=!Num(1)       // should throw exception\n        testNot()=~Num(1)            // should be Num(-2)\n        testNegate()=-Num(1)         // should be Num(-1)\n        testConcat()=Num(1):::Num(2) // should throw exception\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/statements.lts",
    "content": "// Latte have the following statements\n\n// 1.flow control\n\n// ===\n// for\n// ===\n// for [variable] in [iterator/iterable/array/enumeration]\narr=[1,2,3]\nres0=0\nfor i in arr\n    res0 += i\n// res0 is 6\n\n// =====\n// while\n// =====\n// while [expression]\nres1=0\nindex=0\nwhile index<arr.size()\n    res1 += arr[index++]\n// res1 is 6\n\n// 2.logic branch\n// ==\n// if\n// ==\n/*\n if [expression]\n     ...\n elseif [expression]\n     ...\n else\n     ...\n*/\ndef method_if_elseif_else(a,b)\n    if a\n        return 1\n    elseif b\n        return 2\n    else\n        return 3\n\n// 3.exceptions\n// =================\n// try-catch-finally\n// =================\n/*\n try\n     ...\n catch [exVar]\n     ...\n finally\n     ...\n*/\ndef method_try_catch_finally(func)\n    a=0\n    try\n        func.apply()\n        a=1\n    catch e\n        if e is type RuntimeException\n            a=2\n        elseif e is type Error or e is type Exception\n            a=3\n        elseif e is type Throwable\n            a=4\n    finally\n        ++a\n    return a\n// Latte can throw and catch any type. e.g. (throw \"error-message\")\n// As a result, Latte doesn't provide 'catch type', use if-else instead.\n\n// =====\n// throw\n// =====\nres2=null\ntry\n    throw 'abc'\ncatch e\n    res2=e // res2 should be 'abc'\n// throw and catch anything!\n\n// 4.synchronized\n// sync(a,b,c)\n//     ...\n\n// 5.basic grammar\n// ===================\n// variable definition\n// ===================\nvariable1 = 1            // type is java.lang.Object, and initialize with 1\nvariable2 : int = 1      // type is int, and initialize with 1\nvariable3 : int          // type is int, with no initialize expression\n// the variable without init expression would be automatically assigned with 0 or (char)0 or false or null\n// in method block, variables are parsed as local variable\n// it cannnot be uninitialized\n\n// =================\n// method invocation\n// =================\nres3=method_if_elseif_else(true,false)\n// according to the method definition\n// res3 is 1\n\n// ==================\n// invoke constructor\n// ==================\nres4 = Object()\n// Latte doesn't require `new` when constructing objects.\n\n// ===\n// DSL\n// ===\n// a op b\n// a op\nlist1=java::util::ArrayList()\nlist1 add 1\n// same as list.add(1)\n\nlist2=java::util::ArrayList()\nlist2 add 1\nlist2 clear\n// same as list.clear()\n\n// note that the operation priority is like this:\n\n/*\na op b op c op d op\n==>\nit will be parsed into\na.op(b).op(c).op(d).op()\n\nso the priority should be:\n(((a op b) op c) op d) op\n\nand all \"operator like invocation\" priorities are the same, and are lower than any two variable operator's\n*/\n\n// =========\n// get field\n// =========\nres5 = null\ntry\n    res5 = this.list1  // get this.list\ncatch err\n    ...\n// if field not found, it invokes lt::lang::Lang.getField(o,fieldname,callerClass) to get field\n// an exception would be thrown is still not found, which gives details about why it's not found.\n\n// ============\n// index access\n// ============\nlist3=[1,2,3]\nres6 = list3[0]    // get element in an array or invoke get(?) on the object\n// arr[?] ==> arr.get(?)\n// inside [] can contain 0, 1 or more arguments\n\nlist3[0]=2  // set the element value to 2 (for array, set the element value, otherwise invoke set(?1,?2) or put(?1,?2))\n// arr[?1]=?2 ==> arr.set(?1,?2)\n// ?2 can only be one expression, ?1 can be 0, 1 or more expressions\n// if set(?) method not found, the runtime would try to invoke put(?)\n\n// e.g.\nmap={}\nmap[\"a\"]=\"b\"\n"
  },
  {
    "path": "latte-compiler/src/test/resources/lang-demo/typeDef.lt",
    "content": "// Latte allows class and interface definition\nclass I_Am_A_Class\n\n// a class can have constructor parameters\nclass I_Have_Params(\n    // the param is a variable definition\n    param1:int    // an int param\n    // or simply a name\n    param2        // it's java.lang.Object\n)\n\n// you can write params in the same line\nclass I_Have_Params_too(param1:int, param2)\n\n// a class can have one and only one parent class\nclass I_Have_Parent : I_Am_A_Class\n// if parent not presented, it's considered as inheriting java.lang.Object\n\n// the parent class can be initialized with constructor arguments\nclass I_Have_Parent_And_Parent_Have_Args : I_Have_Params(1, \"2\")\n\n// a class can have 0 or 1 or more super interfaces\nabstract class I_Have_Interfaces : java::util::List, java::io::Serializable\n\n// a class can have both parent class and super interfaces\nabstract class I_Have_Both_Class_And_Interface : I_Am_A_Class, java::util::List\n\n// you can notice that, I_Have_Interfaces and I_Have_Both_Class_And_Interface\n// are modified with \"abs\" modifier\n// so a class can have modifiers\n\n// the avaliable modifiers are the same as java language\n// hoever, all types defined in Latte are \"public\"\n// the access level modifiers on class is considered as constructor modifier\nprivate class My_Constructor_Is_Private_But_Type_Is_Still_Public\n\n// a class can have fields\nclass I_Have_Fields\n    i_am_field:int\n    i_am_a_field_with_init_value=\"init value\"\n\n// a class can have method definitions\nclass I_Have_Methods\n    // a method definition can be:\n\n    // method with java.lang.Object return type\n    def i_am_a_simple_method()\n        ...   // statements in the method\n\n    // you can specify the return type\n    // return type can be any type or void/Unit (both void and Unit are valid in Latte)\n    i_am_a_method_with_return_type_spec():Unit\n\n    // you can write a method that's only one statement in this form\n    i_am_a_method_with_only_one_statement()=\"this object will be returned\"\n    // or with type\n    i_am_a_method_with_only_one_statement_with_return_type():String=\"this string will be returned\"\n    // a method with no statements :\n    i_am_a_method_with_no_statements()=...\n    // however it looks like \"i_am_a_simple_method\", but \"i_am_a_simple_method\" have one statement \"pass\"\n    // this method have 0 statements\n\n    // method can have parameters\n    // but note that, the basic form must be a method definition\n    i_have_parameters(param)=...\n\n// a class can have statements in constructing block\nclass I_Have_Statements\n    list=java::util::ArrayList()\n    list.add(1)\n// when instantiate a class, the statements in this block would be invoked\n\n// a class can have static fields, methods and statements\nclass I_Have_Static\n    static\n        field:int\n        method():Unit\n        list=java::util::ArrayList()\n        list + 1\n    // the static can start a new layer\n    // also, it can be followed by any statement\n    static field2:int\n    static method2():Unit\n    static list + 2\n\n// data class\ndata class DataClass\n// the data class generates Getters/Setters/toString/equals/hashCode/0-param-constructor automatically\n// it's used to create Java Beans\n\ndata class DataClassWithFields(id, name)\n// it's the same as the following Java Code:\n/*\n    public class DataClassWithFields {\n        private Object id;\n        private Object name;\n        // constructor\n        public DataClassWithFields(){}\n        public DataClassWithFields(Object id,Object name) {\n            this.id=id;\n            this.name=name;\n        }\n        // getters and setters\n        public Object getId(){return id;}\n        public Object getName(){return name;}\n        public void setId(Object id){this.id=id;}\n        public void setName(Object name){this.name=name;}\n        // toString\n        public String toString(){return \"DataClassWithFields(id=\"+id+\",name=\"+name+\")\";}\n        // hashCode\n        public int hashCode(){return (id==null?0:id.hashCode()) + (name==null?0:name.hashCode());}\n        // equals\n        public boolean equals(Object o){\n            if(o instanceof DataClassWithFields){\n                DataClassWithFields that=(DataClassWithFields)o;\n                return LtRuntime.is(that.id, this.id) && LtRuntime.is(that.name,this.name);\n            }else return false;\n        }\n    }\n*/\n\n// a data class can have methods\ndata class DataClassWithMethods\n    i_am_a_method_in_data_class()=\"1\"\n\n// interface definition\ninterface I_Am_An_Interface\n\n// interfaces can have fields\n// the fields are public static final\ninterface Interface_Have_Fields\n    field : int = 1\n\n// interfaces can have methods\ninterface Interface_Have_Methods\n    // method with 0 statements are considered as abstract methods\n    i_am_an_abstract_method()=...\n\nclass TesterForInterface_Have_Methods : Interface_Have_Methods\n    i_am_an_abstract_method()=\"abs method impl\"\n\n// interfaces do NOT have initialize statements\n\n// function definition\n// functions can implement functional interfaces or extend functional abstract classes\n// a function that implements lt::lang::function::Function0 and returns 1\n// if the type is lt::lang::function::FunctionX, the runtime is able to transform\n// its type into required type.\nfun I_Am_A_Function\n    return 1\n\n// a function with parameters\nfun I_Am_A_Function_With_One_Param(e)\n    return e - 1\n\n// a function specifies its super type\nfun I_Am_A_Function_With_Super_Type(o) : lt::lang::function::Function1\n    return o+1\n"
  },
  {
    "path": "latte-compiler/src/test/resources/test_require.lts",
    "content": "return 1+1"
  },
  {
    "path": "latte-compiler/src/test/resources/test_require2.lts",
    "content": "return Object()"
  },
  {
    "path": "latte-gradle-plugin/.gitignore",
    "content": ".idea/*\n.gradle/*\nbuild/*\n*.ipr\n*.iws\n"
  },
  {
    "path": "latte-gradle-plugin/build.gradle",
    "content": "def VERSION_FILE = file('../latte-build/src/main/resources/version')\nBufferedReader br = new BufferedReader(new FileReader(VERSION_FILE))\ndef VERSION = br.readLine().trim()\nbr.close()\n\ndef ACTION = System.getenv(\"BUILD_ACTION\")\n\ngroup 'org.latte-lang'\nversion VERSION\n\napply plugin: 'groovy'\napply plugin: 'idea'\napply plugin: 'maven'\nif ('deploy' == ACTION) {\n    apply plugin: 'signing'\n}\napply plugin: LatteBuild\n\ncompileJava {\n    sourceCompatibility = 1.6\n    targetCompatibility = 1.6\n}\n\ncompileGroovy {\n    sourceCompatibility = 1.6\n    targetCompatibility = 1.6\n    options.encoding = \"UTF-8\"\n}\n\nrepositories {\n    mavenLocal()\n}\n\ndependencies {\n    compile group: 'org.latte-lang', name: 'latte-compiler', version: VERSION\n    compile gradleApi()\n    compile localGroovy()\n}\n\nuploadArchives {\n    repositories {\n        mavenDeployer {\n            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n            def deploy_user = System.getenv('DEPLOY_USER')\n            def deploy_pass = System.getenv('DEPLOY_PASS')\n\n            repository(url: \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\") {\n                authentication(userName: deploy_user, password: deploy_pass)\n            }\n\n            pom.project {\n                name 'latte-gradle-plugin'\n                packaging 'jar'\n                description 'The latte-lang gradle plugin, which helps compile latte sources in a gradle project.'\n                url 'http://latte-lang.org'\n                scm {\n                    url 'https://github.com/wkgcass/Latte-lang'\n                    connection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                    developerConnection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                }\n                licenses {\n                    license {\n                        name 'MIT LICENSE'\n                        url 'https://github.com/wkgcass/Latte-lang/blob/master/LICENSE/'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'wkgcass'\n                        email 'wkgcass@hotmail.com'\n                    }\n                }\n            }\n        }\n    }\n}\n\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    classifier = 'sources'\n    from sourceSets.main.allSource\n}\n\nartifacts {\n    archives jar\n    archives javadocJar\n    archives sourcesJar\n}\n\njavadoc {\n    options {\n        encoding 'UTF-8'\n        charSet 'UTF-8'\n    }\n}\n\nif ('deploy' == ACTION) {\n    signing {\n        sign configurations.archives\n    }\n}\n\nclass LatteBuild implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def latteBuild = project.task('latteBuild')\n        latteBuild.dependsOn project.tasks['install']\n\n        project.task('latteTest') // do nothing\n\n        def latteDeploy = project.task('latteDeploy')\n        latteDeploy.dependsOn project.tasks['uploadArchives']\n    }\n}\n"
  },
  {
    "path": "latte-gradle-plugin/settings.gradle",
    "content": "rootProject.name = 'latte-gradle-plugin'\n\n"
  },
  {
    "path": "latte-gradle-plugin/src/main/groovy/org/lattelang/LatteGradlePlugin.groovy",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage org.lattelang\n\nimport lt.compiler.SyntaxException\nimport lt.util.Utils\nimport lt.repl.Compiler\nimport org.gradle.api.Action\nimport org.gradle.api.Plugin\nimport org.gradle.api.Project\nimport org.gradle.api.file.FileTreeElement\nimport org.gradle.api.internal.file.SourceDirectorySetFactory\nimport org.gradle.api.internal.plugins.DslObject\nimport org.gradle.api.internal.tasks.DefaultSourceSet\nimport org.gradle.api.logging.Logger\nimport org.gradle.api.plugins.JavaBasePlugin\nimport org.gradle.api.plugins.JavaPluginConvention\nimport org.gradle.api.specs.Spec\nimport org.gradle.api.tasks.SourceSet\n\nimport javax.inject.Inject\n\nclass LatteGradlePlugin implements Plugin<Project> {\n\n    private static File[] filterSourceDirs(Object[] srcDirs, boolean fastFail) {\n        List<File> list = new ArrayList<>()\n        for (Object x : srcDirs) {\n            File f = (File) x;\n            if (checkSourceDir(f, fastFail)) {\n                list.add(f)\n            }\n        }\n        return list.toArray(new File[list.size()])\n    }\n\n    private static boolean checkSourceDir(File sourceDir, boolean fastFail) {\n        if (sourceDir.exists()) {\n            if (sourceDir.isDirectory()) {\n                return true\n            } else throw new Exception(\"File should be latte source file directory [\" + sourceDir.absolutePath + \"]\")\n        } else {\n            if (fastFail) throw new Exception(\"Cannot find latte source file directory [\" + sourceDir.absolutePath + \"]\")\n            else return false\n        }\n    }\n\n    private static boolean checkOutputDir(File outputDir) {\n        if (outputDir.exists()) {\n            if (outputDir.isDirectory()) {\n                return true\n            } else throw new Exception(\"File should be output directory [\" + outputDir.absolutePath + \"]\")\n        } else {\n            if (outputDir.mkdirs()) {\n                return true\n            } else throw new IOException(\"Cannot create directory [\" + outputDir.absolutePath + \"]\")\n        }\n    }\n\n    private static void doCompile(Logger logger, ClassLoader cl, File[] sourceDirs, File outputDir, boolean fastFail) {\n        Map<String, File> fileMap = new HashMap<>()\n        for (File dir : sourceDirs) {\n            fileMap.putAll(Utils.filesInDirectory(dir, '.*\\\\.(lt|latte)', true))\n        }\n        Compiler compiler = new Compiler(cl)\n        compiler.config.fastFail = fastFail\n        compiler.config.result.outputDir = outputDir\n\n        logger.println(\"Compiling latte source files from \" + Arrays.toString(sourceDirs) + \" to [\" + outputDir.absolutePath + \"]\")\n        try {\n            compiler.compile(fileMap)\n        } catch (SyntaxException e) {\n            logger.error(\"Compilation failed!\")\n            throw e\n        }\n\n        logger.info(\"Compilation succeeded!\")\n    }\n\n    private\n    static void compile(Project project, boolean fastFail, boolean isTest) {\n        def mainSrc = project.sourceSets.main.latte.srcDirs\n        def testSrc = project.sourceSets.test.latte.srcDirs\n\n        int javaCompilePathFlag = 0 // 0 -> /classes/main, 1 -> /classes/java/main\n\n        String gradleVer = project.gradle.gradleVersion\n        project.logger.println(\"gradle version is \" + gradleVer)\n        String[] gradleVersions = gradleVer.split(\"\\\\.\")\n        if (gradleVersions.length > 0) {\n            try {\n                int v = Integer.parseInt(gradleVersions[0])\n                if (v >= 4) {\n                    javaCompilePathFlag = 1\n                }\n            } catch (ignore) {\n            }\n        }\n        File mainOutputDir\n        File testOutputDir\n        switch (javaCompilePathFlag) {\n            case 1:\n                mainOutputDir = new File(project.buildDir.absolutePath + '/classes/java/main')\n                testOutputDir = new File(project.buildDir.absolutePath + '/classes/java/test')\n                break;\n            default:\n                mainOutputDir = new File(project.buildDir.absolutePath + '/classes/main')\n                testOutputDir = new File(project.buildDir.absolutePath + '/classes/test')\n        }\n\n        def theSourceDirs = isTest ? testSrc : mainSrc\n        File theOutputDir = isTest ? testOutputDir : mainOutputDir\n\n        File[] sourceDirs = filterSourceDirs(theSourceDirs.toArray(theSourceDirs.size()), false)\n        if (sourceDirs.length > 0 && checkOutputDir(theOutputDir)) {\n            Collection<URL> compileURLs = project.sourceSets[isTest ? 'test' : 'main'].compileClasspath.files.collect {\n                it.toURI().toURL()\n            }\n            if (isTest) {\n                compileURLs.add(testOutputDir.toURI().toURL())\n            }\n            compileURLs.add(mainOutputDir.toURI().toURL())\n            ClassLoader classpath = LoaderUtil.loadClassesIn(compileURLs)\n            doCompile(project.logger, classpath, sourceDirs, theOutputDir, fastFail)\n        }\n    }\n\n    private Project project;\n    private final SourceDirectorySetFactory sourceDirectorySetFactory;\n\n    @Inject\n    public LatteGradlePlugin(SourceDirectorySetFactory sourceDirectorySetFactory) {\n        this.sourceDirectorySetFactory = sourceDirectorySetFactory;\n    }\n\n    @Override\n    void apply(Project project) {\n        this.project = project\n        project.getPluginManager().apply(JavaBasePlugin)\n\n        configureSourceSetDefaults()\n        registerExtensionAndTasks()\n    }\n\n    private void registerExtensionAndTasks() {\n        def ext = project.extensions.create('latteConfig', LatteGradlePluginExtension)\n        def compileLatte = project.task('compileLatte').doLast { t ->\n            compile(project, ext.fastFail, false)\n        }\n\n        def compileTestLatte = project.tasks.create('compileTestLatte').doLast { t ->\n            compile(project, ext.fastFail, true)\n        }\n\n        // dependencies\n        // after latte\n        if (ext.afterJava) {\n            compileLatte.dependsOn project.tasks['compileJava']\n            compileTestLatte.dependsOn project.tasks['compileTestJava']\n        }\n        if (ext.afterGroovy) {\n            compileLatte.dependsOn project.tasks['compileGroovy']\n            compileTestLatte.dependsOn project.tasks['compileTestGroovy']\n        }\n        // before latte\n        project.tasks['classes'].dependsOn compileLatte\n        project.tasks['testClasses'].dependsOn compileTestLatte\n    }\n\n    private void configureSourceSetDefaults() {\n        project.getConvention().getPlugin(JavaPluginConvention).getSourceSets().all(new Action<SourceSet>() {\n            public void execute(SourceSet sourceSet) {\n                final LatteSourceSet latteSourceSet = new DefaultLatteSourceSet(((DefaultSourceSet) sourceSet).getDisplayName(), sourceDirectorySetFactory);\n                new DslObject(sourceSet).getConvention().getPlugins().put(\"latte\", latteSourceSet);\n\n                latteSourceSet.getLatte().srcDir(\"src/\" + sourceSet.getName() + \"/latte\");\n                sourceSet.getResources().getFilter().exclude(new Spec<FileTreeElement>() {\n                    public boolean isSatisfiedBy(FileTreeElement element) {\n                        return latteSourceSet.getLatte().contains(element.getFile());\n                    }\n                });\n                sourceSet.getAllJava().source(latteSourceSet.getLatte());\n                sourceSet.getAllSource().source(latteSourceSet.getLatte());\n            }\n        });\n    }\n}\n\nclass LatteGradlePluginExtension {\n    boolean afterJava = true\n    boolean afterGroovy = false\n    boolean fastFail = false\n}\n"
  },
  {
    "path": "latte-gradle-plugin/src/main/groovy/org/lattelang/LoaderUtil.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage org.lattelang;\n\nimport java.net.URL;\nimport java.net.URLClassLoader;\nimport java.util.Collection;\n\n/**\n * loader utilities\n */\npublic class LoaderUtil {\n        public static ClassLoader loadClassesIn(Collection<URL> dependencies) {\n                URL[] urls = new URL[dependencies.size()];\n                dependencies.toArray(urls);\n                return new URLClassLoader(urls, Thread.currentThread().getContextClassLoader());\n        }\n}\n"
  },
  {
    "path": "latte-gradle-plugin/src/main/java/org/lattelang/DefaultLatteSourceSet.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage org.lattelang;\n\nimport groovy.lang.Closure;\nimport org.gradle.api.file.SourceDirectorySet;\nimport org.gradle.api.internal.file.SourceDirectorySetFactory;\nimport org.gradle.util.ConfigureUtil;\n\n/**\n * default latte source set\n */\npublic class DefaultLatteSourceSet implements LatteSourceSet {\n        private final SourceDirectorySet latte;\n        private final SourceDirectorySet allLatte;\n\n        public DefaultLatteSourceSet(String displayName, SourceDirectorySetFactory sourceDirectorySetFactory) {\n                latte = sourceDirectorySetFactory.create(displayName + \" Latte source\");\n                latte.getFilter().include(\"**/*.lt\", \"**/*.latte\");\n                allLatte = sourceDirectorySetFactory.create(displayName + \" Latte source\");\n                allLatte.source(latte);\n                allLatte.getFilter().include(\"**/*.lt\", \"**/*.latte\");\n        }\n\n        @Override\n        public SourceDirectorySet getLatte() {\n                return latte;\n        }\n\n        @Override\n        public LatteSourceSet groovy(Closure configureClosure) {\n                ConfigureUtil.configure(configureClosure, getLatte());\n                return this;\n        }\n\n        @Override\n        public SourceDirectorySet getAllLatte() {\n                return allLatte;\n        }\n}\n"
  },
  {
    "path": "latte-gradle-plugin/src/main/java/org/lattelang/LatteSourceSet.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage org.lattelang;\n\nimport groovy.lang.Closure;\nimport org.gradle.api.file.SourceDirectorySet;\n\n/**\n * the latte source set\n */\npublic interface LatteSourceSet {\n        SourceDirectorySet getLatte();\n\n        LatteSourceSet groovy(Closure configureClosure);\n\n        SourceDirectorySet getAllLatte();\n}\n"
  },
  {
    "path": "latte-gradle-plugin/src/main/resources/META-INF/gradle-plugins/latte.properties",
    "content": "implementation-class=org.lattelang.LatteGradlePlugin"
  },
  {
    "path": "latte-idea-plugin/.gitignore",
    "content": ".idea/\n*.jar\n*.class\nout/\ngen/\nidea-flex.skeleton\n"
  },
  {
    "path": "latte-idea-plugin/resources/META-INF/plugin.xml",
    "content": "<idea-plugin version=\"2\">\n    <id>com.your.company.unique.plugin.id</id>\n    <name>Plugin display name here</name>\n    <version>1.0</version>\n    <vendor email=\"support@yourcompany.com\" url=\"http://www.yourcompany.com\">YourCompany</vendor>\n\n    <description><![CDATA[\n      Enter short description for your plugin here.<br>\n      <em>most HTML tags may be used</em>\n    ]]></description>\n\n    <change-notes><![CDATA[\n      Add change notes here.<br>\n      <em>most HTML tags may be used</em>\n    ]]>\n    </change-notes>\n\n    <!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/build_number_ranges.html for description -->\n    <idea-version since-build=\"145.0\"/>\n\n    <!-- please see http://www.jetbrains.org/intellij/sdk/docs/basics/getting_started/plugin_compatibility.html\n         on how to target different products -->\n    <!-- uncomment to enable plugin in all products\n    <depends>com.intellij.modules.lang</depends>\n    -->\n\n    <extensions defaultExtensionNs=\"com.intellij\">\n        <fileTypeFactory implementation=\"org.lattelang.idea.LatteFileTypeFactory\"/>\n        <lang.syntaxHighlighterFactory language=\"Latte-lang\"\n                                       implementationClass=\"org.lattelang.idea.highlighter.LatteSyntaxHighlighterFactory\"/>\n    </extensions>\n\n    <actions>\n        <!-- Add your actions here -->\n    </actions>\n\n</idea-plugin>"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/Consts.java",
    "content": "package org.lattelang.idea;\n\nimport com.intellij.openapi.util.IconLoader;\n\nimport javax.swing.*;\n\n/**\n * constants\n */\npublic class Consts {\n        public static final Icon ICON = IconLoader.getIcon(\"/org/lattelang/idea/latte.png\");\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/LatteFileType.java",
    "content": "package org.lattelang.idea;\n\nimport com.intellij.openapi.fileTypes.LanguageFileType;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\nimport javax.swing.*;\n\n/**\n * latte fileType\n */\npublic class LatteFileType extends LanguageFileType {\n        public static LatteFileType INSTANCE = new LatteFileType();\n\n        private LatteFileType() {\n                super(LatteLanguage.INSTANCE);\n        }\n\n        @NotNull\n        @Override\n        public String getName() {\n                return \"Latte-lang file\";\n        }\n\n        @NotNull\n        @Override\n        public String getDescription() {\n                return \"Latte-lang source code\";\n        }\n\n        @NotNull\n        @Override\n        public String getDefaultExtension() {\n                return \"lt\";\n        }\n\n        @Nullable\n        @Override\n        public Icon getIcon() {\n                return Consts.ICON;\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/LatteFileTypeFactory.java",
    "content": "package org.lattelang.idea;\n\nimport com.intellij.openapi.fileTypes.FileTypeConsumer;\nimport com.intellij.openapi.fileTypes.FileTypeFactory;\nimport org.jetbrains.annotations.NotNull;\n\n/**\n * latte file type factory\n */\npublic class LatteFileTypeFactory extends FileTypeFactory {\n        @Override\n        public void createFileTypes(@NotNull FileTypeConsumer fileTypeConsumer) {\n                fileTypeConsumer.consume(LatteFileType.INSTANCE);\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/LatteLanguage.java",
    "content": "package org.lattelang.idea;\n\nimport com.intellij.lang.Language;\n\n/**\n * latte language\n */\npublic class LatteLanguage extends Language {\n        public static final LatteLanguage INSTANCE = new LatteLanguage();\n\n        private LatteLanguage() {\n                super(\"Latte-lang\");\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/highlighter/LatteSyntaxHighlighter.java",
    "content": "/*\n * Copyright 2000-2007 JetBrains s.r.o.\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\npackage org.lattelang.idea.highlighter;\n\nimport com.intellij.lexer.Lexer;\nimport com.intellij.openapi.editor.DefaultLanguageHighlighterColors;\nimport com.intellij.openapi.editor.HighlighterColors;\nimport com.intellij.openapi.editor.colors.TextAttributesKey;\nimport com.intellij.openapi.fileTypes.SyntaxHighlighterBase;\nimport com.intellij.psi.tree.IElementType;\nimport org.jetbrains.annotations.NotNull;\nimport org.lattelang.idea.psi.LatteLexer;\n\nimport static com.intellij.openapi.editor.colors.TextAttributesKey.createTextAttributesKey;\nimport static org.lattelang.idea.psi.LatteTokenTypes.*;\n\npublic class LatteSyntaxHighlighter extends SyntaxHighlighterBase {\n        public static final TextAttributesKey _ERR =\n                createTextAttributesKey(\"ERR\", HighlighterColors.BAD_CHARACTER);\n        public static final TextAttributesKey _NUMBER =\n                createTextAttributesKey(\"NUMBER\", DefaultLanguageHighlighterColors.NUMBER);\n        public static final TextAttributesKey _END_MARK =\n                createTextAttributesKey(\"END_MARK\", DefaultLanguageHighlighterColors.SEMICOLON);\n        public static final TextAttributesKey _KEYWORD =\n                createTextAttributesKey(\"KEYWORD\", DefaultLanguageHighlighterColors.KEYWORD);\n        public static final TextAttributesKey _BOOL =\n                createTextAttributesKey(\"BOOL\", DefaultLanguageHighlighterColors.KEYWORD);\n        public static final TextAttributesKey _COMMENT =\n                createTextAttributesKey(\"COMMENT\", DefaultLanguageHighlighterColors.LINE_COMMENT);\n        public static final TextAttributesKey _STRING =\n                createTextAttributesKey(\"STRING\", DefaultLanguageHighlighterColors.STRING);\n        public static final TextAttributesKey _MODIFIER =\n                createTextAttributesKey(\"MODIFIER\", DefaultLanguageHighlighterColors.KEYWORD);\n\n        private static final TextAttributesKey[] ERR_KEYS = new TextAttributesKey[]{_ERR};\n        private static final TextAttributesKey[] NUMBER_KEYS = new TextAttributesKey[]{_NUMBER};\n        private static final TextAttributesKey[] END_KEYS = new TextAttributesKey[]{_END_MARK};\n        private static final TextAttributesKey[] KEYWORD_KEYS = new TextAttributesKey[]{_KEYWORD};\n        private static final TextAttributesKey[] BOOL_KEYS = new TextAttributesKey[]{_BOOL};\n        private static final TextAttributesKey[] COMMENT_KEYS = new TextAttributesKey[]{_COMMENT};\n        private static final TextAttributesKey[] STRING_KEYS = new TextAttributesKey[]{_STRING};\n        private static final TextAttributesKey[] MODIFIER_KEYS = new TextAttributesKey[]{_MODIFIER};\n        private static final TextAttributesKey[] EMPTY_KEYS = new TextAttributesKey[0];\n\n        @NotNull\n        @Override\n        public Lexer getHighlightingLexer() {\n                return new LatteLexer();\n        }\n\n        @NotNull\n        @Override\n        public TextAttributesKey[] getTokenHighlights(IElementType type) {\n                if (type == NUMBER) {\n                        return NUMBER_KEYS;\n                } else if (type == END_MARK) {\n                        return END_KEYS;\n                } else if (type == KEY) {\n                        return KEYWORD_KEYS;\n                } else if (type == BOOL) {\n                        return BOOL_KEYS;\n                } else if (type == STRING) {\n                        return STRING_KEYS;\n                } else if (type == MODIFIER) {\n                        return MODIFIER_KEYS;\n                } else if (type == COMMENT) {\n                        return COMMENT_KEYS;\n                } else if (type == ERR) {\n                        return ERR_KEYS;\n                } else {\n                        return EMPTY_KEYS;\n                }\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/highlighter/LatteSyntaxHighlighterFactory.java",
    "content": "package org.lattelang.idea.highlighter;\n\nimport com.intellij.openapi.fileTypes.SyntaxHighlighter;\nimport com.intellij.openapi.fileTypes.SyntaxHighlighterFactory;\nimport com.intellij.openapi.project.Project;\nimport com.intellij.openapi.vfs.VirtualFile;\nimport org.jetbrains.annotations.NotNull;\nimport org.jetbrains.annotations.Nullable;\n\n/**\n * latte syntax highlighter factory\n */\npublic class LatteSyntaxHighlighterFactory extends SyntaxHighlighterFactory {\n        @NotNull\n        @Override\n        public SyntaxHighlighter getSyntaxHighlighter(@Nullable Project project, @Nullable VirtualFile virtualFile) {\n                return new LatteSyntaxHighlighter();\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/psi/LatteElementType.java",
    "content": "package org.lattelang.idea.psi;\n\nimport com.intellij.psi.tree.IElementType;\nimport org.jetbrains.annotations.NotNull;\nimport org.lattelang.idea.LatteLanguage;\n\npublic class LatteElementType extends IElementType {\n        public LatteElementType(@NotNull String debugName) {\n                super(debugName, LatteLanguage.INSTANCE);\n        }\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/psi/LatteTokenTypes.java",
    "content": "/*\n * Copyright 2000-2007 JetBrains s.r.o.\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\npackage org.lattelang.idea.psi;\n\nimport com.intellij.psi.tree.IElementType;\n\n/**\n * latte token types\n */\npublic interface LatteTokenTypes {\n        IElementType ERR = new LatteElementType(\"ERR\");\n        IElementType WHITE_SPACE = new LatteElementType(\"WHITE_SPACE\");\n        IElementType VALID_NAME = new LatteElementType(\"VALID_NAME\");\n        IElementType NUMBER = new LatteElementType(\"NUMBER\");\n        IElementType SYMBOL = new LatteElementType(\"SYMBOL\");\n        IElementType END_MARK = new LatteElementType(\"END_MARK\");\n        IElementType KEY = new LatteElementType(\"KEY\");\n        IElementType BOOL = new LatteElementType(\"BOOL\");\n        IElementType STRING = new LatteElementType(\"STRING\");\n        IElementType MODIFIER = new LatteElementType(\"MODIFIER\");\n        IElementType COMMENT = new LatteElementType(\"COMMENT\");\n}\n"
  },
  {
    "path": "latte-idea-plugin/src/org/lattelang/idea/psi/latte.flex",
    "content": "package org.lattelang.idea.psi;\n\nimport com.intellij.lexer.FlexLexer;\nimport com.intellij.psi.tree.IElementType;\nimport com.intellij.psi.TokenType;\n\nimport static org.lattelang.idea.psi.LatteTokenTypes.*;\n\n%%\n\n%class _LatteLexer\n%implements FlexLexer\n%unicode\n%function advance\n%type IElementType\n%eof{  return;\n%eof}\n\n// white space\nWHITE_SPACE = [\\ \\r\\n\\t\\f]\n// bool\nBOOL=true | false | yes | no\n// modifier\nMODIFIER = \"public\" | \"protected\" | \"private\" | \"internal\"\n         | \"abstract\" | \"val\" | \"native\" | \"synchronized\" | \"transient\" | \"volatile\" | \"strictfp\"\n         | \"data\" | \"var\" | \"def\" | \"nonnull\" | \"nonempty\" | \"implicit\"\n// number\n__NUMBER_INT_PART = [1-9][0-9]*\n__NUMBER_DIGIT_PART = \\.[0-9]+\nNUMBER = {__NUMBER_INT_PART} | {__NUMBER_INT_PART}{__NUMBER_DIGIT_PART}\n// string\n__STRING_SINGLE = \\'\n__STRING_DOUBLE = \\\"\n__STRING_ESCAPE = \\\\n | \\\\r | \\\\t | \\\\b | \\\\f | \"\\\\\"\"\\\\\" | \\\\\\\" | \\\\\\'\n__STRING_CONTENT = {__STRING_ESCAPE} | .\nSTRING = {__STRING_SINGLE}{__STRING_CONTENT}*{__STRING_SINGLE}\n       | {__STRING_DOUBLE}{__STRING_CONTENT}*{__STRING_DOUBLE}\n// key\n__INVALID_KEY = \"boolean\"\n__JAVA_KEY = \"abstract\" | \"assert\" | \"boolean\" | \"break\" | \"byte\" | \"case\"\n           | \"catch\" | \"char\" | \"class\" | \"const\" | \"continue\" | \"default\"\n           | \"do\" | \"double\" | \"else\" | \"enum\" | \"extends\" | \"final\" | \"finally\"\n           | \"float\" | \"for\" | \"if\" | \"implements\" | \"import\" | \"instanceof\"\n           | \"int\" | \"interface\" | \"long\" | \"native\" | \"new\" | \"null\" | \"package\"\n           | \"private\" | \"protected\" | \"public\" | \"return\" | \"short\" | \"static\"\n           | \"strictfp\" | \"throw\" | \"try\" | \"while\" | \"void\"\n\n__LATTE_KEY = \"is\" | \"not\" | \"bool\" | \"yes\" | \"no\" | \"type\" | \"as\"\n            | \"in\" | \"elseif\" | \"package\" | \"import\"\n            | \"break\" | \"continue\" | \"return\" | \"fun\" | \"require\"\n            | \"new\" | \"object\" | \"implicit\" | \"match\" | \"case\"\n            | \"annotation\"\nKEY = {__JAVA_KEY} | {__LATTE_KEY}\n// symbol\n__TWO_VAR_OP = \":::\" | \"^^\" | \"*\" | \"/\" | \"%\" | \"+\" | \"-\"\n             | \"<<\" | \">>\" | \">>>\" | \">\" | \"<\" | \">=\" | \"<=\"\n             | \"==\" | \"!=\" | \"===\" | \"!==\" | \"is\" | \"not\"\n             | \"in\" | \"&\" | \"^\" | \"|\" | \"&&\", \"and\" | \"||\", \"or\"\n             | \":=\"\n__ONE_VAR_OP = \"++\" | \"--\" | \"!\" | \"~\" | \"+\" | \"-\"\n__ASSIGN_OP = {__TWO_VAR_OP}\"=\"\n__DESTRUCTING = \"<-\"\n__PATTERN_MATCHING = \"=>\"\n    // braces\n__BRACES = \"(\" | \"{\" | \"[\" | \"]\" | \"}\" | \")\"\n__OTHER_THINGS = \".\" | \":\" | \"::\" | \"=\" | \"@\" | \"...\" | \":::\" | \":=\" | \"#\" | \",\"\nSYMBOL = {__TWO_VAR_OP} | {__ONE_VAR_OP} | {__ASSIGN_OP} | {__DESTRUCTING} | {__PATTERN_MATCHING} | {__BRACES} | {__OTHER_THINGS}\n// valid name\n__VALID_STARTER = (\\$|\\_|[a-zA-Z])\n__VALID_FOLLOW = {__VALID_STARTER}|[0-9]\nVALID_NAME = {__VALID_STARTER}{__VALID_FOLLOW}*\n// end\nEND = \";\"\n// comment\nSINGLE_LINE_COMMENT = \"//\".*\nMULTIPLE_LINE_COMMENT = \"/*\".*[\\r\\n]*.*\"*/\"\n\n%%\n\n{END}                                                       { yybegin(YYINITIAL); return END_MARK; }\n\n{SINGLE_LINE_COMMENT} {MULTIPLE_LINE_COMMENT}               { return COMMENT;}\n\n{BOOL}                                                      { return BOOL; }\n\n{MODIFIER}                                                  { return MODIFIER; }\n\n{NUMBER}                                                    { return NUMBER; }\n\n{STRING}                                                    { return STRING; }\n\n{__INVALID_KEY}                                             { return ERR; }\n{KEY}                                                       { return KEY; }\n\n{SYMBOL}                                                    { return SYMBOL; }\n\n{VALID_NAME}                                                { return VALID_NAME; }\n\n({WHITE_SPACE})+                                            { yybegin(YYINITIAL); return WHITE_SPACE; }\n\n.                                                           { yybegin(YYINITIAL); return ERR; }\n"
  },
  {
    "path": "latte-library/.gitignore",
    "content": ".idea/*\n.gradle/*\nbuild/*\n*.ipr\n*.iws\n"
  },
  {
    "path": "latte-library/build.gradle",
    "content": "def VERSION_FILE = file('../latte-build/src/main/resources/version')\nBufferedReader br = new BufferedReader(new FileReader(VERSION_FILE))\ndef VERSION = br.readLine().trim()\nbr.close()\n\ndef ACTION = System.getenv(\"BUILD_ACTION\")\n\ngroup 'org.latte-lang'\nversion VERSION\n\nbuildscript {\n    def VERSION_FILE_ = file('../latte-build/src/main/resources/version')\n    BufferedReader br_ = new BufferedReader(new FileReader(VERSION_FILE_))\n    def VERSION_ = br_.readLine().trim()\n    br_.close()\n\n    repositories {\n        mavenLocal()\n    }\n    dependencies {\n        classpath 'org.latte-lang:latte-gradle-plugin:' + VERSION_\n        classpath 'org.latte-lang:latte-class-recorder:' + VERSION_\n    }\n}\n\napply plugin: 'java'\napply plugin: 'idea'\napply plugin: 'maven'\napply plugin: 'latte'\nif ('deploy' == ACTION) {\n    apply plugin: 'signing'\n}\napply plugin: 'org.latte-lang.class-recorder'\napply plugin: LatteBuild\n\nsourceSets {\n    main {\n        java\n        latte.srcDirs = ['src/main/latte/async', 'src/main/latte/dsl']\n        resources\n    }\n    test {\n        java\n        latte\n        resources\n    }\n}\n\nrecordConfig {\n    directory = 'classes/main'\n    file = 'lib-classes.txt'\n}\n\nrepositories {\n    mavenLocal()\n    mavenCentral()\n}\n\nsourceCompatibility = 1.6\ntargetCompatibility = 1.6\n[compileJava, compileTestJava]*.options*.encoding = 'UTF-8'\n\nrepositories {\n    mavenCentral()\n}\n\ndependencies {\n    compile group: 'org.latte-lang', name: 'latte-compiler', version: VERSION\n    testCompile group: 'junit', name: 'junit', version: '4.12'\n}\n\nuploadArchives {\n    repositories {\n        mavenDeployer {\n            beforeDeployment { MavenDeployment deployment -> signing.signPom(deployment) }\n\n            def deploy_user = System.getenv('DEPLOY_USER')\n            def deploy_pass = System.getenv('DEPLOY_PASS')\n\n            repository(url: \"https://oss.sonatype.org/service/local/staging/deploy/maven2/\") {\n                authentication(userName: deploy_user, password: deploy_pass)\n            }\n\n            pom.project {\n                name 'latte-library'\n                packaging 'jar'\n                description 'The latte-lang library project, which contains some useful libraries.'\n                url 'http://latte-lang.org'\n                scm {\n                    url 'https://github.com/wkgcass/Latte-lang'\n                    connection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                    developerConnection 'scm:git:https://github.com/wkgcass/Latte-lang.git'\n                }\n                licenses {\n                    license {\n                        name 'MIT LICENSE'\n                        url 'https://github.com/wkgcass/Latte-lang/blob/master/LICENSE/'\n                    }\n                }\n                developers {\n                    developer {\n                        id 'wkgcass'\n                        email 'wkgcass@hotmail.com'\n                    }\n                }\n            }\n        }\n    }\n}\n\ntask javadocJar(type: Jar, dependsOn: javadoc) {\n    classifier = 'javadoc'\n    from 'build/docs/javadoc'\n}\n\ntask sourcesJar(type: Jar) {\n    classifier = 'sources'\n    from sourceSets.main.allSource\n}\n\nartifacts {\n    archives jar\n    archives javadocJar\n    archives sourcesJar\n}\n\njavadoc {\n    options {\n        encoding 'UTF-8'\n        charSet 'UTF-8'\n    }\n}\n\nif ('deploy' == ACTION) {\n    signing {\n        sign configurations.archives\n    }\n}\n\nclass LatteBuild implements Plugin<Project> {\n    @Override\n    void apply(Project project) {\n        def latteBuild = project.task('latteBuild')\n        project.tasks['install'].dependsOn project.tasks['test']\n        latteBuild.dependsOn project.tasks['install']\n\n        def latteTest = project.task('latteTest')\n        latteTest.dependsOn project.tasks['test']\n\n        def latteDeploy = project.task('latteDeploy')\n        latteDeploy.dependsOn project.tasks['uploadArchives']\n    }\n}\n"
  },
  {
    "path": "latte-library/settings.gradle",
    "content": "rootProject.name = 'latte-library'\n"
  },
  {
    "path": "latte-library/src/main/latte/async/lt/async/async.lt",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt::async\n\n/*\nAsync is a library help you run async programs elegantly.\nThe library is buit for async programs but itself doesn't provide threads or thread pools.\nIt simply runs as a single-thread program, but the functions passed in might be from\na framework or library that maintains a thread pool. e.g. Vert.x event loop.\n*/\nclass Async\n    /*\n    waterfall accepts a list of functions, these functions should have two params.\n    the first param of the function is result from previous function (or null if it's the first function)\n    the second param of the function is the next function to be invoked, e.g.\n\n        Async().waterfall(\n            [\n                (res, next)->\n                    ...\n                    next(something)\n                (res, next)->\n                    ...\n                    next(something)\n            ], (err, res)->\n                if err\n                    ...\n                else\n                    ...\n        )\n\n    when an exception occurred, it automatically goes to the final callback function\n    and apply the exception as the first argument, null as the second argument\n    */\n    waterfall(functions, callback):Unit\n        callback = CallbackWrapper2(callback)\n        var next = (res)-> callback(null, res)\n        for i in (functions.length-1) to 0\n            var f = functions[i]\n            next = WaterfallFunNext(f, next, callback)\n        next(null)\n\n    /*\n    parallel accepts a list of functions, these functions should have one parameter,\n    which represents the callback function to invoke, e.g.\n\n        Async().parallel(\n            [\n                (next)->\n                    ...\n                    next(something)\n                (next)->\n                    ...\n                    next(something)\n            ], (err, results)->\n                if err\n                    ...\n                else\n                    var res0 = results[0]\n                    var res1 = results[1]\n                    ...\n        )\n\n    These functions will be invoked and results will be collected,\n    the result order is the same as the functions' but the functions are called\n    at the same time.\n\n    when an exception occurred, it automatically goes to the final callback function\n    and apply the exception as the first argument, null as the second argument\n    */\n    parallel(functions, callback):Unit\n        callback = CallbackWrapper2(callback)\n        var resultMap = {}\n        for i in 0 until functions.length\n            var f = functions[i]\n            var next = ParallelFunNext(resultMap, i, functions.length, callback)\n            f(next)\n\n    /*\n    series accepts a list of functions, these functions should have one parameter,\n    which represents the callback function to invoke, e.g.\n\n        Async().series(\n            [\n                (next)->\n                    ...\n                    next(something)\n                (next)->\n                    ...\n                    next(something)\n            ], (err, results)->\n                if err\n                    ...\n                else\n                    var res0 = results[0]\n                    var res1 = results[1]\n                    ...\n        )\n\n    These functions will be invoked and results will be collected,\n    the result order and function-calling-order are both the same as the functions'\n\n    when an exception occurred, it automatically goes to the final callback function\n    and apply the exception as the first argument, null as the second argument\n    */\n    series(functions, callback):Unit\n        callback = CallbackWrapper2(callback)\n        var resultList = []\n        var next = elem->\n            resultList + elem\n            callback(null, resultList)\n        for i in (functions.length-1) to 0\n            var f = functions[i]\n            next = SeriesFunNext(f, next, callback, resultList, i)\n        next(null)\n\n    /*\n    `each` accepts a list/array and for each element invokes `iterator`, and finally\n    invoke the `callback` function.\n    iterator is a function with two params, the first is current element to handle,\n    the second is a function with 0 param, which let the library know this iteration finishes.\n    `callback` is a function with 1 param, which represents the exception or null\n    if no exception thrown during the process\n\n        Async().each(\n            [1, 2, 3, 4]\n            (item, next)->\n                ...\n                next()\n            err ->\n                if err\n                    ...\n                else\n                    ...\n        )\n\n    The iterations start at the same time.\n    when an exception occurred, it automatically goes to the final callback function\n    and apply the exception as the first argument\n    */\n    each(array, iterator, callback):Unit\n        callback = CallbackWrapper1(callback)\n        var taskStatus = {}\n        for i in 0 until array.length\n            var item = array[i]\n            var next = EachFunNext(taskStatus, i, array.length, callback)\n            try\n                iterator(item, next)\n            catch e\n                callback(e)\n\n    /*\n    `eachSeries` accepts a list/array and for each element invokes `iterator`,\n    and finally invoke the `callback` function.\n    iterator is a function with two params, the first is current element to handle,\n    the second is a function with 0 param, which let the library know this iteration finishes.\n    `callback` is a function with 1 param, which represents the exception or null\n    if no exception thrown during the process\n\n        Async().eachSeries(\n            [1, 2, 3, 4]\n            (item, next)->\n                ...\n                next()\n            err ->\n                if err\n                    ...\n                else\n                    ...\n        )\n\n    The iterations run in an order same as elements order in the given array.\n    when an exception occurred, it automatically goes to the final callback function\n    and apply the exception as the first argument\n    */\n    eachSeries(array, iterator, callback):Unit\n        callback = CallbackWrapper1(callback)\n        var next = ()->\n            callback(null)\n        for i in (array.length-1) to 0\n            var item = array[i]\n            next = EachSeriesFunNext(item, iterator, next, callback)\n        next()\n\n// this class makes sure that the callback method would be invoked only once\nabstract class CallbackWrapper(callback)\n    alreadyCalled = false\n    apply(arg1, arg2):Unit\n        if alreadyCalled\n            return\n        alreadyCalled = true\n        invokeCallback(arg1, arg2)\n    apply(arg1):Unit\n        if alreadyCalled\n            return\n        alreadyCalled = true\n        invokeCallback(arg1, null)\n\n    protected abstract invokeCallback(arg1, arg2)\n\nclass CallbackWrapper1(callback):CallbackWrapper(callback)\n    @Override\n    protected invokeCallback(arg1, arg2)\n        callback(arg1)\n\nclass CallbackWrapper2(callback):CallbackWrapper(callback)\n    @Override\n    protected invokeCallback(arg1, arg2)\n        callback(arg1, arg2)\n\nclass WaterfallFunNext(f, next, callback)\n    callback = CallbackWrapper2(callback)\n    def apply(res)\n        try\n            f(res, next)\n        catch e\n            callback(e, null)\n\nclass ParallelFunNext(resultMap, cursor, functionLength, callback)\n    def apply(res)\n        try\n            resultMap[cursor] = res\n            checkAndInvokeCallback()\n        catch e\n            callback(e, null)\n    private checkAndInvokeCallback():Unit\n        var list = []\n        for i in 0 until functionLength\n            if resultMap.containsKey(i)\n                list + resultMap[i]\n            else\n                return\n        callback(null, list)\n\nclass SeriesFunNext(f, next, callback, resultList, cursor)\n    def apply(res)\n        if cursor > 0\n            resultList + res\n        try\n            f(next)\n        catch e\n            callback(e, null)\n\nclass EachFunNext(taskStatus, cursor, arrayLength, callback)\n    def apply()\n        taskStatus[cursor] = true\n        checkAndInvokeCallback()\n    private checkAndInvokeCallback():Unit\n        for i in 0 until arrayLength\n            if !taskStatus.containsKey(i)\n                return\n        callback(null)\n\nclass EachSeriesFunNext(item, it, next, callback)\n    def apply()\n        try\n            it(item, next)\n        catch e\n            callback(e)\n"
  },
  {
    "path": "latte-library/src/main/latte/dsl/lt/dsl/html.lt",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\n/*\nThis is a package used to generate HTML text.\ne.g.\n\n    html + [\n        head\n        body + [\n            form + [\n                input(typ='text', value='hello world')\n                Input(typ='submit', value='ok')\n            ]\n        ]\n    ]\n\ninvoke toString() method, the result would be\n\n    <html><head></head><body><form><input type=\"text\" value=\"hello world\"><input type=\"submit\" value=\"ok\"></form></body></html>\n\ninvoke pretty() method, the result would be\n\n    <html>\n      <head>\n      </head>\n      <body>\n        <form>\n          <input type=\"text\" value=\"hello world\">\n          <input type=\"submit\" value=\"ok\">\n        </form>\n      </body>\n    </html>\n\nyou can also write css:\n\n    css('body') + {\n      'background-color' : 'grey'\n    }\n\n*/\npackage lt::dsl::html\n\nimport java::util::_\n\nprivate class StringUtils\n    static\n        val htmlEscapeMap = [\n            '<' : \"&lt;\"\n            '>' : \"&gt;\"\n            '&' : \"&amp;\"\n            '\"' : \"&quot;\"\n            ' ' : \"&nbsp;\"\n        ].immutable\n        val attrEscapeMap = [\n            '\"' : \"&quot;\"\n        ].immutable\n        escapeHtml(source):String\n            source = source.toString\n            sb = StringBuilder()\n            arr:[]char = source.toCharArray()\n            for i in 0 until arr.length\n                c:char = arr[i]\n                res = htmlEscapeMap[c]\n                if res\n                    sb append res\n                else\n                    sb append c\n            return sb.toString()\n        escapeAttr(attr):String\n            attr = attr.toString\n            sb = StringBuilder()\n            arr:[]char = attr.toCharArray()\n            for i in 0 until arr.length\n                c:char = arr[i]\n                res = attrEscapeMap[c]\n                if res\n                    sb append res\n                else\n                    sb append c\n            return sb.toString()\n        buildSpaces(i:int):String\n            sb = StringBuilder\n            for x in 0 until i\n                sb append \" \"\n            return sb toString\n\n/*\nWrite css with Latte-lang dsl\ne.g.\n\n    css('body') + {\n      'background-color' : 'grey'\n    }\n\n*/\nclass css(selector)\n    attrs:Map\n    add(attrs:Map):css\n        this.attrs=attrs\n        return this\n    toString():String\n        sb = StringBuilder\n        sb append selector append \"{\"\n        for entry in attrs\n            sb append entry.key append \":\" append entry.value append \";\"\n        sb append \"}\"\n        return sb toString\n    pretty(indentation=0):String\n        sb = StringBuilder\n        sb append StringUtils.buildSpaces(indentation) append selector append \" {\\n\"\n        for entry in attrs\n            sb append StringUtils.buildSpaces(indentation+2) append entry.key append \" : \" append entry.value append \";\\n\"\n        sb append StringUtils.buildSpaces(indentation) append \"}\"\n        return sb toString\n\n/*\nThe base of all HTMLElement. the DOM provides 4 attributes : id, name, class, and style.\nThe toString({}) method returns <simple-name-lower-case attr='value'>.\nIt doesn't contain the closing tag\nUse class HTMLElementWithClosing if the closing tag is required\n*/\nabstract data class HTMLElement(cls)\n    attrMap={}\n    set(attrName:String, o):HTMLElement\n        str = (\n            if o==null || o==Unit\n                return \"\"\n            else\n                return o\n        )\n        attrMap[attrName.replace(\"_\", \"-\")] = str\n        return this\n    attr(attrName:String, o):HTMLElement\n        attrMap[attrName] = (\n            if o==null || o==Unit\n                return \"\"\n            else\n                return o\n        )\n        return this\n    /*\n    add class to the element. the input '_' would be replaced with '-'.\n    */\n    get(className:String):HTMLElement\n        className = className.replace(\"_\", \"-\")\n        if attrMap[\"class\"]\n            attrMap['class'] = attrMap['class'].toString()+\" \"+className\n        else\n            attrMap['class'] = className\n        return this\n\n    toString(attrs):String\n        sb = StringBuilder()\n        sb append \"<\" append this.getClass.getSimpleName\n\n        for entry in attrMap\n            sb append \" \" append entry.key append \"=\\\"\" append StringUtils.escapeAttr(entry.value) append \"\\\"\"\n        if cls\n            sb append \" class=\\\"\" append StringUtils.escapeAttr(cls) append \"\\\"\"\n\n        for entry in attrs\n            if entry.value\n                sb append \" \" append entry.key append \"=\\\"\" append StringUtils.escapeAttr(entry.value) append \"\\\"\"\n\n        sb append \">\"\n\n        return sb toString\n\n    pretty(attrs, indentation:int=0):String\n        sb = StringBuilder\n        sb append StringUtils.buildSpaces(indentation) append toString(attrs)\n        return sb toString\n\n    abstract pretty(indentation:int):String=...\n\n/*\nThe base of all DOM that should have a closing tag\n*/\nabstract data class HTMLElementWithClosing : HTMLElement\n    children : List\n\n    def add(children:List)\n        this.children=children\n        return this\n\n    toString(attrs):String\n        sb=StringBuilder()\n        sb append HTMLElement.this.toString(attrs)\n\n        if children\n            for i in children\n                if i is type String\n                    sb append StringUtils.escapeHtml(i)\n                else\n                    sb append i\n\n        sb append \"</\" append this.getClass.getSimpleName.toLowerCase append \">\"\n        return sb toString\n\n    pretty(attrs, indentation:int=0):String\n        val inc = 2\n        sb = StringBuilder\n        sb append StringUtils.buildSpaces(indentation) append HTMLElement.this.toString(attrs) append \"\\n\"\n\n        if children\n            for i in children\n                if i is type String\n                    sb append StringUtils.buildSpaces(indentation+inc) append StringUtils.escapeHtml(i)\n                else\n                    if i is type HTMLElement or i is type css\n                        sb append i.pretty(indentation+inc as int)\n                    else\n                        sb append StringUtils.buildSpaces(indentation+inc) append i\n                sb append \"\\n\"\n        sb append StringUtils.buildSpaces(indentation) append \"</\" append this.getClass.getSimpleName.toLowerCase append \">\"\n        return sb toString\n\n/*\nsimply use the string as HTML without escaping.\n*/\ndata class Plain(text:String) : HTMLElement\n    toString():String=text\n    pretty(indentation:int=0):String=StringUtils.buildSpaces(indentation)+text\n\n// <html>...</html>\ndata class html : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <head>...</head>\ndata class head : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <meta http-equiv='' scheme=''>\ndata class meta : HTMLElement\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <script src='' type=''>...</script>\ndata class script(typ) : HTMLElementWithClosing\n    toString():String = toString(['type':typ])\n    pretty(indentation:int=0):String = pretty(['type':typ], indentation)\n\n// <link rel='' type='' href=''>\ndata class link(typ) : HTMLElement\n    toString():String = toString(['type':typ])\n    pretty(indentation:int=0):String = pretty(['type':typ], indentation)\n\n// <body>...</body>\ndata class body : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <a href=''>...</a>\ndata class a : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <br>\ndata class br : HTMLElement\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <button type=''>...</button>\ndata class button(typ) : HTMLElementWithClosing\n    toString():String = toString(['type':typ])\n    pretty(indentation:int=0):String = pretty(['type':typ], indentation)\n\n// <code>...</code>\ndata class code : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <div>...</div>\ndata class div : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h1>...</h1>\ndata class h1 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h2>...</h2>\ndata class h2 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h3>...</h3>\ndata class h3 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h4>...</h4>\ndata class h4 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h5>...</h5>\ndata class h5 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <h6>...</h6>\ndata class h6 : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <hr>\ndata class hr : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <iframe src=''>...</iframe>\ndata class iframe : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <img src=''>...</img>\ndata class img : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <label>...</label>\ndata class label : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <form action='' method=''></form>\ndata class form : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <i></i>\ndata class i : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <input type='' value=''>\ndata class input(typ) : HTMLElement\n    toString():String = toString([\"type\" : typ])\n    pretty(indentation:int=0):String = pretty(['type':typ], indentation)\n\n// <textarea>...</textarea>\ndata class textarea : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <select>...</select>\ndata class select : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <span>...</span>\ndata class span : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <option value=''>...</option>\ndata class option : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <nav>...</nav>\ndata class nav : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <ol>...</ol>\ndata class ol : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <ul>...</ul>\ndata class ul : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <li>...</li>\ndata class li : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <p>...</p>\ndata class p : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <pre>...</pre>\ndata class pre : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <style>...</style>\ndata class style : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <table>...</table>\ndata class table : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <thead>...</thead>\ndata class thead : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <tbody>...</tbody>\ndata class tbody : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <tfoot>...</tfoot>\ndata class tfoot : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <title>...</title>\ndata class title : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <tr>...</tr>\ndata class tr : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n\n// <td>...</td>\ndata class td : HTMLElementWithClosing\n    toString():String = toString({})\n    pretty(indentation:int=0):String = pretty({}, indentation)\n"
  },
  {
    "path": "latte-library/src/test/java/lt/library/TestLibraries.java",
    "content": "/*\n * The MIT License (MIT)\n *\n * Copyright (c) 2016 KuiGang Wang\n *\n * Permission is hereby granted, free of charge, to any person obtaining a copy\n * of this software and associated documentation files (the \"Software\"), to deal\n * in the Software without restriction, including without limitation the rights\n * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell\n * copies of the Software, and to permit persons to whom the Software is\n * furnished to do so, subject to the following conditions:\n *\n * The above copyright notice and this permission notice shall be included in all\n * copies or substantial portions of the Software.\n *\n * THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\n * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\n * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\n * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\n * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\n * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\n * SOFTWARE.\n */\n\npackage lt.library;\n\nimport org.junit.Test;\n\nimport java.lang.reflect.Method;\nimport java.util.Arrays;\n\nimport static org.junit.Assert.assertEquals;\n\n/**\n * test libraries\n */\npublic class TestLibraries {\n        @Test\n        public void testHtml() throws Exception {\n                Class<?> TestHtml = Class.forName(\"lt.dsl.html.test.TestHtml\");\n                Class<?> Html = Class.forName(\"lt.dsl.html.html\");\n                Object html = Html.newInstance(); // html=html()\n\n                Method testConstructHtml = TestHtml.getMethod(\"testConstructHtml\");\n\n                assertEquals(html, testConstructHtml.invoke(null));\n\n                Method testHtmlFormat = TestHtml.getMethod(\"testHtmlFormat\");\n                assertEquals(\"\" +\n                        \"<html>\" +\n                        \"<head>\" +\n                        \"</head>\" +\n                        \"<body>\" +\n                        \"<form>\" +\n                        \"<input value=\\\"hello world\\\" type=\\\"text\\\">\" +\n                        \"</form>\" +\n                        \"</body>\" +\n                        \"</html>\", testHtmlFormat.invoke(null).toString());\n\n                Method testHtmlEscape = TestHtml.getMethod(\"testHtmlEscape\");\n                assertEquals(\"\" +\n                                \"<html onload=\\\"window.location.href=&quot;page&quot;\\\">\" +\n                                \"&nbsp;&gt;&lt;&amp;&quot;\" +\n                                \"</html>\"\n                        , testHtmlEscape.invoke(null).toString());\n\n                Method testHtmlPretty = TestHtml.getMethod(\"testHtmlPretty\");\n                assertEquals(\"\" +\n                        \"<html>\\n\" +\n                        \"  <head>\\n\" +\n                        \"    <meta http-equiv=\\\"Pragma\\\" content=\\\"no-cache\\\">\\n\" +\n                        \"    <link rel=\\\"stylesheet\\\" src=\\\"style.css\\\">\\n\" +\n                        \"    <script src=\\\"x.js\\\">\\n\" +\n                        \"    </script>\\n\" +\n                        \"  </head>\\n\" +\n                        \"  <body>\\n\" +\n                        \"    <form method=\\\"post\\\" action=\\\"x.do\\\">\\n\" +\n                        \"      <input name=\\\"x\\\" type=\\\"text\\\">\\n\" +\n                        \"      1\\n\" +\n                        \"      <button type=\\\"submit\\\">\\n\" +\n                        \"        Submit\\n\" +\n                        \"      </button>\\n\" +\n                        \"    </form>\\n\" +\n                        \"  </body>\\n\" +\n                        \"</html>\", testHtmlPretty.invoke(null));\n\n                Method testCss = TestHtml.getMethod(\"testCss\");\n                assertEquals(\"\" +\n                        \"body {\\n\" +\n                        \"  background-color : #123456;\\n\" +\n                        \"}\", testCss.invoke(null));\n\n                Method testHtmlAndCss = TestHtml.getMethod(\"testHtmlAndCss\");\n                assertEquals(\"\" +\n                        \"<html>\\n\" +\n                        \"  <style>\\n\" +\n                        \"    body {\\n\" +\n                        \"      background-color : red;\\n\" +\n                        \"    }\\n\" +\n                        \"  </style>\\n\" +\n                        \"</html>\", testHtmlAndCss.invoke(null));\n\n                Method testHtmlClass = TestHtml.getMethod(\"testHtmlClass\");\n                assertEquals(\n                        \"<button class=\\\"btn btn-default\\\" type=\\\"submit\\\"></button>\", testHtmlClass.invoke(null)\n                );\n        }\n\n        @Test\n        public void testAsync_waterfall() throws Exception {\n                Class<?> TestAsync = Class.forName(\"lt.async.test.TestAsync\");\n\n                Method testWaterfall = TestAsync.getMethod(\"testWaterfall\");\n                assertEquals(Arrays.asList(1, 2, 3), testWaterfall.invoke(null));\n        }\n\n        @Test\n        public void testAsync_parallel() throws Exception {\n                Class<?> TestAsync = Class.forName(\"lt.async.test.TestAsync\");\n\n                Method testParallel = TestAsync.getMethod(\"testParallel\");\n                assertEquals(Arrays.asList(1, 2, 3), testParallel.invoke(null));\n        }\n\n        @Test\n        public void testAsync_series() throws Exception {\n                Class<?> TestAsync = Class.forName(\"lt.async.test.TestAsync\");\n\n                Method testSeries = TestAsync.getMethod(\"testSeries\");\n                assertEquals(Arrays.asList(1, 2, 3), testSeries.invoke(null));\n        }\n\n        @Test\n        public void testAsync_each() throws Exception {\n                Class<?> TestAsync = Class.forName(\"lt.async.test.TestAsync\");\n\n                Method testEach = TestAsync.getMethod(\"testEach\");\n                assertEquals(Arrays.asList(1, 2, 3), testEach.invoke(null));\n        }\n\n        @Test\n        public void testAsync_eachSeries() throws Exception {\n                Class<?> TestAsync = Class.forName(\"lt.async.test.TestAsync\");\n\n                Method testEachSeries = TestAsync.getMethod(\"testEachSeries\");\n                assertEquals(Arrays.asList(1, 2, 3), testEachSeries.invoke(null));\n        }\n}\n"
  },
  {
    "path": "latte-library/src/test/latte/test_async.lt",
    "content": "package lt::async::test\n\nimport lt::async::Async\n\nclass TestAsync\n    static\n        val async = Async()\n        def testWaterfall()\n            arr = []\n            async.waterfall(\n                [\n                    (x, next)->\n                        arr + 1\n                        next(arr)\n                    (res, next)->\n                        res + 2\n                        next(res)\n                    (res, next)->\n                        res + 3\n                        next(res)\n                ],\n                (err, res)->\n                    if err\n                        throw err\n            )\n            return arr\n        def testParallel()\n            result = []\n            async.parallel(\n                [\n                    (next)->\n                        next(1)\n                    (next)->\n                        next(2)\n                    (next)->\n                        next(3)\n                ], (err, results)->\n                    if err\n                        throw err\n                    else\n                        result addAll results\n            )\n            return result\n        def testSeries()\n            result = []\n            async.series(\n                [\n                    (next)->\n                        next(1)\n                    (next)->\n                        next(2)\n                    (next)->\n                        next(3)\n                ], (err, results)->\n                    result addAll results\n            )\n            return result\n        def testEach()\n            result = []\n            async.each(\n                [1, 2, 3]\n                (item, next)->\n                    result + item\n                    next()\n                err->\n                    ...\n            )\n            return result\n        def testEachSeries()\n            result = []\n            async.eachSeries(\n                [1, 2, 3]\n                (item, next)->\n                    result + item\n                    next()\n                err->\n                    ...\n            )\n            return result\n"
  },
  {
    "path": "latte-library/src/test/latte/test_html.lt",
    "content": "package lt::dsl::html::test\n\nimport lt::dsl::html::_\n\nclass TestHtml\n    static\n        testConstructHtml()=html\n        def testHtmlFormat()\n            return html + [\n                head\n                body + [\n                    form + [\n                        input(typ='text', value='hello world')\n                    ]\n                ]\n            ]\n        def testHtmlEscape()\n            return html(onload='window.location.href=\"page\"') + [\n                \" ><&\\\"\"\n            ]\n        def testHtmlPretty()\n            return (\n                html + [\n                    head + [\n                        meta(http_equiv=\"Pragma\", content='no-cache')\n                        link(rel=\"stylesheet\", src=\"style.css\")\n                        script(src=\"x.js\")\n                    ]\n                    body + [\n                        form(method=\"post\", action=\"x.do\") + [\n                            input(typ=\"text\", name=\"x\")\n                            1\n                            button(typ=\"submit\") + [\"Submit\"]\n                        ]\n                    ]\n                ]\n            ).pretty\n        def testCss()\n            return (\n                css('body') + [\n                    'background-color':'#123456'\n                ]\n            ).pretty\n        def testHtmlAndCss()\n            return (\n                html + [\n                    style + [\n                        css('body') + [\n                            'background-color':'red'\n                        ]\n                    ]\n                ]\n            ).pretty\n        def testHtmlClass()\n            return button(typ='submit').btn.btn_default toString\n"
  },
  {
    "path": "mannual-zh.md",
    "content": "# Latte-lang 规范\n\n# 目录\n\n1. [起步](#p1)\n\t1. [基础语法](#p1-1)\n\t2. [文件结构](#p1-2)\n2. [基础](#p2)\n\t1. [字面量](#p2-1)\n\t2. [基本类型](#p2-2)\n\t3. [控制流](#p2-3)\n3. [类和对象](#p3)\n\t1. [类与继承](#p3-1)\n\t2. [接口](#p3-2)\n\t3. [字段和方法](#p3-3)\n\t4. [修饰符](#p3-4)\n\t5. [Data Class](#p3-5)\n\t6. [实例化](#p3-6)\n\t7. [Object Class](#p3-7)\n\t8. [隐式转换](#p3-8)\n4. [函数类和Lambda](#p4)\n\t1. [函数类](#p4-1)\n\t2. [高阶函数和Lambda](#p4-2)\n5. [其他](#p5)\n\t1. [Json 集合](#p5-1)\n\t2. [范围](#p5-2)\n\t3. [类型检查与转换](#p5-3)\n\t4. [运算符绑定](#p5-4)\n\t5. [异常](#p5-5)\n\t6. [注解](#p5-6)\n\t7. [过程(Procedure)](#p5-7)\n    8. [参数可用性检查](#p5-8)\n    9. [解构](#p5-9)\n    10. [模式匹配](#p5-10)\n6. [Java 交互](#p6)\n\t1. [在Latte中调用Java代码](#p6-1)\n\t2. [在Java中调用Latte代码](#p6-2)\n\n<h1 id=\"p1\">1. 起步</h1>\n\n`Latte-lang`是一种JVM语言，基于JDK 1.6。它支持Java的所有语义，能够与Java完美互通，并提供比Java更多的函数式特性。\n\n<h2 id=\"p1-1\">1.1 基础语法</h2>\n\nLatte-lang（后文简称Latte）借鉴了主流语言的语法特征。如果您熟悉`Java`，或者了解过`Kotlin`,`Scala`,`Python`,`JavaScript`,`Swift`中的一到两种，那么阅读`Latte-lang`代码是很轻松的。\n\n> 对Latte影响最大的语言应该是Kotlin和Scala\n\n<h3 id=\"p1-1-1\">1.1.1 注释</h3>\n\n单行注释使用`//`开头。例如\n\n```java\n// i am a comment\n```\n\n多行注释以`/*`开头，以`*/`结尾。例如\n\n```java\n/* comment */\n/*\nmultiple line comment\n*/\na/* comment */=1\n/* the comment splits an expression */\n```\n\n<h3 id=\"p1-1-2\">1.1.2 包与导入</h3>\n\n```kotlin\npackage lt::spec\n\nimport java::util::_\n```\n\n或者使用`.`分割\n\n```kotlin\npackage lt.spec\n\nimport java.util._\n```\n\n代码段由`package`开始。一个latte文件只能包含一个`package`。它定义了其中定义的类、接口所在的“包”。包是一个java概念，可以理解为一个名字空间。\n\n声明了这个文件中定义的所有类和接口都在`lt::spec`包下。子包的名称通过`::`，或者`.`分隔。\n\n文件也可以不声明包，那么包名将被视为空字符串`\"\"`\n\n在导入包时使用`import`关键字，有三种导入方式：\n\n```kotlin\nimport java::awt::_               /* 导入所有java::awt包中的所有类 */\nimport java::util::List           /* 导入类java::util::List */\nimport java::util::Collections._  /* 导入Collections类的所有静态字段和方法 */\n```\n\n>使用`.`无法在语法上区分包与字段访问，所以在latte中建议使用`::`分割包名。但是考虑到其他JVM语言均使用`.`，所以也提供了`.`以符合使用习惯。\n\n<h3 id=\"p1-1-3\">1.1.3 类</h3>\n\n定义类User\n\n```kotlin\nclass User(id: int, name: String)\n```\n\n定义MyList类，并继承了LinkedList类\n\n```kotlin\nclass MyList(ls:List):LinkedList(ls)\n```\n\n定义抽象类MyList，并实现了List接口\n\n```kotlin\nabstract class MyList:List\n```\n\n详见[3.1 类与继承](#p3-1)\n\n定义`data class`\n\n```kotlin\ndata class User(id: int, name: String)\n```\n\n定义data class后，编译器会自动生成所有字段的getter/setter，类的toString/hashCode/equals方法，并继承和实现Serializable、Cloneable接口。\n\n详见[3.5 Data Class](#p3-5)\n\n定义`object class`\n\n```kotlin\nobject Singleton\n```\n\n可以直接使用类名获取该对象。\n\n详见[3.7 object class](#p3-7)\n\n<h3 id=\"p1-1-4\">1.1.4 接口</h3>\n\n定义接口Consumer\n\n```kotlin\ninterface Supplier\n    def supply\n```\n\n详见[3.2 接口](#p3-2)\n\n<h3 id=\"p1-1-5\">1.1.5 函数类</h3>\n\n定义函数类sum\n\n```kotlin\nfun sum(a, b)\n    return a+b\n```\n\n详见[4.1 函数类](#p4-1)\n\n<h3 id=\"p1-1-6\">1.1.6 变量</h3>\n\n只读变量\n\n```kotlin\nval a:int = 1\nval b = 1\n```\n\n可变变量\n\n```kotlin\nvar x = 5\nx += 1\n```\n\n可变变量的`var`可以省略\n\n```python\ny = 6\n```\n\n<h3 id=\"p1-1-7\">1.1.7 字符串模板</h3>\n\n```kotlin\nmain(args : []String)\n    println(\"First argument: ${args[0]}\")\n```\n\n<h3 id=\"p1-1-8\">1.1.8 使用条件表达式</h3>\n\n```python\nif a > b\n    return a\nelse\n    return b\n```\n\n或者\n\n```kotlin\nresult = (if a > b {a} else {b})\n```\n\n>一个方法需要返回值，那么只要末尾一个值为表达式，Latte就会自动生成方法的return语句\n\n详见[2.3.1 If 语句](#p2-3-1)\n\n<h3 id=\"p1-1-9\">1.1.9 for循环</h3>\n\n```swift\nfor item in list\n    println(item)\n```\n\n或者\n\n```swift\nfor i in 0 until list.size\n    println(list[i])\n```\n\n详见[2.3.2 For 语句](#p2-3-2)\n\n<h3 id=\"p-1-1-10\">1.1.10 while循环</h3>\n\n```swift\ni = 0\nwhile i < list.size\n    println(list[i++])\n```\n\n详见[2.3.3 While 语句](#p2-3-3)\n\n<h3 id=\"p-1-1-11\">1.1.11 范围</h3>\n\n检查x是否在范围中\n\n```kotlin\nif x in 1 to y-1\n    print(\"OK\")\n```\n\n从1到5进行循环\n\n```swift\nfor x in 1 to 5\n    print(x)\n```\n\n详见[5.2 范围](#p5-2)\n\n<h3 id=\"p1-1-12\">1.1.12 Lambda</h3>\n\n```kotlin\nlist.stream.\nfilter{it.startsWith(\"A\")}.\nmap{it.toUpperCase()}.\nforEach{print(it)}\n\nf = a -> 1 + a\nf(2) /* 结果为 3 */\n```\n\n详见[4.2 高阶函数和Lambda](#p4-2)\n\n<h3 id=\"p1-1-13\">1.1.13 Json语法</h3>\n\n```js\nlist = [1, 2, 3]\nmap = [\n    \"a\": 1\n    \"b\": 2\n]\n```\n\n详见[5.1 Json 集合](#p5-1)\n\n<h3 id=\"p1-1-14\">1.1.14 返回对象的\"或\"</h3>\n\n拥有JavaScript的`||`的功能。\n\n```js\na = a || 1\n```\n\n<h3 id=\"p1-1-15\">1.1.15 指定生成器</h3>\n\n```\n#js\n    def method(a)\n        return a+1\n```\n\n将会被转换成如下JavaScript代码\n\n```js\nfunction method(a) {\n    return a + 1;\n}\n```\n\n<h3 id=\"p1-1-16\">1.1.16 模式匹配</h3>\n\n```scala\nval (x,y) = Bean(1,2)\n```\n\n详见[5.9 解构](#p5-9)\n\n```scala\no match\n    case Bean(a,b) => ...\n    case People(name, age) if age > 20 => ...\n    case _ => ...\n```\n\n详见[5.10 解构](#p5-10)\n\n<h2 id=\"p1-2\">1.2 文件结构</h2>\n\nLatte源文件以`.lt`或者`.lts`为扩展名。不过实际上后缀名并不重要，手动构造编译器时附加特定参数即可。\n\n<h3 id=\"p1-2-1\">1.2.1 定义层次结构</h3>\n\n编译器首先会检查文件的第一行。第一行可以标注该文件 使用缩进定义层次结构，还是 使用大括号定义层次结构。\n\n例如：\n\n```java\n/// :scanner-brace\n```\n\n表示使用大括号定义层次结构。\n\n```java\n/// :scanner-indent\n```\n\n表示使用缩进定义层次结构。\n\n**默认为缩进**。提供这个选项是为了满足不同人的编码喜好。这两者的选择在词法上完全一样。\n\n>注意：Latte并不限定缩进数量。比上一行“更大的缩进”均代表一个新层次。\n\n<h3 id=\"p1-2-2\">1.2.2 层次结构</h3>\n\n使用*大括号*定义层次结构时，有如下几个符号会开启一个新层：\n\n```\n(\n[\n{\n```\n\n当其对应的符号出现时，这个开启的层将关闭：\n\n```\n)\n]\n}\n```\n\n使用*缩进*定义层次结构时，还有两个符号会开启一个新层: `->`、`=>`\n\n由于层将在缩进“变得更小”时关闭。所以，如下代码不加上括号也可以正确的工作：\n\n```java\nf = x->x+1\nf()\n```\n\n>注：使用大括号定义层次结构时，`->`不会开启新层，若要书写多行语句请使用{...}。此时规则和java完全一致。\n\n这里有一个示例，帮助理解“层”的概念：\n\n\t┌───────────────────────┐\n\t│       ┌─┐             │\n\t│classA(│a│):B          │\n\t│       └─┘             │\n\t│    ┌─────────────────┐│\n\t│    │       ┌────────┐││\n\t│    │method(│arg0    │││\n\t│    │    ┌──┘        │││\n\t│    │    │arg1       │││\n\t│    │    │arg2, arg3 │││\n\t│    │    └───────────┘││\n\t│    │):Unit           ││\n\t│    │    ┌────┐       ││\n\t│    │    │pass│       ││\n\t│    │    └────┘       ││\n\t│    └─────────────────┘│\n\t└───────────────────────┘\n\n该源码将被解析成如下结构：\n\n\t-[class]-[A]-[(]-[│]-[)]-[:]-[B]-[│]\n\t                  └[a]-    ┌──────┘\n\t┌──────────────────────────┘\n\t└────[method]-[(]-[│]-[)]-[│]-\n\t┌──────────────────┘       └───────[pass]-\n\t│\n\t└──[arg0]-[EndNode]-[arg1]-[EndNode]-[arg2]-[StrongEndNode]-[arg3]\n\n**注意:** 本文除非注明，否则均使用“缩进”进行描述。在注明为“大括号”时，会在示例代码开头标注`/// :scanner-brace`。\n\n<h3 id=\"p1-2-4\">1.2.4 层次控制字符</h3>\n\nLatte支持直接使用`{`和`}`定义层次结构。不过要注意，如果写为`{}`则表示空Map(映射)\n\n例如：\n\n```kotlin\nif a > b {1} else {2}\n/* 相当于 */\nif a > b\n    1\nelse\n    2\n```\n\n```js\nvar map = {} /* 这是一个map */\n```\n\n```js\n/* 可以正常编译，定义了一个方法，其中定义一个局部变量，赋值一个map */\ndef method {\n    map = [\n        \"a\": 1\n        \"b\": 2\n    ]\n}\n```\n\n<h1 id=\"p2\">2. 基础</h1>\n\n<h2 id=\"p2-1\">2.1 字面量</h2>\n\nLatte中有6种字面量：\n\n1. number\n2. string\n3. bool\n4. array\n5. map\n\n<h3 id=\"p2-1-1\">2.1.1 number</h3>\n\n数字可以分为整数和浮点数\n\n例如：\n\n\t1\n\t1.2\n\n`1`是一个整数，`1.2`是一个浮点数。\n\n整数字面量可以赋值给任意数字类型，而浮点数字面量只能赋值给`float`和`double`。详见 [2.2 基本类型](#p2-2)。\n\n<h3 id=\"p2-1-2\">2.1.2 string</h3>\n\n字符串可以以`'`或`\"`开头，并以同样的字符结尾。\n\n例如：\n\n\t'a string'\n\t\"a string\"\n\n使用`\\`作为转义字符\n\n例如：\n\n```\n'escape \\''\n\"escape \\\"\"\n```\n\n字符串字面量分为两种，若字符串长度为1，则它可以赋值给`char`类型或`java.lang.String`类型。否则只能赋值给`java.lang.String`类型。\n\n<h3 id=\"p2-1-3\">2.1.3 bool</h3>\n\n布尔型有下述4种书写形式：\n\n\ttrue\n\tfalse\n\tyes\n\tno\n\n`true`和`yes`表示逻辑真，`false`和`no`表示逻辑假。\n\n布尔值字面量只能赋值给`bool`类型。\n\n<h3 id=\"p2-1-4\">2.1.4 array</h3>\n\n数组以`[`开头，并以`]`结尾，其中包含的元素可以用`,`分隔，也可以通过换行分隔。\n\n例如：\n\n```js\n[1,2,3]\n\n[\n    object1\n    object2\n    object3\n]\n\n[\n    object1,\n    object2,\n    object3\n]\n```\n\n<h3 id=\"p2-1-5\">2.1.5 map</h3>\n\n映射(字典)像swift一样，以`[`开头，以`]`结尾。\n\n键值对通过类型符号`:`分隔，不同的entry通过`,`或者换行进行分隔。\n\n例如：\n\n```swift\n['a':1, 'b':2, 'c':3]\n\n[\n    'a':1\n    'b':2\n    'c':3\n]\n\n[\n    'a':1,\n    'b':2,\n    'c':3\n]\n```\n\n<h2 id=\"p2-2\">2.2 基本类型</h2>\n\nLatte保留了Java的8种基本类型。由于Latte是动态类型语言，并且可以在编译期和运行时自动装包和拆包，所以基本类型与包装类型可以认为没有差异。\n\n八种基本类型：\n\n```\nint\nlong\nfloat\ndouble\nshort\nbyte\nchar\nbool\n```\n\n其中`int/long/float/double/short/byte`为数字类型。\n\n注意，与Java不同的是，Latte使用`bool`而非`boolean`。\n\n<h3 id=\"p2-2-1\">2.2.1 基本类型转换</h3>\n\n在转换时，所有基本类型都可以互相转换（除了bool，它可以被任何类型转换到，但不能转换为其他类型，详见[5.8 参数可用性检查](#p5-8)）而不会出现任何错误。但是，在高精度向低精度转换时可能会丢失信息。例如：\n\n```scala\ni:int = 3.14   /* i == 3 丢失了小数部分 */\n\nb:bool = 10  /* b == true 除了数字不是0外，信息都丢失了 (只有0在转换为bool时才会是false) */\n```\n\n<h3 id=\"p2-2-2\">2.2.2 基本类型运算</h3>\n\nLatte支持所有Java的运算符，并在其基础上有所扩展\n\n对于数字的基本运算，其结果均为“精度较高的值”的类型，且最低为`int`型。例如：\n\n```c#\nr1 = (1 as long) + (2 as int)    /* r1 是 long */\nr2 = (1 as byte) + (2 as short)  /* r2 是 int */\n```\n\n由于Latte可以任意转换基本类型，所以这么写也可以正常编译并运行：\n\n```java\na:short = 1\na+=1  /* a == 2 */\na++   /* a == 3 */\n```\n\n>由于Latte支持基本类型的互相转换，你可以直接把`int`的结果赋值给`short`。\n\nLatte支持所有Java运算符，当然也包括位运算。和`java`一样，位运算必须作用于整数上。Latte支持所有整数类型的位运算：`int/long/short/byte`。  \n此外，Latte还支持乘方运算：\n\n```groovy\na ^^ b\n```\n\n结果均为`double`型。\n\n> 本质来说，Latte不存在“运算符”。所有运算符都是方法调用。基本类型的运算是由其包装类型隐式转换后调用方法完成的。\n\n<h2 id=\"p2-3\">2.3 控制流</h2>\n\n<h3 id=\"p2-3-1\">2.3.1 If 语句</h3>\n\n和Java一样，if是一个语句而非像Kotlin，Scala那样作为表达式。\n\n但是，Latte支持`Procedure`，并且可以自动添加返回语句，所以使用起来和作为表达式区别并不大。\n\n```ruby\nif a > b\n    return 1\nelse\n    return 2\n\nval result = (if a>b {1} else {2})\n```\n\n<h3 id=\"p2-3-2\">2.3.2 For 语句</h3>\n\nfor语句格式如下：\n\n```kotlin\nfor item in iter\n    ...\n```\n\n其中`iter`可以是数组、Iterable对象、Iterator对象、Enumerable对象、Map对象。\n\n当`iter`为前4种时，for语句将把其包含的对象依次赋值给`item`并执行循环体。当`iter`为Map对象时，`item`是一个Entry对象，它来自`Map#entrySet()`。\n\n你也可以使用`to`或者`until`，并在循环体内使用下标来访问元素:\n\n```kotlin\nfor i in 0 until arr.length\n    val elem = arr[i]\n    ...\n```\n\n<h3 id=\"p2-3-3\">2.3.3 While 语句</h3>\n\nwhile语句格式如下：\n\n```python\nwhile boolExp\n    ...\n\ndo\n    ...\nwhile boolExp\n```\n\n它的含义和Java完全一致。\n\n<h3 id=\"p2-3-4\">2.3.4 break, continue, return</h3>\n\n在循环中可以使用 `break` 和 `continue` 来控制循环。break将直接跳出循环，continue会跳到循环末尾，然后立即开始下一次循环。它的含义与Java完全一致。\n\n`return`可以用在lambda、方法（包括“内部方法”）、Procedure、脚本、函数类中:\n\n```kotlin\n/* lambda */\nfoo = ()->return 1\n\n/* 方法 */\ndef bar()\n    return 2\n\n/* Procedure */\n(\n    return 3\n)\n\n/* 函数类 */\nfun Fun1\n    return 4\n```\n\n脚本中的return语句表示将这个值返回到外部，在`require`这个脚本时将返回这个值。\n\n如果`return`是这个函数/方法最后的一条语句，或者该函数任意一条逻辑分支的最末尾，那么`return`都可以被省略:\n\n```kotlin\nfun add(a, b)\n    a+b\n\nval result = add(1, 2)\n/* result is 3 */\n```\n\n转换方式很简单，首先取出这个函数/方法的最后一条语句，如果是表达式，而且这个函数/方法要求返回值，则直接将其包装在`AST.Return`中。  \n如果最后一条语句是`if`，那么对其每一个逻辑分支进行该算法。\n\n<h1 id=\"p3\">3. 类和对象</h1>\n\n<h2 id=\"p3-1\">3.1 类与继承</h2>\n\n<h3 id=\"p3-1-1\">3.1.1 类</h3>\n\n类通过`class`关键字进行定义\n\n当类内部不需要填充任何内容时，可以非常简单的书写为：\n\n```kotlin\nclass Empty\n```\n\n当需要提供构造函数参数时，写为：\n\n```kotlin\nclass User(id, name)\n```\n\n当然，你也可以为参数指定类型：\n\n```scala\nclass User(id:int, name:String)\n```\n\n如果不指定类型则类型视为`java.lang.Object`  \n\nLatte不支持在类内部再定义构造函数，不过，你可以指定参数默认值来创建多个构造函数：\n\n```scala\nclass Rational(a:int, b:int=1)\n```\n\n此时你可以使用`Rational(1)`或者`Rational(1, 2)`来实例化这个类。\n\n--\n\n构造函数内容直接书写在class内：\n\n```kotlin\nclass Customer(name: String)\n    logger = Logger.getLogger('')\n    logger.info(\"Customer initialized with value ${name}\")\n```\n\n直接定义在类中的变量，以及构造函数参数，将直接视为字段(Field)。也就是说，上述例子中定义的name和logger都是字段。详见 [3.3 字段和方法](#p3-3) 。\n\n--\n\n使用`private`修饰符来确保类不会被实例化：\n\n```kotlin\nprivate class DontCreateMe\n```\n\n在Latte中，所有类都是`public`的，所以，在`class`前的任何“访问关键字”均为该类构造函数的访问关键字。\n\n<h3 id=\"p3-1-2\">3.1.2 继承</h3>\n\n和Java一样：Latte是单继承，并且所有的类都默认继承自`java.lang.Object`。你可以使用类型符号`:`来指定继承的类。继承的规则和Java完全一致。\n\n```kotlin\nclass Base(p:int)\nclass Derived(p:int) : Base(p)\n```\n\n父类的构造函数参数直接在父类类型后面的括号中指定。\n\n如果使用了父类的无参构造函数，那么可以省略括号：\n\n```kotlin\nclass Example : Object\n```\n\n如果想指定一个类不可被继承，那么需要在它前面加上`val`修饰符：\n\n```kotlin\nval class NoInher\n```\n\n<h3 id=\"p3-1-3\">3.1.3 抽象类</h3>\n\n使用`abstract`关键字定义抽象类：\n\n```kotlin\nabstract class MyAbsClass\n    abstract f()\n```\n\n抽象类规则与Java完全一致。抽象类可以拥有未实现的方法。\n\n继承一个抽象类：\n\n```kotlin\nclass MyImpl : MyAbsClass\n    @Override\n    def f=1\n```\n\n<h3 id=\"p3-1-4\">3.1.4 静态成员</h3>\n\n使用`static`定义静态成员。static可以“看作”一个修饰符，也可以“看作”一个结构块的起始。例如：\n\n```js\nclass TestStatic\n    static\n        public val STATIC_FIELD = 'i am a static field'\n    static func()=1\n```\n\n<h2 id=\"p3-2\">3.2 接口</h2>\n\nLatte接口遵循Java的接口定义。使用`interface`关键字:\n\n```kotlin\ninterface MyInterface\n    foo()=...\n```\n\n定义了`abstract`方法`foo()`。\n\n让一个类实现接口，也使用类型符号`:`。\n\n```kotlin\nclass Child : MyInterface\n    foo()=456\n\nchild = Child\nchild.foo /* result is 456 */\nchild.bar /* result is 123 */\n```\n\n接口可以拥有字段，但是和Java规则一样，字段必须是`static public val`（默认也是）。\n\n```kotlin\ninterface MyInterface\n    FLAG = 1\n```\n\n接口也可以拥有`static`方法（和Java一样）\n\n```js\ninterface TestStaticMethod\n    static\n        method()=111\n\nTestStaticMethod.method() /* result is 111 */\n```\n\n<h2 id=\"p3-3\">3.3 字段和方法</h2>\n\n<h3 id=\"p3-3-1\">3.3.1 定义字段</h3>\n\n你可以在类或接口中定义字段：\n\n```kotlin\nclass Address(name)\n    public street\n    public city\n    public state\n    public zip\n\ninterface MyInterface\n    FLAG = 1\n```\n\n在类中定义的字段默认被`private`修饰，可选的访问修饰符还有`public`, `protected`, `internal`。\n\n字段可以为`static`，只要写在static块中即可（接口默认就是static的，不需要修改）。也可以为不可变的，使用`val`修饰即可。由于构造函数参数也是字段，所以这些修饰符可以直接写在构造函数参数中。例如：\n\n```kotlin\nclass User(protected val id, public val name)\n```\n\n使用字段很简单，直接使用`.`符号访问即可，和Java一致。\n\n```kotlin\nval user = User(1, 'latte')\nuser.name   /* result is 'latte' */\n\nval address = Address('home')\naddress.city = 'hz'\n```\n\nLatte提供所谓的`property`支持：使用`getter`和`setter`来定义`property`。详情见 [3.3.3 Accessor](#p3-3-3)\n\n<h3 id=\"p3-3-2\">3.3.2 方法</h3>\n\nLatte支持多种定义方法的语法，先看一个最完整的方法定义：\n\n```scala\ndef foo(x:int, y:int):int\n    return x + y\n```\n\n如果方法没有参数，那么可以省略里面的内容，甚至省略括号：\n\n```scala\n/* 无参数 */\ndef foo:int\n    return 1\n```\n\n返回类型可以不指定，默认为`java.lang.Object`\n\n```scala\ndef foo\n    return 1\n```\n\n如果方法体只有一行并返回一个值，可以把在方法定义后直接接`=value`\n\n```scala\ndef foo = 1\n```\n\n如果方法体不存在（即空方法），可以只写一个方法名称（如果有参数再把参数加上）\n\n```scala\ndef foo\n```\n\n上述定义的缩写方式可以混合使用。\n\n此外，如果在定义方法的时候（使用了括号）并且（附带一个修饰符/注解，或者定义了返回值，或者使用了`=`语法），那么可以省略`def`\n\n```\nbar():int\nfoobar()='hello'\nfizz():int=1\n```\n\n--\n\n如果明确方法不返回值，那么可以附加`Unit`类型。Latte中只能写作`Unit`，代表了Java中的`void`。  \n但是，在Latte中所有方法都会返回一个值，对于Unit类型的方法，虽然会被编译为void类型，但是依然会返回`Unit`，它是`lt.lang.Unit`类型。\n\n和构造函数参数一样，方法参数也可以设定默认值：\n\n```scala\nfoo(a, b=1)=a+b\nfoo(1)  /* result is 2 */\n```\n\n**注意**，`def`实际上是一个“修饰符”(虽然它什么都不做)，并不属于“关键字”。设置`def`是为了和“省略参数的lambda”进行语法上的区分。\n\n例如：\n\n```js\nfoo(x)\n    ...\n```\n\n实际上会被转化为[4.2.2 Lambda](#p4-2-2)中描述的形式：\n\n```js\nfoo(x)(it->...)\n```\n\n所以使用类似于这种方式(`VALID_NAME ( [PARAM [, PARAM, ...]] ) { ... }`)定义的方法，如果没有注解，也没有其他修饰符，会造成歧义，所以不可省略`def`。\n\n方法返回类型为`Unit`时，你依然可以书写`return value`，这个value会被求值，但是不会被返回。  \n方法非`Unit`时，你也可以直接书写`return`，这时默认返回一个`Unit`。当然，如果返回类型不匹配，编译期依然会报错。\n\n#### 内部方法\n\nLatte支持“内部方法”。所谓内部方法是指在方法内部再定义一个方法。\n\n```\ndef outer\n    def inner\n```\n\n内部方法可以访问外部的所有变量，并且可以修改它们。\n\n>实际上，Lambda、Procedure都基于“内部方法”特性。所以它们也可以修改捕获到的所有变量。\n\n<h3 id=\"p3-3-3\">3.3.3 Accessor</h3>\n\naccessor分为两种，一种是取值：getter，一种是赋值：setter。\n\n对于getter有两种定义方式：\n\n1. 定义为`get{Name}()`\n2. 定义为`{name}()`\n\n对于setter只有一种定义方式：定义为`set{Name}(name)`\n\n```scala\nclass User(id, name)\n    def getId=id\n    setId(id)\n        this.id = id\n    def name=name  /* 放心，这么写是正确的 */\n    setName(name)\n        this.name = name\n```\n\n如此定义就可以像直接访问field一样来调用这几个方法了。\n\n```kotlin\nuser = User(1, 'latte')\nprintln(\"user_id is ${user.id} and user_name is ${user.name}\")\nuser.id = 2\nuser.name = 'jvm'\n```\n\n不过要注意的是：如果字段暴露给访问者，那么还是优先直接取字段或者对字段赋值。\n\n此外，还有一对特殊的accessor:\n\n* `set(String, ?)` 方法签名要求方法名为\"set\"，第一个参数接受一个String，第二个参数接受一个值，类型没有限制。（只不过使用时只能赋值为该类型的子类型）。\n* `get(String)` 方法签名要求方法名为\"get\"，第一个参数接受一个String。\n\n定义有上述accessor的类的实例，在取`o.field`时，将转换为`o.get('field')`。在设置`o1.field = o2`时，将转换为`o1.set('field', o2)`。\n\n<h2 id=\"p3-4\">3.4 修饰符</h2>\n\n<h3 id=\"p3-4-1\">3.4.1 访问修饰符</h3>\n\nLatte有4种访问修饰符：\n\n* public 公有，所有实例均可访问\n* protected 受保护，包名相同的类型，或者子类可访问\n* internal 包内可访问，包名相同的类型可以访问\n* private 私有，只有本类型可访问\n\n访问修饰符可以用来修饰:\n\n* 类\n* 接口\n* 字段\n* 方法\n* 构造函数的参数\n\n其中，类访问修饰符并不是规定给类用的。Latte中，类的访问修饰符永远为`public`，这个修饰符是作为构造函数而存在的。\n\n| 位置   | public | protected | internal | private |\n|-------|--------|-----------|----------|--------|\n| 类    |  √     |     √     |     √    |   √    |\n| 接口  |  √     |           |          |        |\n| 字段  |  √     |     √     |     √    |   √    |\n| 方法  |  √     |     √     |     √    |   √    |\n| 构造函数参数 |  √ |   √     |     √    |   √    |\n\n<h3 id=\"p3-4-2\">3.4.2 其他修饰符</h3>\n\nLatte支持所有Java的修饰符，但是名称可能有改动：\n\n* var 表示可变变量（可省略，默认即为可变）\n* val 表示不可变变量，或者不可被重载的方法，或者不可被继承的类\n* abstract 抽象类/方法\n* native 本地方法\n* synchronized 同步方法\n* transient 不持久化的字段\n* volatile 原子性的字段\n* strictfp 方法内的符点计算完全遵循标准\n* data 类是一个data class：详见 [3.5 data class](#p3-5)\n\n>`val` 其实就是Java的 `final`\n\n<h2 id=\"p3-5\">3.5 Data Class</h2>\n\n编译器会为data class的每一个字段生成一个getter和setter。并生成无参构造函数，`toString()`, `hashCode()`, `equals(Object)`方法。此外，还会实现Serializable和Cloneable接口。\n\n```kotlin\ndata class User(val name: String, val age: int)\n\nuser = User('cass', 22)\nuser.toString()   /* result is User(name='cass', age=22) */\n```\n\n你也可以定义自己的getter/setter/toString/hashCode/equals，编译器将跳过对应方法的生成。\n\n<h2 id=\"p3-6\">3.6 实例化</h2>\n\nLatte不需要`new`关键字就可以实例化一个类。对于无参数的实例化，甚至不需要附加括号：\n\n```kotlin\nclass Empty\nempty = Empty\n\nclass User(id, name)\nuser = User(1, 'latte')\n```\n\n当然，Latte也允许你加上`new`：\n\n```scala\nempty = new Empty\nuser = new User(1, \"latte\")\n```\n\n不过，Latte中的`new`的“优先级”非常低，java中的`new X().doSth()`的写法在Latte中必须写为`(new X).doSth`这样的写法。\n\n> Latte中建议不要写new\n\n此外，Latte提供另外一种特殊的实例化方式  \n调用无参构造函数，并依次赋值：\n\n```python\nclass open(file, mode)\n    public encoding\n\nf = open('/User/a', \"r\", encoding='utf-8')\n```\n\n这是一个语法糖，相当于如下Latte代码：\n\n```kotlin\nf = open('/User/a', \"r\")\nf.encoding = 'utf-8'\n```\n\n即：首先使用不带`=`的参数进行类型的实例化，然后把剩余“参数”看作对accessor的赋值操作。\n\n这个语法糖不光适用于Latte定义的data class，还可以支持任意具有无参构造函数，并有可访问的field或者[accessor](#p3-3-3)的对象。例如标准Java Bean就可以使用这个语法。\n\n```java\nclass User {\n    private int id;\n    private String name;\n    public int getId() {\n        return id;\n    }\n    public void setId(int id) {\n        this.id = id;\n    }\n    public String getName() {\n        return name;\n    }\n    public void setName(String name) {\n        this.name = name;\n    }\n}\n```\n\n<h2 id=\"p3-7\">3.7 Object Class</h2>\n\n```scala\nobject DataProviderManager\n    def registerDataProvider(provider: DataProvider)\n        ...\n    val allDataProviders: Collection = ...\n```\n\n本质上，`object class`定义了一个类，但是这个类不能拥有构造函数的参数，构造函数为private，并拥有一个`static public val`的字段来存放单例。\n\nobject class可以继承父类、实现接口，其规则与普通的class完全相同\n\n```scala\nobject DefaultListener : MouseAdapter()\n    def mouseClicked(e: MouseEvent):Unit\n        ...\n    def mouseEntered(e: MouseEvent):Unit\n        ...\n```\n\n你可以直接使用类名来获取这个单例对象：\n\n```\nval o = DataProviderManager\n```\n\n<h2 id=\"p3-8\">3.8 隐式转换</h2>\n\n隐式转换可以帮助你为对象扩展方法，从而更灵活的进行编程。\n\n使用隐式转换分为四步\n\n### 1. 定义一个类用来表示隐式转换后的类型\n\n这一步是可选的，您可以直接隐式转换到已有的类型。这里为了说明方便，单独定义一个：\n\n```scala\nclass RichInteger(i:Integer)\n    minutes() = i + \" minute\" + ( if i != 1 { \"s\" } else { \"\" } )\n```\n\n### 2. 定义一个隐式对象：\n\n隐式对象是一个普通的`object class`，不过需要用`implicit`修饰它。  \n在其中定义一些\"隐式方法\"，用来进行隐式类型转换。\n\n“隐式方法”就是普通的方法，不过需要用`implicit`修饰它。  \n隐式方法有一些要求：参数只能有一个，其类型为隐式转换的源类型（或源类型的父类型）；返回类型为目标类型。\n\n例如：我们想要将`Integer`转换为`RichInteger`\n\n```scala\nimplicit object TestImplicitCast\n    implicit def cast(i:Integer):RichInteger = RichInteger(i)\n```\n\n### 3. 启用隐式类\n\n```scala\nimport implicit TestImplicitCast\n```\n\n使用`import implicit`引入隐式类。这里注意，隐式类必须使用类名引入，而且，即使隐式类与使用者定义在同一个包下，也必须显式引入。这样错用几率会比较小。\n\n### 4. 使用\n\n```\nval x = 30 minutes\n```\n\n此时，`x`的值即为`\"30 minutes\"`。运行时会寻找可用的隐式转换，并判断转换后是否能够调用指定方法：发现`Integer => RichInteger`可用，且RichInteger可以调用`minutes()`方法；那么最终执行时的代码相当于`val x = TestImplicitCast.cast(30).minutes()`\n\n<h1 id=\"p4\">4. 函数类和Lambda</h1>\n\n<h2 id=\"p4-1\">4.1 函数类</h2>\n\n<h3 id=\"p4-1-1\">4.1.1 函数式接口 和 函数式抽象类</h3>\n\nJava8中规定了：只有一个未实现方法的接口为“函数式接口”。例如：\n\n```java\ninterface Consumer {\n    void consume(Object o);\n}\n```\n\n只有一个`consume`方法没有被实现，所以它是函数式接口。\n\n类似的，Latte中除了支持Java的函数式接口外，还支持定义“函数式抽象类”。\n\n如果一个类有无参的`public`构造函数，且只有一个未被实现的方法，那么这个类是一个函数式抽象类。例如：\n\n```kotlin\nabstract class F\n    abstract apply()=...\n```\n\n<h3 id=\"p4-1-2\">4.1.2 定义函数类</h3>\n\n要使用函数式接口/抽象类，必须有特定的实现。Latte提供一种简便的方式来书写其实现类：\n\n```kotlin\nfun Impl(x, y)\n    return x + y\n```\n\n使用`fun`关键字定义“函数类”，参数即为函数式类型未实现方法的参数，内部语句即为实现的方法的语句。\n\n函数类默认可以不附加类型，它在编译期将被视为`FunctionX`，其中X为参数个数。在运行时，`FunctionX`可以转化为任何参数个数相同的类型。\n\n如果确定其实现的类型，可以使用类型符号`:`定义：\n\n```kotlin\nfun MyTask : Runnable\n    println('hello world')\n```\n\n<h3 id=\"p4-1-3\">4.1.3 使用函数类</h3>\n\n函数类会被编译为Java的类(`class`)，所以，Latte中，它既有函数的特征，又有类的特征：\n\n* 函数类可以被import（就像类一样）\n* 可以直接调用这个类，例如：`Impl(1, 2)`。这条语句将实例化`Impl`并执行它实现的方法（这个用法就像lambda一样）\n* 可以将它作为值赋值给变量（实际上是调用了无参数构造函数，就像类一样）\n\n总之，对于函数类，你完全可以把它当做一个变量来考虑。\n\n```kotlin\nThread(MyTask).start()\n```\n\n同时由于它是正常的类，所以也具有父类型的所有字段/方法：\n\n```kotlin\ntask = MyTask\ntask.run()\n```\n\n<h3 id=\"p4-1-4\">4.1.4 函数式对象</h3>\n\n在Latte中，对于所有的函数式对象，都可以使用“像调用方法那样的语法”。  \n\n```js\ntask()\n```\n\n一个对象是“函数式对象”，有三种情形：\n\n1. 它的类(`.getClass`)的直接父类为函数式抽象类\n2. 它的类(`.getClass`)只实现了一个接口，且这个接口是函数式接口\n3. 这个对象具有`apply(...)`方法\n\n所以，在Latte中，函数式对象就是函数。\n\n<h2 id=\"p4-2\">4.2 高阶函数和Lambda</h2>\n\n<h3 id=\"p4-2-1\">4.2.1 高阶函数</h3>\n\n如果一个函数可以接受另一个函数作为参数，或者返回一个函数，那么这个函数就是高阶函数。\n\n[4.1.3 使用函数类](#p4.1.3) 中提到过“函数式对象”就是“函数”，所以，任何能够接收(并处理)函数式对象，或者返回函数式对象的函数/方法，就是高阶函数。\n\n如下代码是Java使用stream api的做法：\n\n```java\nList<String> strList = ...;\nstrList.stream().\n\tmap(s->Integer.parseInt(s)).\n\tfilter(n->n>10).\n\tcollect(Collectors.toList())\n```\n\n可以看到，map，filter都接受一个函数作为参数，所以它们也可以看作高阶函数。\n\n在Latte中，上述代码可以用Latte的`lambda`语法来表达：\n\n```kotlin\n/// :scanner-brace\n\nstrList = ...\nstrList.stream.\n\tmap { Integer.parseInt(it) }.\n\tfilter { it > 10 }.\n\tcollect(Collectors.toList())\n```\n\n<h3 id=\"p4-2-2\">4.2.2 Lambda</h3>\n\nLatte支持和Java完全一样的Lambda语法：\n\n```java\nstrList.stream().\nmap(s->Integer.parseInt(s)).\nfilter(n->n>10).\ncollect(Collectors.toList())\n```\n\n从外观上看不出任何差别？没错，语法上完全一致（特别是使用大括号区分层次的时候）。  \n使用缩进的情况下，多行lambda可以这么写:\n\n```coffee\nstrList.stream.map(\n    s-> s = s.subString(1)\n        Integer.parseInt(s)\n)\n```\n\n>注：可以不写return，因为Latte会帮你把需要的return补上。这个特性适用于任何“编译为JVM方法”的语法。\n\n如果lambda只有一个参数（例如上述代码），那么名称和`->`可以被省略。其中，名称会被标记为`it`。\n\n```js\nstrList.stream.map\n    it = it.subString(1)\n    Integer.parseInt(it)\n```\n\n这个特性可以让代码更简洁，同时也可以构造更灵活的内部DSL\n\n```python\nlatteIsWrittenInJava\n    if it is great\n        star the repo\n```\n\n>做一丁点处理后，这是可以正常编译的代码！（不需要hack编译器）\n\n可以写成一行\n\n```coffee\nlatteIsWrittenInJava { if it is great { star the repo }}\n```\n\n此外Lambda的变量捕捉机制和Java不同。Latte可以在Lambda中的任何地方修改被捕获的变量。\n\n```coffee\nvar count = 0\n(1 to 10).forEach { count+=it }\nprintln(count)\n```\n\n<h1 id=\"p5\">5. 其他</h1>\n\n<h2 id=\"p5-1\">5.1 Json 集合</h2>\n\nLatte支持Json格式的字面量。\n\nJson数组：\n\n```js\nvar list = [1, 2, 3, 4]\n```\n\n使用Json的数组语法，可以创建一个`java.util.LinkedList`实例，也可以创建一个数组。这取决于你将它赋值给什么类型的变量，或者使用`as`符号把它转换为什么类型。\n\nint数组：\n\n```c#\n[1, 2, 3, 4] as []int\n```\n\nObject数组:\n\n```c#\n[1, 2, 3, 4] as []Object\n```\n\n在Latte中，你可以将一个`java.util.List`类型的对象转换为其它种类的Object。该特性将尝试使用无参构造函数构造目标类型对象，然后对每一个List中的元素，调用add方法。\n\n```kotlin\nclass JsonArray\n    list = []\n    def add(o)=list.add(o)\nres = [1,2,3] as JsonArray\n/*\n same as:\n res = JsonArray()\n for item in [1,2,3]\n     res.add(item)\n */\n```\n\n--\n\nJson对象：\n\n```swift\nvar map = [\n    'one': 1,\n    'two': 2,\n    'three', 3\n]\n```\n\n其中`,`是不必须的。“换行”和`,`都可以用来来分割list的元素，以及map的entry\n\n在Latte中，你还可以把一个\"所有键都是string\"的map转换为指定类型的对象。\n\n```kotlin\ndata class Bean(hello, foo)\nres = [\n    \"hello\" : \"world\"\n    \"foo\"   : \"bar\n] as Bean\n\n/* res will be Bean(hello=world, foo=bar) */\n```\n\n该转换将首先用无参构造函数构造指定类型，然后对map中每一个键，进行Latte的赋值操作。  \n不光可以显式的转换，还可以作为方法参数隐式转换过去。\n\n<h2 id=\"p5-2\">5.2 范围</h2>\n\n在Latte中可以使用`to`或者`until`运算符来定义一个“范围”（range）。这两个运算符只接受整数作为参数。它的结果是一个`java.util.List`实例。\n\n使用`to`可以定义一个包含头和尾的范围，使用`until`可以定义一个只包含头，不包含尾的范围：\n\n```scala\noneToTen = 1 to 10   /* [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] */\noneToNine = 1 until 10  /* [1, 2, 3, 4, 5, 6, 7, 8, 9] */\n```\n\nrange也支持尾比头更小：\n\n```scala\ntenToOne = 10 to 1   /* [10, 9, 8, 7, 6, 5, 4, 3, 2, 1] */\ntenToTwo = 10 to 1   /* [10, 9, 8, 7, 6, 5, 4, 3, 2] */\n```\n\n>范围的实现基于“隐式类型转换”，Latte默认定义的RichInt提供了`to`和`until`方法。\n\n<h2 id=\"p5-3\">5.3 类型检查与转换</h2>\n\n<h3 id=\"p5-3-1\">5.3.1 类型检查</h3>\n\nLatte为静态类型和动态类型混合的语言。总体来说，类型检查比较宽松，并且不一定在编译期检查。\n\nLatte不要求显式转换，在赋值、方法return时，值会自动的尝试转换为需要的类型。\n\n```kotlin\nclass Base\nclass Sub:Base\n\nvar x:Base = Sub\nvar y:Sub = x\n```\n\n其中在赋值给`y`时，自动增加了一个类型转换。\n\n<h3 id=\"p5-3-2\">5.3.2 类型转换</h3>\n\n在调用方法时，自动转换并不会做，因为并不确定变量的类型，也不确定方法参数需要哪种类型。  \n如果编译期没有找到方法，则会在运行时再获取参数对象的类型并进行方法的寻找。如果一定要在编译期确定调用何种方法，可以手动转换类型。\n\n```kotlin\nclass Data\n    i:int\n    def setI(i:int) { this.i=i }\n\nfun call(x)\n    var data:Data = Data\n    data.setI(x as int)\n```\n\n上述例子中，x类型不确定，但是可以显式地转化为int。\n\n<h2 id=\"p5-4\">5.4 运算符绑定</h2>\n\nLatte支持运算符“绑定”。Latte的运算符绑定策略非常简单。每个运算符都看作方法调用。`a+b`看作`a.add(b)`，`a*b`看作`a.multiply(b)`，`!a`看作`a.not()`\n\n这些运算符绑定依照`BigInteger`和`BigDecimal`的命名，所以你可以直接使用运算符来计算大数。\n\n```kotlin\na = BigInteger(3)\nb = BigInteger(4)\nc = a + b\n```\n\n若需要绑定运算符，只需要写出签名相符的方法即可，例如定义一个`Rational`类来表示分数：\n\n```kotlin\nclass Rational(a, b)\n    add(that: Rational)=Rational(this.a * that.b + that.a * this.b, this.a * that.b)\n    toString():String=\"${a}/${b}\"\n\na = Rational(1, 4)  /* 1/4 */\nb = Rational(3, 7)  /* 3/7 */\nc = a + b           /* 19/28 */\n```\n\n有一些运算符是“复合”的，即：它们可以由多个操作构成。例如`++a`，就可以由`(a = a + 1 , return a)`构成。这类运算符不提供绑定，如果有需要，请绑定它们的展开式用到的运算符。\n\n下表描述了所有提供绑定的运算符，以及一些展开式规则：\n\n|  运算符  |   方法签名               |\n|----------|-------------------------|\n| a:::b    | a.concat(b)             |\n| a * b    | a.multiply(b)           |\n| a / b    | a.divide(b)             |\n| a % b    | a.remainder(b)          |\n| a + b    | a.add(b)                |\n| a - b    | a.subtract(b)           |\n| a << b   | a.shiftLeft(b)          |\n| a >> b   | a.shiftRight(b)         |\n| a >>> b  | a.unsignedShiftRight(b) |\n| a > b    | a.gt(b)       |\n| a < b    | a.lt(b)       |\n| a >= b   | a.ge(b)       |\n| a <= b   | a.le(b)       |\n| a == b   | a.eq(b)   |\n| a != b   | !a.ne(b)  |\n| a in b   | b.contains(a) |\n| a & b    | a.`and`(b)    |\n| a ^ b    | a.xor(b)      |\n| a | b    | a.`or`(b)     |\n| !a       | a.logicNot()  |\n| ~a       | a.not()       |\n| -a       | a.negate()    |\n| a\\[0\\]    | a.get(0)      |\n| a\\[0, 1\\] | a.get(0, 1)   |\n\n> `+a` 这种用法在Latte中不对`+`做任何处理，当做`a`  \n> 上面的`a[0, 1]`用法，如果a是一个二维数组，则相当于java的`a[0][1]`  \n> Latte对所有对象均可隐式转换到`RichObject`，在其中提供了`==`和`!=`的绑定，其中会调用对象的`equals`方法\n\nLatte的运算符优先级和Java完全一致，而Latte特有的运算符优先级如下：\n\n* `in` 和 `==` 优先级相同\n* `:::` 优先级最高\n\n由于`==`被绑定到equals方法，所以检查引用相同使用`===`，引用不同使用`!==`。  \n此外，Latte还提供两个运算符`is`和`not`，它除了可以检查引用、equals，在右侧对象是一个Class实例时还可以检查左侧对象是否为右侧对象的实例。\n\n> 虽然`==`绑定到equals方法，但是如果写为`null==x`，编译器能够知道左侧一定为null，这时会检查null值而不是调用equals\n> `!=`同理。\n\n| 运算符  |  展开式                          |\n|--------|----------------------------------|\n| a?=b   |  a = a ? b                       |\n| a++    | tmp = a , a = a + 1 , return tmp |\n| ++a    | a = a + 1 , return a             |\n| a--    | tmp = a , a = a - 1 , return tmp |\n| --a    | a = a - 1 , return a             |\n\n> 其中`?=`的`?`代表任何二元运算符\n\n---\n\nLatte中，和普通的方法调用不同，运算符前不需要附加`.`，也不需要对参数包裹括号。但是因为Latte的运算符和方法调用是一回事，所以为了一致性，普通方法调用也可以将方法名看作运算符来书写：\n\n```scala\nlist isEmpty // list.isEmpty()\nmap put \"Feb\", 2 // map.put(\"Feb\", 2)\n.println o // println(o)\n```\n\n使用逗号分隔多个参数。使用`.`表示直接调用方法（而不是在某个对象或者某个类上调用）。\n\n<h2 id=\"p5-5\">5.5 异常</h2>\n\nLatte和Java总体上是类似的，但是仍有多处不同：\n\n* Latte没有`checked exception`\n* Latte可以`throw`任何类型的对象，比如`throw 'error-message'`\n* Latte可以`catch`任何类型的对象\n* 由于上一条，Latte不提供`catch(Type e)`这种写法，需使用if-elseif-else来处理\n\n```kotlin\nfun isGreaterThanZero(x)\n    if x <= 0 { throw '${x} is littler than 0' }\n\nvar a = -1\ntry\n    isGreaterThanZero(a)\ncatch e\n    e.toCharArray  /* succeed. `e` is a String */\nfinally\n    a = 1\n```\n\n<h2 id=\"p5-6\">5.6 注解</h2>\n\nLatte使用`annotation`关键字定义注解\n\n```kotlin\nannotation Anno\n    a:int = 1\n    b:long\n```\n\nLatte中的注解默认为运行时可见的（而Java中默认不可见）。  \n可以使用`java::lang::annotation::Retention`注解重新规定可见性。  \n同时默认为可以标注在所有地方（和Java一样）。  \n可以使用`java::lang::annotation::Target`注解重新规定标注位置。\n\n> 因为annotation是一个关键字，所以导入包时需要用 点号 包围 `annotation`这个单词。\n\n---\n\nLatte的注解使用方式和Java一致\n\n```kotlin\nclass PrintSelf\n    @Override\n    toString():String='PrintSelf'\n```\n\n不过有一点要注意，Latte的注解不能和其所标注的对象在同一行，除非加一个逗号，比如：\n\n```scala\n@Anno1,@Anno2,method()=...\n```\n\n和Java一样，注解的value参数可以省略`value`这个键本身。\n\n```java\n@Value1('value')\n@Value2(value='value')\n```\n\n<h2 id=\"p5-7\">5.7 过程(Procedure)</h2>\n\nLatte支持把一组语句当做一个值，这个特性称作“过程”。  \n过程由小括号开始，小括号结束。\n\n用这个特性可以省略不必要的中间变量声明。\n\n```kotlin\nclass Rational(a, b)\n    toString():String = a + (\n        if b == 1\n            return \"\"\n        else\n            return \"/\" + b\n    )\n```\n\n过程最终也是编译为“方法”的，可以省略最后的`return`，所以可以写为：\n\n```kotlin\n;; :scanner-brace\nclass Rational(a, b)\n    toString():String = a + ( if b==1 {\"\"} else {\"/\" + b} )\n```\n\n<h2 id=\"p5-8\">5.8 参数可用性检查</h2>\n\nLatte支持**参数**上的null值或“空”值检查，分别使用`nonnull`和`nonempty`修饰符。\n\n由于Latte的`Unit`方法也返回一个值（`Unit`），所以在`nonnull`中不光会检查null值，还会检查Unit。  \n如果出现null则会立即抛出`java.lang.NullPointerException`异常  \n如果出现Unit则会立即抛出`java.lang.IllegalArgumentException`异常\n\n```scala\ndef add(nonnull a, nonnull b)= a + b\n\nadd(null, 1)      /* 抛出NullPointerException */\nadd(Unit, 2) /* 抛出IllegalArgumentException */\n```\n\n对于`nonempty`，检查的范围更广。首先Latte会将这个值转换为`bool`类型（Latte中任何类型都可以转为bool)  \n如果结果为`false`则会抛出异常`java.lang.IllegalArgumentException`\n\n```scala\ndef listNotEmpty(nonempty list)\n\nlistNotEmpty([])  /* 抛出 IllegalArgumentException */\n```\n\n在转换为`bool`时，Latte会尝试\n\n1. 如果是null，则返回false\n2. 如果是Unit，则返回false\n3. 如果是Boolean类型，则返回其对应的`bool`值\n4. 如果是数字类型，则：如果转换为`double`的结果是0，那么返回false，否则返回true\n5. 如果是Character类型，则：如果转换为`int`的结果是0，那么返回false，否则返回true\n6. 如果这个对象带有`def isEmpty:bool`或者`def isEmpty:Boolean`方法，那么调用之，并返回相应结果\n7. 返回true\n\n<h2 id=\"p5-9\">5.9 解构</h2>\n\n<h3 id=\"p5-9-1\">5.9.1 解构用法</h3>\n\n解构指的是将一个对象分解为其组成部分的多个对象。\n\n例如有如下定义和实例化：\n\n```kotlin\ndata class Bean(a,b)\n\nval bean = Bean(1,2)\n```\n\n可以知道，bean是由`1`和`2`组成的，它应当被分解为(1,2)。  \nLatte提供这样简化的分解：\n\n```scala\nval (x,y) = bean\n```\n\n定义了x和y，并分别赋值为1、2。\n\n<h3 id=\"p5-9-2\">5.9.2 解构实现方式</h3>\n\n使用解构，首先需要定义一个static方法`unapply`：\n\n```java\nclass X {\n    static {\n\t    unapply(o)=...\n\t}\n}\n```\n\n这个方法需要接受一个参数，表示被解构的对象，并返回`null`或一个`java::util::List`实例。\n\n如果返回`null`则说明解构失败，如果返回`List`实例，则表示会被分解为存在于列表中的对象。\n\n如果解构失败，则解构表达式返回`false`，否则返回`true`。\n\n可以指定使用“带有unapply方法的类”来执行解构：\n\n```scala\nBean(x,y) <- bean\n```\n\n如果没有指定，则尝试使用右侧对象的类中的unapply方法进行解构。\n\n```scala\n(x,y) <- bean /* 相当于 Bean(x,y) <- bean */\n```\n\n如果没有指定类型，则可以将`<-`替换为`=`。\n\n解构可以放在`if`中使用：\n\n```scala\nif List(a,b,c) <- o\n    println(\"result is ${a},${b},${c}\")\nelse\n    println(\"destruct failed!\")\n```\n\n<h2 id=\"p5-10\">5.10 模式匹配</h2>\n\n和`scala`一样，`Latte`不提供`java`的`switch`语句，但是提供更强大的模式匹配。\n\n```scala\ndef doMatch(o) = o match\n    case 1 => ... /* 根据值匹配 */\n    case b:Apple => ... /* 检查类型并定义一个新的变量 */\n    case _:Banana => ... /* 根据类型匹配 */\n    case Bean(x,y) => ... /* 根据解构匹配 */\n    case Bean(1, Bean(x, _:Integer)) => ... /* 多重模式 */\n    case Bean(x,y) if x > 0 => ... /* 解构后再做判断 */\n    case _ => ... /* 匹配所有（默认行为） */\n```\n\n模式匹配会从上到下依次尝试匹配。如果匹配成功则进入该分支执行语句，最终返回一个值（也可能返回`Unit`）。如果匹配失败，则会抛出`lt::lang::MatchError`。\n\n任何匹配模式都可以添加if语句，仅当if判断成立时才会进入执行。\n\n<h1 id=\"p6\">6. Java交互</h1>\n\n在设计时就考虑了Latte和Java的互操作。所以它们基本是无缝衔接的。\n\n<h2 id=\"p6-1\">6.1 在Latte中调用Java代码</h2>\n\n实际上这里不会出现任何问题。Latte源代码最终是编译到Java字节码的，所以Latte调用Java就像Latte调用自己一样。  \n而设计时也考虑到了互通性，几乎所有Latte特性都可以通过编写Java源代码来模拟。\n\n这里给出一些Latte与Java相同语义的表达：\n\n### 1. 规定变量和它的类型\n\n在Field操作时会有交互。\n\njava:\n\n```java\n      Integer integer;\n      List    list;\nfinal int     anInt;\n      Object  obj;\n```\n\nlatte:\n\n```scala\n    integer : Integer\n    list    : List\nval anInt   : int\n    obj\n```\n\nLatte可以使用`var`表示可变变量，不过也可以不写，默认即为可变变量。Object类型不需要写，同样也是默认值。\n\n### 2. 定义方法、参数类型和返回类型\n\n在调用方法时会有交互。\n\njava:\n\n```java\nvoid method1() {}\nObject method2() { return null; }\nint method3(int x) { return x; }\n```\n\nlatte:\n\n```kotlin\nmethod1():Unit=...\nmethod2()=null\nmethod3(x:int):int = x\n```\n\n### 3. 获取java类，判断类型\n\njava:\n\n```java\nClass c = Object.class;\n\nif (s instanceof String) {}\n```\n\nlatte:\n\n```typescript\nc = type Object\n\nif s is type String\n```\n\n<h2 id=\"p6-2\">6.2 在Java中调用Latte代码</h2>\n\n如果是已编译的Latte二进制文件，那么加载到class-path中，直接在Java中调用即可。Latte在设计时非常小心的不暴露任何“不一致状态”给Java，所以除了反射访问private外，尽管放心的调用吧。\n\n<h3 id=\"p6-2-1\">6.2.1 在Java中编译Latte</h3>\n\n如果是Latte源文件，则需要使用Latte-compiler编译。\n\n```java\nimport lt.repl.Compiler;\n\nCompiler compiler = new Compiler();\nClassLoader cl = compiler.compile(new HashMap<String, Reader>(){{\n\t\tput('source-name.lt', new InputStreamReader(...));\n}});\nClass<?> cls = cl.loadClass('...');\n```\n\n<h3 id=\"p6-2-2\">6.2.2 在Java中执行eval</h3>\n\nLatte支持`eval`，在latte代码中`eval('...')`即可。在Java中，你也可以直接调用\n\n```java\nlt.lang.Utils.eval(\"[\\\"id\\\":1,\\\"lang\\\":\\\"java\\\"]\");\n```\n\n或者使用`Evaluator`获取完整的eval支持:\n\n```java\nList<Integer> list = Arrays.asList(1, 2, 3, 4, 5);\n\nEvaluator evaluator = new Evaluator(new ClassPathLoader(Thread.currentThread().getContextClassLoader()));\nevaluator.setScannerType(Evaluator.SCANNER_TYPE_BRACE);\nevaluator.put(\"list\", list); // 把list对象放进Evaluator上下文中\nEvaluator.Entry entry = evaluator.eval(\"\" +\n\t\"import java::util::stream::Collectors._\\n\" +\n\t\"list.stream.filter{it > 0}.collect(toList())\");\nList newList = (List) entry.result;\n// newList is [3, 4, 5]\n```\n\n<h3 id=\"p6-2-3\">6.2.3 在Java中执行Latte脚本</h3>\n\nLatte支持脚本，脚本以源代码形式呈现。所以你可以构造一个`ScriptCompiler`来执行并取得脚本结果。\n\n```java\nScriptCompiler.Script script = scriptCompiler.compile(\"script\", \"return 1\");\nscript.run().getResult();\n// 或者 run(new String[]{...}) 来指定启动参数\n```\n\nScriptCompiler有多个`compile`的重载，各种情况都可以方便的调用。\n"
  }
]