diff options
84 files changed, 10518 insertions, 1847 deletions
diff --git a/.github/workflows/macos.yml b/.github/workflows/macos.yml index 6dede90..ddfcd2f 100644 --- a/.github/workflows/macos.yml +++ b/.github/workflows/macos.yml | |||
| @@ -22,7 +22,7 @@ jobs: | |||
| 22 | sudo luarocks make | 22 | sudo luarocks make |
| 23 | make test | 23 | make test |
| 24 | - name: luarocks upload | 24 | - name: luarocks upload |
| 25 | if: startsWith(github.ref, 'refs/tags/') | 25 | if: startsWith(github.ref, 'refs/tags/') && !contains(github.event.head_commit.message, '[skip Upload]') |
| 26 | run: | | 26 | run: | |
| 27 | ./yue -e spec/inputs/luarocks_upload.yue ${{ secrets.LUAROCKS_KEY }} | 27 | ./yue -e spec/inputs/luarocks_upload.yue ${{ secrets.LUAROCKS_KEY }} |
| 28 | - name: build for luajit | 28 | - name: build for luajit |
diff --git a/CMakeLists.txt b/CMakeLists.txt index 613019e..5c03f23 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -44,19 +44,33 @@ if (LUA_LIBRARIES MATCHES "LUA_LIBRARIES-NOTFOUND") | |||
| 44 | endif() | 44 | endif() |
| 45 | else () | 45 | else () |
| 46 | message(STATUS "Lua: using information from luarocks") | 46 | message(STATUS "Lua: using information from luarocks") |
| 47 | endif() | 47 | endif() |
| 48 | 48 | ||
| 49 | message(STATUS "Lua: " ${LUA}) | 49 | message(STATUS "Lua: " ${LUA}) |
| 50 | message(STATUS "Lua include: " ${LUA_INCLUDE_DIR}) | 50 | message(STATUS "Lua include: " ${LUA_INCLUDE_DIR}) |
| 51 | message(STATUS "Lua library: ${LUA_LIBRARIES}") | 51 | message(STATUS "Lua library: ${LUA_LIBRARIES}") |
| 52 | 52 | ||
| 53 | enable_language(CXX) | 53 | enable_language(C CXX) |
| 54 | include_directories(src src/3rdParty ${LUA_INCLUDE_DIR}) | 54 | include_directories(src src/3rdParty ${LUA_INCLUDE_DIR}) |
| 55 | add_definitions(-std=c++17 -O3 -fPIC) | 55 | add_definitions(-std=c++17 -O3 -fPIC -DYUE_UTF8_IMPL) |
| 56 | 56 | ||
| 57 | if (APPLE) | 57 | # Detect Android Termux environment |
| 58 | add_compile_options(-Wno-deprecated-declarations) | 58 | # Termux typically has ANDROID_ROOT environment variable set and PREFIX points to Termux directory |
| 59 | endif () | 59 | set(IS_TERMUX FALSE) |
| 60 | if (DEFINED ENV{ANDROID_ROOT}) | ||
| 61 | # Check if PREFIX environment variable points to Termux directory | ||
| 62 | if (DEFINED ENV{PREFIX}) | ||
| 63 | if ("$ENV{PREFIX}" MATCHES "com.termux") | ||
| 64 | set(IS_TERMUX TRUE) | ||
| 65 | message(STATUS "Detected Android Termux environment (via PREFIX: $ENV{PREFIX})") | ||
| 66 | endif() | ||
| 67 | endif() | ||
| 68 | # Alternative check: verify if Termux installation path exists | ||
| 69 | if (NOT IS_TERMUX AND EXISTS "/data/data/com.termux/files/usr") | ||
| 70 | set(IS_TERMUX TRUE) | ||
| 71 | message(STATUS "Detected Android Termux environment (via filesystem check)") | ||
| 72 | endif() | ||
| 73 | endif() | ||
| 60 | 74 | ||
| 61 | add_library(libyue MODULE | 75 | add_library(libyue MODULE |
| 62 | src/yuescript/ast.cpp | 76 | src/yuescript/ast.cpp |
| @@ -70,6 +84,11 @@ set_target_properties(libyue PROPERTIES PREFIX "") | |||
| 70 | set_target_properties(libyue PROPERTIES OUTPUT_NAME "yue") | 84 | set_target_properties(libyue PROPERTIES OUTPUT_NAME "yue") |
| 71 | target_link_libraries(libyue ${LUA_LIBRARIES}) | 85 | target_link_libraries(libyue ${LUA_LIBRARIES}) |
| 72 | 86 | ||
| 87 | # Add YUE_NO_WATCHER macro for Termux environment | ||
| 88 | if (IS_TERMUX) | ||
| 89 | target_compile_definitions(libyue PRIVATE YUE_NO_WATCHER) | ||
| 90 | endif() | ||
| 91 | |||
| 73 | add_executable(yue | 92 | add_executable(yue |
| 74 | src/yuescript/ast.cpp | 93 | src/yuescript/ast.cpp |
| 75 | src/yuescript/parser.cpp | 94 | src/yuescript/parser.cpp |
| @@ -78,80 +97,92 @@ add_executable(yue | |||
| 78 | src/yuescript/yue_compiler.cpp | 97 | src/yuescript/yue_compiler.cpp |
| 79 | src/yuescript/yuescript.cpp | 98 | src/yuescript/yuescript.cpp |
| 80 | src/yue.cpp | 99 | src/yue.cpp |
| 100 | src/3rdParty/colib/ljson.c | ||
| 81 | ) | 101 | ) |
| 82 | 102 | ||
| 83 | target_sources(yue PRIVATE | 103 | # Add efsw sources only if not in Termux environment |
| 84 | src/3rdParty/efsw/Debug.cpp | 104 | if (NOT IS_TERMUX) |
| 85 | src/3rdParty/efsw/DirectorySnapshot.cpp | ||
| 86 | src/3rdParty/efsw/DirectorySnapshotDiff.cpp | ||
| 87 | src/3rdParty/efsw/DirWatcherGeneric.cpp | ||
| 88 | src/3rdParty/efsw/FileInfo.cpp | ||
| 89 | src/3rdParty/efsw/FileSystem.cpp | ||
| 90 | src/3rdParty/efsw/FileWatcher.cpp | ||
| 91 | src/3rdParty/efsw/FileWatcherCWrapper.cpp | ||
| 92 | src/3rdParty/efsw/FileWatcherGeneric.cpp | ||
| 93 | src/3rdParty/efsw/FileWatcherImpl.cpp | ||
| 94 | src/3rdParty/efsw/Log.cpp | ||
| 95 | src/3rdParty/efsw/Mutex.cpp | ||
| 96 | src/3rdParty/efsw/String.cpp | ||
| 97 | src/3rdParty/efsw/System.cpp | ||
| 98 | src/3rdParty/efsw/Thread.cpp | ||
| 99 | src/3rdParty/efsw/Watcher.cpp | ||
| 100 | src/3rdParty/efsw/WatcherGeneric.cpp | ||
| 101 | ) | ||
| 102 | |||
| 103 | if (WIN32) | ||
| 104 | target_sources(yue PRIVATE | ||
| 105 | src/3rdParty/efsw/platform/win/FileSystemImpl.cpp | ||
| 106 | src/3rdParty/efsw/platform/win/MutexImpl.cpp | ||
| 107 | src/3rdParty/efsw/platform/win/SystemImpl.cpp | ||
| 108 | src/3rdParty/efsw/platform/win/ThreadImpl.cpp | ||
| 109 | ) | ||
| 110 | else () | ||
| 111 | target_sources(yue PRIVATE | ||
| 112 | src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp | ||
| 113 | src/3rdParty/efsw/platform/posix/MutexImpl.cpp | ||
| 114 | src/3rdParty/efsw/platform/posix/SystemImpl.cpp | ||
| 115 | src/3rdParty/efsw/platform/posix/ThreadImpl.cpp | ||
| 116 | ) | ||
| 117 | endif() | ||
| 118 | |||
| 119 | if (APPLE) | ||
| 120 | target_sources(yue PRIVATE | 105 | target_sources(yue PRIVATE |
| 121 | src/3rdParty/efsw/FileWatcherFSEvents.cpp | 106 | src/3rdParty/efsw/Debug.cpp |
| 122 | src/3rdParty/efsw/FileWatcherKqueue.cpp | 107 | src/3rdParty/efsw/DirectorySnapshot.cpp |
| 123 | src/3rdParty/efsw/WatcherFSEvents.cpp | 108 | src/3rdParty/efsw/DirectorySnapshotDiff.cpp |
| 124 | src/3rdParty/efsw/WatcherKqueue.cpp | 109 | src/3rdParty/efsw/DirWatcherGeneric.cpp |
| 110 | src/3rdParty/efsw/FileInfo.cpp | ||
| 111 | src/3rdParty/efsw/FileSystem.cpp | ||
| 112 | src/3rdParty/efsw/FileWatcher.cpp | ||
| 113 | src/3rdParty/efsw/FileWatcherCWrapper.cpp | ||
| 114 | src/3rdParty/efsw/FileWatcherGeneric.cpp | ||
| 115 | src/3rdParty/efsw/FileWatcherImpl.cpp | ||
| 116 | src/3rdParty/efsw/Log.cpp | ||
| 117 | src/3rdParty/efsw/Mutex.cpp | ||
| 118 | src/3rdParty/efsw/String.cpp | ||
| 119 | src/3rdParty/efsw/System.cpp | ||
| 120 | src/3rdParty/efsw/Thread.cpp | ||
| 121 | src/3rdParty/efsw/Watcher.cpp | ||
| 122 | src/3rdParty/efsw/WatcherGeneric.cpp | ||
| 125 | ) | 123 | ) |
| 126 | 124 | ||
| 127 | if (NOT CMAKE_SYSTEM_VERSION GREATER 9) | 125 | if (WIN32) |
| 128 | target_compile_definitions(yue PRIVATE EFSW_FSEVENTS_NOT_SUPPORTED) | 126 | target_sources(yue PRIVATE |
| 127 | src/3rdParty/efsw/platform/win/FileSystemImpl.cpp | ||
| 128 | src/3rdParty/efsw/platform/win/MutexImpl.cpp | ||
| 129 | src/3rdParty/efsw/platform/win/SystemImpl.cpp | ||
| 130 | src/3rdParty/efsw/platform/win/ThreadImpl.cpp | ||
| 131 | ) | ||
| 132 | else () | ||
| 133 | target_sources(yue PRIVATE | ||
| 134 | src/3rdParty/efsw/platform/posix/FileSystemImpl.cpp | ||
| 135 | src/3rdParty/efsw/platform/posix/MutexImpl.cpp | ||
| 136 | src/3rdParty/efsw/platform/posix/SystemImpl.cpp | ||
| 137 | src/3rdParty/efsw/platform/posix/ThreadImpl.cpp | ||
| 138 | ) | ||
| 129 | endif() | 139 | endif() |
| 130 | elseif (WIN32) | ||
| 131 | target_sources(yue PRIVATE | ||
| 132 | src/3rdParty/efsw/FileWatcherWin32.cpp | ||
| 133 | src/3rdParty/efsw/WatcherWin32.cpp | ||
| 134 | ) | ||
| 135 | elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") | ||
| 136 | target_sources(yue PRIVATE | ||
| 137 | src/3rdParty/efsw/FileWatcherInotify.cpp | ||
| 138 | src/3rdParty/efsw/WatcherInotify.cpp | ||
| 139 | ) | ||
| 140 | 140 | ||
| 141 | if (NOT EXISTS "/usr/include/sys/inotify.h" AND NOT EXISTS "/usr/local/include/sys/inotify.h") | 141 | if (APPLE) |
| 142 | target_compile_definitions(yue PRIVATE EFSW_INOTIFY_NOSYS) | 142 | target_sources(yue PRIVATE |
| 143 | src/3rdParty/efsw/FileWatcherFSEvents.cpp | ||
| 144 | src/3rdParty/efsw/FileWatcherKqueue.cpp | ||
| 145 | src/3rdParty/efsw/WatcherFSEvents.cpp | ||
| 146 | src/3rdParty/efsw/WatcherKqueue.cpp | ||
| 147 | ) | ||
| 148 | |||
| 149 | if (NOT CMAKE_SYSTEM_VERSION GREATER 9) | ||
| 150 | target_compile_definitions(yue PRIVATE EFSW_FSEVENTS_NOT_SUPPORTED) | ||
| 151 | endif() | ||
| 152 | elseif (WIN32) | ||
| 153 | target_sources(yue PRIVATE | ||
| 154 | src/3rdParty/efsw/FileWatcherWin32.cpp | ||
| 155 | src/3rdParty/efsw/WatcherWin32.cpp | ||
| 156 | ) | ||
| 157 | elseif (${CMAKE_SYSTEM_NAME} MATCHES "Linux") | ||
| 158 | target_sources(yue PRIVATE | ||
| 159 | src/3rdParty/efsw/FileWatcherInotify.cpp | ||
| 160 | src/3rdParty/efsw/WatcherInotify.cpp | ||
| 161 | ) | ||
| 162 | |||
| 163 | if (NOT EXISTS "/usr/include/sys/inotify.h" AND NOT EXISTS "/usr/local/include/sys/inotify.h") | ||
| 164 | target_compile_definitions(yue PRIVATE EFSW_INOTIFY_NOSYS) | ||
| 165 | endif() | ||
| 166 | elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") | ||
| 167 | target_sources(yue PRIVATE | ||
| 168 | src/3rdParty/efsw/FileWatcherKqueue.cpp | ||
| 169 | src/3rdParty/efsw/WatcherKqueue.cpp | ||
| 170 | ) | ||
| 143 | endif() | 171 | endif() |
| 144 | elseif (${CMAKE_SYSTEM_NAME} MATCHES "FreeBSD") | 172 | else() |
| 145 | target_sources(yue PRIVATE | 173 | message(STATUS "Termux environment detected: excluding efsw file watcher sources") |
| 146 | src/3rdParty/efsw/FileWatcherKqueue.cpp | ||
| 147 | src/3rdParty/efsw/WatcherKqueue.cpp | ||
| 148 | ) | ||
| 149 | endif() | 174 | endif() |
| 150 | 175 | ||
| 151 | if (MSVC) | 176 | if (MSVC) |
| 152 | target_compile_definitions(yue PRIVATE _SCL_SECURE_NO_WARNINGS) | 177 | target_compile_definitions(yue PRIVATE _SCL_SECURE_NO_WARNINGS) |
| 153 | else () | 178 | else () |
| 154 | target_compile_options(yue PRIVATE -Wall -Wno-long-long -fPIC) | 179 | target_compile_options(yue PRIVATE -Wall -Wno-long-long -fPIC) |
| 180 | set_source_files_properties(src/3rdParty/colib/ljson.c PROPERTIES COMPILE_FLAGS "-std=c99") | ||
| 181 | endif() | ||
| 182 | |||
| 183 | # Add YUE_NO_WATCHER macro for Termux environment | ||
| 184 | if (IS_TERMUX) | ||
| 185 | target_compile_definitions(yue PRIVATE YUE_NO_WATCHER) | ||
| 155 | endif() | 186 | endif() |
| 156 | 187 | ||
| 157 | if (${CMAKE_BUILD_TYPE} MATCHES "Debug") | 188 | if (${CMAKE_BUILD_TYPE} MATCHES "Debug") |
| @@ -169,10 +200,9 @@ elseif (NOT (${CMAKE_SYSTEM_NAME} MATCHES "Haiku") AND NOT WIN32) | |||
| 169 | else () | 200 | else () |
| 170 | target_link_libraries(yue PRIVATE ${LUA_LIBRARIES}) | 201 | target_link_libraries(yue PRIVATE ${LUA_LIBRARIES}) |
| 171 | endif() | 202 | endif() |
| 172 | 203 | ||
| 173 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | 204 | if (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") |
| 174 | target_link_options(yue PRIVATE -lstdc++fs -ldl) | 205 | target_link_options(yue PRIVATE -ldl) |
| 175 | endif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") | 206 | endif (CMAKE_CXX_COMPILER_ID STREQUAL "GNU") |
| 176 | 207 | ||
| 177 | install(CODE "") | 208 | install(CODE "") |
| 178 | |||
| @@ -1,6 +1,6 @@ | |||
| 1 | MIT License | 1 | MIT License |
| 2 | 2 | ||
| 3 | Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 3 | Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 4 | 4 | ||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 6 | of this software and associated documentation files (the "Software"), to deal | 6 | of this software and associated documentation files (the "Software"), to deal |
diff --git a/doc/docs/.vuepress/components/YueCompiler.vue b/doc/docs/.vuepress/components/YueCompiler.vue index 6b6042c..3a22d1c 100755 --- a/doc/docs/.vuepress/components/YueCompiler.vue +++ b/doc/docs/.vuepress/components/YueCompiler.vue | |||
| @@ -1,21 +1,21 @@ | |||
| 1 | <template> | 1 | <template> |
| 2 | <div style="width: 100%; height: auto;"> | 2 | <div style="width: 100%; height: auto;"> |
| 3 | <div class="parent" style="background-color: #f5f7ff;"> | 3 | <div class="parent" style="background-color: #f5f7ff;"> |
| 4 | <div class="childL" style="height: 2.5em;"> | 4 | <div class="editor-section"> |
| 5 | <div class="childTitle">YueScript {{ info }}</div> | 5 | <div class="childTitle">YueScript {{ info }}</div> |
| 6 | <div class="editor-container" ref='yueEditor'> | ||
| 7 | <ClientOnly> | ||
| 8 | <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor> | ||
| 9 | </ClientOnly> | ||
| 10 | </div> | ||
| 6 | </div> | 11 | </div> |
| 7 | <div class="childR" style="height: 2.5em;"> | 12 | <div class="editor-section"> |
| 8 | <div class="childTitle">Lua</div> | 13 | <div class="childTitle">Lua</div> |
| 9 | </div> | 14 | <div class="editor-container"> |
| 10 | <div class="childL" ref='yueEditor' style="height: 30em;"> | 15 | <ClientOnly> |
| 11 | <ClientOnly> | 16 | <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" :line-numbers="isMobileLayout" readonly></prism-editor> |
| 12 | <prism-editor class="my-editor" v-model="code" :highlight="highlighterYue" @input="codeChanged($event)" line-numbers :readonly="readonly"></prism-editor> | 17 | </ClientOnly> |
| 13 | </ClientOnly> | 18 | </div> |
| 14 | </div> | ||
| 15 | <div class="childR" style="height: 30em;"> | ||
| 16 | <ClientOnly> | ||
| 17 | <prism-editor class="my-editor" v-model="compiled" :highlight="highlighterLua" @input="codeChanged($event)" readonly></prism-editor> | ||
| 18 | </ClientOnly> | ||
| 19 | </div> | 19 | </div> |
| 20 | </div> | 20 | </div> |
| 21 | <div v-if="!compileronly"> | 21 | <div v-if="!compileronly"> |
| @@ -57,9 +57,18 @@ | |||
| 57 | code: '', | 57 | code: '', |
| 58 | compiled: '', | 58 | compiled: '', |
| 59 | result: '', | 59 | result: '', |
| 60 | windowWidth: 0, | ||
| 60 | }; | 61 | }; |
| 61 | }, | 62 | }, |
| 63 | computed: { | ||
| 64 | isMobileLayout() { | ||
| 65 | return this.windowWidth <= 768; | ||
| 66 | }, | ||
| 67 | }, | ||
| 62 | mounted () { | 68 | mounted () { |
| 69 | this.windowWidth = window.innerWidth; | ||
| 70 | window.addEventListener('resize', this.handleResize); | ||
| 71 | |||
| 63 | if (this.text !== '') { | 72 | if (this.text !== '') { |
| 64 | this.$data.code = this.text; | 73 | this.$data.code = this.text; |
| 65 | this.codeChanged(this.text); | 74 | this.codeChanged(this.text); |
| @@ -86,7 +95,13 @@ | |||
| 86 | })(this); | 95 | })(this); |
| 87 | check(); | 96 | check(); |
| 88 | }, | 97 | }, |
| 98 | beforeDestroy() { | ||
| 99 | window.removeEventListener('resize', this.handleResize); | ||
| 100 | }, | ||
| 89 | methods: { | 101 | methods: { |
| 102 | handleResize() { | ||
| 103 | this.windowWidth = window.innerWidth; | ||
| 104 | }, | ||
| 90 | runCode() { | 105 | runCode() { |
| 91 | if (window.yue && this.$data.compiled !== '') { | 106 | if (window.yue && this.$data.compiled !== '') { |
| 92 | let res = ''; | 107 | let res = ''; |
| @@ -136,27 +151,35 @@ | |||
| 136 | resize: none; | 151 | resize: none; |
| 137 | margin-top: 5px; | 152 | margin-top: 5px; |
| 138 | } | 153 | } |
| 139 | .childL { | 154 | |
| 140 | float: left; | 155 | .parent { |
| 141 | width: 50%; | 156 | display: flex; |
| 142 | box-sizing: border-box; | 157 | flex-wrap: wrap; |
| 143 | background-clip: content-box; | 158 | width: 100%; |
| 144 | background: #f5f7ff; | ||
| 145 | } | 159 | } |
| 146 | .childR { | 160 | |
| 147 | float: left; | 161 | .editor-section { |
| 148 | width: 50%; | 162 | width: 50%; |
| 149 | box-sizing: border-box; | 163 | box-sizing: border-box; |
| 150 | background-clip: content-box; | ||
| 151 | background: #f5f7ff; | 164 | background: #f5f7ff; |
| 152 | } | 165 | } |
| 166 | |||
| 167 | .editor-container { | ||
| 168 | height: 55vh; | ||
| 169 | } | ||
| 170 | |||
| 153 | .childTitle { | 171 | .childTitle { |
| 154 | width: 100%; | 172 | width: 100%; |
| 155 | font-size: 1.2em; | 173 | font-size: 1.2em; |
| 156 | color: #b7ae8f; | 174 | color: #b7ae8f; |
| 157 | text-align: center; | 175 | text-align: center; |
| 158 | padding: 0.2em; | 176 | padding: 0.2em; |
| 177 | height: 2.5em; | ||
| 178 | display: flex; | ||
| 179 | align-items: center; | ||
| 180 | justify-content: center; | ||
| 159 | } | 181 | } |
| 182 | |||
| 160 | .button { | 183 | .button { |
| 161 | float: right; | 184 | float: right; |
| 162 | border: none; | 185 | border: none; |
| @@ -173,9 +196,11 @@ | |||
| 173 | margin-top: 10px; | 196 | margin-top: 10px; |
| 174 | margin-right: 5px; | 197 | margin-right: 5px; |
| 175 | } | 198 | } |
| 199 | |||
| 176 | .button:hover { | 200 | .button:hover { |
| 177 | background-color: #beb69a; | 201 | background-color: #beb69a; |
| 178 | } | 202 | } |
| 203 | |||
| 179 | .button:focus, | 204 | .button:focus, |
| 180 | .button:active:focus, | 205 | .button:active:focus, |
| 181 | .button.active:focus, | 206 | .button.active:focus, |
| @@ -207,5 +232,19 @@ | |||
| 207 | .my-editor >>> .prism-editor__textarea:focus { | 232 | .my-editor >>> .prism-editor__textarea:focus { |
| 208 | outline: none; | 233 | outline: none; |
| 209 | } | 234 | } |
| 210 | </style> | ||
| 211 | 235 | ||
| 236 | /* 移动端å“应å¼å¸ƒå±€ */ | ||
| 237 | @media screen and (max-width: 768px) { | ||
| 238 | .parent { | ||
| 239 | flex-direction: column; | ||
| 240 | } | ||
| 241 | |||
| 242 | .editor-section { | ||
| 243 | width: 100%; | ||
| 244 | } | ||
| 245 | |||
| 246 | .editor-container { | ||
| 247 | height: 30vh; | ||
| 248 | } | ||
| 249 | } | ||
| 250 | </style> | ||
diff --git a/doc/docs/README.md b/doc/docs/README.md index 21e47c4..098d7da 100755 --- a/doc/docs/README.md +++ b/doc/docs/README.md | |||
| @@ -3,6 +3,6 @@ home: true | |||
| 3 | heroImage: ./image/yuescript.svg | 3 | heroImage: ./image/yuescript.svg |
| 4 | actionText: Quick Start → | 4 | actionText: Quick Start → |
| 5 | actionLink: /doc/ | 5 | actionLink: /doc/ |
| 6 | footer: MIT Licensed | Copyright © 2017-2025 Li Jin | 6 | footer: MIT Licensed | Copyright © 2017-2026 Li Jin |
| 7 | --- | 7 | --- |
| 8 | 8 | ||
diff --git a/doc/docs/doc/README.md b/doc/docs/doc/README.md index 0853391..5308ebc 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
| @@ -16,17 +16,17 @@ Yue (月) is the name of moon in Chinese and it's pronounced as [jyɛ]. | |||
| 16 | ### An Overview of YueScript | 16 | ### An Overview of YueScript |
| 17 | ```moonscript | 17 | ```moonscript |
| 18 | -- import syntax | 18 | -- import syntax |
| 19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
| 20 | 20 | ||
| 21 | -- object literals | 21 | -- object literals |
| 22 | inventory = | 22 | inventory = |
| 23 | equipment: | 23 | equipment: |
| 24 | * "sword" | 24 | - "sword" |
| 25 | * "shield" | 25 | - "shield" |
| 26 | items: | 26 | items: |
| 27 | * name: "potion" | 27 | - name: "potion" |
| 28 | count: 10 | 28 | count: 10 |
| 29 | * name: "bread" | 29 | - name: "bread" |
| 30 | count: 3 | 30 | count: 3 |
| 31 | 31 | ||
| 32 | -- list comprehension | 32 | -- list comprehension |
| @@ -61,17 +61,17 @@ export 🌛 = "月之脚本" | |||
| 61 | <YueDisplay> | 61 | <YueDisplay> |
| 62 | <pre> | 62 | <pre> |
| 63 | -- import syntax | 63 | -- import syntax |
| 64 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
| 65 | 65 | ||
| 66 | -- object literals | 66 | -- object literals |
| 67 | inventory = | 67 | inventory = |
| 68 | equipment: | 68 | equipment: |
| 69 | * "sword" | 69 | - "sword" |
| 70 | * "shield" | 70 | - "shield" |
| 71 | items: | 71 | items: |
| 72 | * name: "potion" | 72 | - name: "potion" |
| 73 | count: 10 | 73 | count: 10 |
| 74 | * name: "bread" | 74 | - name: "bread" |
| 75 | count: 3 | 75 | count: 3 |
| 76 | 76 | ||
| 77 | -- list comprehension | 77 | -- list comprehension |
| @@ -408,16 +408,16 @@ In YueScript, macro functions allow you to generate code at compile time. By nes | |||
| 408 | 408 | ||
| 409 | ```moonscript | 409 | ```moonscript |
| 410 | macro Enum = (...) -> | 410 | macro Enum = (...) -> |
| 411 | items = {...} | 411 | items = {...} |
| 412 | itemSet = {item, true for item in *items} | 412 | itemSet = {item, true for item in *items} |
| 413 | (item) -> | 413 | (item) -> |
| 414 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | 414 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] |
| 415 | "\"#{item}\"" | 415 | "\"#{item}\"" |
| 416 | 416 | ||
| 417 | macro BodyType = $Enum( | 417 | macro BodyType = $Enum( |
| 418 | Static | 418 | Static |
| 419 | Dynamic | 419 | Dynamic |
| 420 | Kinematic | 420 | Kinematic |
| 421 | ) | 421 | ) |
| 422 | 422 | ||
| 423 | print "Valid enum type:", $BodyType Static | 423 | print "Valid enum type:", $BodyType Static |
| @@ -427,16 +427,16 @@ print "Valid enum type:", $BodyType Static | |||
| 427 | <YueDisplay> | 427 | <YueDisplay> |
| 428 | <pre> | 428 | <pre> |
| 429 | macro Enum = (...) -> | 429 | macro Enum = (...) -> |
| 430 | items = {...} | 430 | items = {...} |
| 431 | itemSet = {item, true for item in *items} | 431 | itemSet = {item, true for item in *items} |
| 432 | (item) -> | 432 | (item) -> |
| 433 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | 433 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] |
| 434 | "\"#{item}\"" | 434 | "\"#{item}\"" |
| 435 | 435 | ||
| 436 | macro BodyType = $Enum( | 436 | macro BodyType = $Enum( |
| 437 | Static | 437 | Static |
| 438 | Dynamic | 438 | Dynamic |
| 439 | Kinematic | 439 | Kinematic |
| 440 | ) | 440 | ) |
| 441 | 441 | ||
| 442 | print "Valid enum type:", $BodyType Static | 442 | print "Valid enum type:", $BodyType Static |
| @@ -444,6 +444,54 @@ print "Valid enum type:", $BodyType Static | |||
| 444 | </pre> | 444 | </pre> |
| 445 | </YueDisplay> | 445 | </YueDisplay> |
| 446 | 446 | ||
| 447 | ### Argument Validation | ||
| 448 | |||
| 449 | You can declare the expected AST node types in the argument list, and check whether the incoming macro arguments meet the expectations at compile time. | ||
| 450 | |||
| 451 | ```moonscript | ||
| 452 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 453 | print( | ||
| 454 | #{num} | ||
| 455 | #{str} | ||
| 456 | ) | ||
| 457 | |||
| 458 | $printNumAndStr 123, "hello" | ||
| 459 | ``` | ||
| 460 | <YueDisplay> | ||
| 461 | <pre> | ||
| 462 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 463 | print( | ||
| 464 | #{num} | ||
| 465 | #{str} | ||
| 466 | ) | ||
| 467 | |||
| 468 | $printNumAndStr 123, "hello" | ||
| 469 | </pre> | ||
| 470 | </YueDisplay> | ||
| 471 | |||
| 472 | If you need more flexible argument checking, you can use the built-in `$is_ast` macro function to manually check at the appropriate place. | ||
| 473 | |||
| 474 | ```moonscript | ||
| 475 | macro printNumAndStr = (num, str) -> | ||
| 476 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 477 | error "expected String as second argument" unless $is_ast String, str | ||
| 478 | "print(#{num}, #{str})" | ||
| 479 | |||
| 480 | $printNumAndStr 123, "hello" | ||
| 481 | ``` | ||
| 482 | <YueDisplay> | ||
| 483 | <pre> | ||
| 484 | macro printNumAndStr = (num, str) -> | ||
| 485 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 486 | error "expected String as second argument" unless $is_ast String, str | ||
| 487 | "print(#{num}, #{str})" | ||
| 488 | |||
| 489 | $printNumAndStr 123, "hello" | ||
| 490 | </pre> | ||
| 491 | </YueDisplay> | ||
| 492 | |||
| 493 | For more details about available AST nodes, please refer to the uppercased definitions in [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp). | ||
| 494 | |||
| 447 | ## Operator | 495 | ## Operator |
| 448 | 496 | ||
| 449 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. | 497 | All of Lua's binary and unary operators are available. Additionally **!=** is as an alias for **~=**, and either **\\** or **::** can be used to write a chaining function call like `tb\func!` or `tb::func!`. And Yuescipt offers some other special operators to write more expressive codes. |
| @@ -486,47 +534,47 @@ Note the evaluation behavior of chained comparisons: | |||
| 486 | 534 | ||
| 487 | ```moonscript | 535 | ```moonscript |
| 488 | v = (x) -> | 536 | v = (x) -> |
| 489 | print x | 537 | print x |
| 490 | x | 538 | x |
| 491 | 539 | ||
| 492 | print v(1) < v(2) <= v(3) | 540 | print v(1) < v(2) <= v(3) |
| 493 | --[[ | 541 | --[[ |
| 494 | output: | 542 | output: |
| 495 | 2 | 543 | 2 |
| 496 | 1 | 544 | 1 |
| 497 | 3 | 545 | 3 |
| 498 | true | 546 | true |
| 499 | ]] | 547 | ]] |
| 500 | 548 | ||
| 501 | print v(1) > v(2) <= v(3) | 549 | print v(1) > v(2) <= v(3) |
| 502 | --[[ | 550 | --[[ |
| 503 | output: | 551 | output: |
| 504 | 2 | 552 | 2 |
| 505 | 1 | 553 | 1 |
| 506 | false | 554 | false |
| 507 | ]] | 555 | ]] |
| 508 | ``` | 556 | ``` |
| 509 | <YueDisplay> | 557 | <YueDisplay> |
| 510 | <pre> | 558 | <pre> |
| 511 | v = (x) -> | 559 | v = (x) -> |
| 512 | print x | 560 | print x |
| 513 | x | 561 | x |
| 514 | 562 | ||
| 515 | print v(1) < v(2) <= v(3) | 563 | print v(1) < v(2) <= v(3) |
| 516 | --[[ | 564 | --[[ |
| 517 | output: | 565 | output: |
| 518 | 2 | 566 | 2 |
| 519 | 1 | 567 | 1 |
| 520 | 3 | 568 | 3 |
| 521 | true | 569 | true |
| 522 | ]] | 570 | ]] |
| 523 | 571 | ||
| 524 | print v(1) > v(2) <= v(3) | 572 | print v(1) > v(2) <= v(3) |
| 525 | --[[ | 573 | --[[ |
| 526 | output: | 574 | output: |
| 527 | 2 | 575 | 2 |
| 528 | 1 | 576 | 1 |
| 529 | false | 577 | false |
| 530 | ]] | 578 | ]] |
| 531 | </pre> | 579 | </pre> |
| 532 | </YueDisplay> | 580 | </YueDisplay> |
| @@ -547,19 +595,36 @@ tab[] = "Value" | |||
| 547 | </pre> | 595 | </pre> |
| 548 | </YueDisplay> | 596 | </YueDisplay> |
| 549 | 597 | ||
| 598 | You can also use the spread operator `...` to append all elements from one list to another: | ||
| 599 | |||
| 600 | ```moonscript | ||
| 601 | tbA = [1, 2, 3] | ||
| 602 | tbB = [4, 5, 6] | ||
| 603 | tbA[] = ...tbB | ||
| 604 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 605 | ``` | ||
| 606 | <YueDisplay> | ||
| 607 | <pre> | ||
| 608 | tbA = [1, 2, 3] | ||
| 609 | tbB = [4, 5, 6] | ||
| 610 | tbA[] = ...tbB | ||
| 611 | -- tbA is now [1, 2, 3, 4, 5, 6] | ||
| 612 | </pre> | ||
| 613 | </YueDisplay> | ||
| 614 | |||
| 550 | ### Table Spreading | 615 | ### Table Spreading |
| 551 | 616 | ||
| 552 | You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. | 617 | You can concatenate array tables or hash tables using spread operator `...` before expressions in table literals. |
| 553 | 618 | ||
| 554 | ```moonscript | 619 | ```moonscript |
| 555 | parts = | 620 | parts = |
| 556 | * "shoulders" | 621 | * "shoulders" |
| 557 | * "knees" | 622 | * "knees" |
| 558 | lyrics = | 623 | lyrics = |
| 559 | * "head" | 624 | * "head" |
| 560 | * ...parts | 625 | * ...parts |
| 561 | * "and" | 626 | * "and" |
| 562 | * "toes" | 627 | * "toes" |
| 563 | 628 | ||
| 564 | copy = {...other} | 629 | copy = {...other} |
| 565 | 630 | ||
| @@ -570,13 +635,13 @@ merge = {...a, ...b} | |||
| 570 | <YueDisplay> | 635 | <YueDisplay> |
| 571 | <pre> | 636 | <pre> |
| 572 | parts = | 637 | parts = |
| 573 | * "shoulders" | 638 | * "shoulders" |
| 574 | * "knees" | 639 | * "knees" |
| 575 | lyrics = | 640 | lyrics = |
| 576 | * "head" | 641 | * "head" |
| 577 | * ...parts | 642 | * ...parts |
| 578 | * "and" | 643 | * "and" |
| 579 | * "toes" | 644 | * "toes" |
| 580 | 645 | ||
| 581 | copy = {...other} | 646 | copy = {...other} |
| 582 | 647 | ||
| @@ -586,6 +651,23 @@ merge = {...a, ...b} | |||
| 586 | </pre> | 651 | </pre> |
| 587 | </YueDisplay> | 652 | </YueDisplay> |
| 588 | 653 | ||
| 654 | ### Table Reversed Indexing | ||
| 655 | |||
| 656 | You can use the **#** operator to get the last elements of a table. | ||
| 657 | |||
| 658 | ```moonscript | ||
| 659 | last = data.items[#] | ||
| 660 | second_last = data.items[#-1] | ||
| 661 | data.items[#] = 1 | ||
| 662 | ``` | ||
| 663 | <YueDisplay> | ||
| 664 | <pre> | ||
| 665 | last = data.items[#] | ||
| 666 | second_last = data.items[#-1] | ||
| 667 | data.items[#] = 1 | ||
| 668 | </pre> | ||
| 669 | </YueDisplay> | ||
| 670 | |||
| 589 | ### Metatable | 671 | ### Metatable |
| 590 | 672 | ||
| 591 | The **<>** operator can be used as a shortcut for metatable manipulation. | 673 | The **<>** operator can be used as a shortcut for metatable manipulation. |
| @@ -752,34 +834,45 @@ a ??= false | |||
| 752 | 834 | ||
| 753 | ### Implicit Object | 835 | ### Implicit Object |
| 754 | 836 | ||
| 755 | You can write a list of implicit structures that starts with the symbol **\*** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. | 837 | You can write a list of implicit structures that starts with the symbol **\*** or **-** inside a table block. If you are creating implicit object, the fields of the object must be with the same indent. |
| 838 | |||
| 756 | ```moonscript | 839 | ```moonscript |
| 840 | -- assignment with implicit object | ||
| 757 | list = | 841 | list = |
| 758 | * 1 | 842 | * 1 |
| 759 | * 2 | 843 | * 2 |
| 760 | * 3 | 844 | * 3 |
| 761 | 845 | ||
| 846 | -- function call with implicit object | ||
| 762 | func | 847 | func |
| 763 | * 1 | 848 | * 1 |
| 764 | * 2 | 849 | * 2 |
| 765 | * 3 | 850 | * 3 |
| 766 | 851 | ||
| 852 | -- return with implicit object | ||
| 853 | f = -> | ||
| 854 | return | ||
| 855 | * 1 | ||
| 856 | * 2 | ||
| 857 | * 3 | ||
| 858 | |||
| 859 | -- table with implicit object | ||
| 767 | tb = | 860 | tb = |
| 768 | name: "abc" | 861 | name: "abc" |
| 769 | 862 | ||
| 770 | values: | 863 | values: |
| 771 | * "a" | 864 | - "a" |
| 772 | * "b" | 865 | - "b" |
| 773 | * "c" | 866 | - "c" |
| 774 | 867 | ||
| 775 | objects: | 868 | objects: |
| 776 | * name: "a" | 869 | - name: "a" |
| 777 | value: 1 | 870 | value: 1 |
| 778 | func: => @value + 1 | 871 | func: => @value + 1 |
| 779 | tb: | 872 | tb: |
| 780 | fieldA: 1 | 873 | fieldA: 1 |
| 781 | 874 | ||
| 782 | * name: "b" | 875 | - name: "b" |
| 783 | value: 2 | 876 | value: 2 |
| 784 | func: => @value + 2 | 877 | func: => @value + 2 |
| 785 | tb: { } | 878 | tb: { } |
| @@ -787,32 +880,42 @@ tb = | |||
| 787 | ``` | 880 | ``` |
| 788 | <YueDisplay> | 881 | <YueDisplay> |
| 789 | <pre> | 882 | <pre> |
| 883 | -- assignment with implicit object | ||
| 790 | list = | 884 | list = |
| 791 | * 1 | 885 | * 1 |
| 792 | * 2 | 886 | * 2 |
| 793 | * 3 | 887 | * 3 |
| 794 | 888 | ||
| 889 | -- function call with implicit object | ||
| 795 | func | 890 | func |
| 796 | * 1 | 891 | * 1 |
| 797 | * 2 | 892 | * 2 |
| 798 | * 3 | 893 | * 3 |
| 799 | 894 | ||
| 895 | -- return with implicit object | ||
| 896 | f = -> | ||
| 897 | return | ||
| 898 | * 1 | ||
| 899 | * 2 | ||
| 900 | * 3 | ||
| 901 | |||
| 902 | -- table with implicit object | ||
| 800 | tb = | 903 | tb = |
| 801 | name: "abc" | 904 | name: "abc" |
| 802 | 905 | ||
| 803 | values: | 906 | values: |
| 804 | * "a" | 907 | - "a" |
| 805 | * "b" | 908 | - "b" |
| 806 | * "c" | 909 | - "c" |
| 807 | 910 | ||
| 808 | objects: | 911 | objects: |
| 809 | * name: "a" | 912 | - name: "a" |
| 810 | value: 1 | 913 | value: 1 |
| 811 | func: => @value + 1 | 914 | func: => @value + 1 |
| 812 | tb: | 915 | tb: |
| 813 | fieldA: 1 | 916 | fieldA: 1 |
| 814 | 917 | ||
| 815 | * name: "b" | 918 | - name: "b" |
| 816 | value: 2 | 919 | value: 2 |
| 817 | func: => @value + 2 | 920 | func: => @value + 2 |
| 818 | tb: { } | 921 | tb: { } |
| @@ -1222,7 +1325,7 @@ If the destructuring statement is complicated, feel free to spread it out over a | |||
| 1222 | </pre> | 1325 | </pre> |
| 1223 | </YueDisplay> | 1326 | </YueDisplay> |
| 1224 | 1327 | ||
| 1225 | It’s common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: | 1328 | It's common to extract values from at table and assign them the local variables that have the same name as the key. In order to avoid repetition we can use the **:** prefix operator: |
| 1226 | 1329 | ||
| 1227 | ```moonscript | 1330 | ```moonscript |
| 1228 | {:concat, :insert} = table | 1331 | {:concat, :insert} = table |
| @@ -1266,6 +1369,52 @@ You can use `_` as placeholder when doing a list destructuring: | |||
| 1266 | </pre> | 1369 | </pre> |
| 1267 | </YueDisplay> | 1370 | </YueDisplay> |
| 1268 | 1371 | ||
| 1372 | ### Range Destructuring | ||
| 1373 | |||
| 1374 | You can use the spread operator `...` in list destructuring to capture a range of values. This is useful when you want to extract specific elements from the beginning and end of a list while collecting the rest in between. | ||
| 1375 | |||
| 1376 | ```moonscript | ||
| 1377 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1378 | [first, ...bulk, last] = orders | ||
| 1379 | print first -- prints: first | ||
| 1380 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 1381 | print last -- prints: last | ||
| 1382 | ``` | ||
| 1383 | <YueDisplay> | ||
| 1384 | <pre> | ||
| 1385 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1386 | [first, ...bulk, last] = orders | ||
| 1387 | print first -- prints: first | ||
| 1388 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 1389 | print last -- prints: last | ||
| 1390 | </pre> | ||
| 1391 | </YueDisplay> | ||
| 1392 | |||
| 1393 | The spread operator can be used in different positions to capture different ranges, and you can use `_` as a placeholder for the values you don't want to capture: | ||
| 1394 | |||
| 1395 | ```moonscript | ||
| 1396 | -- Capture everything after first element | ||
| 1397 | [first, ...rest] = orders | ||
| 1398 | |||
| 1399 | -- Capture everything before last element | ||
| 1400 | [...start, last] = orders | ||
| 1401 | |||
| 1402 | -- Capture things except the middle elements | ||
| 1403 | [first, ..._, last] = orders | ||
| 1404 | ``` | ||
| 1405 | <YueDisplay> | ||
| 1406 | <pre> | ||
| 1407 | -- Capture everything after first element | ||
| 1408 | [first, ...rest] = orders | ||
| 1409 | |||
| 1410 | -- Capture everything before last element | ||
| 1411 | [...start, last] = orders | ||
| 1412 | |||
| 1413 | -- Capture things except the middle elements | ||
| 1414 | [first, ..._, last] = orders | ||
| 1415 | </pre> | ||
| 1416 | </YueDisplay> | ||
| 1417 | |||
| 1269 | ### Destructuring In Other Places | 1418 | ### Destructuring In Other Places |
| 1270 | 1419 | ||
| 1271 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | 1420 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: |
| @@ -1495,6 +1644,47 @@ catch err | |||
| 1495 | </pre> | 1644 | </pre> |
| 1496 | </YueDisplay> | 1645 | </YueDisplay> |
| 1497 | 1646 | ||
| 1647 | ### Try? | ||
| 1648 | |||
| 1649 | `try?` is a simplified use for error handling syntax that omit the boolean status from the `try` statement, and it will return the result from the try block when success, return nil instead of error object otherwise. | ||
| 1650 | |||
| 1651 | ```moonscript | ||
| 1652 | a, b, c = try? func! | ||
| 1653 | |||
| 1654 | -- with nil coalescing operator | ||
| 1655 | a = (try? func!) ?? "default" | ||
| 1656 | |||
| 1657 | -- as function argument | ||
| 1658 | f try? func! | ||
| 1659 | |||
| 1660 | -- with catch block | ||
| 1661 | f try? | ||
| 1662 | print 123 | ||
| 1663 | func! | ||
| 1664 | catch e | ||
| 1665 | print e | ||
| 1666 | e | ||
| 1667 | ``` | ||
| 1668 | <YueDisplay> | ||
| 1669 | <pre> | ||
| 1670 | a, b, c = try? func! | ||
| 1671 | |||
| 1672 | -- with nil coalescing operator | ||
| 1673 | a = (try? func!) ?? "default" | ||
| 1674 | |||
| 1675 | -- as function argument | ||
| 1676 | f try? func! | ||
| 1677 | |||
| 1678 | -- with catch block | ||
| 1679 | f try? | ||
| 1680 | print 123 | ||
| 1681 | func! | ||
| 1682 | catch e | ||
| 1683 | print e | ||
| 1684 | e | ||
| 1685 | </pre> | ||
| 1686 | </YueDisplay> | ||
| 1687 | |||
| 1498 | ## Attributes | 1688 | ## Attributes |
| 1499 | 1689 | ||
| 1500 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. | 1690 | Syntax support for Lua 5.4 attributes. And you can still use both the `const` and `close` declaration and get constant check and scoped callback working when targeting Lua versions below 5.4. |
| @@ -1575,6 +1765,66 @@ binary = 0B10011 | |||
| 1575 | <pre> | 1765 | <pre> |
| 1576 | integer = 1_000_000 | 1766 | integer = 1_000_000 |
| 1577 | hex = 0xEF_BB_BF | 1767 | hex = 0xEF_BB_BF |
| 1768 | binary = 0B10011 | ||
| 1769 | </pre> | ||
| 1770 | </YueDisplay> | ||
| 1771 | |||
| 1772 | ### YAML Multiline String | ||
| 1773 | |||
| 1774 | The `|` prefix introduces a YAML-style multiline string literal: | ||
| 1775 | |||
| 1776 | ```moonscript | ||
| 1777 | str = | | ||
| 1778 | key: value | ||
| 1779 | list: | ||
| 1780 | - item1 | ||
| 1781 | - #{expr} | ||
| 1782 | ``` | ||
| 1783 | <YueDisplay> | ||
| 1784 | <pre> | ||
| 1785 | str = | | ||
| 1786 | key: value | ||
| 1787 | list: | ||
| 1788 | - item1 | ||
| 1789 | - #{expr} | ||
| 1790 | </pre> | ||
| 1791 | </YueDisplay> | ||
| 1792 | |||
| 1793 | This allows writing structured multiline text conveniently. All line breaks and indentation are preserved relative to the first non-empty line, and expressions inside `#{...}` are interpolated automatically as `tostring(expr)`. | ||
| 1794 | |||
| 1795 | YAML Multiline String automatically detects the common leading whitespace prefix (minimum indentation across all non-empty lines) and removes it from all lines. This makes it easy to indent your code visually without affecting the resulting string content. | ||
| 1796 | |||
| 1797 | ```moonscript | ||
| 1798 | fn = -> | ||
| 1799 | str = | | ||
| 1800 | foo: | ||
| 1801 | bar: baz | ||
| 1802 | return str | ||
| 1803 | ``` | ||
| 1804 | <YueDisplay> | ||
| 1805 | <pre> | ||
| 1806 | fn = -> | ||
| 1807 | str = | | ||
| 1808 | foo: | ||
| 1809 | bar: baz | ||
| 1810 | return str | ||
| 1811 | </pre> | ||
| 1812 | </YueDisplay> | ||
| 1813 | |||
| 1814 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
| 1815 | |||
| 1816 | All special characters like quotes (`"`) and backslashes (`\`) in the YAMLMultiline block are automatically escaped so that the generated Lua string is syntactically valid and behaves as expected. | ||
| 1817 | |||
| 1818 | ```moonscript | ||
| 1819 | str = | | ||
| 1820 | path: "C:\Program Files\App" | ||
| 1821 | note: 'He said: "#{Hello}!"' | ||
| 1822 | ``` | ||
| 1823 | <YueDisplay> | ||
| 1824 | <pre> | ||
| 1825 | str = | | ||
| 1826 | path: "C:\Program Files\App" | ||
| 1827 | note: 'He said: "#{Hello}!"' | ||
| 1578 | </pre> | 1828 | </pre> |
| 1579 | </YueDisplay> | 1829 | </YueDisplay> |
| 1580 | 1830 | ||
| @@ -1895,6 +2145,138 @@ if func 1, 2, 3, | |||
| 1895 | </pre> | 2145 | </pre> |
| 1896 | </YueDisplay> | 2146 | </YueDisplay> |
| 1897 | 2147 | ||
| 2148 | ### Parameter Destructuring | ||
| 2149 | |||
| 2150 | YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available: | ||
| 2151 | |||
| 2152 | * **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`). | ||
| 2153 | |||
| 2154 | * **Unwrapped simple table syntax**, starting with a sequence of key-value or shorthand bindings and continuing until another expression terminates it (e.g., `:a, b: b1, :c`). This form extracts multiple fields from the same object. | ||
| 2155 | |||
| 2156 | ```moonscript | ||
| 2157 | f1 = (:a, :b, :c) -> | ||
| 2158 | print a, b, c | ||
| 2159 | |||
| 2160 | f1 a: 1, b: "2", c: {} | ||
| 2161 | |||
| 2162 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2163 | print a1, b, c | ||
| 2164 | |||
| 2165 | arg1 = {a: 0} | ||
| 2166 | f2 arg1, arg2 | ||
| 2167 | ``` | ||
| 2168 | <YueDisplay> | ||
| 2169 | <pre> | ||
| 2170 | f1 = (:a, :b, :c) -> | ||
| 2171 | print a, b, c | ||
| 2172 | |||
| 2173 | f1 a: 1, b: "2", c: {} | ||
| 2174 | |||
| 2175 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2176 | print a1, b, c | ||
| 2177 | |||
| 2178 | arg1 = {a: 0} | ||
| 2179 | f2 arg1, arg2 | ||
| 2180 | </pre> | ||
| 2181 | </YueDisplay> | ||
| 2182 | |||
| 2183 | ### Prefixed Return Expression | ||
| 2184 | |||
| 2185 | When working with deeply nested function bodies, it can be tedious to maintain readability and consistency of the return value. To address this, YueScript introduces the **Prefixed Return Expression** syntax. Its form is as follows: | ||
| 2186 | |||
| 2187 | ```moon | ||
| 2188 | findFirstEven = (list): nil -> | ||
| 2189 | for item in *list | ||
| 2190 | if type(item) == "table" | ||
| 2191 | for sub in *item | ||
| 2192 | if sub % 2 == 0 | ||
| 2193 | return sub | ||
| 2194 | ``` | ||
| 2195 | <YueDisplay> | ||
| 2196 | <pre> | ||
| 2197 | findFirstEven = (list): nil -> | ||
| 2198 | for item in *list | ||
| 2199 | if type(item) == "table" | ||
| 2200 | for sub in *item | ||
| 2201 | if sub % 2 == 0 | ||
| 2202 | return sub | ||
| 2203 | </pre> | ||
| 2204 | </YueDisplay> | ||
| 2205 | |||
| 2206 | This is equivalent to: | ||
| 2207 | |||
| 2208 | ```moon | ||
| 2209 | findFirstEven = (list) -> | ||
| 2210 | for item in *list | ||
| 2211 | if type(item) == "table" | ||
| 2212 | for sub in *item | ||
| 2213 | if sub % 2 == 0 | ||
| 2214 | return sub | ||
| 2215 | nil | ||
| 2216 | ``` | ||
| 2217 | <YueDisplay> | ||
| 2218 | <pre> | ||
| 2219 | findFirstEven = (list) -> | ||
| 2220 | for item in *list | ||
| 2221 | if type(item) == "table" | ||
| 2222 | for sub in *item | ||
| 2223 | if sub % 2 == 0 | ||
| 2224 | return sub | ||
| 2225 | nil | ||
| 2226 | </pre> | ||
| 2227 | </YueDisplay> | ||
| 2228 | |||
| 2229 | The only difference is that you can move the final return expression before the `->` or `=>` token to indicate the function’s implicit return value as the last statement. This way, even in functions with multiple nested loops or conditional branches, you no longer need to write a trailing return expression at the end of the function body, making the logic structure more straightforward and easier to follow. | ||
| 2230 | |||
| 2231 | ### Named Varargs | ||
| 2232 | |||
| 2233 | You can use the `(...t) ->` syntax to automatically store varargs into a named table. This table will contain all passed arguments (including `nil` values), and the `n` field of the table will store the actual number of arguments passed (including `nil` values). | ||
| 2234 | |||
| 2235 | ```moonscript | ||
| 2236 | f = (...t) -> | ||
| 2237 | print "argument count:", t.n | ||
| 2238 | print "table length:", #t | ||
| 2239 | for i = 1, t.n | ||
| 2240 | print t[i] | ||
| 2241 | |||
| 2242 | f 1, 2, 3 | ||
| 2243 | f "a", "b", "c", "d" | ||
| 2244 | f! | ||
| 2245 | |||
| 2246 | -- Handling cases with nil values | ||
| 2247 | process = (...args) -> | ||
| 2248 | sum = 0 | ||
| 2249 | for i = 1, args.n | ||
| 2250 | if args[i] != nil and type(args[i]) == "number" | ||
| 2251 | sum += args[i] | ||
| 2252 | sum | ||
| 2253 | |||
| 2254 | process 1, nil, 3, nil, 5 | ||
| 2255 | ``` | ||
| 2256 | <YueDisplay> | ||
| 2257 | <pre> | ||
| 2258 | f = (...t) -> | ||
| 2259 | print "argument count:", t.n | ||
| 2260 | print "table length:", #t | ||
| 2261 | for i = 1, t.n | ||
| 2262 | print t[i] | ||
| 2263 | |||
| 2264 | f 1, 2, 3 | ||
| 2265 | f "a", "b", "c", "d" | ||
| 2266 | f! | ||
| 2267 | |||
| 2268 | -- Handling cases with nil values | ||
| 2269 | process = (...args) -> | ||
| 2270 | sum = 0 | ||
| 2271 | for i = 1, args.n | ||
| 2272 | if args[i] != nil and type(args[i]) == "number" | ||
| 2273 | sum += args[i] | ||
| 2274 | sum | ||
| 2275 | |||
| 2276 | process 1, nil, 3, nil, 5 | ||
| 2277 | </pre> | ||
| 2278 | </YueDisplay> | ||
| 2279 | |||
| 1898 | ## Backcalls | 2280 | ## Backcalls |
| 1899 | 2281 | ||
| 1900 | Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent. | 2282 | Backcalls are used for unnesting callbacks. They are defined using arrows pointed to the left as the last parameter by default filling in a function call. All the syntax is mostly the same as regular arrow functions except that it is just pointing the other way and the function body does not require indent. |
| @@ -2149,6 +2531,27 @@ doubled = [item * 2 for item in *items] | |||
| 2149 | </pre> | 2531 | </pre> |
| 2150 | </YueDisplay> | 2532 | </YueDisplay> |
| 2151 | 2533 | ||
| 2534 | In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect: | ||
| 2535 | |||
| 2536 | ```moonscript | ||
| 2537 | data = | ||
| 2538 | a: [1, 2, 3] | ||
| 2539 | b: [4, 5, 6] | ||
| 2540 | |||
| 2541 | flat = [...v for k,v in pairs data] | ||
| 2542 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2543 | ``` | ||
| 2544 | <YueDisplay> | ||
| 2545 | <pre> | ||
| 2546 | data = | ||
| 2547 | a: [1, 2, 3] | ||
| 2548 | b: [4, 5, 6] | ||
| 2549 | |||
| 2550 | flat = [...v for k,v in pairs data] | ||
| 2551 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2552 | </pre> | ||
| 2553 | </YueDisplay> | ||
| 2554 | |||
| 2152 | The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. | 2555 | The for and when clauses can be chained as much as desired. The only requirement is that a comprehension has at least one for clause. |
| 2153 | 2556 | ||
| 2154 | Using multiple for clauses is the same as using nested loops: | 2557 | Using multiple for clauses is the same as using nested loops: |
| @@ -2282,6 +2685,45 @@ slice = [item for item in *items[,,2]] | |||
| 2282 | </pre> | 2685 | </pre> |
| 2283 | </YueDisplay> | 2686 | </YueDisplay> |
| 2284 | 2687 | ||
| 2688 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
| 2689 | |||
| 2690 | ```moonscript | ||
| 2691 | -- take the last 4 items | ||
| 2692 | slice = [item for item in *items[-4,-1]] | ||
| 2693 | ``` | ||
| 2694 | <YueDisplay> | ||
| 2695 | <pre> | ||
| 2696 | -- take the last 4 items | ||
| 2697 | slice = [item for item in *items[-4,-1]] | ||
| 2698 | </pre> | ||
| 2699 | </YueDisplay> | ||
| 2700 | |||
| 2701 | The step size can also be negative, which means that the items are taken in reverse order. | ||
| 2702 | |||
| 2703 | ```moonscript | ||
| 2704 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2705 | ``` | ||
| 2706 | <YueDisplay> | ||
| 2707 | <pre> | ||
| 2708 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2709 | </pre> | ||
| 2710 | </YueDisplay> | ||
| 2711 | |||
| 2712 | #### Slicing Expression | ||
| 2713 | |||
| 2714 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
| 2715 | |||
| 2716 | ```moonscript | ||
| 2717 | -- take the 2nd and 4th items as a new list | ||
| 2718 | sub_list = items[2, 4] | ||
| 2719 | ``` | ||
| 2720 | <YueDisplay> | ||
| 2721 | <pre> | ||
| 2722 | -- take the 2nd and 4th items as a new list | ||
| 2723 | sub_list = items[2, 4] | ||
| 2724 | </pre> | ||
| 2725 | </YueDisplay> | ||
| 2726 | |||
| 2285 | ## For Loop | 2727 | ## For Loop |
| 2286 | 2728 | ||
| 2287 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | 2729 | There are two for loop forms, just like in Lua. A numeric one and a generic one: |
| @@ -2396,7 +2838,7 @@ print func_b! -- prints table object | |||
| 2396 | </pre> | 2838 | </pre> |
| 2397 | </YueDisplay> | 2839 | </YueDisplay> |
| 2398 | 2840 | ||
| 2399 | This is done to avoid the needless creation of tables for functions that don’t need to return the results of the loop. | 2841 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. |
| 2400 | 2842 | ||
| 2401 | ## Repeat Loop | 2843 | ## Repeat Loop |
| 2402 | 2844 | ||
| @@ -2675,28 +3117,26 @@ reader\parse_line! until reader\eof! | |||
| 2675 | 3117 | ||
| 2676 | ## Switch | 3118 | ## Switch |
| 2677 | 3119 | ||
| 2678 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. | 3120 | The switch statement is shorthand for writing a series of if statements that check against the same value. Note that the value is only evaluated once. Like if statements, switches can have an else block to handle no matches. Comparison is done with the == operator. In switch statement, you can also use assignment expression to store temporary variable value. |
| 2679 | 3121 | ||
| 2680 | ```moonscript | 3122 | ```moonscript |
| 2681 | name = "Dan" | 3123 | switch name := "Dan" |
| 2682 | switch name | ||
| 2683 | when "Robert" | 3124 | when "Robert" |
| 2684 | print "You are Robert" | 3125 | print "You are Robert" |
| 2685 | when "Dan", "Daniel" | 3126 | when "Dan", "Daniel" |
| 2686 | print "Your name, it's Dan" | 3127 | print "Your name, it's Dan" |
| 2687 | else | 3128 | else |
| 2688 | print "I don't know about your name" | 3129 | print "I don't know about you with name #{name}" |
| 2689 | ``` | 3130 | ``` |
| 2690 | <YueDisplay> | 3131 | <YueDisplay> |
| 2691 | <pre> | 3132 | <pre> |
| 2692 | name = "Dan" | 3133 | switch name := "Dan" |
| 2693 | switch name | ||
| 2694 | when "Robert" | 3134 | when "Robert" |
| 2695 | print "You are Robert" | 3135 | print "You are Robert" |
| 2696 | when "Dan", "Daniel" | 3136 | when "Dan", "Daniel" |
| 2697 | print "Your name, it's Dan" | 3137 | print "Your name, it's Dan" |
| 2698 | else | 3138 | else |
| 2699 | print "I don't know about your name" | 3139 | print "I don't know about you with name #{name}" |
| 2700 | </pre> | 3140 | </pre> |
| 2701 | </YueDisplay> | 3141 | </YueDisplay> |
| 2702 | 3142 | ||
| @@ -2727,7 +3167,7 @@ next_number = switch b | |||
| 2727 | </pre> | 3167 | </pre> |
| 2728 | </YueDisplay> | 3168 | </YueDisplay> |
| 2729 | 3169 | ||
| 2730 | We can use the then keyword to write a switch’s when block on a single line. No extra keyword is needed to write the else block on a single line. | 3170 | We can use the then keyword to write a switch's when block on a single line. No extra keyword is needed to write the else block on a single line. |
| 2731 | 3171 | ||
| 2732 | ```moonscript | 3172 | ```moonscript |
| 2733 | msg = switch math.random(1, 5) | 3173 | msg = switch math.random(1, 5) |
| @@ -2773,7 +3213,7 @@ else | |||
| 2773 | </pre> | 3213 | </pre> |
| 2774 | </YueDisplay> | 3214 | </YueDisplay> |
| 2775 | 3215 | ||
| 2776 | It is worth noting the order of the case comparison expression. The case’s expression is on the left hand side. This can be useful if the case’s expression wants to overwrite how the comparison is done by defining an eq metamethod. | 3216 | It is worth noting the order of the case comparison expression. The case's expression is on the left hand side. This can be useful if the case's expression wants to overwrite how the comparison is done by defining an eq metamethod. |
| 2777 | 3217 | ||
| 2778 | ### Table Matching | 3218 | ### Table Matching |
| 2779 | 3219 | ||
| @@ -2929,6 +3369,27 @@ switch tb | |||
| 2929 | </pre> | 3369 | </pre> |
| 2930 | </YueDisplay> | 3370 | </YueDisplay> |
| 2931 | 3371 | ||
| 3372 | Match against a list and capture a range of elements. | ||
| 3373 | |||
| 3374 | ```moonscript | ||
| 3375 | segments = ["admin", "users", "logs", "view"] | ||
| 3376 | switch segments | ||
| 3377 | when [...groups, resource, action] | ||
| 3378 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3379 | print "Resource:", resource -- prints: "logs" | ||
| 3380 | print "Action:", action -- prints: "view" | ||
| 3381 | ``` | ||
| 3382 | <YueDisplay> | ||
| 3383 | <pre> | ||
| 3384 | segments = ["admin", "users", "logs", "view"] | ||
| 3385 | switch segments | ||
| 3386 | when [...groups, resource, action] | ||
| 3387 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3388 | print "Resource:", resource -- prints: "logs" | ||
| 3389 | print "Action:", action -- prints: "view" | ||
| 3390 | </pre> | ||
| 3391 | </YueDisplay> | ||
| 3392 | |||
| 2932 | ## Object Oriented Programming | 3393 | ## Object Oriented Programming |
| 2933 | 3394 | ||
| 2934 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. | 3395 | In these examples, the generated Lua code may appear overwhelming. It is best to focus on the meaning of the YueScript code at first, then look into the Lua code if you wish to know the implementation details. |
| @@ -3060,7 +3521,7 @@ class BackPack extends Inventory | |||
| 3060 | 3521 | ||
| 3061 | Here we extend our Inventory class, and limit the amount of items it can carry. | 3522 | Here we extend our Inventory class, and limit the amount of items it can carry. |
| 3062 | 3523 | ||
| 3063 | In this example, we don’t define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. | 3524 | In this example, we don't define a constructor on the subclass, so the parent class' constructor is called when we make a new instance. If we did define a constructor then we can use the super method to call the parent constructor. |
| 3064 | 3525 | ||
| 3065 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. | 3526 | Whenever a class inherits from another, it sends a message to the parent class by calling the method __inherited on the parent class if it exists. The function receives two arguments, the class that is being inherited and the child class. |
| 3066 | 3527 | ||
| @@ -3147,13 +3608,13 @@ print BackPack.size -- prints 10 | |||
| 3147 | 3608 | ||
| 3148 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. | 3609 | The class object is what we create when we use a class statement. The class object is stored in a variable of the same name of the class. |
| 3149 | 3610 | ||
| 3150 | The class object can be called like a function in order to create new instances. That’s how we created instances of classes in the examples above. | 3611 | The class object can be called like a function in order to create new instances. That's how we created instances of classes in the examples above. |
| 3151 | 3612 | ||
| 3152 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. | 3613 | A class is made up of two tables. The class table itself, and the base table. The base is used as the metatable for all the instances. All properties listed in the class declaration are placed in the base. |
| 3153 | 3614 | ||
| 3154 | The class object’s metatable reads properties from the base if they don’t exist in the class object. This means we can access functions and properties directly from the class. | 3615 | The class object's metatable reads properties from the base if they don't exist in the class object. This means we can access functions and properties directly from the class. |
| 3155 | 3616 | ||
| 3156 | It is important to note that assigning to the class object does not assign into the base, so it’s not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. | 3617 | It is important to note that assigning to the class object does not assign into the base, so it's not a valid way to add new methods to instances. Instead the base must explicitly be changed. See the __base field below. |
| 3157 | 3618 | ||
| 3158 | The class object has a couple special properties: | 3619 | The class object has a couple special properties: |
| 3159 | 3620 | ||
| @@ -3226,7 +3687,7 @@ print Counter.count -- prints 2 | |||
| 3226 | </pre> | 3687 | </pre> |
| 3227 | </YueDisplay> | 3688 | </YueDisplay> |
| 3228 | 3689 | ||
| 3229 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. | 3690 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. |
| 3230 | 3691 | ||
| 3231 | ```moonscript | 3692 | ```moonscript |
| 3232 | @@hello 1,2,3,4 | 3693 | @@hello 1,2,3,4 |
| @@ -3241,7 +3702,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl | |||
| 3241 | 3702 | ||
| 3242 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. | 3703 | In the body of a class declaration, we can have normal expressions in addition to key/value pairs. In this context, self is equal to the class object. |
| 3243 | 3704 | ||
| 3244 | Here is an alternative way to create a class variable compared to what’s described above: | 3705 | Here is an alternative way to create a class variable compared to what's described above: |
| 3245 | 3706 | ||
| 3246 | ```moonscript | 3707 | ```moonscript |
| 3247 | class Things | 3708 | class Things |
| @@ -3507,19 +3968,19 @@ In this usage, with can be seen as a special form of the K combinator. | |||
| 3507 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 3968 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
| 3508 | 3969 | ||
| 3509 | ```moonscript | 3970 | ```moonscript |
| 3510 | with str = "Hello" | 3971 | with str := "Hello" |
| 3511 | print "original:", str | 3972 | print "original:", str |
| 3512 | print "upper:", \upper! | 3973 | print "upper:", \upper! |
| 3513 | ``` | 3974 | ``` |
| 3514 | <YueDisplay> | 3975 | <YueDisplay> |
| 3515 | <pre> | 3976 | <pre> |
| 3516 | with str = "Hello" | 3977 | with str := "Hello" |
| 3517 | print "original:", str | 3978 | print "original:", str |
| 3518 | print "upper:", \upper! | 3979 | print "upper:", \upper! |
| 3519 | </pre> | 3980 | </pre> |
| 3520 | </YueDisplay> | 3981 | </YueDisplay> |
| 3521 | 3982 | ||
| 3522 | Accessing special keys with `[]` in a `with` statement. | 3983 | You can access special keys with `[]` in a `with` statement. |
| 3523 | 3984 | ||
| 3524 | ```moonscript | 3985 | ```moonscript |
| 3525 | with tb | 3986 | with tb |
| @@ -3542,6 +4003,18 @@ with tb | |||
| 3542 | </pre> | 4003 | </pre> |
| 3543 | </YueDisplay> | 4004 | </YueDisplay> |
| 3544 | 4005 | ||
| 4006 | `with?` is an enhanced version of `with` syntax, which introduces an existential check to safely access objects that may be nil without explicit null checks. | ||
| 4007 | |||
| 4008 | ```moonscript | ||
| 4009 | with? obj | ||
| 4010 | print obj.name | ||
| 4011 | ``` | ||
| 4012 | <YueDisplay> | ||
| 4013 | <pre> | ||
| 4014 | with? obj | ||
| 4015 | print obj.name | ||
| 4016 | </pre> | ||
| 4017 | </YueDisplay> | ||
| 3545 | 4018 | ||
| 3546 | ## Do | 4019 | ## Do |
| 3547 | 4020 | ||
| @@ -3562,7 +4035,7 @@ print var -- nil here | |||
| 3562 | </pre> | 4035 | </pre> |
| 3563 | </YueDisplay> | 4036 | </YueDisplay> |
| 3564 | 4037 | ||
| 3565 | YueScript’s **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. | 4038 | YueScript's **do** can also be used an expression . Allowing you to combine multiple lines into one. The result of the do expression is the last statement in its body. |
| 3566 | 4039 | ||
| 3567 | ```moonscript | 4040 | ```moonscript |
| 3568 | counter = do | 4041 | counter = do |
| @@ -3688,7 +4161,7 @@ print i -- will print 0 | |||
| 3688 | </pre> | 4161 | </pre> |
| 3689 | </YueDisplay> | 4162 | </YueDisplay> |
| 3690 | 4163 | ||
| 3691 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn’t clear what names have already been declared. | 4164 | In my_func, we've overwritten the value of i mistakenly. In this example it is quite obvious, but consider a large, or foreign code base where it isn't clear what names have already been declared. |
| 3692 | 4165 | ||
| 3693 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. | 4166 | It would be helpful to say which variables from the enclosing scope we intend on change, in order to prevent us from changing others by accident. |
| 3694 | 4167 | ||
| @@ -3804,9 +4277,9 @@ The YueScript compiling function. It compiles the YueScript code to Lua code. | |||
| 3804 | **Signature:** | 4277 | **Signature:** |
| 3805 | ```lua | 4278 | ```lua |
| 3806 | to_lua: function(code: string, config?: Config): | 4279 | to_lua: function(code: string, config?: Config): |
| 3807 | --[[codes]] string | nil, | 4280 | --[[codes]] string | nil, |
| 3808 | --[[error]] string | nil, | 4281 | --[[error]] string | nil, |
| 3809 | --[[globals]] {{string, integer, integer}} | nil | 4282 | --[[globals]] {{string, integer, integer}} | nil |
| 3810 | ``` | 4283 | ``` |
| 3811 | 4284 | ||
| 3812 | **Parameters:** | 4285 | **Parameters:** |
| @@ -3929,8 +4402,8 @@ Loads YueScript code from a string into a function. | |||
| 3929 | **Signature:** | 4402 | **Signature:** |
| 3930 | ```lua | 4403 | ```lua |
| 3931 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | 4404 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): |
| 3932 | --[[loaded function]] nil | function(...: any): (any...), | 4405 | --[[loaded function]] nil | function(...: any): (any...), |
| 3933 | --[[error]] string | nil | 4406 | --[[error]] string | nil |
| 3934 | ``` | 4407 | ``` |
| 3935 | 4408 | ||
| 3936 | **Parameters:** | 4409 | **Parameters:** |
| @@ -3960,8 +4433,8 @@ Loads YueScript code from a string into a function. | |||
| 3960 | **Signature:** | 4433 | **Signature:** |
| 3961 | ```lua | 4434 | ```lua |
| 3962 | loadstring: function(input: string, chunkname: string, config?: Config): | 4435 | loadstring: function(input: string, chunkname: string, config?: Config): |
| 3963 | --[[loaded function]] nil | function(...: any): (any...), | 4436 | --[[loaded function]] nil | function(...: any): (any...), |
| 3964 | --[[error]] string | nil | 4437 | --[[error]] string | nil |
| 3965 | ``` | 4438 | ``` |
| 3966 | 4439 | ||
| 3967 | **Parameters:** | 4440 | **Parameters:** |
| @@ -3990,8 +4463,8 @@ Loads YueScript code from a string into a function. | |||
| 3990 | **Signature:** | 4463 | **Signature:** |
| 3991 | ```lua | 4464 | ```lua |
| 3992 | loadstring: function(input: string, config?: Config): | 4465 | loadstring: function(input: string, config?: Config): |
| 3993 | --[[loaded function]] nil | function(...: any): (any...), | 4466 | --[[loaded function]] nil | function(...: any): (any...), |
| 3994 | --[[error]] string | nil | 4467 | --[[error]] string | nil |
| 3995 | ``` | 4468 | ``` |
| 3996 | 4469 | ||
| 3997 | **Parameters:** | 4470 | **Parameters:** |
| @@ -4019,8 +4492,8 @@ Loads YueScript code from a file into a function. | |||
| 4019 | **Signature:** | 4492 | **Signature:** |
| 4020 | ```lua | 4493 | ```lua |
| 4021 | loadfile: function(filename: string, env: table, config?: Config): | 4494 | loadfile: function(filename: string, env: table, config?: Config): |
| 4022 | nil | function(...: any): (any...), | 4495 | nil | function(...: any): (any...), |
| 4023 | string | nil | 4496 | string | nil |
| 4024 | ``` | 4497 | ``` |
| 4025 | 4498 | ||
| 4026 | **Parameters:** | 4499 | **Parameters:** |
| @@ -4049,8 +4522,8 @@ Loads YueScript code from a file into a function. | |||
| 4049 | **Signature:** | 4522 | **Signature:** |
| 4050 | ```lua | 4523 | ```lua |
| 4051 | loadfile: function(filename: string, config?: Config): | 4524 | loadfile: function(filename: string, config?: Config): |
| 4052 | nil | function(...: any): (any...), | 4525 | nil | function(...: any): (any...), |
| 4053 | string | nil | 4526 | string | nil |
| 4054 | ``` | 4527 | ``` |
| 4055 | 4528 | ||
| 4056 | **Parameters:** | 4529 | **Parameters:** |
| @@ -4305,9 +4778,9 @@ Converts the code to the AST. | |||
| 4305 | 4778 | ||
| 4306 | **Signature:** | 4779 | **Signature:** |
| 4307 | ```lua | 4780 | ```lua |
| 4308 | to_ast: function(code: string, flattenLevel?: number, astName?: string): | 4781 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): |
| 4309 | --[[AST]] AST | nil, | 4782 | --[[AST]] AST | nil, |
| 4310 | --[[error]] nil | string | 4783 | --[[error]] nil | string |
| 4311 | ``` | 4784 | ``` |
| 4312 | 4785 | ||
| 4313 | **Parameters:** | 4786 | **Parameters:** |
| @@ -4317,6 +4790,7 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4317 | | code | string | The code. | | 4790 | | code | string | The code. | |
| 4318 | | flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | | 4791 | | flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | |
| 4319 | | astName | string | [Optional] The AST name. Default is "File". | | 4792 | | astName | string | [Optional] The AST name. Default is "File". | |
| 4793 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. | | ||
| 4320 | 4794 | ||
| 4321 | **Returns:** | 4795 | **Returns:** |
| 4322 | 4796 | ||
| @@ -4325,6 +4799,33 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4325 | | AST \| nil | The AST, or nil if the conversion failed. | | 4799 | | AST \| nil | The AST, or nil if the conversion failed. | |
| 4326 | | string \| nil | The error message, or nil if the conversion succeeded. | | 4800 | | string \| nil | The error message, or nil if the conversion succeeded. | |
| 4327 | 4801 | ||
| 4802 | #### format | ||
| 4803 | |||
| 4804 | **Type:** Function. | ||
| 4805 | |||
| 4806 | **Description:** | ||
| 4807 | |||
| 4808 | Formats the YueScript code. | ||
| 4809 | |||
| 4810 | **Signature:** | ||
| 4811 | ```lua | ||
| 4812 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 4813 | ``` | ||
| 4814 | |||
| 4815 | **Parameters:** | ||
| 4816 | |||
| 4817 | | Parameter | Type | Description | | ||
| 4818 | | --- | --- | --- | | ||
| 4819 | | code | string | The code. | | ||
| 4820 | | tabSize | integer | [Optional] The tab size. Default is 4. | | ||
| 4821 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. | | ||
| 4822 | |||
| 4823 | **Returns:** | ||
| 4824 | |||
| 4825 | | Return Type | Description | | ||
| 4826 | | --- | --- | | ||
| 4827 | | string | The formatted code. | | ||
| 4828 | |||
| 4328 | #### __call | 4829 | #### __call |
| 4329 | 4830 | ||
| 4330 | **Type:** Metamethod. | 4831 | **Type:** Metamethod. |
| @@ -4396,6 +4897,19 @@ Whether the compiler should reserve the original line number in the compiled cod | |||
| 4396 | reserve_line_number: boolean | 4897 | reserve_line_number: boolean |
| 4397 | ``` | 4898 | ``` |
| 4398 | 4899 | ||
| 4900 | #### reserve_comment | ||
| 4901 | |||
| 4902 | **Type:** Field. | ||
| 4903 | |||
| 4904 | **Description:** | ||
| 4905 | |||
| 4906 | Whether the compiler should reserve the original comments in the compiled code. | ||
| 4907 | |||
| 4908 | **Signature:** | ||
| 4909 | ```lua | ||
| 4910 | reserve_comment: boolean | ||
| 4911 | ``` | ||
| 4912 | |||
| 4399 | #### space_over_tab | 4913 | #### space_over_tab |
| 4400 | 4914 | ||
| 4401 | **Type:** Field. | 4915 | **Type:** Field. |
| @@ -4446,11 +4960,11 @@ The target Lua version enumeration. | |||
| 4446 | **Signature:** | 4960 | **Signature:** |
| 4447 | ```lua | 4961 | ```lua |
| 4448 | enum LuaTarget | 4962 | enum LuaTarget |
| 4449 | "5.1" | 4963 | "5.1" |
| 4450 | "5.2" | 4964 | "5.2" |
| 4451 | "5.3" | 4965 | "5.3" |
| 4452 | "5.4" | 4966 | "5.4" |
| 4453 | "5.5" | 4967 | "5.5" |
| 4454 | end | 4968 | end |
| 4455 | ``` | 4969 | ``` |
| 4456 | 4970 | ||
| @@ -4527,7 +5041,7 @@ simplified: boolean | |||
| 4527 | 5041 | ||
| 4528 | ## Licence: MIT | 5042 | ## Licence: MIT |
| 4529 | 5043 | ||
| 4530 | Copyright (c) 2017-2025 Li Jin \<dragon-fly@qq.com\> | 5044 | Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\> |
| 4531 | 5045 | ||
| 4532 | Permission is hereby granted, free of charge, to any person obtaining a copy | 5046 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 4533 | of this software and associated documentation files (the "Software"), to deal | 5047 | of this software and associated documentation files (the "Software"), to deal |
diff --git a/doc/docs/zh/README.md b/doc/docs/zh/README.md index f5c9811..05b2069 100755 --- a/doc/docs/zh/README.md +++ b/doc/docs/zh/README.md | |||
| @@ -3,6 +3,6 @@ home: true | |||
| 3 | heroImage: /image/yuescript.svg | 3 | heroImage: /image/yuescript.svg |
| 4 | actionText: 快速上手 → | 4 | actionText: 快速上手 → |
| 5 | actionLink: /zh/doc/ | 5 | actionLink: /zh/doc/ |
| 6 | footer: MIT Licensed | Copyright © 2017-2025 Li Jin | 6 | footer: MIT Licensed | Copyright © 2017-2026 Li Jin |
| 7 | --- | 7 | --- |
| 8 | 8 | ||
diff --git a/doc/docs/zh/doc/README.md b/doc/docs/zh/doc/README.md index 2968f6e..de5dff1 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md | |||
| @@ -9,24 +9,24 @@ title: å‚考手册 | |||
| 9 | 9 | ||
| 10 | ## ä»‹ç» | 10 | ## ä»‹ç» |
| 11 | 11 | ||
| 12 | 月之脚本(YueScript)是一ç§åЍæ€è¯è¨€ï¼Œå¯ä»¥ç¼–译为Lua。它是[MoonScript](https://github.com/leafo/moonscript)çš„æ–¹è¨€ã€‚ç”¨æœˆä¹‹è„šæœ¬ç¼–å†™çš„ä»£ç æ—¢æœ‰è¡¨çŽ°åŠ›åˆéžå¸¸ç®€æ´ã€‚它适åˆç¼–写一些更易于维护的代ç ,并在嵌入 Lua 的环境ä¸è¿è¡Œï¼Œå¦‚æ¸¸æˆæˆ–网站æœåŠ¡å™¨ã€‚ | 12 | 月之脚本(YueScript)是一ç§åЍæ€è¯è¨€ï¼Œå¯ä»¥ç¼–译为 Lua。它是 [MoonScript](https://github.com/leafo/moonscript) çš„æ–¹è¨€ã€‚ç”¨æœˆä¹‹è„šæœ¬ç¼–å†™çš„ä»£ç æ—¢æœ‰è¡¨çŽ°åŠ›åˆéžå¸¸ç®€æ´ã€‚它适åˆç¼–写一些更易于维护的代ç ,并在嵌入 Lua 的环境ä¸è¿è¡Œï¼Œå¦‚æ¸¸æˆæˆ–网站æœåŠ¡å™¨ã€‚ |
| 13 | 13 | ||
| 14 | Yueï¼ˆæœˆï¼‰æ˜¯ä¸æ–‡ä¸â€œæœˆäº®â€çš„å称。 | 14 | Yueï¼ˆæœˆï¼‰æ˜¯ä¸æ–‡ä¸â€œæœˆäº®â€çš„å称。 |
| 15 | 15 | ||
| 16 | ### 月之脚本概览 | 16 | ### 月之脚本概览 |
| 17 | ```moonscript | 17 | ```moonscript |
| 18 | -- å¯¼å…¥è¯æ³• | 18 | -- å¯¼å…¥è¯æ³• |
| 19 | import "yue" as :p, :to_lua | 19 | import p, to_lua from "yue" |
| 20 | 20 | ||
| 21 | -- éšå¼å¯¹è±¡ | 21 | -- éšå¼å¯¹è±¡ |
| 22 | inventory = | 22 | inventory = |
| 23 | equipment: | 23 | equipment: |
| 24 | * "sword" | 24 | - "sword" |
| 25 | * "shield" | 25 | - "shield" |
| 26 | items: | 26 | items: |
| 27 | * name: "potion" | 27 | - name: "potion" |
| 28 | count: 10 | 28 | count: 10 |
| 29 | * name: "bread" | 29 | - name: "bread" |
| 30 | count: 3 | 30 | count: 3 |
| 31 | 31 | ||
| 32 | -- 列表推导 | 32 | -- 列表推导 |
| @@ -61,17 +61,17 @@ export 🌛 = "月之脚本" | |||
| 61 | <YueDisplay> | 61 | <YueDisplay> |
| 62 | <pre> | 62 | <pre> |
| 63 | -- å¯¼å…¥è¯æ³• | 63 | -- å¯¼å…¥è¯æ³• |
| 64 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
| 65 | 65 | ||
| 66 | -- éšå¼å¯¹è±¡ | 66 | -- éšå¼å¯¹è±¡ |
| 67 | inventory = | 67 | inventory = |
| 68 | equipment: | 68 | equipment: |
| 69 | * "sword" | 69 | - "sword" |
| 70 | * "shield" | 70 | - "shield" |
| 71 | items: | 71 | items: |
| 72 | * name: "potion" | 72 | - name: "potion" |
| 73 | count: 10 | 73 | count: 10 |
| 74 | * name: "bread" | 74 | - name: "bread" |
| 75 | count: 3 | 75 | count: 3 |
| 76 | 76 | ||
| 77 | -- 列表推导 | 77 | -- 列表推导 |
| @@ -109,7 +109,7 @@ export 🌛 = "月之脚本" | |||
| 109 | 109 | ||
| 110 | * **Lua 模å—** | 110 | * **Lua 模å—** |
| 111 | 111 | ||
| 112 |  安装 [luarocks](https://luarocks.org),一个Lua模å—的包管ç†å™¨ã€‚ç„¶åŽä½œä¸ºLua模å—å’Œå¯æ‰§è¡Œæ–‡ä»¶å®‰è£…它: | 112 |  安装 [luarocks](https://luarocks.org),一个 Lua 模å—的包管ç†å™¨ã€‚ç„¶åŽä½œä¸º Lua 模å—å’Œå¯æ‰§è¡Œæ–‡ä»¶å®‰è£…它: |
| 113 | 113 | ||
| 114 | ``` | 114 | ``` |
| 115 | > luarocks install yuescript | 115 | > luarocks install yuescript |
| @@ -150,14 +150,14 @@ export 🌛 = "月之脚本" | |||
| 150 | 150 | ||
| 151 | ### Lua æ¨¡å— | 151 | ### Lua æ¨¡å— |
| 152 | 152 | ||
| 153 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: | 153 | 在 Lua ä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: |
| 154 | 154 | ||
| 155 | * **用法 1** | 155 | * **用法 1** |
| 156 | 在Luaä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 | 156 | 在 Lua ä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 |
| 157 | ```Lua | 157 | ```Lua |
| 158 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") | 158 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") |
| 159 | ``` | 159 | ``` |
| 160 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import**进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ | 160 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import** 进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ |
| 161 | 161 | ||
| 162 | * **用法 2** | 162 | * **用法 2** |
| 163 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ | 163 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ |
| @@ -172,7 +172,7 @@ end) | |||
| 172 | ``` | 172 | ``` |
| 173 | 173 | ||
| 174 | * **用法 3** | 174 | * **用法 3** |
| 175 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ | 175 | 在 Lua ä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ |
| 176 | ```lua | 176 | ```lua |
| 177 | local yue = require("yue") | 177 | local yue = require("yue") |
| 178 | local codes, err, globals = yue.to_lua([[ | 178 | local codes, err, globals = yue.to_lua([[ |
| @@ -222,12 +222,12 @@ f! | |||
| 222 | 䏿·»åŠ ä»»ä½•é€‰é¡¹æ‰§è¡Œå‘½ä»¤å¯ä»¥è¿›å…¥REPL模å¼ï¼Œ | 222 | 䏿·»åŠ ä»»ä½•é€‰é¡¹æ‰§è¡Œå‘½ä»¤å¯ä»¥è¿›å…¥REPL模å¼ï¼Œ |
| 223 | 在å•è¡Œè¾“å…¥ç¬¦å· '$' å¹¶æ¢è¡ŒåŽï¼Œå¯ä»¥å¼€å§‹æˆ–æ˜¯åœæ¢å¤šè¡Œè¾“å…¥æ¨¡å¼ | 223 | 在å•è¡Œè¾“å…¥ç¬¦å· '$' å¹¶æ¢è¡ŒåŽï¼Œå¯ä»¥å¼€å§‹æˆ–æ˜¯åœæ¢å¤šè¡Œè¾“å…¥æ¨¡å¼ |
| 224 | ``` | 224 | ``` |
| 225 |   使用案例: | 225 |   使用案例: |
| 226 |   递归编译当å‰è·¯å¾„下扩展å为 **.yue** çš„æ¯ä¸ªæœˆä¹‹è„šæœ¬æ–‡ä»¶ï¼š **yue .** | 226 |   递归编译当å‰è·¯å¾„下扩展å为 **.yue** çš„æ¯ä¸ªæœˆä¹‹è„šæœ¬æ–‡ä»¶ï¼š **yue .** |
| 227 |   编译并将结果ä¿å˜åˆ°ç›®æ ‡è·¯å¾„: **yue -t /target/path/ .** | 227 |   编译并将结果ä¿å˜åˆ°ç›®æ ‡è·¯å¾„: **yue -t /target/path/ .** |
| 228 |   编译并ä¿ç•™è°ƒè¯•ä¿¡æ¯ï¼š **yue -l .** | 228 |   编译并ä¿ç•™è°ƒè¯•ä¿¡æ¯ï¼š **yue -l .** |
| 229 |   编译并生æˆåŽ‹ç¼©ä»£ç : **yue -m .** | 229 |   编译并生æˆåŽ‹ç¼©ä»£ç : **yue -m .** |
| 230 |   直接执行代ç : **yue -e 'print 123'** | 230 |   直接执行代ç : **yue -e 'print 123'** |
| 231 |   执行一个月之脚本文件: **yue -e main.yue** | 231 |   执行一个月之脚本文件: **yue -e main.yue** |
| 232 | 232 | ||
| 233 | ## å® | 233 | ## å® |
| @@ -407,16 +407,16 @@ print $LINE -- 获å–当å‰ä»£ç 行数:2 | |||
| 407 | 407 | ||
| 408 | ```moonscript | 408 | ```moonscript |
| 409 | macro Enum = (...) -> | 409 | macro Enum = (...) -> |
| 410 | items = {...} | 410 | items = {...} |
| 411 | itemSet = {item, true for item in *items} | 411 | itemSet = {item, true for item in *items} |
| 412 | (item) -> | 412 | (item) -> |
| 413 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | 413 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] |
| 414 | "\"#{item}\"" | 414 | "\"#{item}\"" |
| 415 | 415 | ||
| 416 | macro BodyType = $Enum( | 416 | macro BodyType = $Enum( |
| 417 | Static | 417 | Static |
| 418 | Dynamic | 418 | Dynamic |
| 419 | Kinematic | 419 | Kinematic |
| 420 | ) | 420 | ) |
| 421 | 421 | ||
| 422 | print "有效的枚举类型:", $BodyType Static | 422 | print "有效的枚举类型:", $BodyType Static |
| @@ -425,16 +425,16 @@ print "有效的枚举类型:", $BodyType Static | |||
| 425 | <YueDisplay> | 425 | <YueDisplay> |
| 426 | <pre> | 426 | <pre> |
| 427 | macro Enum = (...) -> | 427 | macro Enum = (...) -> |
| 428 | items = {...} | 428 | items = {...} |
| 429 | itemSet = {item, true for item in *items} | 429 | itemSet = {item, true for item in *items} |
| 430 | (item) -> | 430 | (item) -> |
| 431 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] | 431 | error "got \"#{item}\", expecting one of #{table.concat items, ', '}" unless itemSet[item] |
| 432 | "\"#{item}\"" | 432 | "\"#{item}\"" |
| 433 | 433 | ||
| 434 | macro BodyType = $Enum( | 434 | macro BodyType = $Enum( |
| 435 | Static | 435 | Static |
| 436 | Dynamic | 436 | Dynamic |
| 437 | Kinematic | 437 | Kinematic |
| 438 | ) | 438 | ) |
| 439 | 439 | ||
| 440 | print "有效的枚举类型:", $BodyType Static | 440 | print "有效的枚举类型:", $BodyType Static |
| @@ -442,9 +442,57 @@ print "有效的枚举类型:", $BodyType Static | |||
| 442 | </pre> | 442 | </pre> |
| 443 | </YueDisplay> | 443 | </YueDisplay> |
| 444 | 444 | ||
| 445 | ### å®å‚数检查 | ||
| 446 | |||
| 447 | å¯ä»¥ç›´æŽ¥åœ¨å‚数列表ä¸å£°æ˜ŽæœŸæœ›çš„ AST èŠ‚ç‚¹ç±»åž‹ï¼Œå¹¶åœ¨ç¼–è¯‘æ—¶æ£€æŸ¥ä¼ å…¥çš„å®å‚数是å¦ç¬¦åˆé¢„期。 | ||
| 448 | |||
| 449 | ```moonscript | ||
| 450 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 451 | print( | ||
| 452 | #{num} | ||
| 453 | #{str} | ||
| 454 | ) | ||
| 455 | |||
| 456 | $printNumAndStr 123, "hello" | ||
| 457 | ``` | ||
| 458 | <YueDisplay> | ||
| 459 | <pre> | ||
| 460 | macro printNumAndStr = (num `Num, str `String) -> | | ||
| 461 | print( | ||
| 462 | #{num} | ||
| 463 | #{str} | ||
| 464 | ) | ||
| 465 | |||
| 466 | $printNumAndStr 123, "hello" | ||
| 467 | </pre> | ||
| 468 | </YueDisplay> | ||
| 469 | |||
| 470 | 如果需è¦åšæ›´åŠ çµæ´»çš„傿•°æ£€æŸ¥æ“作,å¯ä»¥ä½¿ç”¨å†…置的 `$is_ast` å®å‡½æ•°åœ¨åˆé€‚çš„ä½ç½®è¿›è¡Œæ‰‹åŠ¨æ£€æŸ¥ã€‚ | ||
| 471 | |||
| 472 | ```moonscript | ||
| 473 | macro printNumAndStr = (num, str) -> | ||
| 474 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 475 | error "expected String as second argument" unless $is_ast String, str | ||
| 476 | "print(#{num}, #{str})" | ||
| 477 | |||
| 478 | $printNumAndStr 123, "hello" | ||
| 479 | ``` | ||
| 480 | <YueDisplay> | ||
| 481 | <pre> | ||
| 482 | macro printNumAndStr = (num, str) -> | ||
| 483 | error "expected Num as first argument" unless $is_ast Num, num | ||
| 484 | error "expected String as second argument" unless $is_ast String, str | ||
| 485 | "print(#{num}, #{str})" | ||
| 486 | |||
| 487 | $printNumAndStr 123, "hello" | ||
| 488 | </pre> | ||
| 489 | </YueDisplay> | ||
| 490 | |||
| 491 | 更多关于å¯ç”¨ AST 节点的详细信æ¯ï¼Œè¯·å‚考 [yue_parser.cpp](https://github.com/IppClub/YueScript/blob/main/src/yuescript/yue_parser.cpp) ä¸å¤§å†™çš„规则定义。 | ||
| 492 | |||
| 445 | ## æ“作符 | 493 | ## æ“作符 |
| 446 | 494 | ||
| 447 | Lua的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 | 495 | Lua 的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 |
| 448 | 496 | ||
| 449 | ```moonscript | 497 | ```moonscript |
| 450 | tb\func! if tb ~= nil | 498 | tb\func! if tb ~= nil |
| @@ -484,56 +532,56 @@ print 1 <= a <= 10 | |||
| 484 | 532 | ||
| 485 | ```moonscript | 533 | ```moonscript |
| 486 | v = (x) -> | 534 | v = (x) -> |
| 487 | print x | 535 | print x |
| 488 | x | 536 | x |
| 489 | 537 | ||
| 490 | print v(1) < v(2) <= v(3) | 538 | print v(1) < v(2) <= v(3) |
| 491 | --[[ | 539 | --[[ |
| 492 | 输出: | 540 | 输出: |
| 493 | 2 | 541 | 2 |
| 494 | 1 | 542 | 1 |
| 495 | 3 | 543 | 3 |
| 496 | true | 544 | true |
| 497 | ]] | 545 | ]] |
| 498 | 546 | ||
| 499 | print v(1) > v(2) <= v(3) | 547 | print v(1) > v(2) <= v(3) |
| 500 | --[[ | 548 | --[[ |
| 501 | 输出: | 549 | 输出: |
| 502 | 2 | 550 | 2 |
| 503 | 1 | 551 | 1 |
| 504 | false | 552 | false |
| 505 | ]] | 553 | ]] |
| 506 | ``` | 554 | ``` |
| 507 | <YueDisplay> | 555 | <YueDisplay> |
| 508 | <pre> | 556 | <pre> |
| 509 | v = (x) -> | 557 | v = (x) -> |
| 510 | print x | 558 | print x |
| 511 | x | 559 | x |
| 512 | 560 | ||
| 513 | print v(1) < v(2) <= v(3) | 561 | print v(1) < v(2) <= v(3) |
| 514 | --[[ | 562 | --[[ |
| 515 | 输出: | 563 | 输出: |
| 516 | 2 | 564 | 2 |
| 517 | 1 | 565 | 1 |
| 518 | 3 | 566 | 3 |
| 519 | true | 567 | true |
| 520 | ]] | 568 | ]] |
| 521 | 569 | ||
| 522 | print v(1) > v(2) <= v(3) | 570 | print v(1) > v(2) <= v(3) |
| 523 | --[[ | 571 | --[[ |
| 524 | 输出: | 572 | 输出: |
| 525 | 2 | 573 | 2 |
| 526 | 1 | 574 | 1 |
| 527 | false | 575 | false |
| 528 | ]] | 576 | ]] |
| 529 | </pre> | 577 | </pre> |
| 530 | </YueDisplay> | 578 | </YueDisplay> |
| 531 | 579 | ||
| 532 | 在上é¢çš„例å里,ä¸é—´çš„表达å¼`v(2)`仅被计算一次,如果把表达å¼å†™æˆ`v(1) < v(2) and v(2) <= v(3)`的方å¼ï¼Œä¸é—´çš„`v(2)`æ‰ä¼šè¢«è®¡ç®—ä¸¤æ¬¡ã€‚åœ¨é“¾å¼æ¯”较ä¸ï¼Œæ±‚值的顺åºå¾€å¾€æ˜¯æœªå®šä¹‰çš„。所以强烈建议ä¸è¦åœ¨é“¾å¼æ¯”较ä¸ä½¿ç”¨å…·æœ‰å‰¯ä½œç”¨ï¼ˆæ¯”å¦‚åšæ‰“å°æ“作)的表达å¼ã€‚如果需è¦ä½¿ç”¨æœ‰å‰¯ä½œç”¨çš„函数,应明确使用çŸè·¯ `and` è¿ç®—符æ¥åšè¿žæŽ¥ã€‚ | 580 | 在上é¢çš„例å里,ä¸é—´çš„è¡¨è¾¾å¼ `v(2)` 仅被计算一次,如果把表达å¼å†™æˆ `v(1) < v(2) and v(2) <= v(3)` 的方å¼ï¼Œä¸é—´çš„ `v(2)` æ‰ä¼šè¢«è®¡ç®—ä¸¤æ¬¡ã€‚åœ¨é“¾å¼æ¯”较ä¸ï¼Œæ±‚值的顺åºå¾€å¾€æ˜¯æœªå®šä¹‰çš„。所以强烈建议ä¸è¦åœ¨é“¾å¼æ¯”较ä¸ä½¿ç”¨å…·æœ‰å‰¯ä½œç”¨ï¼ˆæ¯”å¦‚åšæ‰“å°æ“作)的表达å¼ã€‚如果需è¦ä½¿ç”¨æœ‰å‰¯ä½œç”¨çš„函数,应明确使用çŸè·¯ `and` è¿ç®—符æ¥åšè¿žæŽ¥ã€‚ |
| 533 | 581 | ||
| 534 | ### è¡¨è¿½åŠ | 582 | ### è¡¨è¿½åŠ |
| 535 | 583 | ||
| 536 | **[] =** æ“作符用于å‘Luaè¡¨çš„æœ€åŽæ’入值。 | 584 | **[] =** æ“ä½œç¬¦ç”¨äºŽå‘ Lua è¡¨çš„æœ€åŽæ’入值。 |
| 537 | 585 | ||
| 538 | ```moonscript | 586 | ```moonscript |
| 539 | tab = [] | 587 | tab = [] |
| @@ -546,19 +594,36 @@ tab[] = "Value" | |||
| 546 | </pre> | 594 | </pre> |
| 547 | </YueDisplay> | 595 | </YueDisplay> |
| 548 | 596 | ||
| 597 | ä½ è¿˜å¯ä»¥ä½¿ç”¨å±•å¼€æ“作符 `...` æ¥å°†ä¸€ä¸ªåˆ—表ä¸çš„æ‰€æœ‰å…ƒç´ è¿½åŠ åˆ°å¦ä¸€ä¸ªåˆ—表ä¸ï¼š | ||
| 598 | |||
| 599 | ```moonscript | ||
| 600 | tbA = [1, 2, 3] | ||
| 601 | tbB = [4, 5, 6] | ||
| 602 | tbA[] = ...tbB | ||
| 603 | -- tbA 现在为 [1, 2, 3, 4, 5, 6] | ||
| 604 | ``` | ||
| 605 | <YueDisplay> | ||
| 606 | <pre> | ||
| 607 | tbA = [1, 2, 3] | ||
| 608 | tbB = [4, 5, 6] | ||
| 609 | tbA[] = ...tbB | ||
| 610 | -- tbA 现在为 [1, 2, 3, 4, 5, 6] | ||
| 611 | </pre> | ||
| 612 | </YueDisplay> | ||
| 613 | |||
| 549 | ### 表扩展 | 614 | ### 表扩展 |
| 550 | 615 | ||
| 551 | ä½ å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在Luaè¡¨ä¸æ’入数组表或哈希表。 | 616 | ä½ å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在 Lua è¡¨ä¸æ’入数组表或哈希表。 |
| 552 | 617 | ||
| 553 | ```moonscript | 618 | ```moonscript |
| 554 | parts = | 619 | parts = |
| 555 | * "shoulders" | 620 | * "shoulders" |
| 556 | * "knees" | 621 | * "knees" |
| 557 | lyrics = | 622 | lyrics = |
| 558 | * "head" | 623 | * "head" |
| 559 | * ...parts | 624 | * ...parts |
| 560 | * "and" | 625 | * "and" |
| 561 | * "toes" | 626 | * "toes" |
| 562 | 627 | ||
| 563 | copy = {...other} | 628 | copy = {...other} |
| 564 | 629 | ||
| @@ -569,13 +634,13 @@ merge = {...a, ...b} | |||
| 569 | <YueDisplay> | 634 | <YueDisplay> |
| 570 | <pre> | 635 | <pre> |
| 571 | parts = | 636 | parts = |
| 572 | * "shoulders" | 637 | * "shoulders" |
| 573 | * "knees" | 638 | * "knees" |
| 574 | lyrics = | 639 | lyrics = |
| 575 | * "head" | 640 | * "head" |
| 576 | * ...parts | 641 | * ...parts |
| 577 | * "and" | 642 | * "and" |
| 578 | * "toes" | 643 | * "toes" |
| 579 | 644 | ||
| 580 | copy = {...other} | 645 | copy = {...other} |
| 581 | 646 | ||
| @@ -585,12 +650,29 @@ merge = {...a, ...b} | |||
| 585 | </pre> | 650 | </pre> |
| 586 | </YueDisplay> | 651 | </YueDisplay> |
| 587 | 652 | ||
| 653 | ### 表åå‘索引 | ||
| 654 | |||
| 655 | ä½ å¯ä»¥ä½¿ç”¨ **#** æ“作符æ¥åå‘索引表ä¸çš„å…ƒç´ ã€‚ | ||
| 656 | |||
| 657 | ```moonscript | ||
| 658 | last = data.items[#] | ||
| 659 | second_last = data.items[#-1] | ||
| 660 | data.items[#] = 1 | ||
| 661 | ``` | ||
| 662 | <YueDisplay> | ||
| 663 | <pre> | ||
| 664 | last = data.items[#] | ||
| 665 | second_last = data.items[#-1] | ||
| 666 | data.items[#] = 1 | ||
| 667 | </pre> | ||
| 668 | </YueDisplay> | ||
| 669 | |||
| 588 | ### 元表 | 670 | ### 元表 |
| 589 | 671 | ||
| 590 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ | 672 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ |
| 591 | 673 | ||
| 592 | * **元表创建** | 674 | * **元表创建** |
| 593 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 | 675 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。 |
| 594 | 676 | ||
| 595 | ```moonscript | 677 | ```moonscript |
| 596 | mt = {} | 678 | mt = {} |
| @@ -732,7 +814,7 @@ readFile "example.txt" | |||
| 732 | 814 | ||
| 733 | ### 空值åˆå¹¶ | 815 | ### 空值åˆå¹¶ |
| 734 | 816 | ||
| 735 | 如果其左æ“ä½œæ•°ä¸æ˜¯**nil**,则nilåˆå¹¶è¿ç®—符 **??** 返回其左æ“作数的值;å¦åˆ™ï¼Œå®ƒå°†è®¡ç®—峿“作数并返回其结果。如果左æ“作数计算结果为éžnil的值,**??** è¿ç®—符将ä¸å†è®¡ç®—其峿“作数。 | 817 | 如果其左æ“ä½œæ•°ä¸æ˜¯ **nil**,则nilåˆå¹¶è¿ç®—符 **??** 返回其左æ“作数的值;å¦åˆ™ï¼Œå®ƒå°†è®¡ç®—峿“作数并返回其结果。如果左æ“ä½œæ•°è®¡ç®—ç»“æžœä¸ºéž nil 的值,**??** è¿ç®—符将ä¸å†è®¡ç®—其峿“作数。 |
| 736 | ```moonscript | 818 | ```moonscript |
| 737 | local a, b, c, d | 819 | local a, b, c, d |
| 738 | a = b ?? c ?? d | 820 | a = b ?? c ?? d |
| @@ -751,67 +833,87 @@ a ??= false | |||
| 751 | 833 | ||
| 752 | ### éšå¼å¯¹è±¡ | 834 | ### éšå¼å¯¹è±¡ |
| 753 | 835 | ||
| 754 | ä½ å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 开始编写一系列éšå¼ç»“æž„ã€‚å¦‚æžœä½ æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 | 836 | ä½ å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 或是 **-** 开始编写一系列éšå¼ç»“æž„ã€‚å¦‚æžœä½ æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 |
| 837 | |||
| 755 | ```moonscript | 838 | ```moonscript |
| 839 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
| 756 | list = | 840 | list = |
| 757 | * 1 | 841 | * 1 |
| 758 | * 2 | 842 | * 2 |
| 759 | * 3 | 843 | * 3 |
| 760 | 844 | ||
| 845 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
| 761 | func | 846 | func |
| 762 | * 1 | 847 | * 1 |
| 763 | * 2 | 848 | * 2 |
| 764 | * 3 | 849 | * 3 |
| 765 | 850 | ||
| 851 | -- 返回时使用éšå¼å¯¹è±¡ | ||
| 852 | f = -> | ||
| 853 | return | ||
| 854 | * 1 | ||
| 855 | * 2 | ||
| 856 | * 3 | ||
| 857 | |||
| 858 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
| 766 | tb = | 859 | tb = |
| 767 | name: "abc" | 860 | name: "abc" |
| 768 | 861 | ||
| 769 | values: | 862 | values: |
| 770 | * "a" | 863 | - "a" |
| 771 | * "b" | 864 | - "b" |
| 772 | * "c" | 865 | - "c" |
| 773 | 866 | ||
| 774 | objects: | 867 | objects: |
| 775 | * name: "a" | 868 | - name: "a" |
| 776 | value: 1 | 869 | value: 1 |
| 777 | func: => @value + 1 | 870 | func: => @value + 1 |
| 778 | tb: | 871 | tb: |
| 779 | fieldA: 1 | 872 | fieldA: 1 |
| 780 | 873 | ||
| 781 | * name: "b" | 874 | - name: "b" |
| 782 | value: 2 | 875 | value: 2 |
| 783 | func: => @value + 2 | 876 | func: => @value + 2 |
| 784 | tb: { } | 877 | tb: { } |
| 785 | |||
| 786 | ``` | 878 | ``` |
| 787 | <YueDisplay> | 879 | <YueDisplay> |
| 788 | <pre> | 880 | <pre> |
| 881 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
| 789 | list = | 882 | list = |
| 790 | * 1 | 883 | * 1 |
| 791 | * 2 | 884 | * 2 |
| 792 | * 3 | 885 | * 3 |
| 793 | 886 | ||
| 887 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
| 794 | func | 888 | func |
| 795 | * 1 | 889 | * 1 |
| 796 | * 2 | 890 | * 2 |
| 797 | * 3 | 891 | * 3 |
| 798 | 892 | ||
| 893 | -- 返回时使用éšå¼å¯¹è±¡ | ||
| 894 | f = -> | ||
| 895 | return | ||
| 896 | * 1 | ||
| 897 | * 2 | ||
| 898 | * 3 | ||
| 899 | |||
| 900 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
| 799 | tb = | 901 | tb = |
| 800 | name: "abc" | 902 | name: "abc" |
| 801 | 903 | ||
| 802 | values: | 904 | values: |
| 803 | * "a" | 905 | - "a" |
| 804 | * "b" | 906 | - "b" |
| 805 | * "c" | 907 | - "c" |
| 806 | 908 | ||
| 807 | objects: | 909 | objects: |
| 808 | * name: "a" | 910 | - name: "a" |
| 809 | value: 1 | 911 | value: 1 |
| 810 | func: => @value + 1 | 912 | func: => @value + 1 |
| 811 | tb: | 913 | tb: |
| 812 | fieldA: 1 | 914 | fieldA: 1 |
| 813 | 915 | ||
| 814 | * name: "b" | 916 | - name: "b" |
| 815 | value: 2 | 917 | value: 2 |
| 816 | func: => @value + 2 | 918 | func: => @value + 2 |
| 817 | tb: { } | 919 | tb: { } |
| @@ -991,7 +1093,7 @@ export default -> | |||
| 991 | 1093 | ||
| 992 | ## 赋值 | 1094 | ## 赋值 |
| 993 | 1095 | ||
| 994 | 月之脚本ä¸å®šä¹‰çš„å˜é‡æ˜¯åЍæ€ç±»åž‹çš„,并默认为局部å˜é‡ã€‚ä½†ä½ å¯ä»¥é€šè¿‡**local**å’Œ**global**å£°æ˜Žæ¥æ”¹å˜å£°æ˜Žå˜é‡çš„作用范围。 | 1096 | 月之脚本ä¸å®šä¹‰çš„å˜é‡æ˜¯åЍæ€ç±»åž‹çš„,并默认为局部å˜é‡ã€‚ä½†ä½ å¯ä»¥é€šè¿‡ **local** å’Œ **global** å£°æ˜Žæ¥æ”¹å˜å£°æ˜Žå˜é‡çš„作用范围。 |
| 995 | 1097 | ||
| 996 | ```moonscript | 1098 | ```moonscript |
| 997 | hello = "world" | 1099 | hello = "world" |
| @@ -1120,9 +1222,9 @@ do | |||
| 1120 | 1222 | ||
| 1121 | ## 解构赋值 | 1223 | ## 解构赋值 |
| 1122 | 1224 | ||
| 1123 | 解构赋值是一ç§å¿«é€Ÿä»ŽLuaè¡¨ä¸æŒ‰å称或基于数组ä¸çš„ä½ç½®æå–值的方法。 | 1225 | 解构赋值是一ç§å¿«é€Ÿä»Ž Lua è¡¨ä¸æŒ‰å称或基于数组ä¸çš„ä½ç½®æå–值的方法。 |
| 1124 | 1226 | ||
| 1125 | é€šå¸¸å½“ä½ çœ‹åˆ°ä¸€ä¸ªå—é¢é‡çš„Lua表,比如{1,2,3},它ä½äºŽèµ‹å€¼çš„å³ä¾§ï¼Œå› 为它是一个值。解构赋值è¯å¥çš„写法就是交æ¢äº†å—é¢é‡Lua表的角色,并将其放在赋值è¯å¥çš„左侧。 | 1227 | é€šå¸¸å½“ä½ çœ‹åˆ°ä¸€ä¸ªå—é¢é‡çš„ Lua 表,比如 `{1,2,3}`,它ä½äºŽèµ‹å€¼çš„å³ä¾§ï¼Œå› 为它是一个值。解构赋值è¯å¥çš„写法就是交æ¢äº†å—é¢é‡ Lua 表的角色,并将其放在赋值è¯å¥çš„左侧。 |
| 1126 | 1228 | ||
| 1127 | 最好是通过示例æ¥è§£é‡Šã€‚ä»¥ä¸‹æ˜¯å¦‚ä½•ä»Žè¡¨æ ¼ä¸è§£åŒ…å‰ä¸¤ä¸ªå€¼çš„æ–¹æ³•: | 1229 | 最好是通过示例æ¥è§£é‡Šã€‚ä»¥ä¸‹æ˜¯å¦‚ä½•ä»Žè¡¨æ ¼ä¸è§£åŒ…å‰ä¸¤ä¸ªå€¼çš„æ–¹æ³•: |
| 1128 | 1230 | ||
| @@ -1221,7 +1323,7 @@ print first, second, color | |||
| 1221 | </pre> | 1323 | </pre> |
| 1222 | </YueDisplay> | 1324 | </YueDisplay> |
| 1223 | 1325 | ||
| 1224 | 有时候我们会需è¦ä»ŽLuaè¡¨ä¸æå–值并将它们赋给与键åŒå的局部å˜é‡ã€‚为了é¿å…编写é‡å¤ä»£ç ,我们å¯ä»¥ä½¿ç”¨ **:** å‰ç¼€æ“作符: | 1326 | 有时候我们会需è¦ä»Ž Lua è¡¨ä¸æå–值并将它们赋给与键åŒå的局部å˜é‡ã€‚为了é¿å…编写é‡å¤ä»£ç ,我们å¯ä»¥ä½¿ç”¨ **:** å‰ç¼€æ“作符: |
| 1225 | 1327 | ||
| 1226 | ```moonscript | 1328 | ```moonscript |
| 1227 | {:concat, :insert} = table | 1329 | {:concat, :insert} = table |
| @@ -1265,9 +1367,55 @@ print first, second, color | |||
| 1265 | </pre> | 1367 | </pre> |
| 1266 | </YueDisplay> | 1368 | </YueDisplay> |
| 1267 | 1369 | ||
| 1268 | ### 在其它地方的解构 | 1370 | ### 范围解构 |
| 1371 | |||
| 1372 | ä½ å¯ä»¥ä½¿ç”¨å±•å¼€è¿ç®—符 `...` åœ¨åˆ—è¡¨è§£æž„ä¸æ¥æ•获一个范围的值到å列表ä¸ã€‚è¿™åœ¨å½“ä½ æƒ³è¦ä»Žåˆ—表的开头和结尾æå–ç‰¹å®šå…ƒç´ ï¼ŒåŒæ—¶æ”¶é›†ä¸é—´çš„å…ƒç´ æ—¶éžå¸¸æœ‰ç”¨ã€‚ | ||
| 1373 | |||
| 1374 | ```moonscript | ||
| 1375 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1376 | [first, ...bulk, last] = orders | ||
| 1377 | print first -- 打å°: first | ||
| 1378 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
| 1379 | print last -- 打å°: last | ||
| 1380 | ``` | ||
| 1381 | <YueDisplay> | ||
| 1382 | <pre> | ||
| 1383 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1384 | [first, ...bulk, last] = orders | ||
| 1385 | print first -- 打å°: first | ||
| 1386 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
| 1387 | print last -- 打å°: last | ||
| 1388 | </pre> | ||
| 1389 | </YueDisplay> | ||
| 1269 | 1390 | ||
| 1270 | 解构也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨for循环: | 1391 | 展开è¿ç®—符å¯ä»¥ç”¨åœ¨ä¸åŒçš„ä½ç½®æ¥æ•获ä¸åŒçš„èŒƒå›´ï¼Œå¹¶ä¸”ä½ å¯ä»¥ä½¿ç”¨ `_` 作为å ä½ç¬¦æ¥è¡¨ç¤ºä½ 想跳过对应范围的æ•获: |
| 1392 | |||
| 1393 | ```moonscript | ||
| 1394 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
| 1395 | [first, ...rest] = orders | ||
| 1396 | |||
| 1397 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
| 1398 | [...start, last] = orders | ||
| 1399 | |||
| 1400 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
| 1401 | [first, ..._, last] = orders | ||
| 1402 | ``` | ||
| 1403 | <YueDisplay> | ||
| 1404 | <pre> | ||
| 1405 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
| 1406 | [first, ...rest] = orders | ||
| 1407 | |||
| 1408 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
| 1409 | [...start, last] = orders | ||
| 1410 | |||
| 1411 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
| 1412 | [first, ..._, last] = orders | ||
| 1413 | </pre> | ||
| 1414 | </YueDisplay> | ||
| 1415 | |||
| 1416 | ### 在其它地方的解构赋值 | ||
| 1417 | |||
| 1418 | 解构赋值也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨ for 循环ä¸ï¼š | ||
| 1271 | 1419 | ||
| 1272 | ```moonscript | 1420 | ```moonscript |
| 1273 | tuples = [ | 1421 | tuples = [ |
| @@ -1290,7 +1438,7 @@ for [left, right] in *tuples | |||
| 1290 | </pre> | 1438 | </pre> |
| 1291 | </YueDisplay> | 1439 | </YueDisplay> |
| 1292 | 1440 | ||
| 1293 | æˆ‘ä»¬çŸ¥é“æ•°ç»„表ä¸çš„æ¯ä¸ªå…ƒç´ éƒ½æ˜¯ä¸€ä¸ªä¸¤é¡¹çš„å…ƒç»„ï¼Œæ‰€ä»¥æˆ‘ä»¬å¯ä»¥ç›´æŽ¥åœ¨forè¯å¥çš„åç§°åå¥ä¸ä½¿ç”¨è§£æž„æ¥è§£åŒ…它。 | 1441 | æˆ‘ä»¬çŸ¥é“æ•°ç»„表ä¸çš„æ¯ä¸ªå…ƒç´ éƒ½æ˜¯ä¸€ä¸ªä¸¤é¡¹çš„å…ƒç»„ï¼Œæ‰€ä»¥æˆ‘ä»¬å¯ä»¥ç›´æŽ¥åœ¨ for è¯å¥çš„åç§°åå¥ä¸ä½¿ç”¨è§£æž„æ¥è§£åŒ…它。 |
| 1294 | 1442 | ||
| 1295 | ## If 赋值 | 1443 | ## If 赋值 |
| 1296 | 1444 | ||
| @@ -1358,7 +1506,7 @@ while byte := stream\read_one! | |||
| 1358 | 1506 | ||
| 1359 | ## å¯å˜å‚数赋值 | 1507 | ## å¯å˜å‚数赋值 |
| 1360 | 1508 | ||
| 1361 | ä½ å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨Lua的方å¼è®¿é—®å…¶å†…容。 | 1509 | ä½ å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨ Lua 的方å¼è®¿é—®å…¶å†…容。 |
| 1362 | ```moonscript | 1510 | ```moonscript |
| 1363 | list = [1, 2, 3, 4, 5] | 1511 | list = [1, 2, 3, 4, 5] |
| 1364 | fn = (ok) -> ok, table.unpack list | 1512 | fn = (ok) -> ok, table.unpack list |
| @@ -1435,7 +1583,7 @@ func --[[端å£]] 3000, --[[ip]] "192.168.1.1" | |||
| 1435 | 1583 | ||
| 1436 | ## é”™è¯¯å¤„ç† | 1584 | ## é”™è¯¯å¤„ç† |
| 1437 | 1585 | ||
| 1438 | 用于统一进行Lua错误处ç†çš„便æ·è¯æ³•。 | 1586 | 用于统一进行 Lua 错误处ç†çš„便æ·è¯æ³•。 |
| 1439 | 1587 | ||
| 1440 | ```moonscript | 1588 | ```moonscript |
| 1441 | try | 1589 | try |
| @@ -1494,9 +1642,50 @@ catch err | |||
| 1494 | </pre> | 1642 | </pre> |
| 1495 | </YueDisplay> | 1643 | </YueDisplay> |
| 1496 | 1644 | ||
| 1645 | ### 错误处ç†ç®€åŒ– | ||
| 1646 | |||
| 1647 | `try?` 是 `try` çš„åŠŸèƒ½ç®€åŒ–è¯æ³•,它ä¸å†è¿”回 `try` è¯å¥çš„布尔状æ€ï¼Œå¹¶åœ¨æˆåŠŸæ—¶ç›´æŽ¥è¿”å›ž `try` 代ç å—的结果,失败时返回 `nil` 值而éžé”™è¯¯å¯¹è±¡ã€‚ | ||
| 1648 | |||
| 1649 | ```moonscript | ||
| 1650 | a, b, c = try? func! | ||
| 1651 | |||
| 1652 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
| 1653 | a = (try? func!) ?? "default" | ||
| 1654 | |||
| 1655 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
| 1656 | f try? func! | ||
| 1657 | |||
| 1658 | -- 带 catch å—çš„ try! | ||
| 1659 | f try? | ||
| 1660 | print 123 | ||
| 1661 | func! | ||
| 1662 | catch e | ||
| 1663 | print e | ||
| 1664 | e | ||
| 1665 | ``` | ||
| 1666 | <YueDisplay> | ||
| 1667 | <pre> | ||
| 1668 | a, b, c = try? func! | ||
| 1669 | |||
| 1670 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
| 1671 | a = (try? func!) ?? "default" | ||
| 1672 | |||
| 1673 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
| 1674 | f try? func! | ||
| 1675 | |||
| 1676 | -- 带 catch å—çš„ try! | ||
| 1677 | f try? | ||
| 1678 | print 123 | ||
| 1679 | func! | ||
| 1680 | catch e | ||
| 1681 | print e | ||
| 1682 | e | ||
| 1683 | </pre> | ||
| 1684 | </YueDisplay> | ||
| 1685 | |||
| 1497 | ## 属性 | 1686 | ## 属性 |
| 1498 | 1687 | ||
| 1499 | 月之脚本现在æä¾›äº†Lua 5.4新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的Luaç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ5.4æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const`å’Œ`close`çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 | 1688 | 月之脚本现在æä¾›äº† Lua 5.4 新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的 Lua ç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ 5.4 æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const` å’Œ `close` çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 |
| 1500 | 1689 | ||
| 1501 | ```moonscript | 1690 | ```moonscript |
| 1502 | const a = 123 | 1691 | const a = 123 |
| @@ -1537,9 +1726,9 @@ global const Constant = 123 | |||
| 1537 | 1726 | ||
| 1538 | ## å—é¢é‡ | 1727 | ## å—é¢é‡ |
| 1539 | 1728 | ||
| 1540 | Luaä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和**nil**。 | 1729 | Lua ä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和 **nil**。 |
| 1541 | 1730 | ||
| 1542 | 但与Luaä¸åŒçš„æ˜¯ï¼Œå•引å·å’ŒåŒå¼•å·å—符串内部å…许有æ¢è¡Œï¼š | 1731 | 但与 Lua ä¸åŒçš„æ˜¯ï¼Œå•引å·å’ŒåŒå¼•å·å—符串内部å…许有æ¢è¡Œï¼š |
| 1543 | 1732 | ||
| 1544 | ```moonscript | 1733 | ```moonscript |
| 1545 | some_string = "这是一个å—符串 | 1734 | some_string = "这是一个å—符串 |
| @@ -1574,6 +1763,66 @@ binary = 0B10011 | |||
| 1574 | <pre> | 1763 | <pre> |
| 1575 | integer = 1_000_000 | 1764 | integer = 1_000_000 |
| 1576 | hex = 0xEF_BB_BF | 1765 | hex = 0xEF_BB_BF |
| 1766 | binary = 0B10011 | ||
| 1767 | </pre> | ||
| 1768 | </YueDisplay> | ||
| 1769 | |||
| 1770 | ### YAML é£Žæ ¼å—符串 | ||
| 1771 | |||
| 1772 | 使用 `|` å‰ç¼€æ ‡è®°ä¸€ä¸ªå¤šè¡Œ YAML é£Žæ ¼å—符串: | ||
| 1773 | |||
| 1774 | ```moonscript | ||
| 1775 | str = | | ||
| 1776 | key: value | ||
| 1777 | list: | ||
| 1778 | - item1 | ||
| 1779 | - #{expr} | ||
| 1780 | ``` | ||
| 1781 | <YueDisplay> | ||
| 1782 | <pre> | ||
| 1783 | str = | | ||
| 1784 | key: value | ||
| 1785 | list: | ||
| 1786 | - item1 | ||
| 1787 | - #{expr} | ||
| 1788 | </pre> | ||
| 1789 | </YueDisplay> | ||
| 1790 | |||
| 1791 | 其效果类似于原生 Lua çš„å¤šè¡Œæ‹¼æŽ¥ï¼Œæ‰€æœ‰æ–‡æœ¬ï¼ˆå«æ¢è¡Œï¼‰å°†è¢«ä¿ç•™ä¸‹æ¥ï¼Œå¹¶æ”¯æŒ `#{...}` è¯æ³•,通过 `tostring(expr)` æ’入表达å¼ç»“果。 | ||
| 1792 | |||
| 1793 | YAML é£Žæ ¼çš„å¤šè¡Œå—ç¬¦ä¸²ä¼šè‡ªåŠ¨æ£€æµ‹é¦–è¡ŒåŽæœ€å°çš„公共缩进,并从所有行ä¸åˆ 除该å‰ç¼€ç©ºç™½å—ç¬¦ã€‚è¿™è®©ä½ å¯ä»¥åœ¨ä»£ç ä¸å¯¹é½æ–‡æœ¬ï¼Œä½†è¾“出å—符串ä¸ä¼šå¸¦å¤šä½™ç¼©è¿›ã€‚ | ||
| 1794 | |||
| 1795 | ```moonscript | ||
| 1796 | fn = -> | ||
| 1797 | str = | | ||
| 1798 | foo: | ||
| 1799 | bar: baz | ||
| 1800 | return str | ||
| 1801 | ``` | ||
| 1802 | <YueDisplay> | ||
| 1803 | <pre> | ||
| 1804 | fn = -> | ||
| 1805 | str = | | ||
| 1806 | foo: | ||
| 1807 | bar: baz | ||
| 1808 | return str | ||
| 1809 | </pre> | ||
| 1810 | </YueDisplay> | ||
| 1811 | |||
| 1812 | 输出å—符串ä¸çš„ foo: 对é½åˆ°è¡Œé¦–,ä¸ä¼šå¸¦æœ‰å‡½æ•°ç¼©è¿›ç©ºæ ¼ã€‚ä¿ç•™å†…部缩进的相对结构,适åˆä¹¦å†™ç»“æž„åŒ–åµŒå¥—æ ·å¼çš„内容。 | ||
| 1813 | |||
| 1814 | 支æŒè‡ªåЍ处ç†å—符ä¸çš„引å·ã€åæ–œæ ç‰ç‰¹æ®Šç¬¦å·ï¼Œæ— 需手动转义: | ||
| 1815 | |||
| 1816 | ```moonscript | ||
| 1817 | str = | | ||
| 1818 | path: "C:\Program Files\App" | ||
| 1819 | note: 'He said: "#{Hello}!"' | ||
| 1820 | ``` | ||
| 1821 | <YueDisplay> | ||
| 1822 | <pre> | ||
| 1823 | str = | | ||
| 1824 | path: "C:\Program Files\App" | ||
| 1825 | note: 'He said: "#{Hello}!"' | ||
| 1577 | </pre> | 1826 | </pre> |
| 1578 | </YueDisplay> | 1827 | </YueDisplay> |
| 1579 | 1828 | ||
| @@ -1678,7 +1927,7 @@ print "æ•°å—的和是", sum 10, 20 | |||
| 1678 | </pre> | 1927 | </pre> |
| 1679 | </YueDisplay> | 1928 | </YueDisplay> |
| 1680 | 1929 | ||
| 1681 | å¦‚æžœä½ éœ€è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨return关键å—: | 1930 | å¦‚æžœä½ éœ€è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨ return 关键å—: |
| 1682 | 1931 | ||
| 1683 | ```moonscript | 1932 | ```moonscript |
| 1684 | sum = (x, y) -> return x + y | 1933 | sum = (x, y) -> return x + y |
| @@ -1704,7 +1953,7 @@ a, b = mystery 10, 20 | |||
| 1704 | 1953 | ||
| 1705 | ### ç²—ç®å¤´ | 1954 | ### ç²—ç®å¤´ |
| 1706 | 1955 | ||
| 1707 | å› ä¸ºåœ¨Luaä¸è°ƒç”¨æ–¹æ³•时,ç»å¸¸ä¹ æƒ¯å°†å¯¹è±¡ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 入,所以月之脚本æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥åˆ›å»ºè‡ªåŠ¨åŒ…å«self傿•°çš„函数。 | 1956 | å› ä¸ºåœ¨ Lua ä¸è°ƒç”¨æ–¹æ³•时,ç»å¸¸ä¹ æƒ¯å°†å¯¹è±¡ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 入,所以月之脚本æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥åˆ›å»ºè‡ªåŠ¨åŒ…å« self 傿•°çš„函数。 |
| 1708 | 1957 | ||
| 1709 | ```moonscript | 1958 | ```moonscript |
| 1710 | func = (num) => @value + num | 1959 | func = (num) => @value + num |
| @@ -1717,7 +1966,7 @@ func = (num) => @value + num | |||
| 1717 | 1966 | ||
| 1718 | ### 傿•°é»˜è®¤å€¼ | 1967 | ### 傿•°é»˜è®¤å€¼ |
| 1719 | 1968 | ||
| 1720 | å¯ä»¥ä¸ºå‡½æ•°çš„傿•°æä¾›é»˜è®¤å€¼ã€‚å¦‚æžœå‚æ•°çš„值为nilï¼Œåˆ™ç¡®å®šè¯¥å‚æ•°ä¸ºç©ºã€‚任何具有默认值的nil傿•°åœ¨å‡½æ•°ä½“è¿è¡Œä¹‹å‰éƒ½ä¼šè¢«æ›¿æ¢ã€‚ | 1969 | å¯ä»¥ä¸ºå‡½æ•°çš„傿•°æä¾›é»˜è®¤å€¼ã€‚å¦‚æžœå‚æ•°çš„值为 nilï¼Œåˆ™ç¡®å®šè¯¥å‚æ•°ä¸ºç©ºã€‚任何具有默认值的 nil 傿•°åœ¨å‡½æ•°ä½“è¿è¡Œä¹‹å‰éƒ½ä¼šè¢«æ›¿æ¢ã€‚ |
| 1721 | 1970 | ||
| 1722 | ```moonscript | 1971 | ```moonscript |
| 1723 | my_function = (name = "æŸç‰©", height = 100) -> | 1972 | my_function = (name = "æŸç‰©", height = 100) -> |
| @@ -1789,7 +2038,7 @@ my_func 5, 6, 7, | |||
| 1789 | </pre> | 2038 | </pre> |
| 1790 | </YueDisplay> | 2039 | </YueDisplay> |
| 1791 | 2040 | ||
| 1792 | å› ä¸ºLua表也使用逗å·ä½œä¸ºåˆ†éš”符,这ç§ç¼©è¿›è¯æ³•有助于让值æˆä¸ºå‚æ•°åˆ—è¡¨çš„ä¸€éƒ¨åˆ†ï¼Œè€Œä¸æ˜¯Lua表的一部分。 | 2041 | å› ä¸º Lua 表也使用逗å·ä½œä¸ºåˆ†éš”符,这ç§ç¼©è¿›è¯æ³•有助于让值æˆä¸ºå‚æ•°åˆ—è¡¨çš„ä¸€éƒ¨åˆ†ï¼Œè€Œä¸æ˜¯ Lua 表的一部分。 |
| 1793 | 2042 | ||
| 1794 | ```moonscript | 2043 | ```moonscript |
| 1795 | x = [ | 2044 | x = [ |
| @@ -1856,6 +2105,138 @@ if func 1, 2, 3, | |||
| 1856 | </pre> | 2105 | </pre> |
| 1857 | </YueDisplay> | 2106 | </YueDisplay> |
| 1858 | 2107 | ||
| 2108 | ### 傿•°è§£æž„ | ||
| 2109 | |||
| 2110 | 月之脚本支æŒåœ¨å‡½æ•°å½¢å‚ä½ç½®å¯¹ä¼ 入对象进行解构。适用两类解构表åé¢é‡ï¼š | ||
| 2111 | |||
| 2112 | - 使用 {} 包裹的å—é¢é‡/对象形å‚ï¼Œæ”¯æŒæä¾›èŽ·å¾—ç©ºå—æ®µæ—¶çš„默认值(例如 {:a, :b}ã€{a: a1 = 123})。 | ||
| 2113 | |||
| 2114 | - æ— {} 包裹ã€ä»¥é”®å€¼/简写键åºåˆ—开头,直至é‡åˆ°å…¶å®ƒè¡¨è¾¾å¼ç»ˆæ¢ï¼ˆä¾‹å¦‚ :a, b: b1, :c),表示从åŒä¸€ä¸ªå¯¹è±¡ä¸è§£æž„å¤šä¸ªå—æ®µã€‚ | ||
| 2115 | |||
| 2116 | ```moonscript | ||
| 2117 | f1 = (:a, :b, :c) -> | ||
| 2118 | print a, b, c | ||
| 2119 | |||
| 2120 | f1 a: 1, b: "2", c: {} | ||
| 2121 | |||
| 2122 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2123 | print a1, b, c | ||
| 2124 | |||
| 2125 | arg1 = {a: 0} | ||
| 2126 | f2 arg1, arg2 | ||
| 2127 | ``` | ||
| 2128 | <YueDisplay> | ||
| 2129 | <pre> | ||
| 2130 | f1 = (:a, :b, :c) -> | ||
| 2131 | print a, b, c | ||
| 2132 | |||
| 2133 | f1 a: 1, b: "2", c: {} | ||
| 2134 | |||
| 2135 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2136 | print a1, b, c | ||
| 2137 | |||
| 2138 | arg1 = {a: 0} | ||
| 2139 | f2 arg1, arg2 | ||
| 2140 | </pre> | ||
| 2141 | </YueDisplay> | ||
| 2142 | |||
| 2143 | ### å‰ç½®è¿”å›žè¡¨è¾¾å¼ | ||
| 2144 | |||
| 2145 | 在深度嵌套的函数体ä¸ï¼Œä¸ºäº†æå‡è¿”回值的å¯è¯»æ€§åŠç¼–写便利性,我们新增了 “å‰ç½®è¿”回表达å¼â€ è¯æ³•。其形å¼å¦‚下: | ||
| 2146 | |||
| 2147 | ```moon | ||
| 2148 | findFirstEven = (list): nil -> | ||
| 2149 | for item in *list | ||
| 2150 | if type(item) == "table" | ||
| 2151 | for sub in *item | ||
| 2152 | if sub % 2 == 0 | ||
| 2153 | return sub | ||
| 2154 | ``` | ||
| 2155 | <YueDisplay> | ||
| 2156 | <pre> | ||
| 2157 | findFirstEven = (list): nil -> | ||
| 2158 | for item in *list | ||
| 2159 | if type(item) == "table" | ||
| 2160 | for sub in *item | ||
| 2161 | if sub % 2 == 0 | ||
| 2162 | return sub | ||
| 2163 | </pre> | ||
| 2164 | </YueDisplay> | ||
| 2165 | |||
| 2166 | 这个写法ç‰ä»·äºŽï¼š | ||
| 2167 | |||
| 2168 | ```moon | ||
| 2169 | findFirstEven = (list) -> | ||
| 2170 | for item in *list | ||
| 2171 | if type(item) == "table" | ||
| 2172 | for sub in *item | ||
| 2173 | if sub % 2 == 0 | ||
| 2174 | return sub | ||
| 2175 | nil | ||
| 2176 | ``` | ||
| 2177 | <YueDisplay> | ||
| 2178 | <pre> | ||
| 2179 | findFirstEven = (list) -> | ||
| 2180 | for item in *list | ||
| 2181 | if type(item) == "table" | ||
| 2182 | for sub in *item | ||
| 2183 | if sub % 2 == 0 | ||
| 2184 | return sub | ||
| 2185 | nil | ||
| 2186 | </pre> | ||
| 2187 | </YueDisplay> | ||
| 2188 | |||
| 2189 | å”¯ä¸€çš„åŒºåˆ«åœ¨äºŽï¼šä½ å¯ä»¥å°†å‡½æ•°çš„è¿”å›žå€¼è¡¨è¾¾å¼æå‰å†™åœ¨ `->` 或 `=>` å‰ï¼Œç”¨ä»¥æŒ‡ç¤ºè¯¥å‡½æ•°åº”éšå¼è¿”回该表达å¼çš„å€¼ã€‚è¿™æ ·å³ä½¿åœ¨å¤šå±‚循环或æ¡ä»¶åˆ¤æ–çš„åœºæ™¯ä¸‹ï¼Œä¹Ÿæ— éœ€ç¼–å†™å°¾è¡Œæ‚¬æŒ‚çš„è¿”å›žè¡¨è¾¾å¼ï¼Œé€»è¾‘ç»“æž„ä¼šæ›´åŠ ç›´è§‚æ¸…æ™°ã€‚ | ||
| 2190 | |||
| 2191 | ### 命åå˜é•¿å‚æ•° | ||
| 2192 | |||
| 2193 | ä½ å¯ä»¥ä½¿ç”¨ `(...t) ->` è¯æ³•æ¥å°†å˜é•¿å‚数自动å˜å‚¨åˆ°ä¸€ä¸ªå‘½å表ä¸ã€‚è¿™ä¸ªè¡¨ä¼šåŒ…å«æ‰€æœ‰ä¼ å…¥çš„å‚æ•°ï¼ˆåŒ…括 `nil` 值),并且会在表的 `n` å—æ®µä¸å˜å‚¨å®žé™…ä¼ å…¥çš„å‚æ•°ä¸ªæ•°ï¼ˆåŒ…括 `nil` 值在内的个数)。 | ||
| 2194 | |||
| 2195 | ```moonscript | ||
| 2196 | f = (...t) -> | ||
| 2197 | print "傿•°ä¸ªæ•°:", t.n | ||
| 2198 | print "表长度:", #t | ||
| 2199 | for i = 1, t.n | ||
| 2200 | print t[i] | ||
| 2201 | |||
| 2202 | f 1, 2, 3 | ||
| 2203 | f "a", "b", "c", "d" | ||
| 2204 | f! | ||
| 2205 | |||
| 2206 | -- 处ç†åŒ…å« nil 的情况 | ||
| 2207 | process = (...args) -> | ||
| 2208 | sum = 0 | ||
| 2209 | for i = 1, args.n | ||
| 2210 | if args[i] != nil and type(args[i]) == "number" | ||
| 2211 | sum += args[i] | ||
| 2212 | sum | ||
| 2213 | |||
| 2214 | process 1, nil, 3, nil, 5 | ||
| 2215 | ``` | ||
| 2216 | <YueDisplay> | ||
| 2217 | <pre> | ||
| 2218 | f = (...t) -> | ||
| 2219 | print "傿•°ä¸ªæ•°:", t.n | ||
| 2220 | print "表长度:", #t | ||
| 2221 | for i = 1, t.n | ||
| 2222 | print t[i] | ||
| 2223 | |||
| 2224 | f 1, 2, 3 | ||
| 2225 | f "a", "b", "c", "d" | ||
| 2226 | f! | ||
| 2227 | |||
| 2228 | -- 处ç†åŒ…å« nil 的情况 | ||
| 2229 | process = (...args) -> | ||
| 2230 | sum = 0 | ||
| 2231 | for i = 1, args.n | ||
| 2232 | if args[i] != nil and type(args[i]) == "number" | ||
| 2233 | sum += args[i] | ||
| 2234 | sum | ||
| 2235 | |||
| 2236 | process 1, nil, 3, nil, 5 | ||
| 2237 | </pre> | ||
| 2238 | </YueDisplay> | ||
| 2239 | |||
| 1859 | ## åå‘回调 | 2240 | ## åå‘回调 |
| 1860 | 2241 | ||
| 1861 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ | 2242 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ |
| @@ -1920,7 +2301,7 @@ print result, msg | |||
| 1920 | 2301 | ||
| 1921 | ## è¡¨æ ¼å—é¢é‡ | 2302 | ## è¡¨æ ¼å—é¢é‡ |
| 1922 | 2303 | ||
| 1923 | å’ŒLuaä¸€æ ·ï¼Œè¡¨æ ¼å¯ä»¥é€šè¿‡èŠ±æ‹¬å·è¿›è¡Œå®šä¹‰ã€‚ | 2304 | å’Œ Lua ä¸€æ ·ï¼Œè¡¨æ ¼å¯ä»¥é€šè¿‡èŠ±æ‹¬å·è¿›è¡Œå®šä¹‰ã€‚ |
| 1924 | 2305 | ||
| 1925 | ```moonscript | 2306 | ```moonscript |
| 1926 | some_values = [1, 2, 3, 4] | 2307 | some_values = [1, 2, 3, 4] |
| @@ -2003,7 +2384,7 @@ y = type: "ç‹—", legs: 4, tails: 1 | |||
| 2003 | </pre> | 2384 | </pre> |
| 2004 | </YueDisplay> | 2385 | </YueDisplay> |
| 2005 | 2386 | ||
| 2006 | è¡¨æ ¼å—é¢é‡çš„é”®å¯ä»¥ä½¿ç”¨Luaè¯è¨€çš„关键å—ï¼Œè€Œæ— éœ€è½¬ä¹‰ï¼š | 2387 | è¡¨æ ¼å—é¢é‡çš„é”®å¯ä»¥ä½¿ç”¨ Lua è¯è¨€çš„关键å—ï¼Œè€Œæ— éœ€è½¬ä¹‰ï¼š |
| 2007 | 2388 | ||
| 2008 | ```moonscript | 2389 | ```moonscript |
| 2009 | tbl = { | 2390 | tbl = { |
| @@ -2039,7 +2420,7 @@ print_table :hair, :height | |||
| 2039 | </pre> | 2420 | </pre> |
| 2040 | </YueDisplay> | 2421 | </YueDisplay> |
| 2041 | 2422 | ||
| 2042 | å¦‚æžœä½ å¸Œæœ›è¡¨ä¸å—段的键是æŸä¸ªè¡¨è¾¾å¼çš„结果,那么å¯ä»¥ç”¨ **[ ]** 包裹它,就åƒåœ¨Luaä¸ä¸€æ ·ã€‚å¦‚æžœé”®ä¸æœ‰ä»»ä½•特殊å—符,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨å—符串å—é¢é‡ä½œä¸ºé”®ï¼Œçœç•¥æ–¹æ‹¬å·ã€‚ | 2423 | å¦‚æžœä½ å¸Œæœ›è¡¨ä¸å—段的键是æŸä¸ªè¡¨è¾¾å¼çš„结果,那么å¯ä»¥ç”¨ **[ ]** 包裹它,就åƒåœ¨ Lua ä¸ä¸€æ ·ã€‚å¦‚æžœé”®ä¸æœ‰ä»»ä½•特殊å—符,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨å—符串å—é¢é‡ä½œä¸ºé”®ï¼Œçœç•¥æ–¹æ‹¬å·ã€‚ |
| 2043 | 2424 | ||
| 2044 | ```moonscript | 2425 | ```moonscript |
| 2045 | t = { | 2426 | t = { |
| @@ -2056,7 +2437,7 @@ t = { | |||
| 2056 | </pre> | 2437 | </pre> |
| 2057 | </YueDisplay> | 2438 | </YueDisplay> |
| 2058 | 2439 | ||
| 2059 | Luaçš„è¡¨åŒæ—¶å…·æœ‰æ•°ç»„éƒ¨åˆ†å’Œå“ˆå¸Œéƒ¨åˆ†ï¼Œä½†æœ‰æ—¶å€™ä½ ä¼šå¸Œæœ›åœ¨ä¹¦å†™Lua表时,对Luaè¡¨åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„è¯ä¹‰åŒºåˆ†ã€‚ç„¶åŽä½ å¯ä»¥ç”¨ **[ ]** è€Œä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表ä¸å†™å…¥ä»»ä½•键值对。 | 2440 | Lua çš„è¡¨åŒæ—¶å…·æœ‰æ•°ç»„éƒ¨åˆ†å’Œå“ˆå¸Œéƒ¨åˆ†ï¼Œä½†æœ‰æ—¶å€™ä½ ä¼šå¸Œæœ›åœ¨ä¹¦å†™ Lua 表时,对 Lua è¡¨åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„è¯ä¹‰åŒºåˆ†ã€‚ç„¶åŽä½ å¯ä»¥ç”¨ **[ ]** è€Œä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表ä¸å†™å…¥ä»»ä½•键值对。 |
| 2060 | 2441 | ||
| 2061 | ```moonscript | 2442 | ```moonscript |
| 2062 | some_values = [ 1, 2, 3, 4 ] | 2443 | some_values = [ 1, 2, 3, 4 ] |
| @@ -2071,11 +2452,11 @@ list_with_one_element = [ 1, ] | |||
| 2071 | 2452 | ||
| 2072 | ## æŽ¨å¯¼å¼ | 2453 | ## æŽ¨å¯¼å¼ |
| 2073 | 2454 | ||
| 2074 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Luaè¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸ä½ åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ | 2455 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生 Lua è¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸ä½ åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ |
| 2075 | 2456 | ||
| 2076 | ### åˆ—è¡¨æŽ¨å¯¼å¼ | 2457 | ### åˆ—è¡¨æŽ¨å¯¼å¼ |
| 2077 | 2458 | ||
| 2078 | 以下æ“作创建了一个items表的副本,但所有包å«çš„值都翻å€äº†ã€‚ | 2459 | 以下æ“作创建了一个 items 表的副本,但所有包å«çš„值都翻å€äº†ã€‚ |
| 2079 | 2460 | ||
| 2080 | ```moonscript | 2461 | ```moonscript |
| 2081 | items = [1, 2, 3, 4] | 2462 | items = [1, 2, 3, 4] |
| @@ -2088,7 +2469,7 @@ doubled = [item * 2 for i, item in ipairs items] | |||
| 2088 | </pre> | 2469 | </pre> |
| 2089 | </YueDisplay> | 2470 | </YueDisplay> |
| 2090 | 2471 | ||
| 2091 | å¯ä»¥ä½¿ç”¨whenåå¥ç›é€‰æ–°è¡¨ä¸åŒ…å«çš„项目: | 2472 | å¯ä»¥ä½¿ç”¨ `when` åå¥ç›é€‰æ–°è¡¨ä¸åŒ…å«çš„项目: |
| 2092 | 2473 | ||
| 2093 | ```moonscript | 2474 | ```moonscript |
| 2094 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | 2475 | slice = [item for i, item in ipairs items when i > 1 and i < 3] |
| @@ -2099,7 +2480,7 @@ slice = [item for i, item in ipairs items when i > 1 and i < 3] | |||
| 2099 | </pre> | 2480 | </pre> |
| 2100 | </YueDisplay> | 2481 | </YueDisplay> |
| 2101 | 2482 | ||
| 2102 | å› ä¸ºæˆ‘ä»¬å¸¸å¸¸éœ€è¦è¿ä»£æ•°å€¼ç´¢å¼•表的值,所以引入了 **\*** æ“作符æ¥åšè¯æ³•简化。doubled示例å¯ä»¥é‡å†™ä¸ºï¼š | 2483 | å› ä¸ºæˆ‘ä»¬å¸¸å¸¸éœ€è¦è¿ä»£æ•°å€¼ç´¢å¼•表的值,所以引入了 **\*** æ“作符æ¥åšè¯æ³•简化。doubled 示例å¯ä»¥é‡å†™ä¸ºï¼š |
| 2103 | 2484 | ||
| 2104 | ```moonscript | 2485 | ```moonscript |
| 2105 | doubled = [item * 2 for item in *items] | 2486 | doubled = [item * 2 for item in *items] |
| @@ -2110,9 +2491,30 @@ doubled = [item * 2 for item in *items] | |||
| 2110 | </pre> | 2491 | </pre> |
| 2111 | </YueDisplay> | 2492 | </YueDisplay> |
| 2112 | 2493 | ||
| 2113 | forå’Œwhenåå¥å¯ä»¥æ ¹æ®éœ€è¦è¿›è¡Œé“¾å¼æ“ä½œã€‚å”¯ä¸€çš„è¦æ±‚是推导å¼ä¸è‡³å°‘è¦æœ‰ä¸€ä¸ªforåå¥ã€‚ | 2494 | 在列表推导å¼ä¸ï¼Œä½ 还å¯ä»¥ä½¿ç”¨å±•å¼€æ“作符 `...` æ¥å®žçŽ°å¯¹åˆ—è¡¨åµŒå¥—å±‚çº§è¿›è¡Œæ‰å¹³åŒ–的处ç†ï¼š |
| 2495 | |||
| 2496 | ```moonscript | ||
| 2497 | data = | ||
| 2498 | a: [1, 2, 3] | ||
| 2499 | b: [4, 5, 6] | ||
| 2500 | |||
| 2501 | flat = [...v for k,v in pairs data] | ||
| 2502 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2503 | ``` | ||
| 2504 | <YueDisplay> | ||
| 2505 | <pre> | ||
| 2506 | data = | ||
| 2507 | a: [1, 2, 3] | ||
| 2508 | b: [4, 5, 6] | ||
| 2509 | |||
| 2510 | flat = [...v for k,v in pairs data] | ||
| 2511 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2512 | </pre> | ||
| 2513 | </YueDisplay> | ||
| 2514 | |||
| 2515 | for å’Œ when åå¥å¯ä»¥æ ¹æ®éœ€è¦è¿›è¡Œé“¾å¼æ“ä½œã€‚å”¯ä¸€çš„è¦æ±‚是推导å¼ä¸è‡³å°‘è¦æœ‰ä¸€ä¸ª for åå¥ã€‚ | ||
| 2114 | 2516 | ||
| 2115 | 使用多个foråå¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„æ•ˆæžœç›¸åŒï¼š | 2517 | 使用多个 for åå¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„æ•ˆæžœç›¸åŒï¼š |
| 2116 | 2518 | ||
| 2117 | ```moonscript | 2519 | ```moonscript |
| 2118 | x_coords = [4, 5, 6, 7] | 2520 | x_coords = [4, 5, 6, 7] |
| @@ -2131,7 +2533,7 @@ for y in *y_coords] | |||
| 2131 | </pre> | 2533 | </pre> |
| 2132 | </YueDisplay> | 2534 | </YueDisplay> |
| 2133 | 2535 | ||
| 2134 | 在推导å¼ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨ç®€å•的数值for循环: | 2536 | 在推导å¼ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨ç®€å•的数值 for 循环: |
| 2135 | 2537 | ||
| 2136 | ```moonscript | 2538 | ```moonscript |
| 2137 | evens = [i for i = 1, 100 when i % 2 == 0] | 2539 | evens = [i for i = 1, 100 when i % 2 == 0] |
| @@ -2146,7 +2548,7 @@ evens = [i for i = 1, 100 when i % 2 == 0] | |||
| 2146 | 2548 | ||
| 2147 | è¡¨æ ¼æŽ¨å¯¼å¼å’Œåˆ—表推导å¼çš„è¯æ³•éžå¸¸ç›¸ä¼¼ï¼Œåªæ˜¯è¦ä½¿ç”¨ **{** å’Œ **}** å¹¶ä»Žæ¯æ¬¡è¿ä»£ä¸å–两个值。 | 2549 | è¡¨æ ¼æŽ¨å¯¼å¼å’Œåˆ—表推导å¼çš„è¯æ³•éžå¸¸ç›¸ä¼¼ï¼Œåªæ˜¯è¦ä½¿ç”¨ **{** å’Œ **}** å¹¶ä»Žæ¯æ¬¡è¿ä»£ä¸å–两个值。 |
| 2148 | 2550 | ||
| 2149 | 以下示例生æˆäº†è¡¨æ ¼thing的副本: | 2551 | 以下示例生æˆäº†è¡¨æ ¼ thing 的副本: |
| 2150 | 2552 | ||
| 2151 | ```moonscript | 2553 | ```moonscript |
| 2152 | thing = { | 2554 | thing = { |
| @@ -2208,9 +2610,9 @@ tbl = {unpack tuple for tuple in *tuples} | |||
| 2208 | 2610 | ||
| 2209 | ### 切片 | 2611 | ### 切片 |
| 2210 | 2612 | ||
| 2211 | 当使用 **\*** æ“作符时,月之脚本还æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥é™åˆ¶è¦éåŽ†çš„åˆ—è¡¨èŒƒå›´ã€‚è¿™ä¸ªè¯æ³•也相当于在for循环ä¸è®¾ç½®è¿ä»£è¾¹ç•Œå’Œæ¥é•¿ã€‚ | 2613 | 当使用 **\*** æ“作符时,月之脚本还æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥é™åˆ¶è¦éåŽ†çš„åˆ—è¡¨èŒƒå›´ã€‚è¿™ä¸ªè¯æ³•也相当于在 for 循环ä¸è®¾ç½®è¿ä»£è¾¹ç•Œå’Œæ¥é•¿ã€‚ |
| 2212 | 2614 | ||
| 2213 | 下é¢çš„æ¡ˆä¾‹ä¸ï¼Œæˆ‘们在切片ä¸è®¾ç½®æœ€å°å’Œæœ€å¤§è¾¹ç•Œï¼Œå–索引在1到5之间(包括1å’Œ5)的所有项目: | 2615 | 下é¢çš„æ¡ˆä¾‹ä¸ï¼Œæˆ‘们在切片ä¸è®¾ç½®æœ€å°å’Œæœ€å¤§è¾¹ç•Œï¼Œå–索引在 1 到 5 之间(包括 1 å’Œ 5)的所有项目: |
| 2214 | 2616 | ||
| 2215 | ```moonscript | 2617 | ```moonscript |
| 2216 | slice = [item for item in *items[1, 5]] | 2618 | slice = [item for item in *items[1, 5]] |
| @@ -2232,7 +2634,7 @@ slice = [item for item in *items[2,]] | |||
| 2232 | </pre> | 2634 | </pre> |
| 2233 | </YueDisplay> | 2635 | </YueDisplay> |
| 2234 | 2636 | ||
| 2235 | 如果çœç•¥äº†æœ€å°è¾¹ç•Œï¼Œä¾¿é»˜è®¤ä¼šè®¾ç½®ä¸º1ã€‚è¿™é‡Œæˆ‘ä»¬åªæä¾›ä¸€ä¸ªæ¥é•¿ï¼Œå¹¶ç•™ä¸‹å…¶ä»–è¾¹ç•Œä¸ºç©ºã€‚è¿™æ ·ä¼šä½¿å¾—ä»£ç å–出所有奇数索引的项目:(1, 3, 5, …) | 2637 | 如果çœç•¥äº†æœ€å°è¾¹ç•Œï¼Œä¾¿é»˜è®¤ä¼šè®¾ç½®ä¸º 1ã€‚è¿™é‡Œæˆ‘ä»¬åªæä¾›ä¸€ä¸ªæ¥é•¿ï¼Œå¹¶ç•™ä¸‹å…¶ä»–è¾¹ç•Œä¸ºç©ºã€‚è¿™æ ·ä¼šä½¿å¾—ä»£ç å–出所有奇数索引的项目:(1, 3, 5, …) |
| 2236 | 2638 | ||
| 2237 | ```moonscript | 2639 | ```moonscript |
| 2238 | slice = [item for item in *items[,,2]] | 2640 | slice = [item for item in *items[,,2]] |
| @@ -2244,9 +2646,48 @@ slice = [item for item in *items[,,2]] | |||
| 2244 | </pre> | 2646 | </pre> |
| 2245 | </YueDisplay> | 2647 | </YueDisplay> |
| 2246 | 2648 | ||
| 2649 | 最å°å’Œæœ€å¤§è¾¹ç•Œéƒ½å¯ä»¥æ˜¯è´Ÿæ•°ï¼Œä½¿ç”¨è´Ÿæ•°æ„味ç€è¾¹ç•Œæ˜¯ä»Žè¡¨çš„æœ«å°¾å¼€å§‹è®¡ç®—的。 | ||
| 2650 | |||
| 2651 | ```moonscript | ||
| 2652 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
| 2653 | slice = [item for item in *items[-4,-1]] | ||
| 2654 | ``` | ||
| 2655 | <YueDisplay> | ||
| 2656 | <pre> | ||
| 2657 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
| 2658 | slice = [item for item in *items[-4,-1]] | ||
| 2659 | </pre> | ||
| 2660 | </YueDisplay> | ||
| 2661 | |||
| 2662 | 切片的æ¥é•¿ä¹Ÿå¯ä»¥æ˜¯è´Ÿæ•°ï¼Œè¿™æ„味ç€å…ƒç´ 会以相å的顺åºè¢«å–出。 | ||
| 2663 | |||
| 2664 | ```moonscript | ||
| 2665 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2666 | ``` | ||
| 2667 | <YueDisplay> | ||
| 2668 | <pre> | ||
| 2669 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2670 | </pre> | ||
| 2671 | </YueDisplay> | ||
| 2672 | |||
| 2673 | #### åˆ‡ç‰‡è¡¨è¾¾å¼ | ||
| 2674 | |||
| 2675 | 切片也å¯ä»¥ä½œä¸ºè¡¨è¾¾å¼æ¥ä½¿ç”¨ã€‚å¯ä»¥ç”¨äºŽèŽ·å–一个表包å«çš„å列表。 | ||
| 2676 | |||
| 2677 | ```moonscript | ||
| 2678 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
| 2679 | sub_list = items[2, 4] | ||
| 2680 | ``` | ||
| 2681 | <YueDisplay> | ||
| 2682 | <pre> | ||
| 2683 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
| 2684 | sub_list = items[2, 4] | ||
| 2685 | </pre> | ||
| 2686 | </YueDisplay> | ||
| 2687 | |||
| 2247 | ## for 循环 | 2688 | ## for 循环 |
| 2248 | 2689 | ||
| 2249 | Lua䏿œ‰ä¸¤ç§for循环形å¼ï¼Œæ•°å—型和通用型: | 2690 | Lua 䏿œ‰ä¸¤ç§ for 循环形å¼ï¼Œæ•°å—型和通用型: |
| 2250 | 2691 | ||
| 2251 | ```moonscript | 2692 | ```moonscript |
| 2252 | for i = 10, 20 | 2693 | for i = 10, 20 |
| @@ -2299,7 +2740,7 @@ for j = 1, 10, 3 do print j | |||
| 2299 | </pre> | 2740 | </pre> |
| 2300 | </YueDisplay> | 2741 | </YueDisplay> |
| 2301 | 2742 | ||
| 2302 | for循环也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚for循环主体ä¸çš„æœ€åŽä¸€æ¡è¯å¥ä¼šè¢«å¼ºåˆ¶è½¬æ¢ä¸ºä¸€ä¸ªè¿”回值的表达å¼ï¼Œå¹¶ä¼šå°†è¡¨è¾¾å¼è®¡ç®—ç»“æžœçš„å€¼è¿½åŠ åˆ°ä¸€ä¸ªä½œä¸ºç»“æžœçš„æ•°ç»„è¡¨ä¸ã€‚ | 2743 | for 循环也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚for 循环主体ä¸çš„æœ€åŽä¸€æ¡è¯å¥ä¼šè¢«å¼ºåˆ¶è½¬æ¢ä¸ºä¸€ä¸ªè¿”回值的表达å¼ï¼Œå¹¶ä¼šå°†è¡¨è¾¾å¼è®¡ç®—ç»“æžœçš„å€¼è¿½åŠ åˆ°ä¸€ä¸ªä½œä¸ºç»“æžœçš„æ•°ç»„è¡¨ä¸ã€‚ |
| 2303 | 2744 | ||
| 2304 | å°†æ¯ä¸ªå¶æ•°åŠ å€ï¼š | 2745 | å°†æ¯ä¸ªå¶æ•°åŠ å€ï¼š |
| 2305 | 2746 | ||
| @@ -2320,9 +2761,9 @@ doubled_evens = for i = 1, 20 | |||
| 2320 | </pre> | 2761 | </pre> |
| 2321 | </YueDisplay> | 2762 | </YueDisplay> |
| 2322 | 2763 | ||
| 2323 | æ¤å¤–,for循环还支æŒå¸¦è¿”回值的breakè¯å¥ï¼Œè¿™æ ·å¾ªçŽ¯æœ¬èº«å°±å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œåœ¨æ»¡è¶³æ¡ä»¶æ—¶æå‰é€€å‡ºå¹¶è¿”回有æ„义的结果。 | 2764 | æ¤å¤–,for 循环还支æŒå¸¦è¿”回值的 break è¯å¥ï¼Œè¿™æ ·å¾ªçŽ¯æœ¬èº«å°±å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œåœ¨æ»¡è¶³æ¡ä»¶æ—¶æå‰é€€å‡ºå¹¶è¿”回有æ„义的结果。 |
| 2324 | 2765 | ||
| 2325 | 例如,查找第一个大于10的数å—: | 2766 | 例如,查找第一个大于 10 的数å—: |
| 2326 | 2767 | ||
| 2327 | ```moonscript | 2768 | ```moonscript |
| 2328 | first_large = for n in *numbers | 2769 | first_large = for n in *numbers |
| @@ -2335,9 +2776,9 @@ first_large = for n in *numbers | |||
| 2335 | </pre> | 2776 | </pre> |
| 2336 | </YueDisplay> | 2777 | </YueDisplay> |
| 2337 | 2778 | ||
| 2338 | ä½ è¿˜å¯ä»¥ç»“åˆfor循环表达å¼ä¸Žcontinueè¯å¥æ¥è¿‡æ»¤å€¼ã€‚ | 2779 | ä½ è¿˜å¯ä»¥ç»“åˆ for 循环表达å¼ä¸Ž continue è¯å¥æ¥è¿‡æ»¤å€¼ã€‚ |
| 2339 | 2780 | ||
| 2340 | 注æ„出现在函数体末尾的for循环,ä¸ä¼šè¢«å½“作是一个表达å¼å¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥æ˜¾å¼åœ°ä½¿ç”¨è¿”回è¯å¥åŠ for循环表达å¼ã€‚ | 2781 | 注æ„出现在函数体末尾的 for 循环,ä¸ä¼šè¢«å½“作是一个表达å¼å¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回 nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥æ˜¾å¼åœ°ä½¿ç”¨è¿”回è¯å¥åŠ for 循环表达å¼ã€‚ |
| 2341 | 2782 | ||
| 2342 | ```moonscript | 2783 | ```moonscript |
| 2343 | func_a = -> for i = 1, 10 do print i | 2784 | func_a = -> for i = 1, 10 do print i |
| @@ -2360,7 +2801,7 @@ print func_b! -- æ‰“å° table 对象 | |||
| 2360 | 2801 | ||
| 2361 | ## repeat 循环 | 2802 | ## repeat 循环 |
| 2362 | 2803 | ||
| 2363 | repeat循环是从Luaè¯è¨€ä¸æ¬è¿‡æ¥çš„ç›¸ä¼¼è¯æ³•: | 2804 | repeat 循环是从 Lua è¯è¨€ä¸æ¬è¿‡æ¥çš„ç›¸ä¼¼è¯æ³•: |
| 2364 | 2805 | ||
| 2365 | ```moonscript | 2806 | ```moonscript |
| 2366 | i = 10 | 2807 | i = 10 |
| @@ -2381,7 +2822,7 @@ until i == 0 | |||
| 2381 | 2822 | ||
| 2382 | ## while 循环 | 2823 | ## while 循环 |
| 2383 | 2824 | ||
| 2384 | 在月之脚本ä¸çš„while循环有四ç§å†™æ³•: | 2825 | 在月之脚本ä¸çš„ while 循环有四ç§å†™æ³•: |
| 2385 | 2826 | ||
| 2386 | ```moonscript | 2827 | ```moonscript |
| 2387 | i = 10 | 2828 | i = 10 |
| @@ -2420,7 +2861,7 @@ until running == false do my_function! | |||
| 2420 | </pre> | 2861 | </pre> |
| 2421 | </YueDisplay> | 2862 | </YueDisplay> |
| 2422 | 2863 | ||
| 2423 | åƒforå¾ªçŽ¯çš„è¯æ³•ä¸€æ ·ï¼Œwhile循环也å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ä½¿ç”¨ã€‚为了使函数返回while循环的累积列表值,必须明确使用返回è¯å¥è¿”回while循环表达å¼ã€‚ | 2864 | åƒ for å¾ªçŽ¯çš„è¯æ³•ä¸€æ ·ï¼Œwhile 循环也å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ä½¿ç”¨ã€‚为了使函数返回 while 循环的累积列表值,必须明确使用返回è¯å¥è¿”回 while 循环表达å¼ã€‚ |
| 2424 | 2865 | ||
| 2425 | ## ç»§ç» | 2866 | ## ç»§ç» |
| 2426 | 2867 | ||
| @@ -2538,13 +2979,14 @@ print message -- 打å°: 我很高 | |||
| 2538 | </pre> | 2979 | </pre> |
| 2539 | </YueDisplay> | 2980 | </YueDisplay> |
| 2540 | 2981 | ||
| 2541 | ifçš„åä¹‰è¯æ˜¯unless(相当于if not,如果 vs 除éžï¼‰ï¼š | 2982 | if çš„åä¹‰è¯æ˜¯ unless(相当于 if not,æ£å¦‚“如果â€å¯¹åº”“除éžâ€ï¼‰ï¼š |
| 2542 | 2983 | ||
| 2543 | ```moonscript | 2984 | ```moonscript |
| 2544 | unless os.date("%A") == "Monday" | 2985 | unless os.date("%A") == "Monday" |
| 2545 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" | 2986 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" |
| 2546 | ``` | 2987 | ``` |
| 2547 | <YueDisplay> | 2988 | <YueDisplay> |
| 2989 | |||
| 2548 | <pre> | 2990 | <pre> |
| 2549 | unless os.date("%A") == "Monday" | 2991 | unless os.date("%A") == "Monday" |
| 2550 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" | 2992 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" |
| @@ -2596,7 +3038,7 @@ print "ä½ å¾ˆå¹¸è¿!" unless math.random! > 0.1 | |||
| 2596 | 3038 | ||
| 2597 | ## 代ç 行修饰符 | 3039 | ## 代ç 行修饰符 |
| 2598 | 3040 | ||
| 2599 | 为了方便编写代ç ,循环è¯å¥å’Œifè¯å¥å¯ä»¥åº”用于å•行代ç è¯å¥çš„æœ«å°¾ï¼š | 3041 | 为了方便编写代ç ,循环è¯å¥å’Œ if è¯å¥å¯ä»¥åº”用于å•行代ç è¯å¥çš„æœ«å°¾ï¼š |
| 2600 | 3042 | ||
| 2601 | ```moonscript | 3043 | ```moonscript |
| 2602 | print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" | 3044 | print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" |
| @@ -2607,7 +3049,7 @@ print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" | |||
| 2607 | </pre> | 3049 | </pre> |
| 2608 | </YueDisplay> | 3050 | </YueDisplay> |
| 2609 | 3051 | ||
| 2610 | 修饰for循环的示例: | 3052 | 修饰 for 循环的示例: |
| 2611 | 3053 | ||
| 2612 | ```moonscript | 3054 | ```moonscript |
| 2613 | print "项目: ", item for item in *items | 3055 | print "项目: ", item for item in *items |
| @@ -2618,7 +3060,7 @@ print "项目: ", item for item in *items | |||
| 2618 | </pre> | 3060 | </pre> |
| 2619 | </YueDisplay> | 3061 | </YueDisplay> |
| 2620 | 3062 | ||
| 2621 | 修饰while循环的示例: | 3063 | 修饰 while 循环的示例: |
| 2622 | 3064 | ||
| 2623 | ```moonscript | 3065 | ```moonscript |
| 2624 | game\update! while game\isRunning! | 3066 | game\update! while game\isRunning! |
| @@ -2635,34 +3077,32 @@ reader\parse_line! until reader\eof! | |||
| 2635 | 3077 | ||
| 2636 | ## switch è¯å¥ | 3078 | ## switch è¯å¥ |
| 2637 | 3079 | ||
| 2638 | switchè¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和ifè¯å¥ä¸€æ ·ï¼Œswitchè¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ªelse代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„Lua代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用==æ“作符完æˆçš„。 | 3080 | switch è¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和 if è¯å¥ä¸€æ ·ï¼Œswitch è¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ª else 代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„ Lua 代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用 == æ“作符完æˆçš„。switch è¯å¥ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨èµ‹å€¼è¡¨è¾¾å¼æ¥å‚¨å˜ä¸´æ—¶å˜é‡å€¼ã€‚ |
| 2639 | 3081 | ||
| 2640 | ```moonscript | 3082 | ```moonscript |
| 2641 | name = "Dan" | 3083 | switch name := "Dan" |
| 2642 | switch name | ||
| 2643 | when "Robert" | 3084 | when "Robert" |
| 2644 | print "ä½ æ˜¯Robert" | 3085 | print "ä½ æ˜¯Robert" |
| 2645 | when "Dan", "Daniel" | 3086 | when "Dan", "Daniel" |
| 2646 | print "ä½ çš„åå—æ˜¯Dan" | 3087 | print "ä½ çš„åå—æ˜¯Dan" |
| 2647 | else | 3088 | else |
| 2648 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 3089 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
| 2649 | ``` | 3090 | ``` |
| 2650 | <YueDisplay> | 3091 | <YueDisplay> |
| 2651 | <pre> | 3092 | <pre> |
| 2652 | name = "Dan" | 3093 | switch name := "Dan" |
| 2653 | switch name | ||
| 2654 | when "Robert" | 3094 | when "Robert" |
| 2655 | print "ä½ æ˜¯Robert" | 3095 | print "ä½ æ˜¯Robert" |
| 2656 | when "Dan", "Daniel" | 3096 | when "Dan", "Daniel" |
| 2657 | print "ä½ çš„åå—æ˜¯Dan" | 3097 | print "ä½ çš„åå—æ˜¯Dan" |
| 2658 | else | 3098 | else |
| 2659 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 3099 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
| 2660 | </pre> | 3100 | </pre> |
| 2661 | </YueDisplay> | 3101 | </YueDisplay> |
| 2662 | 3102 | ||
| 2663 | switchè¯å¥çš„whenåå¥ä¸å¯ä»¥é€šè¿‡ä½¿ç”¨é€—å·åˆ†éš”的列表æ¥åŒ¹é…多个值。 | 3103 | switch è¯å¥çš„ when åå¥ä¸å¯ä»¥é€šè¿‡ä½¿ç”¨é€—å·åˆ†éš”的列表æ¥åŒ¹é…多个值。 |
| 2664 | 3104 | ||
| 2665 | switchè¯å¥ä¹Ÿå¯ä»¥ä½œä¸ºè¡¨è¾¾å¼ä½¿ç”¨ï¼Œä¸‹é¢æˆ‘们å¯ä»¥å°†switchè¯å¥è¿”回的结果分é…给一个å˜é‡ï¼š | 3105 | switch è¯å¥ä¹Ÿå¯ä»¥ä½œä¸ºè¡¨è¾¾å¼ä½¿ç”¨ï¼Œä¸‹é¢æˆ‘们å¯ä»¥å°† switch è¯å¥è¿”回的结果分é…给一个å˜é‡ï¼š |
| 2666 | 3106 | ||
| 2667 | ```moonscript | 3107 | ```moonscript |
| 2668 | b = 1 | 3108 | b = 1 |
| @@ -2687,7 +3127,7 @@ next_number = switch b | |||
| 2687 | </pre> | 3127 | </pre> |
| 2688 | </YueDisplay> | 3128 | </YueDisplay> |
| 2689 | 3129 | ||
| 2690 | 我们å¯ä»¥ä½¿ç”¨then关键å—在whenåå¥çš„åŒä¸€è¡Œä¸Šç¼–写处ç†ä»£ç 。else代ç å—çš„åŽç»ä»£ç ä¸è¦å†™åœ¨åŒä¸€è¡Œä¸Šä¸éœ€è¦é¢å¤–的关键å—。 | 3130 | 我们å¯ä»¥ä½¿ç”¨ then 关键å—在 when åå¥çš„åŒä¸€è¡Œä¸Šç¼–写处ç†ä»£ç 。else 代ç å—çš„åŽç»ä»£ç ä¸è¦å†™åœ¨åŒä¸€è¡Œä¸Šä¸éœ€è¦é¢å¤–的关键å—。 |
| 2691 | 3131 | ||
| 2692 | ```moonscript | 3132 | ```moonscript |
| 2693 | msg = switch math.random(1, 5) | 3133 | msg = switch math.random(1, 5) |
| @@ -2704,7 +3144,7 @@ msg = switch math.random(1, 5) | |||
| 2704 | </pre> | 3144 | </pre> |
| 2705 | </YueDisplay> | 3145 | </YueDisplay> |
| 2706 | 3146 | ||
| 2707 | 如果在编写switchè¯å¥æ—¶å¸Œæœ›å°‘å†™ä¸€ä¸ªç¼©è¿›ï¼Œé‚£ä¹ˆä½ å¯ä»¥æŠŠç¬¬ä¸€ä¸ªwhenå奿”¾åœ¨switch开始è¯å¥çš„第一行,然åŽåŽç»çš„åè¯å¥å°±éƒ½å¯ä»¥éƒ½å°‘写一个缩进。 | 3147 | 如果在编写 switch è¯å¥æ—¶å¸Œæœ›å°‘å†™ä¸€ä¸ªç¼©è¿›ï¼Œé‚£ä¹ˆä½ å¯ä»¥æŠŠç¬¬ä¸€ä¸ª when å奿”¾åœ¨ switch 开始è¯å¥çš„第一行,然åŽåŽç»çš„åè¯å¥å°±éƒ½å¯ä»¥éƒ½å°‘写一个缩进。 |
| 2708 | 3148 | ||
| 2709 | ```moonscript | 3149 | ```moonscript |
| 2710 | switch math.random(1, 5) | 3150 | switch math.random(1, 5) |
| @@ -2733,11 +3173,11 @@ else | |||
| 2733 | </pre> | 3173 | </pre> |
| 2734 | </YueDisplay> | 3174 | </YueDisplay> |
| 2735 | 3175 | ||
| 2736 | 值得注æ„的是,在生æˆLuaä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨==表达å¼çš„å³ä¾§ã€‚å½“ä½ å¸Œæœ›ç»™whenåå¥çš„æ¯”较对象定义一个\_\_eq元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ | 3176 | 值得注æ„çš„æ˜¯ï¼Œåœ¨ç”Ÿæˆ Lua ä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨ == 表达å¼çš„å³ä¾§ã€‚å½“ä½ å¸Œæœ›ç»™ when åå¥çš„æ¯”较对象定义一个 \_\_eq 元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ |
| 2737 | 3177 | ||
| 2738 | ### è¡¨æ ¼åŒ¹é… | 3178 | ### è¡¨æ ¼åŒ¹é… |
| 2739 | 3179 | ||
| 2740 | 在switchçš„whenåå¥ä¸ï¼Œå¦‚æžœæœŸå¾…æ£€æŸ¥ç›®æ ‡æ˜¯ä¸€ä¸ªè¡¨æ ¼ï¼Œä¸”å¯ä»¥é€šè¿‡ç‰¹å®šçš„结构进行解构并获得éžnilå€¼ï¼Œé‚£ä¹ˆä½ å¯ä»¥å°è¯•ä½¿ç”¨è¡¨æ ¼åŒ¹é…çš„è¯æ³•。 | 3180 | 在 switch çš„ when åå¥ä¸ï¼Œå¦‚æžœæœŸå¾…æ£€æŸ¥ç›®æ ‡æ˜¯ä¸€ä¸ªè¡¨æ ¼ï¼Œä¸”å¯ä»¥é€šè¿‡ç‰¹å®šçš„ç»“æž„è¿›è¡Œè§£æž„å¹¶èŽ·å¾—éž nil å€¼ï¼Œé‚£ä¹ˆä½ å¯ä»¥å°è¯•ä½¿ç”¨è¡¨æ ¼åŒ¹é…çš„è¯æ³•。 |
| 2741 | 3181 | ||
| 2742 | ```moonscript | 3182 | ```moonscript |
| 2743 | items = | 3183 | items = |
| @@ -2889,9 +3329,30 @@ switch tb | |||
| 2889 | </pre> | 3329 | </pre> |
| 2890 | </YueDisplay> | 3330 | </YueDisplay> |
| 2891 | 3331 | ||
| 3332 | 匹é…一个列表并æ•èŽ·ç‰¹å®šèŒƒå›´å†…çš„å…ƒç´ ã€‚ | ||
| 3333 | |||
| 3334 | ```moonscript | ||
| 3335 | segments = ["admin", "users", "logs", "view"] | ||
| 3336 | switch segments | ||
| 3337 | when [...groups, resource, action] | ||
| 3338 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
| 3339 | print "Resource:", resource -- 打å°: "logs" | ||
| 3340 | print "Action:", action -- 打å°: "view" | ||
| 3341 | ``` | ||
| 3342 | <YueDisplay> | ||
| 3343 | <pre> | ||
| 3344 | segments = ["admin", "users", "logs", "view"] | ||
| 3345 | switch segments | ||
| 3346 | when [...groups, resource, action] | ||
| 3347 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
| 3348 | print "Resource:", resource -- 打å°: "logs" | ||
| 3349 | print "Action:", action -- 打å°: "view" | ||
| 3350 | </pre> | ||
| 3351 | </YueDisplay> | ||
| 3352 | |||
| 2892 | ## é¢å‘对象编程 | 3353 | ## é¢å‘对象编程 |
| 2893 | 3354 | ||
| 2894 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚æžœä½ æƒ³çŸ¥é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹Lua代ç 。 | 3355 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„ Lua 代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚æžœä½ æƒ³çŸ¥é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹ Lua 代ç 。 |
| 2895 | 3356 | ||
| 2896 | 一个简å•的类: | 3357 | 一个简å•的类: |
| 2897 | 3358 | ||
| @@ -2920,11 +3381,11 @@ class Inventory | |||
| 2920 | </pre> | 3381 | </pre> |
| 2921 | </YueDisplay> | 3382 | </YueDisplay> |
| 2922 | 3383 | ||
| 2923 | 在月之脚本ä¸é‡‡ç”¨é¢å‘å¯¹è±¡çš„ç¼–ç¨‹æ–¹å¼æ—¶ï¼Œé€šå¸¸ä¼šä½¿ç”¨ç±»å£°æ˜Žè¯å¥ç»“åˆLuaè¡¨æ ¼å—é¢é‡æ¥åšç±»å®šä¹‰ã€‚这个类的定义包å«äº†å®ƒçš„æ‰€æœ‰æ–¹æ³•和属性。在这ç§ç»“æž„ä¸ï¼Œé”®å为“newâ€çš„æˆå‘˜æ‰®æ¼”äº†ä¸€ä¸ªé‡è¦çš„è§’è‰²ï¼Œæ˜¯ä½œä¸ºæž„é€ å‡½æ•°æ¥ä½¿ç”¨ã€‚ | 3384 | 在月之脚本ä¸é‡‡ç”¨é¢å‘å¯¹è±¡çš„ç¼–ç¨‹æ–¹å¼æ—¶ï¼Œé€šå¸¸ä¼šä½¿ç”¨ç±»å£°æ˜Žè¯å¥ç»“åˆ Lua è¡¨æ ¼å—é¢é‡æ¥åšç±»å®šä¹‰ã€‚这个类的定义包å«äº†å®ƒçš„æ‰€æœ‰æ–¹æ³•和属性。在这ç§ç»“æž„ä¸ï¼Œé”®å为 “new†的æˆå‘˜æ‰®æ¼”了一个é‡è¦çš„è§’è‰²ï¼Œæ˜¯ä½œä¸ºæž„é€ å‡½æ•°æ¥ä½¿ç”¨ã€‚ |
| 2924 | 3385 | ||
| 2925 | 值得注æ„的是,类ä¸çš„æ–¹æ³•都采用了粗ç®å¤´å‡½æ•°è¯æ³•ã€‚å½“åœ¨ç±»çš„å®žä¾‹ä¸Šè°ƒç”¨æ–¹æ³•æ—¶ï¼Œè¯¥å®žä¾‹ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°è¢«ä¼ å…¥ï¼Œå› æ¤ç²—ç®å¤´å‡½æ•°ç”¨äºŽç”Ÿæˆä¸€ä¸ªå为“selfâ€çš„傿•°ã€‚ | 3386 | 值得注æ„的是,类ä¸çš„æ–¹æ³•都采用了粗ç®å¤´å‡½æ•°è¯æ³•ã€‚å½“åœ¨ç±»çš„å®žä¾‹ä¸Šè°ƒç”¨æ–¹æ³•æ—¶ï¼Œè¯¥å®žä¾‹ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°è¢«ä¼ å…¥ï¼Œå› æ¤ç²—ç®å¤´å‡½æ•°ç”¨äºŽç”Ÿæˆä¸€ä¸ªå为 “selfâ€ çš„å‚æ•°ã€‚ |
| 2926 | 3387 | ||
| 2927 | æ¤å¤–,“@â€å‰ç¼€åœ¨å˜é‡å上起到了简化作用,代表“selfâ€ã€‚例如,`@items` å°±ç‰åŒäºŽ `self.items`。 | 3388 | æ¤å¤–,“@†å‰ç¼€åœ¨å˜é‡å上起到了简化作用,代表 “selfâ€ã€‚例如,`@items` å°±ç‰åŒäºŽ `self.items`。 |
| 2928 | 3389 | ||
| 2929 | 为了创建类的一个新实例,å¯ä»¥å°†ç±»å当作一个函数æ¥è°ƒç”¨ï¼Œè¿™æ ·å°±å¯ä»¥ç”Ÿæˆå¹¶è¿”回一个新的实例。 | 3390 | 为了创建类的一个新实例,å¯ä»¥å°†ç±»å当作一个函数æ¥è°ƒç”¨ï¼Œè¿™æ ·å°±å¯ä»¥ç”Ÿæˆå¹¶è¿”回一个新的实例。 |
| 2930 | 3391 | ||
| @@ -2946,7 +3407,7 @@ inv\add_item "pants" | |||
| 2946 | 3407 | ||
| 2947 | 需è¦ç‰¹åˆ«æ³¨æ„的是,类的所有属性在其实例之间是共享的。这对于函数类型的æˆå‘˜å±žæ€§é€šå¸¸ä¸ä¼šé€ æˆé—®é¢˜ï¼Œä½†å¯¹äºŽå…¶ä»–类型的属性,å¯èƒ½ä¼šå¯¼è‡´æ„外的结果。 | 3408 | 需è¦ç‰¹åˆ«æ³¨æ„的是,类的所有属性在其实例之间是共享的。这对于函数类型的æˆå‘˜å±žæ€§é€šå¸¸ä¸ä¼šé€ æˆé—®é¢˜ï¼Œä½†å¯¹äºŽå…¶ä»–类型的属性,å¯èƒ½ä¼šå¯¼è‡´æ„外的结果。 |
| 2948 | 3409 | ||
| 2949 | 例如,在下é¢çš„示例ä¸ï¼Œclotheså±žæ€§åœ¨æ‰€æœ‰å®žä¾‹ä¹‹é—´å…±äº«ã€‚å› æ¤ï¼Œå¯¹è¿™ä¸ªå±žæ€§åœ¨ä¸€ä¸ªå®žä¾‹ä¸çš„修改,将会影å“到其他所有实例。 | 3410 | 例如,在下é¢çš„示例ä¸ï¼Œclothes å±žæ€§åœ¨æ‰€æœ‰å®žä¾‹ä¹‹é—´å…±äº«ã€‚å› æ¤ï¼Œå¯¹è¿™ä¸ªå±žæ€§åœ¨ä¸€ä¸ªå®žä¾‹ä¸çš„修改,将会影å“到其他所有实例。 |
| 2950 | 3411 | ||
| 2951 | ```moonscript | 3412 | ```moonscript |
| 2952 | class Person | 3413 | class Person |
| @@ -2998,7 +3459,7 @@ class Person | |||
| 2998 | 3459 | ||
| 2999 | ### 继承 | 3460 | ### 继承 |
| 3000 | 3461 | ||
| 3001 | `extends`关键å—å¯ä»¥åœ¨ç±»å£°æ˜Žä¸ä½¿ç”¨ï¼Œä»¥ç»§æ‰¿å¦ä¸€ä¸ªç±»çš„属性和方法。 | 3462 | `extends` 关键å—å¯ä»¥åœ¨ç±»å£°æ˜Žä¸ä½¿ç”¨ï¼Œä»¥ç»§æ‰¿å¦ä¸€ä¸ªç±»çš„属性和方法。 |
| 3002 | 3463 | ||
| 3003 | ```moonscript | 3464 | ```moonscript |
| 3004 | class BackPack extends Inventory | 3465 | class BackPack extends Inventory |
| @@ -3018,11 +3479,11 @@ class BackPack extends Inventory | |||
| 3018 | </YueDisplay> | 3479 | </YueDisplay> |
| 3019 | 3480 | ||
| 3020 | 3481 | ||
| 3021 | 在这一部分,我们对月之脚本ä¸çš„`Inventory`ç±»è¿›è¡Œäº†æ‰©å±•ï¼ŒåŠ å…¥äº†å¯¹å¯ä»¥æºå¸¦ç‰©å“æ•°é‡çš„é™åˆ¶ã€‚ | 3482 | 在这一部分,我们对月之脚本ä¸çš„ `Inventory` ç±»è¿›è¡Œäº†æ‰©å±•ï¼ŒåŠ å…¥äº†å¯¹å¯ä»¥æºå¸¦ç‰©å“æ•°é‡çš„é™åˆ¶ã€‚ |
| 3022 | 3483 | ||
| 3023 | 在这个特定的例åä¸ï¼Œåç±»å¹¶æ²¡æœ‰å®šä¹‰è‡ªå·±çš„æž„é€ å‡½æ•°ã€‚å› æ¤ï¼Œå½“åˆ›å»ºä¸€ä¸ªæ–°çš„å®žä¾‹æ—¶ï¼Œç³»ç»Ÿä¼šé»˜è®¤è°ƒç”¨çˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ä½†å¦‚æžœæˆ‘ä»¬åœ¨åç±»ä¸å®šä¹‰äº†æž„é€ å‡½æ•°ï¼Œæˆ‘ä»¬å¯ä»¥åˆ©ç”¨`super`方法æ¥è°ƒç”¨å¹¶æ‰§è¡Œçˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ | 3484 | 在这个特定的例åä¸ï¼Œåç±»å¹¶æ²¡æœ‰å®šä¹‰è‡ªå·±çš„æž„é€ å‡½æ•°ã€‚å› æ¤ï¼Œå½“åˆ›å»ºä¸€ä¸ªæ–°çš„å®žä¾‹æ—¶ï¼Œç³»ç»Ÿä¼šé»˜è®¤è°ƒç”¨çˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ä½†å¦‚æžœæˆ‘ä»¬åœ¨åç±»ä¸å®šä¹‰äº†æž„é€ å‡½æ•°ï¼Œæˆ‘ä»¬å¯ä»¥åˆ©ç”¨ `super` 方法æ¥è°ƒç”¨å¹¶æ‰§è¡Œçˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ |
| 3024 | 3485 | ||
| 3025 | æ¤å¤–,当一个类继承自å¦ä¸€ä¸ªç±»æ—¶ï¼Œå®ƒä¼šå°è¯•调用父类上的`__inherited`方法(如果这个方法å˜åœ¨çš„è¯ï¼‰ï¼Œä»¥æ¤æ¥å‘父类å‘é€é€šçŸ¥ã€‚这个`__inherited`函数接å—ä¸¤ä¸ªå‚æ•°ï¼šè¢«ç»§æ‰¿çš„父类和继承的å类。 | 3486 | æ¤å¤–,当一个类继承自å¦ä¸€ä¸ªç±»æ—¶ï¼Œå®ƒä¼šå°è¯•调用父类上的 `__inherited` 方法(如果这个方法å˜åœ¨çš„è¯ï¼‰ï¼Œä»¥æ¤æ¥å‘父类å‘é€é€šçŸ¥ã€‚这个 `__inherited` 函数接å—ä¸¤ä¸ªå‚æ•°ï¼šè¢«ç»§æ‰¿çš„父类和继承的å类。 |
| 3026 | 3487 | ||
| 3027 | ```moonscript | 3488 | ```moonscript |
| 3028 | class Shelf | 3489 | class Shelf |
| @@ -3045,15 +3506,15 @@ class Cupboard extends Shelf | |||
| 3045 | 3506 | ||
| 3046 | ### super å…³é”®å— | 3507 | ### super å…³é”®å— |
| 3047 | 3508 | ||
| 3048 | `super`是一个特别的关键å—,它有两ç§ä¸åŒçš„使用方å¼ï¼šæ—¢å¯ä»¥å½“作一个对象æ¥çœ‹å¾…,也å¯ä»¥åƒè°ƒç”¨å‡½æ•°é‚£æ ·ä½¿ç”¨ã€‚它仅在类的内部使用时具有特殊的功能。 | 3509 | `super` 是一个特别的关键å—,它有两ç§ä¸åŒçš„使用方å¼ï¼šæ—¢å¯ä»¥å½“作一个对象æ¥çœ‹å¾…,也å¯ä»¥åƒè°ƒç”¨å‡½æ•°é‚£æ ·ä½¿ç”¨ã€‚它仅在类的内部使用时具有特殊的功能。 |
| 3049 | 3510 | ||
| 3050 | 当`super`被作为一个函数调用时,它将调用父类ä¸ä¸Žä¹‹åŒåçš„å‡½æ•°ã€‚æ¤æ—¶ï¼Œå½“å‰çš„`self`ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 递,æ£å¦‚ä¸Šé¢æåˆ°çš„ç»§æ‰¿ç¤ºä¾‹æ‰€å±•ç¤ºçš„é‚£æ ·ã€‚ | 3511 | 当 `super` 被作为一个函数调用时,它将调用父类ä¸ä¸Žä¹‹åŒåçš„å‡½æ•°ã€‚æ¤æ—¶ï¼Œå½“å‰çš„ `self` ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 递,æ£å¦‚ä¸Šé¢æåˆ°çš„ç»§æ‰¿ç¤ºä¾‹æ‰€å±•ç¤ºçš„é‚£æ ·ã€‚ |
| 3051 | 3512 | ||
| 3052 | 在将`super`å½“ä½œæ™®é€šå€¼ä½¿ç”¨æ—¶ï¼Œå®ƒå®žé™…ä¸Šæ˜¯å¯¹çˆ¶ç±»å¯¹è±¡çš„å¼•ç”¨ã€‚é€šè¿‡è¿™ç§æ–¹å¼ï¼Œæˆ‘们å¯ä»¥è®¿é—®çˆ¶ç±»ä¸å¯èƒ½è¢«å类覆盖的值,就åƒè®¿é—®ä»»ä½•æ™®é€šå¯¹è±¡ä¸€æ ·ã€‚ | 3513 | 在将 `super` å½“ä½œæ™®é€šå€¼ä½¿ç”¨æ—¶ï¼Œå®ƒå®žé™…ä¸Šæ˜¯å¯¹çˆ¶ç±»å¯¹è±¡çš„å¼•ç”¨ã€‚é€šè¿‡è¿™ç§æ–¹å¼ï¼Œæˆ‘们å¯ä»¥è®¿é—®çˆ¶ç±»ä¸å¯èƒ½è¢«å类覆盖的值,就åƒè®¿é—®ä»»ä½•æ™®é€šå¯¹è±¡ä¸€æ ·ã€‚ |
| 3053 | 3514 | ||
| 3054 | æ¤å¤–,当使用`\`æ“作符与`super`一起使用时,`self`将被æ’å…¥ä¸ºç¬¬ä¸€ä¸ªå‚æ•°ï¼Œè€Œä¸æ˜¯ä½¿ç”¨`super`本身的值。而在使用`.`æ“ä½œç¬¦æ¥æ£€ç´¢å‡½æ•°æ—¶ï¼Œåˆ™ä¼šè¿”回父类ä¸çš„原始函数。 | 3515 | æ¤å¤–,当使用 `\` æ“作符与 `super` 一起使用时,`self`将被æ’å…¥ä¸ºç¬¬ä¸€ä¸ªå‚æ•°ï¼Œè€Œä¸æ˜¯ä½¿ç”¨ `super` 本身的值。而在使用`.`æ“ä½œç¬¦æ¥æ£€ç´¢å‡½æ•°æ—¶ï¼Œåˆ™ä¼šè¿”回父类ä¸çš„原始函数。 |
| 3055 | 3516 | ||
| 3056 | 䏋颿˜¯ä¸€äº›ä½¿ç”¨`super`çš„ä¸åŒæ–¹æ³•的示例: | 3517 | 䏋颿˜¯ä¸€äº›ä½¿ç”¨ `super` çš„ä¸åŒæ–¹æ³•的示例: |
| 3057 | 3518 | ||
| 3058 | ```moonscript | 3519 | ```moonscript |
| 3059 | class MyClass extends ParentClass | 3520 | class MyClass extends ParentClass |
| @@ -3112,9 +3573,9 @@ print BackPack.size -- æ‰“å° 10 | |||
| 3112 | 3573 | ||
| 3113 | å¦‚æžœåœ¨ç±»å¯¹è±¡çš„å…ƒè¡¨ä¸æ‰¾ä¸åˆ°æŸä¸ªå±žæ€§ï¼Œç³»ç»Ÿä¼šä»ŽåŸºè¡¨ä¸æ£€ç´¢è¯¥å±žæ€§ã€‚这就æ„å‘³ç€æˆ‘们å¯ä»¥ç›´æŽ¥ä»Žç±»æœ¬èº«è®¿é—®åˆ°å…¶æ–¹æ³•和属性。 | 3574 | å¦‚æžœåœ¨ç±»å¯¹è±¡çš„å…ƒè¡¨ä¸æ‰¾ä¸åˆ°æŸä¸ªå±žæ€§ï¼Œç³»ç»Ÿä¼šä»ŽåŸºè¡¨ä¸æ£€ç´¢è¯¥å±žæ€§ã€‚这就æ„å‘³ç€æˆ‘们å¯ä»¥ç›´æŽ¥ä»Žç±»æœ¬èº«è®¿é—®åˆ°å…¶æ–¹æ³•和属性。 |
| 3114 | 3575 | ||
| 3115 | 需è¦ç‰¹åˆ«æ³¨æ„的是,对类对象的赋值并ä¸ä¼šå½±å“åˆ°åŸºè¡¨ï¼Œå› æ¤è¿™ä¸æ˜¯å‘å®žä¾‹æ·»åŠ æ–°æ–¹æ³•çš„æ£ç¡®æ–¹å¼ã€‚相å,需è¦ç›´æŽ¥ä¿®æ”¹åŸºè¡¨ã€‚关于这点,å¯ä»¥å‚考下é¢çš„“__baseâ€å—段。 | 3576 | 需è¦ç‰¹åˆ«æ³¨æ„的是,对类对象的赋值并ä¸ä¼šå½±å“åˆ°åŸºè¡¨ï¼Œå› æ¤è¿™ä¸æ˜¯å‘å®žä¾‹æ·»åŠ æ–°æ–¹æ³•çš„æ£ç¡®æ–¹å¼ã€‚相å,需è¦ç›´æŽ¥ä¿®æ”¹åŸºè¡¨ã€‚关于这点,å¯ä»¥å‚考下é¢çš„ “__baseâ€ å—æ®µã€‚ |
| 3116 | 3577 | ||
| 3117 | æ¤å¤–,类对象包å«å‡ 个特殊的属性:当类被声明时,类的å称会作为一个å—符串å˜å‚¨åœ¨ç±»å¯¹è±¡çš„“__nameâ€å—段ä¸ã€‚ | 3578 | æ¤å¤–,类对象包å«å‡ 个特殊的属性:当类被声明时,类的å称会作为一个å—符串å˜å‚¨åœ¨ç±»å¯¹è±¡çš„ “__nameâ€ å—æ®µä¸ã€‚ |
| 3118 | 3579 | ||
| 3119 | ```moonscript | 3580 | ```moonscript |
| 3120 | print BackPack.__name -- æ‰“å° Backpack | 3581 | print BackPack.__name -- æ‰“å° Backpack |
| @@ -3196,7 +3657,7 @@ print Counter.count -- 输出 2 | |||
| 3196 | 3657 | ||
| 3197 | ### 类声明è¯å¥ | 3658 | ### 类声明è¯å¥ |
| 3198 | 3659 | ||
| 3199 | 在类声明的主体ä¸ï¼Œé™¤äº†é”®/值对外,我们还å¯ä»¥ç¼–写普通的表达å¼ã€‚在这ç§ç±»å£°æ˜Žä½“ä¸çš„æ™®é€šä»£ç 的上下文ä¸ï¼Œselfç‰äºŽç±»å¯¹è±¡ï¼Œè€Œä¸æ˜¯å®žä¾‹å¯¹è±¡ã€‚ | 3660 | 在类声明的主体ä¸ï¼Œé™¤äº†é”®/值对外,我们还å¯ä»¥ç¼–写普通的表达å¼ã€‚在这ç§ç±»å£°æ˜Žä½“ä¸çš„æ™®é€šä»£ç 的上下文ä¸ï¼Œself ç‰äºŽç±»å¯¹è±¡ï¼Œè€Œä¸æ˜¯å®žä¾‹å¯¹è±¡ã€‚ |
| 3200 | 3661 | ||
| 3201 | 以下是创建类å˜é‡çš„å¦ä¸€ç§æ–¹æ³•: | 3662 | 以下是创建类å˜é‡çš„å¦ä¸€ç§æ–¹æ³•: |
| 3202 | 3663 | ||
| @@ -3236,9 +3697,9 @@ class MoreThings | |||
| 3236 | 3697 | ||
| 3237 | ### @ 和 @@ 值 | 3698 | ### @ 和 @@ 值 |
| 3238 | 3699 | ||
| 3239 | 当@å’Œ@@å‰ç¼€åœ¨ä¸€ä¸ªåå—剿—¶ï¼Œå®ƒä»¬åˆ†åˆ«ä»£è¡¨åœ¨selfå’Œself.\_\_classä¸è®¿é—®çš„那个åå—。 | 3700 | 当 @ å’Œ @@ å‰ç¼€åœ¨ä¸€ä¸ªåå—剿—¶ï¼Œå®ƒä»¬åˆ†åˆ«ä»£è¡¨åœ¨ self å’Œ self.\_\_class ä¸è®¿é—®çš„那个åå—。 |
| 3240 | 3701 | ||
| 3241 | 如果它们å•独使用,它们是selfå’Œself.\_\_class的别å。 | 3702 | 如果它们å•独使用,它们是 self å’Œ self.\_\_class 的别å。 |
| 3242 | 3703 | ||
| 3243 | ```moonscript | 3704 | ```moonscript |
| 3244 | assert @ == self | 3705 | assert @ == self |
| @@ -3251,7 +3712,7 @@ assert @@ == self.__class | |||
| 3251 | </pre> | 3712 | </pre> |
| 3252 | </YueDisplay> | 3713 | </YueDisplay> |
| 3253 | 3714 | ||
| 3254 | 例如,使用@@从实例方法快速创建åŒä¸€ç±»çš„æ–°å®žä¾‹çš„æ–¹æ³•: | 3715 | 例如,使用 @@ 从实例方法快速创建åŒä¸€ç±»çš„æ–°å®žä¾‹çš„æ–¹æ³•: |
| 3255 | 3716 | ||
| 3256 | ```moonscript | 3717 | ```moonscript |
| 3257 | some_instance_method = (...) => @@ ... | 3718 | some_instance_method = (...) => @@ ... |
| @@ -3329,7 +3790,7 @@ x = class Bucket | |||
| 3329 | 3790 | ||
| 3330 | ### 匿åç±» | 3791 | ### 匿åç±» |
| 3331 | 3792 | ||
| 3332 | 声明类时å¯ä»¥çœç•¥å称。如果类的表达å¼ä¸åœ¨èµ‹å€¼è¯å¥ä¸ï¼Œ\_\_name属性将为nil。如果出现在赋值è¯å¥ä¸ï¼Œèµ‹å€¼æ“作左侧的å称将代替nil。 | 3793 | 声明类时å¯ä»¥çœç•¥å称。如果类的表达å¼ä¸åœ¨èµ‹å€¼è¯å¥ä¸ï¼Œ\_\_name 属性将为 nil。如果出现在赋值è¯å¥ä¸ï¼Œèµ‹å€¼æ“作左侧的å称将代替 nil。 |
| 3333 | 3794 | ||
| 3334 | ```moonscript | 3795 | ```moonscript |
| 3335 | BigBucket = class extends Bucket | 3796 | BigBucket = class extends Bucket |
| @@ -3400,11 +3861,11 @@ assert y.__class.__parent ~= X -- X 䏿˜¯ Y 的父类 | |||
| 3400 | 3861 | ||
| 3401 | ## with è¯å¥ | 3862 | ## with è¯å¥ |
| 3402 | 3863 | ||
| 3403 | 在编写Luaä»£ç æ—¶ï¼Œæˆ‘们在创建对象åŽçš„å¸¸è§æ“作是立å³è°ƒç”¨è¿™ä¸ªå¯¹è±¡ä¸€ç³»åˆ—æ“作函数并设置一系列属性。 | 3864 | 在编写 Lua ä»£ç æ—¶ï¼Œæˆ‘们在创建对象åŽçš„å¸¸è§æ“作是立å³è°ƒç”¨è¿™ä¸ªå¯¹è±¡ä¸€ç³»åˆ—æ“作函数并设置一系列属性。 |
| 3404 | 3865 | ||
| 3405 | 这导致在代ç ä¸å¤šæ¬¡é‡å¤å¼•用对象的åç§°ï¼Œå¢žåŠ äº†ä¸å¿…è¦çš„æ–‡æœ¬å™ªéŸ³ã€‚一个常è§çš„è§£å†³æ–¹æ¡ˆæ˜¯åœ¨åˆ›å»ºå¯¹è±¡æ—¶ï¼Œåœ¨æž„é€ å‡½æ•°ä¼ å…¥ä¸€ä¸ªè¡¨ï¼Œè¯¥è¡¨åŒ…å«è¦è¦†ç›–设置的键和值的集åˆã€‚è¿™æ ·åšçš„ç¼ºç‚¹æ˜¯è¯¥å¯¹è±¡çš„æž„é€ å‡½æ•°å¿…é¡»æ”¯æŒè¿™ç§åˆå§‹åŒ–å½¢å¼ã€‚ | 3866 | 这导致在代ç ä¸å¤šæ¬¡é‡å¤å¼•用对象的åç§°ï¼Œå¢žåŠ äº†ä¸å¿…è¦çš„æ–‡æœ¬å™ªéŸ³ã€‚一个常è§çš„è§£å†³æ–¹æ¡ˆæ˜¯åœ¨åˆ›å»ºå¯¹è±¡æ—¶ï¼Œåœ¨æž„é€ å‡½æ•°ä¼ å…¥ä¸€ä¸ªè¡¨ï¼Œè¯¥è¡¨åŒ…å«è¦è¦†ç›–设置的键和值的集åˆã€‚è¿™æ ·åšçš„ç¼ºç‚¹æ˜¯è¯¥å¯¹è±¡çš„æž„é€ å‡½æ•°å¿…é¡»æ”¯æŒè¿™ç§åˆå§‹åŒ–å½¢å¼ã€‚ |
| 3406 | 3867 | ||
| 3407 | withå—æœ‰åŠ©äºŽç®€åŒ–ç¼–å†™è¿™æ ·çš„ä»£ç 。在withå—内,我们å¯ä»¥ä½¿ç”¨ä»¥.或\开头的特殊è¯å¥ï¼Œè¿™äº›è¯å¥ä»£è¡¨æˆ‘们æ£åœ¨ä½¿ç”¨çš„对象的æ“作。 | 3868 | with å—æœ‰åŠ©äºŽç®€åŒ–ç¼–å†™è¿™æ ·çš„ä»£ç 。在 with å—内,我们å¯ä»¥ä½¿ç”¨ä»¥ . 或 \ 开头的特殊è¯å¥ï¼Œè¿™äº›è¯å¥ä»£è¡¨æˆ‘们æ£åœ¨ä½¿ç”¨çš„对象的æ“作。 |
| 3408 | 3869 | ||
| 3409 | 例如,我们å¯ä»¥è¿™æ ·å¤„ç†ä¸€ä¸ªæ–°åˆ›å»ºçš„对象: | 3870 | 例如,我们å¯ä»¥è¿™æ ·å¤„ç†ä¸€ä¸ªæ–°åˆ›å»ºçš„对象: |
| 3410 | 3871 | ||
| @@ -3425,7 +3886,7 @@ with Person! | |||
| 3425 | </pre> | 3886 | </pre> |
| 3426 | </YueDisplay> | 3887 | </YueDisplay> |
| 3427 | 3888 | ||
| 3428 | withè¯å¥ä¹Ÿå¯ä»¥ç”¨ä½œä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶è¿”回它的代ç å—æ£åœ¨å¤„ç†çš„对象。 | 3889 | with è¯å¥ä¹Ÿå¯ä»¥ç”¨ä½œä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶è¿”回它的代ç å—æ£åœ¨å¤„ç†çš„对象。 |
| 3429 | 3890 | ||
| 3430 | ```moonscript | 3891 | ```moonscript |
| 3431 | file = with File "favorite_foods.txt" | 3892 | file = with File "favorite_foods.txt" |
| @@ -3459,24 +3920,24 @@ me = create_person "Leaf", [dad, mother, sister] | |||
| 3459 | </pre> | 3920 | </pre> |
| 3460 | </YueDisplay> | 3921 | </YueDisplay> |
| 3461 | 3922 | ||
| 3462 | 在æ¤ç”¨æ³•ä¸ï¼Œwithå¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ | 3923 | 在æ¤ç”¨æ³•ä¸ï¼Œwith å¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ |
| 3463 | 3924 | ||
| 3464 | å¦‚æžœä½ æƒ³ç»™è¡¨è¾¾å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwithè¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ | 3925 | å¦‚æžœä½ æƒ³ç»™è¡¨è¾¾å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwith è¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ |
| 3465 | 3926 | ||
| 3466 | ```moonscript | 3927 | ```moonscript |
| 3467 | with str = "ä½ å¥½" | 3928 | with str := "ä½ å¥½" |
| 3468 | print "原始:", str | 3929 | print "原始:", str |
| 3469 | print "大写:", \upper! | 3930 | print "大写:", \upper! |
| 3470 | ``` | 3931 | ``` |
| 3471 | <YueDisplay> | 3932 | <YueDisplay> |
| 3472 | <pre> | 3933 | <pre> |
| 3473 | with str = "ä½ å¥½" | 3934 | with str := "ä½ å¥½" |
| 3474 | print "原始:", str | 3935 | print "原始:", str |
| 3475 | print "大写:", \upper! | 3936 | print "大写:", \upper! |
| 3476 | </pre> | 3937 | </pre> |
| 3477 | </YueDisplay> | 3938 | </YueDisplay> |
| 3478 | 3939 | ||
| 3479 | 在withè¯å¥ä¸å¯ä»¥ä½¿ç”¨`[]`访问特殊键。 | 3940 | ä½ å¯ä»¥åœ¨ `with` è¯å¥ä¸ä½¿ç”¨ `[]` 访问特殊键。 |
| 3480 | 3941 | ||
| 3481 | ```moonscript | 3942 | ```moonscript |
| 3482 | with tb | 3943 | with tb |
| @@ -3499,9 +3960,22 @@ with tb | |||
| 3499 | </pre> | 3960 | </pre> |
| 3500 | </YueDisplay> | 3961 | </YueDisplay> |
| 3501 | 3962 | ||
| 3963 | `with?` 是 `with` è¯æ³•的一个增强版本,引入了å˜åœ¨æ€§æ£€æŸ¥ï¼Œç”¨äºŽåœ¨ä¸æ˜¾å¼åˆ¤ç©ºçš„æƒ…况下安全访问å¯èƒ½ä¸º nil 的对象。 | ||
| 3964 | |||
| 3965 | ```moonscript | ||
| 3966 | with? obj | ||
| 3967 | print obj.name | ||
| 3968 | ``` | ||
| 3969 | <YueDisplay> | ||
| 3970 | <pre> | ||
| 3971 | with? obj | ||
| 3972 | print obj.name | ||
| 3973 | </pre> | ||
| 3974 | </YueDisplay> | ||
| 3975 | |||
| 3502 | ## do è¯å¥ | 3976 | ## do è¯å¥ |
| 3503 | 3977 | ||
| 3504 | 当用作è¯å¥æ—¶ï¼Œdoè¯å¥çš„作用就åƒåœ¨Luaä¸å·®ä¸å¤šã€‚ | 3978 | 当用作è¯å¥æ—¶ï¼Œdo è¯å¥çš„作用就åƒåœ¨ Lua ä¸å·®ä¸å¤šã€‚ |
| 3505 | 3979 | ||
| 3506 | ```moonscript | 3980 | ```moonscript |
| 3507 | do | 3981 | do |
| @@ -3518,7 +3992,7 @@ print var -- 这里是nil | |||
| 3518 | </pre> | 3992 | </pre> |
| 3519 | </YueDisplay> | 3993 | </YueDisplay> |
| 3520 | 3994 | ||
| 3521 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…è®¸ä½ å°†å¤šè¡Œä»£ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°†doè¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 | 3995 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…è®¸ä½ å°†å¤šè¡Œä»£ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°† do è¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 |
| 3522 | 3996 | ||
| 3523 | ```moonscript | 3997 | ```moonscript |
| 3524 | counter = do | 3998 | counter = do |
| @@ -3702,7 +4176,7 @@ print i, k -- 这些已ç»è¢«æ›´æ–° | |||
| 3702 | 4176 | ||
| 3703 | ## 月之脚本è¯è¨€åº“ | 4177 | ## 月之脚本è¯è¨€åº“ |
| 3704 | 4178 | ||
| 3705 | 使用`require("yue")`æ¥è®¿é—®ã€‚ | 4179 | 使用 `require("yue")` æ¥è®¿é—®ã€‚ |
| 3706 | 4180 | ||
| 3707 | ### yue | 4181 | ### yue |
| 3708 | 4182 | ||
| @@ -3760,9 +4234,9 @@ yue_compiled: {string: string} | |||
| 3760 | **ç¾å:** | 4234 | **ç¾å:** |
| 3761 | ```lua | 4235 | ```lua |
| 3762 | to_lua: function(code: string, config?: Config): | 4236 | to_lua: function(code: string, config?: Config): |
| 3763 | --[[codes]] string | nil, | 4237 | --[[codes]] string | nil, |
| 3764 | --[[error]] string | nil, | 4238 | --[[error]] string | nil, |
| 3765 | --[[globals]] {{string, integer, integer}} | nil | 4239 | --[[globals]] {{string, integer, integer}} | nil |
| 3766 | ``` | 4240 | ``` |
| 3767 | 4241 | ||
| 3768 | **傿•°ï¼š** | 4242 | **傿•°ï¼š** |
| @@ -3885,8 +4359,8 @@ remove_loader: function(): boolean | |||
| 3885 | **ç¾å:** | 4359 | **ç¾å:** |
| 3886 | ```lua | 4360 | ```lua |
| 3887 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | 4361 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): |
| 3888 | --[[loaded function]] nil | function(...: any): (any...), | 4362 | --[[loaded function]] nil | function(...: any): (any...), |
| 3889 | --[[error]] string | nil | 4363 | --[[error]] string | nil |
| 3890 | ``` | 4364 | ``` |
| 3891 | 4365 | ||
| 3892 | **傿•°ï¼š** | 4366 | **傿•°ï¼š** |
| @@ -3916,8 +4390,8 @@ loadstring: function(input: string, chunkname: string, env: table, config?: Conf | |||
| 3916 | **ç¾å:** | 4390 | **ç¾å:** |
| 3917 | ```lua | 4391 | ```lua |
| 3918 | loadstring: function(input: string, chunkname: string, config?: Config): | 4392 | loadstring: function(input: string, chunkname: string, config?: Config): |
| 3919 | --[[loaded function]] nil | function(...: any): (any...), | 4393 | --[[loaded function]] nil | function(...: any): (any...), |
| 3920 | --[[error]] string | nil | 4394 | --[[error]] string | nil |
| 3921 | ``` | 4395 | ``` |
| 3922 | 4396 | ||
| 3923 | **傿•°ï¼š** | 4397 | **傿•°ï¼š** |
| @@ -3946,8 +4420,8 @@ loadstring: function(input: string, chunkname: string, config?: Config): | |||
| 3946 | **ç¾å:** | 4420 | **ç¾å:** |
| 3947 | ```lua | 4421 | ```lua |
| 3948 | loadstring: function(input: string, config?: Config): | 4422 | loadstring: function(input: string, config?: Config): |
| 3949 | --[[loaded function]] nil | function(...: any): (any...), | 4423 | --[[loaded function]] nil | function(...: any): (any...), |
| 3950 | --[[error]] string | nil | 4424 | --[[error]] string | nil |
| 3951 | ``` | 4425 | ``` |
| 3952 | 4426 | ||
| 3953 | **傿•°ï¼š** | 4427 | **傿•°ï¼š** |
| @@ -3975,8 +4449,8 @@ loadstring: function(input: string, config?: Config): | |||
| 3975 | **ç¾å:** | 4449 | **ç¾å:** |
| 3976 | ```lua | 4450 | ```lua |
| 3977 | loadfile: function(filename: string, env: table, config?: Config): | 4451 | loadfile: function(filename: string, env: table, config?: Config): |
| 3978 | nil | function(...: any): (any...), | 4452 | nil | function(...: any): (any...), |
| 3979 | string | nil | 4453 | string | nil |
| 3980 | ``` | 4454 | ``` |
| 3981 | 4455 | ||
| 3982 | **傿•°ï¼š** | 4456 | **傿•°ï¼š** |
| @@ -4005,8 +4479,8 @@ loadfile: function(filename: string, env: table, config?: Config): | |||
| 4005 | **ç¾å:** | 4479 | **ç¾å:** |
| 4006 | ```lua | 4480 | ```lua |
| 4007 | loadfile: function(filename: string, config?: Config): | 4481 | loadfile: function(filename: string, config?: Config): |
| 4008 | nil | function(...: any): (any...), | 4482 | nil | function(...: any): (any...), |
| 4009 | string | nil | 4483 | string | nil |
| 4010 | ``` | 4484 | ``` |
| 4011 | 4485 | ||
| 4012 | **傿•°ï¼š** | 4486 | **傿•°ï¼š** |
| @@ -4261,9 +4735,9 @@ type AST = {string, integer, integer, any} | |||
| 4261 | 4735 | ||
| 4262 | **ç¾å:** | 4736 | **ç¾å:** |
| 4263 | ```lua | 4737 | ```lua |
| 4264 | to_ast: function(code: string, flattenLevel?: number, astName?: string): | 4738 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): |
| 4265 | --[[AST]] AST | nil, | 4739 | --[[AST]] AST | nil, |
| 4266 | --[[error]] nil | string | 4740 | --[[error]] nil | string |
| 4267 | ``` | 4741 | ``` |
| 4268 | 4742 | ||
| 4269 | **傿•°ï¼š** | 4743 | **傿•°ï¼š** |
| @@ -4272,6 +4746,42 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4272 | | --- | --- | --- | | 4746 | | --- | --- | --- | |
| 4273 | | code | string | 代ç 。 | | 4747 | | code | string | 代ç 。 | |
| 4274 | | flattenLevel | integer | [å¯é€‰] æ‰å¹³åŒ–级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | | 4748 | | flattenLevel | integer | [å¯é€‰] æ‰å¹³åŒ–级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | |
| 4749 | | astName | string | [å¯é€‰] AST å称。默认为 "File"。 | | ||
| 4750 | | reserveComment | boolean | [å¯é€‰] 是å¦ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚é»˜è®¤ä¸º false。 | | ||
| 4751 | |||
| 4752 | **返回值:** | ||
| 4753 | |||
| 4754 | | 返回类型 | æè¿° | | ||
| 4755 | | --- | --- | | ||
| 4756 | | AST \| nil | AST,如果转æ¢å¤±è´¥åˆ™ä¸º nil。 | | ||
| 4757 | | string \| nil | 错误消æ¯ï¼Œå¦‚æžœè½¬æ¢æˆåŠŸåˆ™ä¸º nil。 | | ||
| 4758 | |||
| 4759 | #### format | ||
| 4760 | |||
| 4761 | **类型:** 函数。 | ||
| 4762 | |||
| 4763 | **æè¿°ï¼š** | ||
| 4764 | |||
| 4765 | æ ¼å¼åŒ– YueScript 代ç 。 | ||
| 4766 | |||
| 4767 | **ç¾å:** | ||
| 4768 | ```lua | ||
| 4769 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 4770 | ``` | ||
| 4771 | |||
| 4772 | **傿•°ï¼š** | ||
| 4773 | |||
| 4774 | | 傿•°å | 类型 | æè¿° | | ||
| 4775 | | --- | --- | --- | | ||
| 4776 | | code | string | 代ç 。 | | ||
| 4777 | | tabSize | integer | [å¯é€‰] 制表符大å°ã€‚默认为 4。 | | ||
| 4778 | | reserveComment | boolean | [å¯é€‰] 是å¦ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚é»˜è®¤ä¸º true。 | | ||
| 4779 | |||
| 4780 | **返回值:** | ||
| 4781 | |||
| 4782 | | 返回类型 | æè¿° | | ||
| 4783 | | --- | --- | | ||
| 4784 | | string | æ ¼å¼åŒ–åŽçš„代ç 。 | | ||
| 4275 | 4785 | ||
| 4276 | #### __call | 4786 | #### __call |
| 4277 | 4787 | ||
| @@ -4344,6 +4854,19 @@ implicit_return_root: boolean | |||
| 4344 | reserve_line_number: boolean | 4854 | reserve_line_number: boolean |
| 4345 | ``` | 4855 | ``` |
| 4346 | 4856 | ||
| 4857 | #### reserve_comment | ||
| 4858 | |||
| 4859 | **类型:** æˆå‘˜å˜é‡ã€‚ | ||
| 4860 | |||
| 4861 | **æè¿°ï¼š** | ||
| 4862 | |||
| 4863 | 编译器是å¦åº”该在编译åŽçš„代ç ä¸ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚ | ||
| 4864 | |||
| 4865 | **ç¾å:** | ||
| 4866 | ```lua | ||
| 4867 | reserve_comment: boolean | ||
| 4868 | ``` | ||
| 4869 | |||
| 4347 | #### space_over_tab | 4870 | #### space_over_tab |
| 4348 | 4871 | ||
| 4349 | **类型:** æˆå‘˜å˜é‡ã€‚ | 4872 | **类型:** æˆå‘˜å˜é‡ã€‚ |
| @@ -4394,11 +4917,11 @@ line_offset: integer | |||
| 4394 | **ç¾å:** | 4917 | **ç¾å:** |
| 4395 | ```lua | 4918 | ```lua |
| 4396 | enum LuaTarget | 4919 | enum LuaTarget |
| 4397 | "5.1" | 4920 | "5.1" |
| 4398 | "5.2" | 4921 | "5.2" |
| 4399 | "5.3" | 4922 | "5.3" |
| 4400 | "5.4" | 4923 | "5.4" |
| 4401 | "5.5" | 4924 | "5.5" |
| 4402 | end | 4925 | end |
| 4403 | ``` | 4926 | ``` |
| 4404 | 4927 | ||
| @@ -3,6 +3,7 @@ | |||
| 3 | BIN_NAME := yue | 3 | BIN_NAME := yue |
| 4 | # Compiler used | 4 | # Compiler used |
| 5 | CXX ?= g++ | 5 | CXX ?= g++ |
| 6 | CC ?= gcc | ||
| 6 | # Extension of source files used in the project | 7 | # Extension of source files used in the project |
| 7 | SRC_EXT = cpp | 8 | SRC_EXT = cpp |
| 8 | # Path to the source directory, relative to the makefile | 9 | # Path to the source directory, relative to the makefile |
| @@ -10,7 +11,7 @@ SRC_PATH = ./src | |||
| 10 | # Space-separated pkg-config libraries used by this project | 11 | # Space-separated pkg-config libraries used by this project |
| 11 | LIBS = | 12 | LIBS = |
| 12 | # General compiler flags | 13 | # General compiler flags |
| 13 | COMPILE_FLAGS = -std=c++17 -Wall -Wextra -Wno-deprecated-declarations | 14 | COMPILE_FLAGS = -std=c++17 -Wall -Wextra -DYUE_UTF8_IMPL |
| 14 | # Additional release-specific flags | 15 | # Additional release-specific flags |
| 15 | RCOMPILE_FLAGS = -D NDEBUG -O3 | 16 | RCOMPILE_FLAGS = -D NDEBUG -O3 |
| 16 | # Additional debug-specific flags | 17 | # Additional debug-specific flags |
| @@ -54,13 +55,42 @@ endif | |||
| 54 | INCLUDES += -I $(SRC_PATH)/3rdParty/lua | 55 | INCLUDES += -I $(SRC_PATH)/3rdParty/lua |
| 55 | LINK_FLAGS += -L $(SRC_PATH)/3rdParty/lua -llua -ldl | 56 | LINK_FLAGS += -L $(SRC_PATH)/3rdParty/lua -llua -ldl |
| 56 | endif | 57 | endif |
| 58 | |||
| 59 | # Detect Android Termux environment | ||
| 60 | # Termux typically has ANDROID_ROOT environment variable set and PREFIX points to Termux directory | ||
| 61 | IS_TERMUX := false | ||
| 62 | ANDROID_ROOT_VAR := $(shell echo $$ANDROID_ROOT) | ||
| 63 | PREFIX_VAR := $(shell echo $$PREFIX) | ||
| 64 | ifneq ($(ANDROID_ROOT_VAR),) | ||
| 65 | # Check if PREFIX environment variable points to Termux directory | ||
| 66 | ifneq ($(PREFIX_VAR),) | ||
| 67 | ifneq ($(findstring com.termux,$(PREFIX_VAR)),) | ||
| 68 | IS_TERMUX := true | ||
| 69 | endif | ||
| 70 | endif | ||
| 71 | # Alternative check: verify if Termux installation path exists | ||
| 72 | ifeq ($(IS_TERMUX),false) | ||
| 73 | ifneq ($(shell test -d /data/data/com.termux/files/usr && echo yes),) | ||
| 74 | IS_TERMUX := true | ||
| 75 | endif | ||
| 76 | endif | ||
| 77 | endif | ||
| 78 | |||
| 79 | # Auto-set NO_WATCHER for Termux environment if not explicitly set | ||
| 80 | ifeq ($(IS_TERMUX),true) | ||
| 81 | ifeq ($(NO_WATCHER),) | ||
| 82 | NO_WATCHER := true | ||
| 83 | $(info Detected Android Termux environment, automatically setting NO_WATCHER=true) | ||
| 84 | endif | ||
| 85 | endif | ||
| 86 | |||
| 57 | ifeq ($(NO_WATCHER),true) | 87 | ifeq ($(NO_WATCHER),true) |
| 58 | COMPILE_FLAGS += -DYUE_NO_WATCHER | 88 | COMPILE_FLAGS += -DYUE_NO_WATCHER |
| 59 | endif | 89 | endif |
| 60 | 90 | ||
| 61 | # Add platform related linker flag | 91 | # Add platform related linker flag |
| 62 | ifneq ($(UNAME_S),Darwin) | 92 | ifneq ($(UNAME_S),Darwin) |
| 63 | LINK_FLAGS += -lstdc++fs -Wl,-E | 93 | LINK_FLAGS += -Wl,-E |
| 64 | PLAT = linux | 94 | PLAT = linux |
| 65 | else | 95 | else |
| 66 | LINK_FLAGS += -framework CoreFoundation -framework CoreServices | 96 | LINK_FLAGS += -framework CoreFoundation -framework CoreServices |
| @@ -96,10 +126,13 @@ endif | |||
| 96 | 126 | ||
| 97 | # Combine compiler and linker flags | 127 | # Combine compiler and linker flags |
| 98 | release: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS) | 128 | release: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS) |
| 129 | release: export CFLAGS := $(CFLAGS) $(filter-out -std=c++17,$(COMPILE_FLAGS)) $(RCOMPILE_FLAGS) | ||
| 99 | release: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(RLINK_FLAGS) | 130 | release: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(RLINK_FLAGS) |
| 100 | debug: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(DCOMPILE_FLAGS) | 131 | debug: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(DCOMPILE_FLAGS) |
| 132 | debug: export CFLAGS := $(CFLAGS) $(filter-out -std=c++17,$(COMPILE_FLAGS)) $(DCOMPILE_FLAGS) | ||
| 101 | debug: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(DLINK_FLAGS) | 133 | debug: export LDFLAGS := $(LDFLAGS) $(LINK_FLAGS) $(DLINK_FLAGS) |
| 102 | shared: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS) $(TARGET_FLAGS) | 134 | shared: export CXXFLAGS := $(CXXFLAGS) $(COMPILE_FLAGS) $(RCOMPILE_FLAGS) $(TARGET_FLAGS) |
| 135 | shared: export CFLAGS := $(CFLAGS) $(filter-out -std=c++17,$(COMPILE_FLAGS)) $(RCOMPILE_FLAGS) $(TARGET_FLAGS) | ||
| 103 | 136 | ||
| 104 | # Build and output paths | 137 | # Build and output paths |
| 105 | release: export BUILD_PATH := build/release | 138 | release: export BUILD_PATH := build/release |
| @@ -134,9 +167,15 @@ ifeq ($(NO_LUA),true) | |||
| 134 | SOURCES := $(filter-out $(SRC_PATH)/yuescript/yuescript.cpp, $(SOURCES)) | 167 | SOURCES := $(filter-out $(SRC_PATH)/yuescript/yuescript.cpp, $(SOURCES)) |
| 135 | endif | 168 | endif |
| 136 | 169 | ||
| 170 | # Add colib ljson.c source file | ||
| 171 | SOURCES += $(SRC_PATH)/3rdParty/colib/ljson.c | ||
| 172 | |||
| 137 | # Set the object file names, with the source directory stripped | 173 | # Set the object file names, with the source directory stripped |
| 138 | # from the path, and the build path prepended in its place | 174 | # from the path, and the build path prepended in its place |
| 139 | OBJECTS = $(SOURCES:$(SRC_PATH)/%.$(SRC_EXT)=$(BUILD_PATH)/%.o) | 175 | CPP_SOURCES = $(filter %.cpp,$(SOURCES)) |
| 176 | C_SOURCES = $(filter %.c,$(SOURCES)) | ||
| 177 | OBJECTS = $(CPP_SOURCES:$(SRC_PATH)/%.cpp=$(BUILD_PATH)/%.o) | ||
| 178 | OBJECTS += $(C_SOURCES:$(SRC_PATH)/%.c=$(BUILD_PATH)/%.o) | ||
| 140 | # Set the dependency files that will be used to add header dependencies | 179 | # Set the dependency files that will be used to add header dependencies |
| 141 | DEPS = $(OBJECTS:.o=.d) | 180 | DEPS = $(OBJECTS:.o=.d) |
| 142 | 181 | ||
| @@ -225,8 +264,10 @@ wasm-node: clean | |||
| 225 | -O2 \ | 264 | -O2 \ |
| 226 | -o wasm/dist/esm/yuescript.mjs \ | 265 | -o wasm/dist/esm/yuescript.mjs \ |
| 227 | -I $(SRC_PATH) \ | 266 | -I $(SRC_PATH) \ |
| 267 | -I $(SRC_PATH)/3rdParty/ \ | ||
| 228 | -I $(SRC_PATH)/3rdParty/lua \ | 268 | -I $(SRC_PATH)/3rdParty/lua \ |
| 229 | -std=c++17 \ | 269 | -std=c++17 \ |
| 270 | -DYUE_UTF8_IMPL \ | ||
| 230 | --bind \ | 271 | --bind \ |
| 231 | -fexceptions \ | 272 | -fexceptions \ |
| 232 | -Wno-deprecated-declarations \ | 273 | -Wno-deprecated-declarations \ |
| @@ -265,8 +306,10 @@ wasm-node: clean | |||
| 265 | -o wasm/dist/cjs/yuescript.cjs \ | 306 | -o wasm/dist/cjs/yuescript.cjs \ |
| 266 | --emit-tsd="yuescript.d.ts" \ | 307 | --emit-tsd="yuescript.d.ts" \ |
| 267 | -I $(SRC_PATH) \ | 308 | -I $(SRC_PATH) \ |
| 309 | -I $(SRC_PATH)/3rdParty/ \ | ||
| 268 | -I $(SRC_PATH)/3rdParty/lua \ | 310 | -I $(SRC_PATH)/3rdParty/lua \ |
| 269 | -std=c++17 \ | 311 | -std=c++17 \ |
| 312 | -DYUE_UTF8_IMPL \ | ||
| 270 | --bind \ | 313 | --bind \ |
| 271 | -fexceptions \ | 314 | -fexceptions \ |
| 272 | -Wno-deprecated-declarations \ | 315 | -Wno-deprecated-declarations \ |
| @@ -309,8 +352,10 @@ wasm: clean | |||
| 309 | -O2 \ | 352 | -O2 \ |
| 310 | -o doc/docs/.vuepress/public/js/yuescript.js \ | 353 | -o doc/docs/.vuepress/public/js/yuescript.js \ |
| 311 | -I $(SRC_PATH) \ | 354 | -I $(SRC_PATH) \ |
| 355 | -I $(SRC_PATH)/3rdParty/ \ | ||
| 312 | -I $(SRC_PATH)/3rdParty/lua \ | 356 | -I $(SRC_PATH)/3rdParty/lua \ |
| 313 | -std=c++17 \ | 357 | -std=c++17 \ |
| 358 | -DYUE_UTF8_IMPL \ | ||
| 314 | --bind \ | 359 | --bind \ |
| 315 | -fexceptions \ | 360 | -fexceptions \ |
| 316 | -Wno-deprecated-declarations | 361 | -Wno-deprecated-declarations |
| @@ -440,3 +485,11 @@ $(BUILD_PATH)/%.o: $(SRC_PATH)/%.$(SRC_EXT) | |||
| 440 | $(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ | 485 | $(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ |
| 441 | @echo -en "\t Compile time: " | 486 | @echo -en "\t Compile time: " |
| 442 | @$(END_TIME) | 487 | @$(END_TIME) |
| 488 | |||
| 489 | # C source file rules | ||
| 490 | $(BUILD_PATH)/%.o: $(SRC_PATH)/%.c | ||
| 491 | @echo "Compiling: $< -> $@" | ||
| 492 | @$(START_TIME) | ||
| 493 | $(CMD_PREFIX)$(CC) $(CFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ | ||
| 494 | @echo -en "\t Compile time: " | ||
| 495 | @$(END_TIME) | ||
diff --git a/spec/inputs/destructure.yue b/spec/inputs/destructure.yue index 674dfe4..179056c 100644 --- a/spec/inputs/destructure.yue +++ b/spec/inputs/destructure.yue | |||
| @@ -94,7 +94,7 @@ do | |||
| 94 | -- | 94 | -- |
| 95 | 95 | ||
| 96 | do | 96 | do |
| 97 | with {a,b} = thing | 97 | with {a,b} := thing |
| 98 | print a, b | 98 | print a, b |
| 99 | 99 | ||
| 100 | 100 | ||
| @@ -240,5 +240,53 @@ do | |||
| 240 | switch tb | 240 | switch tb |
| 241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} | 241 | when {c: {<"abc">: meta_field = "def"}, <[[any string]]>: {d: abc = 123}, <'str'>: {e: def = {}}} |
| 242 | print meta_field, abc, def | 242 | print meta_field, abc, def |
| 243 | |||
| 244 | do | ||
| 245 | clients = ["VIP_Alice", "User_Bob", "User_Clara", "VIP_Eva"] | ||
| 246 | [vipStart, ...regulars, vipEnd] = clients | ||
| 247 | print vipStart -- "VIP_Alice" | ||
| 248 | print regulars -- {"User_Bob", "User_Clara"} | ||
| 249 | print vipEnd -- "VIP_Eva" | ||
| 250 | |||
| 251 | do | ||
| 252 | setupMeeting = (participants) -> | ||
| 253 | [chair, ..._, secretary] = participants | ||
| 254 | print chair, secretary | ||
| 255 | |||
| 256 | setupMeeting ["Alice", "Bob", "Charlie", "David"] | ||
| 257 | -- Output: Alice David | ||
| 258 | |||
| 259 | do | ||
| 260 | getTransactions = -> | ||
| 261 | { | ||
| 262 | {id: "T1", amount: 100} | ||
| 263 | {id: "T2", amount: 200} | ||
| 264 | {id: "T3", amount: 300} | ||
| 265 | } | ||
| 266 | |||
| 267 | :id, :amount = getTransactions![#] | ||
| 268 | assert id == "T3" | ||
| 269 | assert amount == 300 | ||
| 270 | |||
| 271 | do | ||
| 272 | [ | ||
| 273 | _ | ||
| 274 | ...middle | ||
| 275 | _ | ||
| 276 | ] = tb | ||
| 277 | |||
| 278 | do | ||
| 279 | {a, :abc, b, :def, ...sub, d, e} = tb | ||
| 280 | |||
| 281 | do | ||
| 282 | for {:a, :b} in *items | ||
| 283 | print a, b | ||
| 284 | |||
| 285 | for :a, :b in *items | ||
| 286 | print a, b | ||
| 287 | |||
| 288 | for :body in pairs data | ||
| 289 | print body if body | ||
| 290 | |||
| 243 | nil | 291 | nil |
| 244 | 292 | ||
diff --git a/spec/inputs/funcs.yue b/spec/inputs/funcs.yue index e647edc..d19c2d1 100644 --- a/spec/inputs/funcs.yue +++ b/spec/inputs/funcs.yue | |||
| @@ -98,7 +98,7 @@ f( | |||
| 98 | 98 | ||
| 99 | x = (a, | 99 | x = (a, |
| 100 | b) -> | 100 | b) -> |
| 101 | print "what" | 101 | print "what" |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | y = (a="hi", | 104 | y = (a="hi", |
| @@ -193,4 +193,35 @@ do | |||
| 193 | func = (): -> check 123 | 193 | func = (): -> check 123 |
| 194 | print func! -- get nil | 194 | print func! -- get nil |
| 195 | 195 | ||
| 196 | do | ||
| 197 | f = ({:a, :b, :c}) -> print a, b, c | ||
| 198 | f = (:a, :b, :c) -> print a, b, c | ||
| 199 | g = (x, :y) -> print x, y | ||
| 200 | i = ({a: ax = 0, b: by = 0}) -> print ax, by | ||
| 201 | j = (name, {id: uid = "n/a", :role = "guest"}) -> print name, uid, role | ||
| 202 | m = ({user: {:name, :age}, meta: {:ver = 1}}) -> print name, age, ver | ||
| 203 | m1 = ({user: {:name, :age}, :meta = {}}) -> print name, age, meta and meta.ver or "nil" | ||
| 204 | new = ({:name = "anon", :age = 0}) => | ||
| 205 | @name = name | ||
| 206 | @age = age | ||
| 207 | set = ({:name = @name, :age = @age}) => | ||
| 208 | @name = name | ||
| 209 | @age = age | ||
| 210 | logKV = ({:k, :v}, ...) -> | ||
| 211 | print "kv:", k, v | ||
| 212 | print "rest count:", select "#", ... | ||
| 213 | macro gen = (fname) -> | | ||
| 214 | #{fname} = ({:a, :b = 0}) -> print a, b | ||
| 215 | $gen foo | ||
| 216 | t1 = (:a, x) -> print a, x | ||
| 217 | t2 = (:a) -> print a | ||
| 218 | w = ( | ||
| 219 | id | ||
| 220 | {:x = 0, :y = 0} | ||
| 221 | :flag | ||
| 222 | ) -> | ||
| 223 | print id, x, y, flag | ||
| 224 | g1 = ({:a, a: ax}) -> print a, ax | ||
| 225 | g4 = ({:a, :b, ...rest}) -> print a, b | ||
| 226 | |||
| 196 | nil | 227 | nil |
diff --git a/spec/inputs/import.yue b/spec/inputs/import.yue index b8ffc24..ee1fdfc 100644 --- a/spec/inputs/import.yue +++ b/spec/inputs/import.yue | |||
| @@ -23,7 +23,7 @@ do | |||
| 23 | b, c from z | 23 | b, c from z |
| 24 | 24 | ||
| 25 | do | 25 | do |
| 26 | import a | 26 | import a, |
| 27 | b | 27 | b |
| 28 | c from z | 28 | c from z |
| 29 | 29 | ||
| @@ -139,3 +139,13 @@ do | |||
| 139 | import "m" as {c: d} | 139 | import "m" as {c: d} |
| 140 | import "m" as {g, {<close>: i}} | 140 | import "m" as {g, {<close>: i}} |
| 141 | 141 | ||
| 142 | do | ||
| 143 | import require | ||
| 144 | import string as stringlib | ||
| 145 | import string.format | ||
| 146 | import io.read as io_read | ||
| 147 | |||
| 148 | type = -> | ||
| 149 | import type as tp | ||
| 150 | import 月 as yue | ||
| 151 | |||
diff --git a/spec/inputs/lists.yue b/spec/inputs/lists.yue index 921cae0..dd951a5 100644 --- a/spec/inputs/lists.yue +++ b/spec/inputs/lists.yue | |||
| @@ -87,4 +87,194 @@ do | |||
| 87 | [a, b] = hello | 87 | [a, b] = hello |
| 88 | [name = "nameless", job = "jobless"] = person | 88 | [name = "nameless", job = "jobless"] = person |
| 89 | 89 | ||
| 90 | do | ||
| 91 | transactions = ["T001", "T002", "T003", "T004", "T005"] | ||
| 92 | middleTransactions = transactions[2, -2] | ||
| 93 | print middleTransactions -- => {"T002", "T003", "T004"} | ||
| 94 | |||
| 95 | do | ||
| 96 | logs = | ||
| 97 | - start: 0, end: 100 | ||
| 98 | - start: 100, end: 200 | ||
| 99 | - start: 200, end: 123 | ||
| 100 | print logs[#].end -- => 123 | ||
| 101 | |||
| 102 | do | ||
| 103 | pendingOrders = ["O001", "O002", "O003", "O004"] | ||
| 104 | print pendingOrders[# - 1] -- => "O003" | ||
| 105 | |||
| 106 | do | ||
| 107 | getOrders = -> | ||
| 108 | { | ||
| 109 | { id: "O1001", status: "pending" } | ||
| 110 | { id: "O1002", status: "processing" } | ||
| 111 | { id: "O1003", status: "done" } | ||
| 112 | } | ||
| 113 | |||
| 114 | lastStatus = getOrders()[#].status | ||
| 115 | assert lastStatus == "done" | ||
| 116 | |||
| 117 | do | ||
| 118 | cloneList1 = (list) -> list[,] | ||
| 119 | cloneList2 = (list) -> [...list,] | ||
| 120 | cloneTable = (tb) -> {...tb} | ||
| 121 | |||
| 122 | do | ||
| 123 | print( | ||
| 124 | globalTB[#] | ||
| 125 | a.b.c[# - 2] | ||
| 126 | x?\y?!.z?[# - 3] | ||
| 127 | ) | ||
| 128 | |||
| 129 | do | ||
| 130 | f = -> | ||
| 131 | print( | ||
| 132 | globalTB[#]\end 123 | ||
| 133 | a.b.c[5,-5][# - 2] | ||
| 134 | x?\y?!.z?[# - 3]?[, -3] | ||
| 135 | ) | ||
| 136 | |||
| 137 | do | ||
| 138 | tb = [1, 2, 3] | ||
| 139 | tb[#] = 40 | ||
| 140 | tb[# - 1] = 20 | ||
| 141 | |||
| 142 | do | ||
| 143 | a = b = c = "x" | ||
| 144 | lst = [] | ||
| 145 | lst[#] = a | ||
| 146 | lst[# - 1] = b | ||
| 147 | |||
| 148 | do | ||
| 149 | x, y, z = 1, 2, 3 | ||
| 150 | arr = [] | ||
| 151 | arr[#], head = x, y | ||
| 152 | arr[#] = z | ||
| 153 | |||
| 154 | do | ||
| 155 | triple = ["keep", "skip", "tail"] | ||
| 156 | [head, _, tailv] = triple | ||
| 157 | buf = [] | ||
| 158 | buf[#] = head | ||
| 159 | buf[#] = tailv | ||
| 160 | |||
| 161 | do | ||
| 162 | src = ["a", "", "c", nil, "d"] | ||
| 163 | collected = [] | ||
| 164 | for item in *src | ||
| 165 | if item and #item > 0 | ||
| 166 | collected[#] = item | ||
| 167 | |||
| 168 | do | ||
| 169 | nums = [1, 2, 3, 4, 5] | ||
| 170 | last_two = [v for v in *nums when v > 3] | ||
| 171 | nums[#] = last_two[1] | ||
| 172 | nums[#] = last_two[2] | ||
| 173 | |||
| 174 | do | ||
| 175 | store = [] | ||
| 176 | store[#] = { meta: { id: 1, ok: true }, payload: [10, 20] } | ||
| 177 | store[#] = { meta: { id: 1, ok: false }, payload: [10, 20, 30] } | ||
| 178 | |||
| 179 | do | ||
| 180 | f = -> | ||
| 181 | q = [] | ||
| 182 | tb.tmp = [n for n = 1, 4] | ||
| 183 | if #tb.tmp >= 3 | ||
| 184 | q[#] = {head: tb.tmp[1], tail: tb.tmp[#]} | ||
| 185 | |||
| 186 | do | ||
| 187 | make_pair = (a, b) -> [a, b] | ||
| 188 | pairs = [] | ||
| 189 | p1 = make_pair 7, 8 | ||
| 190 | pairs[#] = p1 | ||
| 191 | k, v = "key", 42 | ||
| 192 | pairs[#] = {k: k, v: v} | ||
| 193 | |||
| 194 | do | ||
| 195 | cfg = {mode: "safe", tags: []} | ||
| 196 | if cfg.mode == "safe" | ||
| 197 | cfg.mode = "fast" | ||
| 198 | cfg.tags[#] = "newbie" | ||
| 199 | |||
| 200 | do | ||
| 201 | mat = [ [1,2], [3,4], [5,6]] | ||
| 202 | last_row = mat[#] | ||
| 203 | rows = [] | ||
| 204 | rows[#] = last_row[1] | ||
| 205 | |||
| 206 | do | ||
| 207 | kv = [] | ||
| 208 | kv[#] = {k: "a", v: 1} | ||
| 209 | kv[#] = {k: "b", v: 2} | ||
| 210 | pair_last = kv[#] | ||
| 211 | dict = {} | ||
| 212 | dict[pair_last.k] = pair_last.v | ||
| 213 | dict[pair_last.k] = 3 | ||
| 214 | |||
| 215 | do | ||
| 216 | base = [ i for i = 1, 4 ] | ||
| 217 | pack = [] | ||
| 218 | pack[#] = [ base[1], base[#] ] | ||
| 219 | pack[#] = { first: base[1], last: base[#] } | ||
| 220 | |||
| 221 | do | ||
| 222 | opts = {limit: 10} | ||
| 223 | {:limit, :offset = 0} = opts | ||
| 224 | pages = [] | ||
| 225 | pages[#] = {limit: limit, offset: offset} | ||
| 226 | |||
| 227 | do | ||
| 228 | chain = { a: { b: { c: 0 } }, list: [ {x:0}, {x:0} ] } | ||
| 229 | chain.a.b.c = 1 | ||
| 230 | chain.list[1].x = 10 | ||
| 231 | chain.list[#].x = 20 | ||
| 232 | chain.list[# - 1] = { x: 30 } | ||
| 233 | |||
| 234 | do | ||
| 235 | node = {left: {v:0}, right: {v:0}} | ||
| 236 | bag = [] | ||
| 237 | { :left, :right } = node | ||
| 238 | bag[#], left.v, right.v = "k", 1, 2 | ||
| 239 | |||
| 240 | do | ||
| 241 | a1, a2, a3 = 100, 200, 300 | ||
| 242 | mix = [] | ||
| 243 | mix[#], mix[#], meta = a1, a2, {tag: "ok"} | ||
| 244 | |||
| 245 | do | ||
| 246 | cfg2 = {limit: 5, opts: {flag: false}} | ||
| 247 | {limit: lim, opts: opt2} = cfg2 | ||
| 248 | bucket = {xs: []} | ||
| 249 | bucket.xs[#], bucket.flag, opt2.flags[] = lim, true, 123 | ||
| 250 | |||
| 251 | do | ||
| 252 | ret2 = ()-> 7, 8 | ||
| 253 | box = [] | ||
| 254 | box[#], x1 = ret2! | ||
| 255 | |||
| 256 | do | ||
| 257 | q = [1, 2] | ||
| 258 | lastq = q[#] | ||
| 259 | q[# - 1] = lastq * 10 | ||
| 260 | |||
| 261 | do | ||
| 262 | mat2 = [[9,8], [7,6]] | ||
| 263 | t = { hold: nil } | ||
| 264 | t.hold = mat2[#][1] | ||
| 265 | |||
| 266 | do | ||
| 267 | f = -> globalTB[#][#] = 1 | ||
| 268 | f1 = -> globalTB[#][# - 1] | ||
| 269 | |||
| 270 | do | ||
| 271 | tbA[] = ...tbB | ||
| 272 | a, tb[], b[], c = 1, ...x, 3, 4 | ||
| 273 | |||
| 274 | data = | ||
| 275 | a: {1,2,3} | ||
| 276 | b: {4,5,6} | ||
| 277 | |||
| 278 | flat = [...v for k,v in pairs data] | ||
| 279 | |||
| 90 | nil | 280 | nil |
diff --git a/spec/inputs/loops.yue b/spec/inputs/loops.yue index 9a91b42..5df10ca 100644 --- a/spec/inputs/loops.yue +++ b/spec/inputs/loops.yue | |||
| @@ -251,4 +251,17 @@ do | |||
| 251 | if value > 5 | 251 | if value > 5 |
| 252 | item | 252 | item |
| 253 | 253 | ||
| 254 | 254 | do | |
| 255 | repeat print 1 until true | ||
| 256 | |||
| 257 | x = repeat | ||
| 258 | a = func! | ||
| 259 | break a.x | ||
| 260 | until a.v | ||
| 261 | |||
| 262 | items = repeat | ||
| 263 | item = getItem! | ||
| 264 | break unless item | ||
| 265 | item if item.value > 0 | ||
| 266 | until false | ||
| 267 | |||
diff --git a/spec/inputs/macro.yue b/spec/inputs/macro.yue index 5d5f1a9..191f09f 100644 --- a/spec/inputs/macro.yue +++ b/spec/inputs/macro.yue | |||
| @@ -60,6 +60,11 @@ macro NumAndStr = (num, str) -> | |||
| 60 | 60 | ||
| 61 | print $NumAndStr 123, 'xyz' | 61 | print $NumAndStr 123, 'xyz' |
| 62 | 62 | ||
| 63 | macro NumAndStr2 = (num`Num, str`SingleString) -> | | ||
| 64 | [#{num}, #{str}] | ||
| 65 | |||
| 66 | print $NumAndStr2 456, 'abc' | ||
| 67 | |||
| 63 | $asserts item == nil | 68 | $asserts item == nil |
| 64 | 69 | ||
| 65 | $myconfig false | 70 | $myconfig false |
| @@ -100,13 +105,14 @@ macro filter = (items, action)-> | |||
| 100 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" | 105 | $showMacro "filter", "[_ for _ in *#{items} when #{action}]" |
| 101 | 106 | ||
| 102 | macro reduce = (items, def, action)-> | 107 | macro reduce = (items, def, action)-> |
| 103 | $showMacro "reduce", "if ##{items} == 0 | 108 | $showMacro "reduce", | |
| 104 | #{def} | 109 | if ##{items} == 0 |
| 105 | else | 110 | #{def} |
| 106 | _1 = #{def} | 111 | else |
| 107 | for _2 in *#{items} | 112 | _1 = #{def} |
| 108 | _1 = #{action} | 113 | for _2 in *#{items} |
| 109 | _1" | 114 | _1 = #{action} |
| 115 | _1 | ||
| 110 | 116 | ||
| 111 | macro foreach = (items, action)-> | 117 | macro foreach = (items, action)-> |
| 112 | $showMacro "foreach", "for _ in *#{items} | 118 | $showMacro "foreach", "for _ in *#{items} |
| @@ -154,13 +160,15 @@ macro curry = (...)-> | |||
| 154 | f = $curry x,y,z,do | 160 | f = $curry x,y,z,do |
| 155 | print x,y,z | 161 | print x,y,z |
| 156 | 162 | ||
| 157 | macro get_inner = (var)-> "do | 163 | macro get_inner = (var)-> | |
| 158 | a = 1 | 164 | do |
| 159 | a + 1" | 165 | a = 1 |
| 166 | a + 1 | ||
| 160 | 167 | ||
| 161 | macro get_inner_hygienic = (var)-> "(-> | 168 | macro get_inner_hygienic = (var)-> | |
| 162 | local a = 1 | 169 | (-> |
| 163 | a + 1)!" | 170 | local a = 1 |
| 171 | a + 1)! | ||
| 164 | 172 | ||
| 165 | do | 173 | do |
| 166 | a = 8 | 174 | a = 8 |
| @@ -196,6 +204,18 @@ end | |||
| 196 | 204 | ||
| 197 | print x | 205 | print x |
| 198 | 206 | ||
| 207 | import "yue" | ||
| 208 | macro lua = (code`YAMLMultiline) -> { | ||
| 209 | code: yue.loadstring(code)! | ||
| 210 | type: "lua" | ||
| 211 | } | ||
| 212 | |||
| 213 | $lua | | ||
| 214 | local function f2(a) | ||
| 215 | return a + 1 | ||
| 216 | end | ||
| 217 | x = x + f2(3) | ||
| 218 | |||
| 199 | macro def = (fname, ...)-> | 219 | macro def = (fname, ...)-> |
| 200 | args = {...} | 220 | args = {...} |
| 201 | last = table.remove args | 221 | last = table.remove args |
| @@ -317,7 +337,13 @@ $chainC( | |||
| 317 | Destroy! | 337 | Destroy! |
| 318 | ) | 338 | ) |
| 319 | 339 | ||
| 320 | macro tb = -> "{'abc', a:123, <call>:=> 998}" | 340 | macro tb = -> | |
| 341 | { | ||
| 342 | 'abc' | ||
| 343 | a: 123 | ||
| 344 | <call>: => 998 | ||
| 345 | } | ||
| 346 | |||
| 321 | print $tb[1], $tb.a, ($tb)!, $tb! | 347 | print $tb[1], $tb.a, ($tb)!, $tb! |
| 322 | 348 | ||
| 323 | print "current line: #{ $LINE }" | 349 | print "current line: #{ $LINE }" |
diff --git a/spec/inputs/macro_export.yue b/spec/inputs/macro_export.yue index cc7d459..22905b5 100644 --- a/spec/inputs/macro_export.yue +++ b/spec/inputs/macro_export.yue | |||
| @@ -8,13 +8,12 @@ export macro config = (debugging = true)-> | |||
| 8 | "" | 8 | "" |
| 9 | 9 | ||
| 10 | export macro showMacro = (name, res)-> | 10 | export macro showMacro = (name, res)-> |
| 11 | if debugMacro then " | 11 | if debugMacro then | |
| 12 | do | 12 | do |
| 13 | txt = #{res} | 13 | txt = #{res} |
| 14 | print '[macro ' .. #{name} .. ']' | 14 | print '[macro #{name}]' |
| 15 | print txt | 15 | print txt |
| 16 | txt | 16 | txt |
| 17 | " | ||
| 18 | else | 17 | else |
| 19 | res | 18 | res |
| 20 | 19 | ||
| @@ -35,14 +34,16 @@ export macro copy = (src, dst, ...)-> | |||
| 35 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" | 34 | src != "_src_" and src != "_dst_" and dst != "_src_" and dst != "_dst_" |
| 36 | "copy targets can not be _src_ or _dst_" | 35 | "copy targets can not be _src_ or _dst_" |
| 37 | ) | 36 | ) |
| 38 | " | 37 | copyFields = table.concat( |
| 39 | do | 38 | ["_dst_.#{field} = _src_.#{field}" for field in *{...}] |
| 40 | local _src_, _dst_ | 39 | "\n\t\t\t" |
| 41 | with _dst_ = #{dst} | 40 | ) |
| 42 | with _src_ = #{src} | 41 | | |
| 43 | #{table.concat for field in *{...} do " | 42 | do |
| 44 | _dst_.#{field} = _src_.#{field} | 43 | local _src_, _dst_ |
| 45 | "}" | 44 | with _dst_ := #{dst} |
| 45 | with _src_ := #{src} | ||
| 46 | #{copyFields} | ||
| 46 | 47 | ||
| 47 | export macro enum = (...) -> | 48 | export macro enum = (...) -> |
| 48 | items = {...} | 49 | items = {...} |
diff --git a/spec/inputs/macro_teal.yue b/spec/inputs/macro_teal.yue index 0cfd862..e51bcd7 100644 --- a/spec/inputs/macro_teal.yue +++ b/spec/inputs/macro_teal.yue | |||
| @@ -4,11 +4,16 @@ $ -> | |||
| 4 | options.target_extension = "tl" | 4 | options.target_extension = "tl" |
| 5 | package.path ..= ";./spec/lib/?.lua" | 5 | package.path ..= ";./spec/lib/?.lua" |
| 6 | 6 | ||
| 7 | macro to_lua = (code)-> | 7 | macro to_lua = (code)-> | |
| 8 | "require('yue').to_lua(#{code}, reserve_line_number:false, same_module:true)" | 8 | require('yue').to_lua #{code}, |
| 9 | reserve_line_number: false | ||
| 10 | same_module: true | ||
| 9 | 11 | ||
| 10 | macro trim = (name)-> | 12 | macro trim = (name)-> | |
| 11 | "if result := #{name}\\match '[\\'\"](.*)[\\'\"]' then result else #{name}" | 13 | if result := #{name}\match '[\'"](.*)[\'"]' |
| 14 | result | ||
| 15 | else | ||
| 16 | #{name} | ||
| 12 | 17 | ||
| 13 | export macro local = (decl, value = nil)-> | 18 | export macro local = (decl, value = nil)-> |
| 14 | import "yue" as {options:{:tl_enabled}} | 19 | import "yue" as {options:{:tl_enabled}} |
diff --git a/spec/inputs/macro_todo.yue b/spec/inputs/macro_todo.yue index 752c9cb..c9c8f77 100644 --- a/spec/inputs/macro_todo.yue +++ b/spec/inputs/macro_todo.yue | |||
| @@ -5,9 +5,6 @@ export macro todoInner = (module, line, msg)-> | |||
| 5 | type: "lua" | 5 | type: "lua" |
| 6 | } | 6 | } |
| 7 | 7 | ||
| 8 | export macro todo = (msg)-> | 8 | export macro todo = (msg)-> | |
| 9 | if msg | 9 | $todoInner $FILE, $LINE#{msg and ", #{msg}" or ""} |
| 10 | "$todoInner $FILE, $LINE, #{msg}" | ||
| 11 | else | ||
| 12 | "$todoInner $FILE, $LINE" | ||
| 13 | 10 | ||
diff --git a/spec/inputs/props.yue b/spec/inputs/props.yue new file mode 100644 index 0000000..bbb7aae --- /dev/null +++ b/spec/inputs/props.yue | |||
| @@ -0,0 +1,61 @@ | |||
| 1 | class Props | ||
| 2 | __index: (name): nil => | ||
| 3 | cls = @.<> | ||
| 4 | if item := cls.__getter?[name] -- access properties | ||
| 5 | return item @ | ||
| 6 | elseif item := rawget cls, name -- access member functions | ||
| 7 | return item | ||
| 8 | else | ||
| 9 | c = cls | ||
| 10 | while c := c.<> -- recursive to access base classes | ||
| 11 | if item := c.__getter?[name] | ||
| 12 | cls.__getter ??= {} | ||
| 13 | cls.__getter[name] = item -- cache base properties to class | ||
| 14 | return item @ | ||
| 15 | elseif item := rawget c, name | ||
| 16 | rawset cls, name, item -- cache base member to class | ||
| 17 | return item | ||
| 18 | |||
| 19 | __newindex: (name, value) => | ||
| 20 | cls = @.<> | ||
| 21 | if item := cls.__setter?[name] -- access properties | ||
| 22 | item @, value | ||
| 23 | else | ||
| 24 | c = cls | ||
| 25 | while c := c.<> -- recursive to access base classes | ||
| 26 | if item := c.__setter?[name] | ||
| 27 | cls.__setter ??= {} | ||
| 28 | cls.__setter[name] = item -- cache base property to class | ||
| 29 | item @, value | ||
| 30 | return | ||
| 31 | rawset @, name, value -- assign field to self | ||
| 32 | |||
| 33 | assignReadOnly = -> error "assigning a readonly property" | ||
| 34 | |||
| 35 | prop: (name, props) => | ||
| 36 | { | ||
| 37 | :get | ||
| 38 | :set = assignReadOnly | ||
| 39 | } = props | ||
| 40 | if getter := rawget @__base, "__getter" | ||
| 41 | getter[name] = get | ||
| 42 | else | ||
| 43 | rawset @__base, "__getter", [name]: get | ||
| 44 | if setter := rawget @__base, "__setter" | ||
| 45 | setter[name] = set | ||
| 46 | else | ||
| 47 | rawset @__base, "__setter", [name]: set | ||
| 48 | |||
| 49 | class A extends Props | ||
| 50 | @prop 'x' | ||
| 51 | get: => @_x + 1000 | ||
| 52 | set: (v) => @_x = v | ||
| 53 | new: => | ||
| 54 | @_x = 0 | ||
| 55 | |||
| 56 | class B extends A | ||
| 57 | @prop 'abc', get: => "hello" | ||
| 58 | |||
| 59 | b = B! | ||
| 60 | b.x = 999 | ||
| 61 | print b.x, b.abc | ||
diff --git a/spec/inputs/string.yue b/spec/inputs/string.yue index f91383e..611205d 100644 --- a/spec/inputs/string.yue +++ b/spec/inputs/string.yue | |||
| @@ -74,3 +74,76 @@ _ = "hello" | |||
| 74 | something"hello"\world! | 74 | something"hello"\world! |
| 75 | something "hello"\world! | 75 | something "hello"\world! |
| 76 | 76 | ||
| 77 | do | ||
| 78 | str = | | ||
| 79 | key: value | ||
| 80 | str = | | ||
| 81 | config: | ||
| 82 | enabled: true | ||
| 83 | level: 5 | ||
| 84 | str = | | ||
| 85 | header: start | ||
| 86 | |||
| 87 | footer: end | ||
| 88 | str = | | ||
| 89 | name: #{username} | ||
| 90 | str = | | ||
| 91 | count: #{total} items | ||
| 92 | str = | | ||
| 93 | user: #{name} | ||
| 94 | id: #{id} | ||
| 95 | str = | | ||
| 96 | path: "C:\\Program Files\\App" | ||
| 97 | desc: 'single "quote" test' | ||
| 98 | str = | | ||
| 99 | key: value | ||
| 100 | next: 123 | ||
| 101 | str = | | ||
| 102 | list: | ||
| 103 | - "one" | ||
| 104 | - "two" | ||
| 105 | str = | | ||
| 106 | -- comment | ||
| 107 | content text | ||
| 108 | -- comment | ||
| 109 | str = | | ||
| 110 | #{1 + 2} | ||
| 111 | #{2 + 3} | ||
| 112 | #{"a" .. "b"} | ||
| 113 | obj = | ||
| 114 | settings: | | ||
| 115 | mode: #{mode} | ||
| 116 | flags: | ||
| 117 | - #{flag1} | ||
| 118 | - default | ||
| 119 | fn = -> | | ||
| 120 | Hello | ||
| 121 | name: #{userName} | ||
| 122 | str = | | ||
| 123 | result: | ||
| 124 | status: #{if ok then "pass" else "fail"} | ||
| 125 | code: #{code} | ||
| 126 | summary = | | ||
| 127 | date: #{os.date()} | ||
| 128 | values: | ||
| 129 | - | ||
| 130 | a: #{aVal} | ||
| 131 | b: #{bVal or defaultB} | ||
| 132 | msg = send | | ||
| 133 | Hello, #{user}! | ||
| 134 | Today is #{os.date("%A")}. | ||
| 135 | desc = do | ||
| 136 | prefix = "Result" | ||
| 137 | | | ||
| 138 | #{prefix}: | ||
| 139 | value: #{compute!} | ||
| 140 | (| | ||
| 141 | 1 | ||
| 142 | 2 | ||
| 143 | 3 | ||
| 144 | |||
| 145 | |||
| 146 | export yaml = | | ||
| 147 | version: #{ver} | ||
| 148 | ok: true | ||
| 149 | |||
diff --git a/spec/inputs/switch.yue b/spec/inputs/switch.yue index 7ff3118..2b0669c 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
| @@ -220,4 +220,73 @@ do | |||
| 220 | ] | 220 | ] |
| 221 | print "matched", sixth | 221 | print "matched", sixth |
| 222 | 222 | ||
| 223 | nil \ No newline at end of file | 223 | do |
| 224 | switch v := "hello" | ||
| 225 | when "hello" | ||
| 226 | print "matched hello" | ||
| 227 | else | ||
| 228 | print "not matched" | ||
| 229 | -- output: matched hello | ||
| 230 | |||
| 231 | do | ||
| 232 | f = -> "ok" | ||
| 233 | switch val := f! | ||
| 234 | when "ok" | ||
| 235 | print "it's ok" | ||
| 236 | -- output: it's ok | ||
| 237 | |||
| 238 | |||
| 239 | do | ||
| 240 | g = -> 42 | ||
| 241 | switch result := g! | ||
| 242 | when 1, 2 | ||
| 243 | print "small" | ||
| 244 | when 42 | ||
| 245 | print "life universe everything" | ||
| 246 | else | ||
| 247 | print "other #{result}" | ||
| 248 | -- output: life universe everything | ||
| 249 | |||
| 250 | do | ||
| 251 | check = -> | ||
| 252 | if true | ||
| 253 | "yes" | ||
| 254 | else | ||
| 255 | "no" | ||
| 256 | |||
| 257 | switch x := check! | ||
| 258 | when "yes" | ||
| 259 | print "affirmative" | ||
| 260 | else | ||
| 261 | print "negative" | ||
| 262 | -- output: affirmative | ||
| 263 | |||
| 264 | do | ||
| 265 | t = (): tb -> | ||
| 266 | tb = {a: 1} | ||
| 267 | tb.a = 2 | ||
| 268 | |||
| 269 | switch data := t! | ||
| 270 | when {a: 2} | ||
| 271 | print "matched" | ||
| 272 | else | ||
| 273 | print "not matched" | ||
| 274 | |||
| 275 | do | ||
| 276 | clientData = ["Meta", "CUST_1001", "CHK123"] | ||
| 277 | switch clientData | ||
| 278 | when [...metadata, customerId, checksum] | ||
| 279 | print metadata -- {"Meta"} | ||
| 280 | print customerId -- "CUST_1001" | ||
| 281 | print checksum -- "CHK123" | ||
| 282 | |||
| 283 | do | ||
| 284 | handlePath = (segments) -> | ||
| 285 | switch segments | ||
| 286 | when [..._, resource, action] | ||
| 287 | print "Resource:", resource | ||
| 288 | print "Action:", action | ||
| 289 | |||
| 290 | handlePath ["admin", "logs", "view"] | ||
| 291 | |||
| 292 | nil | ||
diff --git a/spec/inputs/syntax.yue b/spec/inputs/syntax.yue index a414d6f..eee518a 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
| @@ -392,7 +392,7 @@ invokeA( | |||
| 392 | v = { | 392 | v = { |
| 393 | a -1 | 393 | a -1 |
| 394 | a( | 394 | a( |
| 395 | -1) | 395 | -1) |
| 396 | a \ | 396 | a \ |
| 397 | - 1 | 397 | - 1 |
| 398 | a-1 | 398 | a-1 |
| @@ -405,7 +405,7 @@ v = { | |||
| 405 | 405 | ||
| 406 | a ~1 | 406 | a ~1 |
| 407 | a( | 407 | a( |
| 408 | ~1) | 408 | ~1) |
| 409 | a \ | 409 | a \ |
| 410 | ~ 1 | 410 | ~ 1 |
| 411 | a~1 | 411 | a~1 |
| @@ -478,5 +478,13 @@ do | |||
| 478 | f2 = -> | 478 | f2 = -> |
| 479 | -- | 479 | -- |
| 480 | 480 | ||
| 481 | do | ||
| 482 | return res if res ~= "" | ||
| 483 | |||
| 484 | |||
| 485 | do | ||
| 486 | return res if res ~= "" | ||
| 487 | -- | ||
| 488 | |||
| 481 | nil | 489 | nil |
| 482 | 490 | ||
diff --git a/spec/inputs/tables.yue b/spec/inputs/tables.yue index 0de8a8c..702e04a 100644 --- a/spec/inputs/tables.yue +++ b/spec/inputs/tables.yue | |||
| @@ -245,6 +245,24 @@ menus = | |||
| 245 | click: -> | 245 | click: -> |
| 246 | } | 246 | } |
| 247 | 247 | ||
| 248 | _ = | ||
| 249 | boolean: | ||
| 250 | - true | ||
| 251 | - false | ||
| 252 | float: | ||
| 253 | - 3.14 | ||
| 254 | - -6.8523015e+5 | ||
| 255 | int: | ||
| 256 | - 123 | ||
| 257 | - -0b1010_0111_0100_1010_1110 | ||
| 258 | null: | ||
| 259 | nodeName: 'node' | ||
| 260 | parent: nil | ||
| 261 | string: | ||
| 262 | - 'Hello world' | ||
| 263 | - "newline | ||
| 264 | newline2" | ||
| 265 | |||
| 248 | tb = {...other} | 266 | tb = {...other} |
| 249 | 267 | ||
| 250 | tbMix = { | 268 | tbMix = { |
diff --git a/spec/inputs/test/format_spec.yue b/spec/inputs/test/format_spec.yue index cbd9d22..3ad2c7f 100644 --- a/spec/inputs/test/format_spec.yue +++ b/spec/inputs/test/format_spec.yue | |||
| @@ -119,7 +119,7 @@ for file in *files | |||
| 119 | original_ast = yue.to_ast code | 119 | original_ast = yue.to_ast code |
| 120 | assert.is_not_nil original_ast | 120 | assert.is_not_nil original_ast |
| 121 | rewriteLineCol original_ast | 121 | rewriteLineCol original_ast |
| 122 | formated = yue.format code | 122 | formated = yue.format code, 0, false |
| 123 | ast = yue.to_ast formated | 123 | ast = yue.to_ast formated |
| 124 | assert.is_not_nil ast | 124 | assert.is_not_nil ast |
| 125 | rewriteLineCol ast | 125 | rewriteLineCol ast |
diff --git a/spec/inputs/try_catch.yue b/spec/inputs/try_catch.yue index 4e05bc6..6c29a52 100644 --- a/spec/inputs/try_catch.yue +++ b/spec/inputs/try_catch.yue | |||
| @@ -62,6 +62,126 @@ f = -> | |||
| 62 | do | 62 | do |
| 63 | <- x | 63 | <- x |
| 64 | local tb, a, b, c | 64 | local tb, a, b, c |
| 65 | f = -> try tb.f a, b, c | 65 | f1 = -> try tb.f a, b, c |
| 66 | |||
| 67 | do | ||
| 68 | f1 = -> do | ||
| 69 | ok, ... = try func! | ||
| 70 | ... | ||
| 71 | |||
| 72 | do | ||
| 73 | local func | ||
| 74 | a, b, c = try? func! | ||
| 75 | |||
| 76 | do | ||
| 77 | a, b, c = try? func! | ||
| 78 | |||
| 79 | do | ||
| 80 | a = (try? func!) ?? "default" | ||
| 81 | |||
| 82 | do | ||
| 83 | f try? func! | ||
| 84 | |||
| 85 | do | ||
| 86 | f try? | ||
| 87 | print 123 | ||
| 88 | func! | ||
| 89 | catch e | ||
| 90 | print e | ||
| 91 | e | ||
| 66 | 92 | ||
| 67 | nil | 93 | nil |
| 94 | |||
| 95 | do | ||
| 96 | try | ||
| 97 | func 1, 2, 3 | ||
| 98 | catch err | ||
| 99 | print err | ||
| 100 | |||
| 101 | try func 1, 2, 3 | ||
| 102 | catch err | ||
| 103 | print err | ||
| 104 | |||
| 105 | try | ||
| 106 | print "trying" | ||
| 107 | func 1, 2, 3 | ||
| 108 | |||
| 109 | do | ||
| 110 | success, result = try | ||
| 111 | func 1, 2, 3 | ||
| 112 | catch err | ||
| 113 | print err | ||
| 114 | |||
| 115 | success, result = try func 1, 2, 3 | ||
| 116 | |||
| 117 | tb = {} | ||
| 118 | |||
| 119 | try tb.func | ||
| 120 | try tb.func! | ||
| 121 | try tb.func() | ||
| 122 | try (tb.func!) | ||
| 123 | try (tb\func(1, 2, 3)) | ||
| 124 | |||
| 125 | try tb.func 1 | ||
| 126 | try tb.func(1) | ||
| 127 | |||
| 128 | if (try func 1 | ||
| 129 | catch err | ||
| 130 | print err) | ||
| 131 | print "OK" | ||
| 132 | |||
| 133 | if try (func 1) | ||
| 134 | catch err | ||
| 135 | print err | ||
| 136 | print "OK" | ||
| 137 | |||
| 138 | do | ||
| 139 | if success, result := try func "abc", 123 | ||
| 140 | print result | ||
| 141 | |||
| 142 | success, result = try func "abc", 123 | ||
| 143 | catch err | ||
| 144 | print err | ||
| 145 | |||
| 146 | print result if success, result := try func "abc", 123 | ||
| 147 | catch err | ||
| 148 | print err | ||
| 149 | |||
| 150 | do | ||
| 151 | try | ||
| 152 | func 1, 2, 3 | ||
| 153 | |||
| 154 | try func 1, 2, 3 | ||
| 155 | |||
| 156 | do | ||
| 157 | <- x | ||
| 158 | local tb, a, b, c | ||
| 159 | f1 = -> try tb.f a, b, c | ||
| 160 | |||
| 161 | do | ||
| 162 | f1 = -> do | ||
| 163 | ok, ... = try func! | ||
| 164 | ... | ||
| 165 | |||
| 166 | do | ||
| 167 | local func | ||
| 168 | a, b, c = try? func! | ||
| 169 | |||
| 170 | do | ||
| 171 | a, b, c = try? func! | ||
| 172 | |||
| 173 | do | ||
| 174 | a = (try? func!) ?? "default" | ||
| 175 | |||
| 176 | do | ||
| 177 | f try? func! | ||
| 178 | |||
| 179 | do | ||
| 180 | f try? | ||
| 181 | print 123 | ||
| 182 | func! | ||
| 183 | catch e | ||
| 184 | print e | ||
| 185 | e | ||
| 186 | |||
| 187 | nil | ||
diff --git a/spec/inputs/unicode/destructure.yue b/spec/inputs/unicode/destructure.yue index 3c3a369..a5ffd5d 100644 --- a/spec/inputs/unicode/destructure.yue +++ b/spec/inputs/unicode/destructure.yue | |||
| @@ -84,7 +84,7 @@ do | |||
| 84 | -- | 84 | -- |
| 85 | 85 | ||
| 86 | do | 86 | do |
| 87 | with {å…ƒç´ a,å…ƒç´ b} = 东西 | 87 | with {å…ƒç´ a,å…ƒç´ b} := 东西 |
| 88 | æ‰“å° å…ƒç´ a, å…ƒç´ b | 88 | æ‰“å° å…ƒç´ a, å…ƒç´ b |
| 89 | 89 | ||
| 90 | 90 | ||
diff --git a/spec/inputs/unicode/funcs.yue b/spec/inputs/unicode/funcs.yue index c563356..cb35500 100644 --- a/spec/inputs/unicode/funcs.yue +++ b/spec/inputs/unicode/funcs.yue | |||
| @@ -98,7 +98,7 @@ _æ— æ•ˆå˜é‡ = -> 真å if æŸç‰© | |||
| 98 | 98 | ||
| 99 | å˜é‡x = (傿•°a, | 99 | å˜é‡x = (傿•°a, |
| 100 | 傿•°b) -> | 100 | 傿•°b) -> |
| 101 | æ‰“å° "什么" | 101 | æ‰“å° "什么" |
| 102 | 102 | ||
| 103 | 103 | ||
| 104 | å˜é‡y = (傿•°a="hi", | 104 | å˜é‡y = (傿•°a="hi", |
diff --git a/spec/inputs/unicode/import.yue b/spec/inputs/unicode/import.yue index c229edb..a7724ab 100644 --- a/spec/inputs/unicode/import.yue +++ b/spec/inputs/unicode/import.yue | |||
| @@ -23,7 +23,7 @@ do | |||
| 23 | å—æ®µb, å—æ®µc from 对象z | 23 | å—æ®µb, å—æ®µc from 对象z |
| 24 | 24 | ||
| 25 | do | 25 | do |
| 26 | import å—æ®µa | 26 | import å—æ®µa, |
| 27 | å—æ®µb | 27 | å—æ®µb |
| 28 | å—æ®µc from 对象z | 28 | å—æ®µc from 对象z |
| 29 | 29 | ||
diff --git a/spec/inputs/unicode/macro_export.yue b/spec/inputs/unicode/macro_export.yue index 3c9a942..56571cd 100644 --- a/spec/inputs/unicode/macro_export.yue +++ b/spec/inputs/unicode/macro_export.yue | |||
| @@ -37,8 +37,8 @@ export macro å¤åˆ¶ = (æº, ç›®æ ‡, ...)-> | |||
| 37 | " | 37 | " |
| 38 | do | 38 | do |
| 39 | local _æº_, _ç›®æ ‡_ | 39 | local _æº_, _ç›®æ ‡_ |
| 40 | with _ç›®æ ‡_ = #{ç›®æ ‡} | 40 | with _ç›®æ ‡_ := #{ç›®æ ‡} |
| 41 | with _æº_ = #{æº} | 41 | with _æº_ := #{æº} |
| 42 | #{table.concat for å—æ®µ in *{...} do " | 42 | #{table.concat for å—æ®µ in *{...} do " |
| 43 | _ç›®æ ‡_.#{å—æ®µ} = _æº_.#{å—æ®µ} | 43 | _ç›®æ ‡_.#{å—æ®µ} = _æº_.#{å—æ®µ} |
| 44 | "}" | 44 | "}" |
diff --git a/spec/inputs/unicode/syntax.yue b/spec/inputs/unicode/syntax.yue index 8a98416..01d5c87 100644 --- a/spec/inputs/unicode/syntax.yue +++ b/spec/inputs/unicode/syntax.yue | |||
| @@ -376,7 +376,7 @@ with 对象 | |||
| 376 | å˜é‡v = { | 376 | å˜é‡v = { |
| 377 | å˜é‡a -1 | 377 | å˜é‡a -1 |
| 378 | å˜é‡a( | 378 | å˜é‡a( |
| 379 | -1) | 379 | -1) |
| 380 | å˜é‡a \ | 380 | å˜é‡a \ |
| 381 | - 1 | 381 | - 1 |
| 382 | å˜é‡a-1 | 382 | å˜é‡a-1 |
| @@ -389,7 +389,7 @@ with 对象 | |||
| 389 | 389 | ||
| 390 | å˜é‡a ~1 | 390 | å˜é‡a ~1 |
| 391 | å˜é‡a( | 391 | å˜é‡a( |
| 392 | ~1) | 392 | ~1) |
| 393 | å˜é‡a \ | 393 | å˜é‡a \ |
| 394 | ~ 1 | 394 | ~ 1 |
| 395 | å˜é‡a~1 | 395 | å˜é‡a~1 |
diff --git a/spec/inputs/unicode/vararg.yue b/spec/inputs/unicode/vararg.yue index e59e114..b508fbb 100644 --- a/spec/inputs/unicode/vararg.yue +++ b/spec/inputs/unicode/vararg.yue | |||
| @@ -55,12 +55,12 @@ | |||
| 55 | _ = -> | 55 | _ = -> |
| 56 | 列表 = {1, 2, 3, 4, 5} | 56 | 列表 = {1, 2, 3, 4, 5} |
| 57 | 函数å = (确定) -> | 57 | 函数å = (确定) -> |
| 58 | 确定, table.unpack 列表 | 58 | 确定, table.unpack 列表 |
| 59 | 确定, ... = 函数å true | 59 | 确定, ... = 函数å true |
| 60 | æ‰“å° ç¡®å®š, ... | 60 | æ‰“å° ç¡®å®š, ... |
| 61 | 61 | ||
| 62 | å¤šå‚æ•°å‡½æ•° = -> | 62 | å¤šå‚æ•°å‡½æ•° = -> |
| 63 | 10, nil, 20, nil, 30 | 63 | 10, nil, 20, nil, 30 |
| 64 | 64 | ||
| 65 | ... = å¤šå‚æ•°å‡½æ•°! | 65 | ... = å¤šå‚æ•°å‡½æ•°! |
| 66 | æ‰“å° select "#", ... | 66 | æ‰“å° select "#", ... |
diff --git a/spec/inputs/unicode/with.yue b/spec/inputs/unicode/with.yue index ecbfdab..3c15add 100644 --- a/spec/inputs/unicode/with.yue +++ b/spec/inputs/unicode/with.yue | |||
| @@ -45,19 +45,19 @@ do | |||
| 45 | with å˜é‡a | 45 | with å˜é‡a |
| 46 | æ‰“å° .世界 | 46 | æ‰“å° .世界 |
| 47 | 47 | ||
| 48 | æ¨¡å— = with _æ¨¡å— = {} | 48 | æ¨¡å— = with _æ¨¡å— := {} |
| 49 | .事物 = "ä½ å¥½" | 49 | .事物 = "ä½ å¥½" |
| 50 | 50 | ||
| 51 | with å˜é‡a, å˜é‡b = 东西, 布 | 51 | with å˜é‡a, å˜é‡b := 东西, 布 |
| 52 | æ‰“å° .世界 | 52 | æ‰“å° .世界 |
| 53 | 53 | ||
| 54 | å˜é‡x = with å˜é‡a, å˜é‡b = 1, 2 | 54 | å˜é‡x = with å˜é‡a, å˜é‡b := 1, 2 |
| 55 | æ‰“å° å˜é‡a + å˜é‡b | 55 | æ‰“å° å˜é‡a + å˜é‡b |
| 56 | 56 | ||
| 57 | æ‰“å° with å˜é‡a, å˜é‡b = 1, 2 | 57 | æ‰“å° with å˜é‡a, å˜é‡b := 1, 2 |
| 58 | æ‰“å° å˜é‡a + å˜é‡b | 58 | æ‰“å° å˜é‡a + å˜é‡b |
| 59 | 59 | ||
| 60 | p = with ä½ å¥½!.å—æ®µx, 世界!.å—æ®µy = 1, 2 | 60 | p = with ä½ å¥½!.å—æ®µx, 世界!.å—æ®µy := 1, 2 |
| 61 | æ‰“å° å˜é‡a + å˜é‡b | 61 | æ‰“å° å˜é‡a + å˜é‡b |
| 62 | 62 | ||
| 63 | -- | 63 | -- |
| @@ -68,16 +68,16 @@ do | |||
| 68 | å˜é‡x\大写! | 68 | å˜é‡x\大写! |
| 69 | 69 | ||
| 70 | do | 70 | do |
| 71 | with å˜é‡k = "ä¹”" | 71 | with å˜é‡k := "ä¹”" |
| 72 | æ‰“å° \大写! | 72 | æ‰“å° \大写! |
| 73 | 73 | ||
| 74 | do | 74 | do |
| 75 | with å˜é‡a,å˜é‡b,å˜é‡c = "", "", "" | 75 | with å˜é‡a,å˜é‡b,å˜é‡c := "", "", "" |
| 76 | æ‰“å° \大写! | 76 | æ‰“å° \大写! |
| 77 | 77 | ||
| 78 | do | 78 | do |
| 79 | å˜é‡a = "床铺" | 79 | å˜é‡a = "床铺" |
| 80 | with å˜é‡a,å˜é‡b,å˜é‡c = "", "", "" | 80 | with å˜é‡a,å˜é‡b,å˜é‡c := "", "", "" |
| 81 | æ‰“å° \大写! | 81 | æ‰“å° \大写! |
| 82 | 82 | ||
| 83 | do | 83 | do |
| @@ -85,7 +85,7 @@ do | |||
| 85 | æ‰“å° \大写! | 85 | æ‰“å° \大写! |
| 86 | 86 | ||
| 87 | do | 87 | do |
| 88 | with å˜é‡k.å˜é‡j = "ä¹”" | 88 | with å˜é‡k.å˜é‡j := "ä¹”" |
| 89 | æ‰“å° \大写! | 89 | æ‰“å° \大写! |
| 90 | 90 | ||
| 91 | do | 91 | do |
| @@ -96,7 +96,7 @@ do | |||
| 96 | 96 | ||
| 97 | do | 97 | do |
| 98 | with å˜é‡a | 98 | with å˜é‡a |
| 99 | with .b = 2 | 99 | with .b := 2 |
| 100 | æ‰“å° .c | 100 | æ‰“å° .c |
| 101 | 101 | ||
| 102 | do | 102 | do |
| @@ -131,12 +131,12 @@ do | |||
| 131 | 131 | ||
| 132 | do | 132 | do |
| 133 | global 掩ç | 133 | global 掩ç |
| 134 | with? 掩ç = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 134 | with? 掩ç := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
| 135 | .触摸å¯ç”¨ = true | 135 | .触摸å¯ç”¨ = true |
| 136 | .åžå™¬è§¦æ‘¸ = true | 136 | .åžå™¬è§¦æ‘¸ = true |
| 137 | 137 | ||
| 138 | do | 138 | do |
| 139 | with? 掩ç = 实心矩形 宽: w, 高: h, 颜色: 0x66000000 | 139 | with? 掩ç := 实心矩形 宽: w, 高: h, 颜色: 0x66000000 |
| 140 | .触摸å¯ç”¨ = true | 140 | .触摸å¯ç”¨ = true |
| 141 | .åžå™¬è§¦æ‘¸ = true | 141 | .åžå™¬è§¦æ‘¸ = true |
| 142 | 142 | ||
diff --git a/spec/inputs/vararg.yue b/spec/inputs/vararg.yue index 941cd97..4f8a0d7 100644 --- a/spec/inputs/vararg.yue +++ b/spec/inputs/vararg.yue | |||
| @@ -55,12 +55,12 @@ join = (...) -> | |||
| 55 | _ = -> | 55 | _ = -> |
| 56 | list = {1, 2, 3, 4, 5} | 56 | list = {1, 2, 3, 4, 5} |
| 57 | fn = (ok) -> | 57 | fn = (ok) -> |
| 58 | ok, table.unpack list | 58 | ok, table.unpack list |
| 59 | ok, ... = fn true | 59 | ok, ... = fn true |
| 60 | print ok, ... | 60 | print ok, ... |
| 61 | 61 | ||
| 62 | fn_many_args = -> | 62 | fn_many_args = -> |
| 63 | 10, nil, 20, nil, 30 | 63 | 10, nil, 20, nil, 30 |
| 64 | 64 | ||
| 65 | ... = fn_many_args! | 65 | ... = fn_many_args! |
| 66 | print select "#", ... | 66 | print select "#", ... |
| @@ -86,3 +86,47 @@ join = (...) -> | |||
| 86 | print ... | 86 | print ... |
| 87 | nil | 87 | nil |
| 88 | 88 | ||
| 89 | do | ||
| 90 | f1 = (...t) -> | ||
| 91 | print t.n | ||
| 92 | print #t | ||
| 93 | for i = 1, t.n | ||
| 94 | print t[i] | ||
| 95 | |||
| 96 | f1 1, 2, 3 | ||
| 97 | f1 "a", "b", "c", "d" | ||
| 98 | f1! | ||
| 99 | |||
| 100 | f2 = (...args) -> | ||
| 101 | print "args count:", args.n | ||
| 102 | print "args length:", #args | ||
| 103 | for i = 1, args.n | ||
| 104 | if args[i] == nil | ||
| 105 | print "position", i, "is nil" | ||
| 106 | else | ||
| 107 | print "position", i, ":", args[i] | ||
| 108 | |||
| 109 | f2 1, nil, 3, nil, 5 | ||
| 110 | |||
| 111 | f3 = (prefix, ...items) -> | ||
| 112 | result = {} | ||
| 113 | for i = 1, items.n | ||
| 114 | result[i] = prefix .. tostring items[i] | ||
| 115 | result | ||
| 116 | |||
| 117 | f3 "item_", 1, 2, 3 | ||
| 118 | |||
| 119 | f4 = (...empty) -> | ||
| 120 | print "empty count:", empty.n | ||
| 121 | print "empty length:", #empty | ||
| 122 | |||
| 123 | f4! | ||
| 124 | |||
| 125 | process = (...data) -> | ||
| 126 | sum = 0 | ||
| 127 | for i = 1, data.n | ||
| 128 | if type(data[i]) == "number" | ||
| 129 | sum += data[i] | ||
| 130 | sum | ||
| 131 | |||
| 132 | process 1, 2, 3, "skip", 5 | ||
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index 3fee48e..19ed2a7 100644 --- a/spec/inputs/with.yue +++ b/spec/inputs/with.yue | |||
| @@ -48,21 +48,21 @@ do | |||
| 48 | with a -- only one value allowed | 48 | with a -- only one value allowed |
| 49 | print .world | 49 | print .world |
| 50 | 50 | ||
| 51 | mod = with _M = {} | 51 | mod = with _M := {} |
| 52 | .Thing = "hi" | 52 | .Thing = "hi" |
| 53 | 53 | ||
| 54 | -- operate on a only | 54 | -- operate on a only |
| 55 | with a, b = something, pooh | 55 | with a, b := something, pooh |
| 56 | print .world | 56 | print .world |
| 57 | 57 | ||
| 58 | x = with a, b = 1, 2 | 58 | x = with a, b := 1, 2 |
| 59 | print a + b | 59 | print a + b |
| 60 | 60 | ||
| 61 | print with a, b = 1, 2 | 61 | print with a, b := 1, 2 |
| 62 | print a + b | 62 | print a + b |
| 63 | 63 | ||
| 64 | -- assignment lhs must be evaluated in the order they appear | 64 | -- assignment lhs must be evaluated in the order they appear |
| 65 | p = with hello!.x, world!.y = 1, 2 | 65 | p = with hello!.x, world!.y := 1, 2 |
| 66 | print a + b | 66 | print a + b |
| 67 | 67 | ||
| 68 | -- | 68 | -- |
| @@ -73,16 +73,16 @@ do | |||
| 73 | x\upper! | 73 | x\upper! |
| 74 | 74 | ||
| 75 | do | 75 | do |
| 76 | with k = "jo" | 76 | with k := "jo" |
| 77 | print \upper! | 77 | print \upper! |
| 78 | 78 | ||
| 79 | do | 79 | do |
| 80 | with a,b,c = "", "", "" | 80 | with a,b,c := "", "", "" |
| 81 | print \upper! | 81 | print \upper! |
| 82 | 82 | ||
| 83 | do | 83 | do |
| 84 | a = "bunk" | 84 | a = "bunk" |
| 85 | with a,b,c = "", "", "" | 85 | with a,b,c := "", "", "" |
| 86 | print \upper! | 86 | print \upper! |
| 87 | 87 | ||
| 88 | do | 88 | do |
| @@ -90,7 +90,7 @@ do | |||
| 90 | print \upper! | 90 | print \upper! |
| 91 | 91 | ||
| 92 | do | 92 | do |
| 93 | with k.j = "jo" | 93 | with k.j := "jo" |
| 94 | print \upper! | 94 | print \upper! |
| 95 | 95 | ||
| 96 | do | 96 | do |
| @@ -103,7 +103,7 @@ do | |||
| 103 | do | 103 | do |
| 104 | with a | 104 | with a |
| 105 | -- nested `with`s with assignments should change the scope correctly | 105 | -- nested `with`s with assignments should change the scope correctly |
| 106 | with .b = 2 | 106 | with .b := 2 |
| 107 | print .c | 107 | print .c |
| 108 | 108 | ||
| 109 | do | 109 | do |
| @@ -138,12 +138,12 @@ do | |||
| 138 | 138 | ||
| 139 | do | 139 | do |
| 140 | global mask | 140 | global mask |
| 141 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 141 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
| 142 | .touchEnabled = true | 142 | .touchEnabled = true |
| 143 | .swallowTouches = true | 143 | .swallowTouches = true |
| 144 | 144 | ||
| 145 | do | 145 | do |
| 146 | with? mask = SolidRect width: w, height: h, color: 0x66000000 | 146 | with? mask := SolidRect width: w, height: h, color: 0x66000000 |
| 147 | .touchEnabled = true | 147 | .touchEnabled = true |
| 148 | .swallowTouches = true | 148 | .swallowTouches = true |
| 149 | 149 | ||
| @@ -161,4 +161,13 @@ do | |||
| 161 | if .v | 161 | if .v |
| 162 | break .a | 162 | break .a |
| 163 | 163 | ||
| 164 | a = while true | ||
| 165 | break with? tb | ||
| 166 | break 1 | ||
| 167 | |||
| 168 | do | ||
| 169 | a = for i = 1, 100 | ||
| 170 | with? x := tb[i] | ||
| 171 | break x if .id := 1 | ||
| 172 | |||
| 164 | nil | 173 | nil |
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua index bc720f6..e4f2871 100644 --- a/spec/outputs/5.1/loops.lua +++ b/spec/outputs/5.1/loops.lua | |||
| @@ -587,3 +587,31 @@ do | |||
| 587 | end | 587 | end |
| 588 | list = _accum_0 | 588 | list = _accum_0 |
| 589 | end | 589 | end |
| 590 | do | ||
| 591 | repeat | ||
| 592 | print(1) | ||
| 593 | until true | ||
| 594 | do | ||
| 595 | local _accum_0 | ||
| 596 | repeat | ||
| 597 | a = func() | ||
| 598 | _accum_0 = a.x | ||
| 599 | break | ||
| 600 | until a.v | ||
| 601 | x = _accum_0 | ||
| 602 | end | ||
| 603 | local items | ||
| 604 | local _accum_0 = { } | ||
| 605 | local _len_0 = 1 | ||
| 606 | repeat | ||
| 607 | local item = getItem() | ||
| 608 | if not item then | ||
| 609 | break | ||
| 610 | end | ||
| 611 | if item.value > 0 then | ||
| 612 | _accum_0[_len_0] = item | ||
| 613 | _len_0 = _len_0 + 1 | ||
| 614 | end | ||
| 615 | until false | ||
| 616 | items = _accum_0 | ||
| 617 | end | ||
diff --git a/spec/outputs/5.1/try_catch.lua b/spec/outputs/5.1/try_catch.lua index efd92c6..d2b58bc 100644 --- a/spec/outputs/5.1/try_catch.lua +++ b/spec/outputs/5.1/try_catch.lua | |||
| @@ -22,6 +22,43 @@ end | |||
| 22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
| 23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
| 24 | end | 24 | end |
| 25 | local _anon_func_8 = function(_arg_0, ...) | ||
| 26 | local ok = _arg_0 | ||
| 27 | return ... | ||
| 28 | end | ||
| 29 | local _anon_func_10 = function(_arg_0, ...) | ||
| 30 | local _ok_0 = _arg_0 | ||
| 31 | if _ok_0 then | ||
| 32 | return ... | ||
| 33 | end | ||
| 34 | end | ||
| 35 | local _anon_func_9 = function(func, pcall) | ||
| 36 | return _anon_func_10(pcall(func)) | ||
| 37 | end | ||
| 38 | local _anon_func_12 = function(_arg_0, ...) | ||
| 39 | local _ok_0 = _arg_0 | ||
| 40 | if _ok_0 then | ||
| 41 | return ... | ||
| 42 | end | ||
| 43 | end | ||
| 44 | local _anon_func_11 = function(func, pcall) | ||
| 45 | return _anon_func_12(pcall(func)) | ||
| 46 | end | ||
| 47 | local _anon_func_14 = function(_arg_0, ...) | ||
| 48 | local _ok_0 = _arg_0 | ||
| 49 | if _ok_0 then | ||
| 50 | return ... | ||
| 51 | end | ||
| 52 | end | ||
| 53 | local _anon_func_13 = function(func, print, xpcall) | ||
| 54 | return _anon_func_14(xpcall(function() | ||
| 55 | print(123) | ||
| 56 | return func() | ||
| 57 | end, function(e) | ||
| 58 | print(e) | ||
| 59 | return e | ||
| 60 | end)) | ||
| 61 | end | ||
| 25 | local f | 62 | local f |
| 26 | f = function() | 63 | f = function() |
| 27 | xpcall(function() | 64 | xpcall(function() |
| @@ -104,10 +141,236 @@ f = function() | |||
| 104 | do | 141 | do |
| 105 | x(function() | 142 | x(function() |
| 106 | local tb, a, b, c | 143 | local tb, a, b, c |
| 107 | f = function() | 144 | local f1 |
| 145 | f1 = function() | ||
| 108 | return pcall(_anon_func_7, a, b, c, tb) | 146 | return pcall(_anon_func_7, a, b, c, tb) |
| 109 | end | 147 | end |
| 110 | end) | 148 | end) |
| 111 | end | 149 | end |
| 150 | do | ||
| 151 | local f1 | ||
| 152 | f1 = function() | ||
| 153 | do | ||
| 154 | return _anon_func_8(pcall(function() | ||
| 155 | return func() | ||
| 156 | end)) | ||
| 157 | end | ||
| 158 | end | ||
| 159 | end | ||
| 160 | do | ||
| 161 | local func | ||
| 162 | local a, b, c | ||
| 163 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
| 164 | if _ok_0 then | ||
| 165 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 166 | end | ||
| 167 | end | ||
| 168 | do | ||
| 169 | local a, b, c | ||
| 170 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 171 | return func() | ||
| 172 | end) | ||
| 173 | if _ok_0 then | ||
| 174 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 175 | end | ||
| 176 | end | ||
| 177 | do | ||
| 178 | local a | ||
| 179 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
| 180 | if _exp_0 ~= nil then | ||
| 181 | a = _exp_0 | ||
| 182 | else | ||
| 183 | a = "default" | ||
| 184 | end | ||
| 185 | end | ||
| 186 | do | ||
| 187 | f(_anon_func_11(func, pcall)) | ||
| 188 | end | ||
| 189 | do | ||
| 190 | f(_anon_func_13(func, print, xpcall)) | ||
| 191 | end | ||
| 112 | return nil | 192 | return nil |
| 113 | end | 193 | end |
| 194 | local _anon_func_15 = function(a, b, c, tb) | ||
| 195 | return tb.f(a, b, c) | ||
| 196 | end | ||
| 197 | local _anon_func_16 = function(_arg_0, ...) | ||
| 198 | local ok = _arg_0 | ||
| 199 | return ... | ||
| 200 | end | ||
| 201 | do | ||
| 202 | xpcall(function() | ||
| 203 | return func(1, 2, 3) | ||
| 204 | end, function(err) | ||
| 205 | return print(err) | ||
| 206 | end) | ||
| 207 | xpcall(function() | ||
| 208 | return func(1, 2, 3) | ||
| 209 | end, function(err) | ||
| 210 | return print(err) | ||
| 211 | end) | ||
| 212 | pcall(function() | ||
| 213 | print("trying") | ||
| 214 | return func(1, 2, 3) | ||
| 215 | end) | ||
| 216 | do | ||
| 217 | local success, result = xpcall(function() | ||
| 218 | return func(1, 2, 3) | ||
| 219 | end, function(err) | ||
| 220 | return print(err) | ||
| 221 | end) | ||
| 222 | success, result = pcall(function() | ||
| 223 | return func(1, 2, 3) | ||
| 224 | end) | ||
| 225 | end | ||
| 226 | local tb = { } | ||
| 227 | pcall(function() | ||
| 228 | return tb.func | ||
| 229 | end) | ||
| 230 | pcall(function() | ||
| 231 | return tb.func() | ||
| 232 | end) | ||
| 233 | pcall(function() | ||
| 234 | return tb.func() | ||
| 235 | end) | ||
| 236 | pcall(function() | ||
| 237 | return (tb.func()) | ||
| 238 | end) | ||
| 239 | pcall(function() | ||
| 240 | return (tb:func(1, 2, 3)) | ||
| 241 | end) | ||
| 242 | pcall(function() | ||
| 243 | return tb.func(1) | ||
| 244 | end) | ||
| 245 | pcall(function() | ||
| 246 | return tb.func(1) | ||
| 247 | end) | ||
| 248 | if (xpcall(function() | ||
| 249 | return func(1) | ||
| 250 | end, function(err) | ||
| 251 | return print(err) | ||
| 252 | end)) then | ||
| 253 | print("OK") | ||
| 254 | end | ||
| 255 | if xpcall(function() | ||
| 256 | return (func(1)) | ||
| 257 | end, function(err) | ||
| 258 | return print(err) | ||
| 259 | end) then | ||
| 260 | print("OK") | ||
| 261 | end | ||
| 262 | do | ||
| 263 | do | ||
| 264 | local success, result = pcall(function() | ||
| 265 | return func("abc", 123) | ||
| 266 | end) | ||
| 267 | if success then | ||
| 268 | print(result) | ||
| 269 | end | ||
| 270 | end | ||
| 271 | local success, result = xpcall(function() | ||
| 272 | return func("abc", 123) | ||
| 273 | end, function(err) | ||
| 274 | return print(err) | ||
| 275 | end) | ||
| 276 | success, result = xpcall(function() | ||
| 277 | return func("abc", 123) | ||
| 278 | end, function(err) | ||
| 279 | return print(err) | ||
| 280 | end) | ||
| 281 | if success then | ||
| 282 | print(result) | ||
| 283 | end | ||
| 284 | end | ||
| 285 | do | ||
| 286 | pcall(function() | ||
| 287 | return func(1, 2, 3) | ||
| 288 | end) | ||
| 289 | pcall(function() | ||
| 290 | return func(1, 2, 3) | ||
| 291 | end) | ||
| 292 | end | ||
| 293 | do | ||
| 294 | x(function() | ||
| 295 | local tb, a, b, c | ||
| 296 | local f1 | ||
| 297 | f1 = function() | ||
| 298 | return pcall(_anon_func_15, a, b, c, tb) | ||
| 299 | end | ||
| 300 | end) | ||
| 301 | end | ||
| 302 | do | ||
| 303 | local f1 | ||
| 304 | f1 = function() | ||
| 305 | do | ||
| 306 | return _anon_func_16(pcall(function() | ||
| 307 | return func() | ||
| 308 | end)) | ||
| 309 | end | ||
| 310 | end | ||
| 311 | end | ||
| 312 | do | ||
| 313 | local func | ||
| 314 | local a, b, c | ||
| 315 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
| 316 | if _ok_0 then | ||
| 317 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 318 | end | ||
| 319 | end | ||
| 320 | do | ||
| 321 | local a, b, c | ||
| 322 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 323 | return func() | ||
| 324 | end) | ||
| 325 | if _ok_0 then | ||
| 326 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 327 | end | ||
| 328 | end | ||
| 329 | do | ||
| 330 | local a | ||
| 331 | local _exp_0 = ((function() | ||
| 332 | return (function(_arg_0, ...) | ||
| 333 | local _ok_0 = _arg_0 | ||
| 334 | if _ok_0 then | ||
| 335 | return ... | ||
| 336 | end | ||
| 337 | end)(pcall(function() | ||
| 338 | return func() | ||
| 339 | end)) | ||
| 340 | end)()) | ||
| 341 | if _exp_0 ~= nil then | ||
| 342 | a = _exp_0 | ||
| 343 | else | ||
| 344 | a = "default" | ||
| 345 | end | ||
| 346 | end | ||
| 347 | do | ||
| 348 | f((function() | ||
| 349 | return (function(_arg_0, ...) | ||
| 350 | local _ok_0 = _arg_0 | ||
| 351 | if _ok_0 then | ||
| 352 | return ... | ||
| 353 | end | ||
| 354 | end)(pcall(function() | ||
| 355 | return func() | ||
| 356 | end)) | ||
| 357 | end)()) | ||
| 358 | end | ||
| 359 | do | ||
| 360 | f((function() | ||
| 361 | return (function(_arg_0, ...) | ||
| 362 | local _ok_0 = _arg_0 | ||
| 363 | if _ok_0 then | ||
| 364 | return ... | ||
| 365 | end | ||
| 366 | end)(xpcall(function() | ||
| 367 | print(123) | ||
| 368 | return func() | ||
| 369 | end, function(e) | ||
| 370 | print(e) | ||
| 371 | return e | ||
| 372 | end)) | ||
| 373 | end)()) | ||
| 374 | end | ||
| 375 | end | ||
| 376 | return nil | ||
diff --git a/spec/outputs/assign.lua b/spec/outputs/assign.lua index 162c5a8..89c5f8a 100644 --- a/spec/outputs/assign.lua +++ b/spec/outputs/assign.lua | |||
| @@ -43,10 +43,8 @@ do | |||
| 43 | end | 43 | end |
| 44 | end | 44 | end |
| 45 | local _anon_func_0 = function(print) | 45 | local _anon_func_0 = function(print) |
| 46 | do | 46 | print(123) |
| 47 | print(123) | 47 | return { } |
| 48 | return { } | ||
| 49 | end | ||
| 50 | end | 48 | end |
| 51 | return _(function() | 49 | return _(function() |
| 52 | setmetatable(a, _anon_func_0(print)) | 50 | setmetatable(a, _anon_func_0(print)) |
diff --git a/spec/outputs/codes_from_doc.lua b/spec/outputs/codes_from_doc.lua index 3ee20bb..de5abdd 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua | |||
| @@ -73,8 +73,8 @@ local apple = setmetatable({ | |||
| 73 | if (getmetatable(apple) ~= nil) then | 73 | if (getmetatable(apple) ~= nil) then |
| 74 | p(apple.size, apple.color, getmetatable(apple).__index) | 74 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 75 | end | 75 | end |
| 76 | local _ud83c_udf1b = "月之脚本" | 76 | local _u1f31b = "月之脚本" |
| 77 | _module_0["🌛"] = _ud83c_udf1b | 77 | _module_0["🌛"] = _u1f31b |
| 78 | return _module_0 | 78 | return _module_0 |
| 79 | local area = 6.2831853071796 * 5 | 79 | local area = 6.2831853071796 * 5 |
| 80 | print('hello world') | 80 | print('hello world') |
| @@ -109,6 +109,12 @@ end | |||
| 109 | print("yuescript") | 109 | print("yuescript") |
| 110 | print(3) | 110 | print(3) |
| 111 | print("Valid enum type:", "Static") | 111 | print("Valid enum type:", "Static") |
| 112 | do | ||
| 113 | print(123, "hello") | ||
| 114 | end | ||
| 115 | do | ||
| 116 | print(123, "hello") | ||
| 117 | end | ||
| 112 | if tb ~= nil then | 118 | if tb ~= nil then |
| 113 | tb:func() | 119 | tb:func() |
| 114 | end | 120 | end |
| @@ -141,6 +147,21 @@ print((function() | |||
| 141 | end)()) | 147 | end)()) |
| 142 | local tab = { } | 148 | local tab = { } |
| 143 | tab[#tab + 1] = "Value" | 149 | tab[#tab + 1] = "Value" |
| 150 | local tbA = { | ||
| 151 | 1, | ||
| 152 | 2, | ||
| 153 | 3 | ||
| 154 | } | ||
| 155 | local tbB = { | ||
| 156 | 4, | ||
| 157 | 5, | ||
| 158 | 6 | ||
| 159 | } | ||
| 160 | local _len_0 = #tbA + 1 | ||
| 161 | for _index_0 = 1, #tbB do | ||
| 162 | local _elm_0 = tbB[_index_0] | ||
| 163 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 164 | end | ||
| 144 | local parts = { | 165 | local parts = { |
| 145 | "shoulders", | 166 | "shoulders", |
| 146 | "knees" | 167 | "knees" |
| @@ -209,6 +230,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 209 | end | 230 | end |
| 210 | end | 231 | end |
| 211 | merge = _tab_0 | 232 | merge = _tab_0 |
| 233 | local last | ||
| 234 | do | ||
| 235 | local _item_0 = data.items | ||
| 236 | last = _item_0[#_item_0] | ||
| 237 | end | ||
| 238 | local second_last | ||
| 239 | do | ||
| 240 | local _item_0 = data.items | ||
| 241 | second_last = _item_0[#_item_0 - 1] | ||
| 242 | end | ||
| 243 | local _obj_0 = data.items | ||
| 244 | _obj_0[#_obj_0] = 1 | ||
| 212 | local mt = { } | 245 | local mt = { } |
| 213 | local add | 246 | local add |
| 214 | add = function(self, right) | 247 | add = function(self, right) |
| @@ -339,6 +372,14 @@ func({ | |||
| 339 | 2, | 372 | 2, |
| 340 | 3 | 373 | 3 |
| 341 | }) | 374 | }) |
| 375 | local f | ||
| 376 | f = function() | ||
| 377 | return { | ||
| 378 | 1, | ||
| 379 | 2, | ||
| 380 | 3 | ||
| 381 | } | ||
| 382 | end | ||
| 342 | local tb = { | 383 | local tb = { |
| 343 | name = "abc", | 384 | name = "abc", |
| 344 | values = { | 385 | values = { |
| @@ -579,6 +620,59 @@ end | |||
| 579 | local two, four | 620 | local two, four |
| 580 | local _obj_0 = items | 621 | local _obj_0 = items |
| 581 | two, four = _obj_0[2], _obj_0[4] | 622 | two, four = _obj_0[2], _obj_0[4] |
| 623 | local orders = { | ||
| 624 | "first", | ||
| 625 | "second", | ||
| 626 | "third", | ||
| 627 | "fourth", | ||
| 628 | "last" | ||
| 629 | } | ||
| 630 | local first, bulk, last = orders[1], (function() | ||
| 631 | local _accum_0 = { } | ||
| 632 | local _len_0 = 1 | ||
| 633 | local _max_0 = #orders + -2 + 1 | ||
| 634 | for _index_0 = 2, _max_0 do | ||
| 635 | local _item_0 = orders[_index_0] | ||
| 636 | _accum_0[_len_0] = _item_0 | ||
| 637 | _len_0 = _len_0 + 1 | ||
| 638 | end | ||
| 639 | return _accum_0 | ||
| 640 | end)(), orders[#orders] | ||
| 641 | print(first) | ||
| 642 | print(bulk) | ||
| 643 | print(last) | ||
| 644 | local first, rest | ||
| 645 | do | ||
| 646 | local _obj_0 = orders | ||
| 647 | first, rest = _obj_0[1], (function() | ||
| 648 | local _accum_0 = { } | ||
| 649 | local _len_0 = 1 | ||
| 650 | local _max_0 = #_obj_0 | ||
| 651 | for _index_0 = 2, _max_0 do | ||
| 652 | local _item_0 = _obj_0[_index_0] | ||
| 653 | _accum_0[_len_0] = _item_0 | ||
| 654 | _len_0 = _len_0 + 1 | ||
| 655 | end | ||
| 656 | return _accum_0 | ||
| 657 | end)() | ||
| 658 | end | ||
| 659 | local start, last | ||
| 660 | do | ||
| 661 | local _obj_0 = orders | ||
| 662 | start, last = (function() | ||
| 663 | local _accum_0 = { } | ||
| 664 | local _len_0 = 1 | ||
| 665 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 666 | for _index_0 = 1, _max_0 do | ||
| 667 | local _item_0 = _obj_0[_index_0] | ||
| 668 | _accum_0[_len_0] = _item_0 | ||
| 669 | _len_0 = _len_0 + 1 | ||
| 670 | end | ||
| 671 | return _accum_0 | ||
| 672 | end)(), _obj_0[#_obj_0] | ||
| 673 | end | ||
| 674 | local _obj_0 = orders | ||
| 675 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 582 | local tuples = { | 676 | local tuples = { |
| 583 | { | 677 | { |
| 584 | "hello", | 678 | "hello", |
| @@ -643,6 +737,36 @@ end | |||
| 643 | local first = select(1, ...) | 737 | local first = select(1, ...) |
| 644 | return print(ok, count, first) | 738 | return print(ok, count, first) |
| 645 | end)(fn(true)) | 739 | end)(fn(true)) |
| 740 | local f | ||
| 741 | f = function(...) | ||
| 742 | local t = { | ||
| 743 | n = select("#", ...), | ||
| 744 | ... | ||
| 745 | } | ||
| 746 | print("argument count:", t.n) | ||
| 747 | print("table length:", #t) | ||
| 748 | for i = 1, t.n do | ||
| 749 | print(t[i]) | ||
| 750 | end | ||
| 751 | end | ||
| 752 | f(1, 2, 3) | ||
| 753 | f("a", "b", "c", "d") | ||
| 754 | f() | ||
| 755 | local process | ||
| 756 | process = function(...) | ||
| 757 | local args = { | ||
| 758 | n = select("#", ...), | ||
| 759 | ... | ||
| 760 | } | ||
| 761 | local sum = 0 | ||
| 762 | for i = 1, args.n do | ||
| 763 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 764 | sum = sum + args[i] | ||
| 765 | end | ||
| 766 | end | ||
| 767 | return sum | ||
| 768 | end | ||
| 769 | process(1, nil, 3, nil, 5) | ||
| 646 | Rx.Observable.fromRange(1, 8):filter(function(x) | 770 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 647 | return x % 2 == 0 | 771 | return x % 2 == 0 |
| 648 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 772 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -680,6 +804,56 @@ end) | |||
| 680 | if success then | 804 | if success then |
| 681 | print(result) | 805 | print(result) |
| 682 | end | 806 | end |
| 807 | local a, b, c | ||
| 808 | do | ||
| 809 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 810 | return func() | ||
| 811 | end) | ||
| 812 | if _ok_0 then | ||
| 813 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 814 | end | ||
| 815 | end | ||
| 816 | do | ||
| 817 | local _exp_0 = ((function() | ||
| 818 | return (function(_arg_0, ...) | ||
| 819 | local _ok_0 = _arg_0 | ||
| 820 | if _ok_0 then | ||
| 821 | return ... | ||
| 822 | end | ||
| 823 | end)(pcall(function() | ||
| 824 | return func() | ||
| 825 | end)) | ||
| 826 | end)()) | ||
| 827 | if _exp_0 ~= nil then | ||
| 828 | a = _exp_0 | ||
| 829 | else | ||
| 830 | a = "default" | ||
| 831 | end | ||
| 832 | end | ||
| 833 | f((function() | ||
| 834 | return (function(_arg_0, ...) | ||
| 835 | local _ok_0 = _arg_0 | ||
| 836 | if _ok_0 then | ||
| 837 | return ... | ||
| 838 | end | ||
| 839 | end)(pcall(function() | ||
| 840 | return func() | ||
| 841 | end)) | ||
| 842 | end)()) | ||
| 843 | f((function() | ||
| 844 | return (function(_arg_0, ...) | ||
| 845 | local _ok_0 = _arg_0 | ||
| 846 | if _ok_0 then | ||
| 847 | return ... | ||
| 848 | end | ||
| 849 | end)(xpcall(function() | ||
| 850 | print(123) | ||
| 851 | return func() | ||
| 852 | end, function(e) | ||
| 853 | print(e) | ||
| 854 | return e | ||
| 855 | end)) | ||
| 856 | end)()) | ||
| 683 | local a <const> = 123 | 857 | local a <const> = 123 |
| 684 | local _ <close> = setmetatable({ }, { | 858 | local _ <close> = setmetatable({ }, { |
| 685 | __close = function() | 859 | __close = function() |
| @@ -695,6 +869,13 @@ print("I am " .. tostring(math.random() * 100) .. "% sure.") | |||
| 695 | local integer = 1000000 | 869 | local integer = 1000000 |
| 696 | local hex = 0xEFBBBF | 870 | local hex = 0xEFBBBF |
| 697 | local binary = 19 | 871 | local binary = 19 |
| 872 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 873 | local fn | ||
| 874 | fn = function() | ||
| 875 | local str = "foo:\n bar: baz" | ||
| 876 | return str | ||
| 877 | end | ||
| 878 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 698 | local my_function | 879 | local my_function |
| 699 | my_function = function() end | 880 | my_function = function() end |
| 700 | my_function() | 881 | my_function() |
| @@ -789,6 +970,36 @@ if func(1, 2, 3, "hello", "world") then | |||
| 789 | print("hello") | 970 | print("hello") |
| 790 | print("I am inside if") | 971 | print("I am inside if") |
| 791 | end | 972 | end |
| 973 | local f1 | ||
| 974 | f1 = function(_arg_0) | ||
| 975 | local a, b, c | ||
| 976 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 977 | return print(a, b, c) | ||
| 978 | end | ||
| 979 | f1({ | ||
| 980 | a = 1, | ||
| 981 | b = "2", | ||
| 982 | c = { } | ||
| 983 | }) | ||
| 984 | local f2 | ||
| 985 | f2 = function(_arg_0, c) | ||
| 986 | local a1, b | ||
| 987 | a1, b = _arg_0.a, _arg_0.b | ||
| 988 | if a1 == nil then | ||
| 989 | a1 = 123 | ||
| 990 | end | ||
| 991 | if b == nil then | ||
| 992 | b = 'abc' | ||
| 993 | end | ||
| 994 | if c == nil then | ||
| 995 | c = { } | ||
| 996 | end | ||
| 997 | return print(a1, b, c) | ||
| 998 | end | ||
| 999 | local arg1 = { | ||
| 1000 | a = 0 | ||
| 1001 | } | ||
| 1002 | f2(arg1, arg2) | ||
| 792 | f(function() | 1003 | f(function() |
| 793 | return print("hello") | 1004 | return print("hello") |
| 794 | end) | 1005 | end) |
| @@ -914,6 +1125,28 @@ for _index_0 = 1, #_list_0 do | |||
| 914 | _len_0 = _len_0 + 1 | 1125 | _len_0 = _len_0 + 1 |
| 915 | end | 1126 | end |
| 916 | doubled = _accum_0 | 1127 | doubled = _accum_0 |
| 1128 | local data = { | ||
| 1129 | a = { | ||
| 1130 | 1, | ||
| 1131 | 2, | ||
| 1132 | 3 | ||
| 1133 | }, | ||
| 1134 | b = { | ||
| 1135 | 4, | ||
| 1136 | 5, | ||
| 1137 | 6 | ||
| 1138 | } | ||
| 1139 | } | ||
| 1140 | local flat | ||
| 1141 | local _accum_0 = { } | ||
| 1142 | for k, v in pairs(data) do | ||
| 1143 | local _len_0 = #_accum_0 + 1 | ||
| 1144 | for _index_0 = 1, #v do | ||
| 1145 | local _elm_0 = v[_index_0] | ||
| 1146 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 1147 | end | ||
| 1148 | end | ||
| 1149 | flat = _accum_0 | ||
| 917 | local x_coords = { | 1150 | local x_coords = { |
| 918 | 4, | 1151 | 4, |
| 919 | 5, | 1152 | 5, |
| @@ -1004,8 +1237,18 @@ local slice | |||
| 1004 | local _accum_0 = { } | 1237 | local _accum_0 = { } |
| 1005 | local _len_0 = 1 | 1238 | local _len_0 = 1 |
| 1006 | local _list_0 = items | 1239 | local _list_0 = items |
| 1007 | local _max_0 = 5 | 1240 | for _index_0 = 1, 5 do |
| 1008 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | 1241 | local item = _list_0[_index_0] |
| 1242 | _accum_0[_len_0] = item | ||
| 1243 | _len_0 = _len_0 + 1 | ||
| 1244 | end | ||
| 1245 | slice = _accum_0 | ||
| 1246 | local slice | ||
| 1247 | local _accum_0 = { } | ||
| 1248 | local _len_0 = 1 | ||
| 1249 | local _list_0 = items | ||
| 1250 | local _max_0 = #_list_0 | ||
| 1251 | for _index_0 = 2, _max_0 do | ||
| 1009 | local item = _list_0[_index_0] | 1252 | local item = _list_0[_index_0] |
| 1010 | _accum_0[_len_0] = item | 1253 | _accum_0[_len_0] = item |
| 1011 | _len_0 = _len_0 + 1 | 1254 | _len_0 = _len_0 + 1 |
| @@ -1015,7 +1258,8 @@ local slice | |||
| 1015 | local _accum_0 = { } | 1258 | local _accum_0 = { } |
| 1016 | local _len_0 = 1 | 1259 | local _len_0 = 1 |
| 1017 | local _list_0 = items | 1260 | local _list_0 = items |
| 1018 | for _index_0 = 2, #_list_0 do | 1261 | local _max_0 = #_list_0 |
| 1262 | for _index_0 = 1, _max_0, 2 do | ||
| 1019 | local item = _list_0[_index_0] | 1263 | local item = _list_0[_index_0] |
| 1020 | _accum_0[_len_0] = item | 1264 | _accum_0[_len_0] = item |
| 1021 | _len_0 = _len_0 + 1 | 1265 | _len_0 = _len_0 + 1 |
| @@ -1025,12 +1269,35 @@ local slice | |||
| 1025 | local _accum_0 = { } | 1269 | local _accum_0 = { } |
| 1026 | local _len_0 = 1 | 1270 | local _len_0 = 1 |
| 1027 | local _list_0 = items | 1271 | local _list_0 = items |
| 1028 | for _index_0 = 1, #_list_0, 2 do | 1272 | local _min_0 = #_list_0 + -4 + 1 |
| 1273 | local _max_0 = #_list_0 + -1 + 1 | ||
| 1274 | for _index_0 = _min_0, _max_0 do | ||
| 1029 | local item = _list_0[_index_0] | 1275 | local item = _list_0[_index_0] |
| 1030 | _accum_0[_len_0] = item | 1276 | _accum_0[_len_0] = item |
| 1031 | _len_0 = _len_0 + 1 | 1277 | _len_0 = _len_0 + 1 |
| 1032 | end | 1278 | end |
| 1033 | slice = _accum_0 | 1279 | slice = _accum_0 |
| 1280 | local reverse_slice | ||
| 1281 | local _accum_0 = { } | ||
| 1282 | local _len_0 = 1 | ||
| 1283 | local _list_0 = items | ||
| 1284 | local _min_0 = #_list_0 + -1 + 1 | ||
| 1285 | for _index_0 = _min_0, 1, -1 do | ||
| 1286 | local item = _list_0[_index_0] | ||
| 1287 | _accum_0[_len_0] = item | ||
| 1288 | _len_0 = _len_0 + 1 | ||
| 1289 | end | ||
| 1290 | reverse_slice = _accum_0 | ||
| 1291 | local sub_list | ||
| 1292 | local _accum_0 = { } | ||
| 1293 | local _len_0 = 1 | ||
| 1294 | local _list_0 = items | ||
| 1295 | for _index_0 = 2, 4 do | ||
| 1296 | local _item_0 = _list_0[_index_0] | ||
| 1297 | _accum_0[_len_0] = _item_0 | ||
| 1298 | _len_0 = _len_0 + 1 | ||
| 1299 | end | ||
| 1300 | sub_list = _accum_0 | ||
| 1034 | for i = 10, 20 do | 1301 | for i = 10, 20 do |
| 1035 | print(i) | 1302 | print(i) |
| 1036 | end | 1303 | end |
| @@ -1041,8 +1308,7 @@ for key, value in pairs(object) do | |||
| 1041 | print(key, value) | 1308 | print(key, value) |
| 1042 | end | 1309 | end |
| 1043 | local _list_0 = items | 1310 | local _list_0 = items |
| 1044 | local _max_0 = 4 | 1311 | for _index_0 = 2, 4 do |
| 1045 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 1046 | local item = _list_0[_index_0] | 1312 | local item = _list_0[_index_0] |
| 1047 | print(item) | 1313 | print(item) |
| 1048 | end | 1314 | end |
| @@ -1226,7 +1492,7 @@ if "Robert" == name then | |||
| 1226 | elseif "Dan" == name or "Daniel" == name then | 1492 | elseif "Dan" == name or "Daniel" == name then |
| 1227 | print("Your name, it's Dan") | 1493 | print("Your name, it's Dan") |
| 1228 | else | 1494 | else |
| 1229 | print("I don't know about your name") | 1495 | print("I don't know about you with name " .. tostring(name)) |
| 1230 | end | 1496 | end |
| 1231 | local b = 1 | 1497 | local b = 1 |
| 1232 | local next_number | 1498 | local next_number |
| @@ -1483,6 +1749,35 @@ if _tab_0 then | |||
| 1483 | print("matched", fourth) | 1749 | print("matched", fourth) |
| 1484 | end | 1750 | end |
| 1485 | end | 1751 | end |
| 1752 | local segments = { | ||
| 1753 | "admin", | ||
| 1754 | "users", | ||
| 1755 | "logs", | ||
| 1756 | "view" | ||
| 1757 | } | ||
| 1758 | local _type_0 = type(segments) | ||
| 1759 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1760 | if _tab_0 then | ||
| 1761 | local groups | ||
| 1762 | do | ||
| 1763 | local _accum_0 = { } | ||
| 1764 | local _len_0 = 1 | ||
| 1765 | local _max_0 = #segments + -3 + 1 | ||
| 1766 | for _index_0 = 1, _max_0 do | ||
| 1767 | local _item_0 = segments[_index_0] | ||
| 1768 | _accum_0[_len_0] = _item_0 | ||
| 1769 | _len_0 = _len_0 + 1 | ||
| 1770 | end | ||
| 1771 | groups = _accum_0 | ||
| 1772 | end | ||
| 1773 | local resource = segments[#segments - 1] | ||
| 1774 | local action = segments[#segments] | ||
| 1775 | if resource ~= nil and action ~= nil then | ||
| 1776 | print("Group:", groups) | ||
| 1777 | print("Resource:", resource) | ||
| 1778 | print("Action:", action) | ||
| 1779 | end | ||
| 1780 | end | ||
| 1486 | local Inventory | 1781 | local Inventory |
| 1487 | local _class_0 | 1782 | local _class_0 |
| 1488 | local _base_0 = { | 1783 | local _base_0 = { |
| @@ -2139,6 +2434,10 @@ do | |||
| 2139 | _with_1["key-name"] = value | 2434 | _with_1["key-name"] = value |
| 2140 | end | 2435 | end |
| 2141 | _with_0[#_with_0 + 1] = "abc" | 2436 | _with_0[#_with_0 + 1] = "abc" |
| 2437 | local _with_0 = obj | ||
| 2438 | if _with_0 ~= nil then | ||
| 2439 | print(obj.name) | ||
| 2440 | end | ||
| 2142 | do | 2441 | do |
| 2143 | local var = "hello" | 2442 | local var = "hello" |
| 2144 | print(var) | 2443 | print(var) |
| @@ -2282,8 +2581,8 @@ local apple = setmetatable({ | |||
| 2282 | if (getmetatable(apple) ~= nil) then | 2581 | if (getmetatable(apple) ~= nil) then |
| 2283 | p(apple.size, apple.color, getmetatable(apple).__index) | 2582 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 2284 | end | 2583 | end |
| 2285 | local _ud83c_udf1b = "月之脚本" | 2584 | local _u1f31b = "月之脚本" |
| 2286 | _module_0["🌛"] = _ud83c_udf1b | 2585 | _module_0["🌛"] = _u1f31b |
| 2287 | return _module_0 | 2586 | return _module_0 |
| 2288 | local area = 6.2831853071796 * 5 | 2587 | local area = 6.2831853071796 * 5 |
| 2289 | print('hello world') | 2588 | print('hello world') |
| @@ -2318,6 +2617,12 @@ end | |||
| 2318 | print("yuescript") | 2617 | print("yuescript") |
| 2319 | print(3) | 2618 | print(3) |
| 2320 | print("Valid enum type:", "Static") | 2619 | print("Valid enum type:", "Static") |
| 2620 | do | ||
| 2621 | print(123, "hello") | ||
| 2622 | end | ||
| 2623 | do | ||
| 2624 | print(123, "hello") | ||
| 2625 | end | ||
| 2321 | if tb ~= nil then | 2626 | if tb ~= nil then |
| 2322 | tb:func() | 2627 | tb:func() |
| 2323 | end | 2628 | end |
| @@ -2350,6 +2655,21 @@ print((function() | |||
| 2350 | end)()) | 2655 | end)()) |
| 2351 | local tab = { } | 2656 | local tab = { } |
| 2352 | tab[#tab + 1] = "Value" | 2657 | tab[#tab + 1] = "Value" |
| 2658 | local tbA = { | ||
| 2659 | 1, | ||
| 2660 | 2, | ||
| 2661 | 3 | ||
| 2662 | } | ||
| 2663 | local tbB = { | ||
| 2664 | 4, | ||
| 2665 | 5, | ||
| 2666 | 6 | ||
| 2667 | } | ||
| 2668 | local _len_0 = #tbA + 1 | ||
| 2669 | for _index_0 = 1, #tbB do | ||
| 2670 | local _elm_0 = tbB[_index_0] | ||
| 2671 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2672 | end | ||
| 2353 | local parts = { | 2673 | local parts = { |
| 2354 | "shoulders", | 2674 | "shoulders", |
| 2355 | "knees" | 2675 | "knees" |
| @@ -2418,6 +2738,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 2418 | end | 2738 | end |
| 2419 | end | 2739 | end |
| 2420 | merge = _tab_0 | 2740 | merge = _tab_0 |
| 2741 | local last | ||
| 2742 | do | ||
| 2743 | local _item_0 = data.items | ||
| 2744 | last = _item_0[#_item_0] | ||
| 2745 | end | ||
| 2746 | local second_last | ||
| 2747 | do | ||
| 2748 | local _item_0 = data.items | ||
| 2749 | second_last = _item_0[#_item_0 - 1] | ||
| 2750 | end | ||
| 2751 | local _obj_0 = data.items | ||
| 2752 | _obj_0[#_obj_0] = 1 | ||
| 2421 | local mt = { } | 2753 | local mt = { } |
| 2422 | local add | 2754 | local add |
| 2423 | add = function(self, right) | 2755 | add = function(self, right) |
| @@ -2548,6 +2880,14 @@ func({ | |||
| 2548 | 2, | 2880 | 2, |
| 2549 | 3 | 2881 | 3 |
| 2550 | }) | 2882 | }) |
| 2883 | local f | ||
| 2884 | f = function() | ||
| 2885 | return { | ||
| 2886 | 1, | ||
| 2887 | 2, | ||
| 2888 | 3 | ||
| 2889 | } | ||
| 2890 | end | ||
| 2551 | local tb = { | 2891 | local tb = { |
| 2552 | name = "abc", | 2892 | name = "abc", |
| 2553 | values = { | 2893 | values = { |
| @@ -2788,6 +3128,59 @@ end | |||
| 2788 | local two, four | 3128 | local two, four |
| 2789 | local _obj_0 = items | 3129 | local _obj_0 = items |
| 2790 | two, four = _obj_0[2], _obj_0[4] | 3130 | two, four = _obj_0[2], _obj_0[4] |
| 3131 | local orders = { | ||
| 3132 | "first", | ||
| 3133 | "second", | ||
| 3134 | "third", | ||
| 3135 | "fourth", | ||
| 3136 | "last" | ||
| 3137 | } | ||
| 3138 | local first, bulk, last = orders[1], (function() | ||
| 3139 | local _accum_0 = { } | ||
| 3140 | local _len_0 = 1 | ||
| 3141 | local _max_0 = #orders + -2 + 1 | ||
| 3142 | for _index_0 = 2, _max_0 do | ||
| 3143 | local _item_0 = orders[_index_0] | ||
| 3144 | _accum_0[_len_0] = _item_0 | ||
| 3145 | _len_0 = _len_0 + 1 | ||
| 3146 | end | ||
| 3147 | return _accum_0 | ||
| 3148 | end)(), orders[#orders] | ||
| 3149 | print(first) | ||
| 3150 | print(bulk) | ||
| 3151 | print(last) | ||
| 3152 | local first, rest | ||
| 3153 | do | ||
| 3154 | local _obj_0 = orders | ||
| 3155 | first, rest = _obj_0[1], (function() | ||
| 3156 | local _accum_0 = { } | ||
| 3157 | local _len_0 = 1 | ||
| 3158 | local _max_0 = #_obj_0 | ||
| 3159 | for _index_0 = 2, _max_0 do | ||
| 3160 | local _item_0 = _obj_0[_index_0] | ||
| 3161 | _accum_0[_len_0] = _item_0 | ||
| 3162 | _len_0 = _len_0 + 1 | ||
| 3163 | end | ||
| 3164 | return _accum_0 | ||
| 3165 | end)() | ||
| 3166 | end | ||
| 3167 | local start, last | ||
| 3168 | do | ||
| 3169 | local _obj_0 = orders | ||
| 3170 | start, last = (function() | ||
| 3171 | local _accum_0 = { } | ||
| 3172 | local _len_0 = 1 | ||
| 3173 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 3174 | for _index_0 = 1, _max_0 do | ||
| 3175 | local _item_0 = _obj_0[_index_0] | ||
| 3176 | _accum_0[_len_0] = _item_0 | ||
| 3177 | _len_0 = _len_0 + 1 | ||
| 3178 | end | ||
| 3179 | return _accum_0 | ||
| 3180 | end)(), _obj_0[#_obj_0] | ||
| 3181 | end | ||
| 3182 | local _obj_0 = orders | ||
| 3183 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 2791 | local tuples = { | 3184 | local tuples = { |
| 2792 | { | 3185 | { |
| 2793 | "hello", | 3186 | "hello", |
| @@ -2852,6 +3245,36 @@ end | |||
| 2852 | local first = select(1, ...) | 3245 | local first = select(1, ...) |
| 2853 | return print(ok, count, first) | 3246 | return print(ok, count, first) |
| 2854 | end)(fn(true)) | 3247 | end)(fn(true)) |
| 3248 | local f | ||
| 3249 | f = function(...) | ||
| 3250 | local t = { | ||
| 3251 | n = select("#", ...), | ||
| 3252 | ... | ||
| 3253 | } | ||
| 3254 | print("argument count:", t.n) | ||
| 3255 | print("table length:", #t) | ||
| 3256 | for i = 1, t.n do | ||
| 3257 | print(t[i]) | ||
| 3258 | end | ||
| 3259 | end | ||
| 3260 | f(1, 2, 3) | ||
| 3261 | f("a", "b", "c", "d") | ||
| 3262 | f() | ||
| 3263 | local process | ||
| 3264 | process = function(...) | ||
| 3265 | local args = { | ||
| 3266 | n = select("#", ...), | ||
| 3267 | ... | ||
| 3268 | } | ||
| 3269 | local sum = 0 | ||
| 3270 | for i = 1, args.n do | ||
| 3271 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 3272 | sum = sum + args[i] | ||
| 3273 | end | ||
| 3274 | end | ||
| 3275 | return sum | ||
| 3276 | end | ||
| 3277 | process(1, nil, 3, nil, 5) | ||
| 2855 | Rx.Observable.fromRange(1, 8):filter(function(x) | 3278 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 2856 | return x % 2 == 0 | 3279 | return x % 2 == 0 |
| 2857 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 3280 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -2889,6 +3312,56 @@ end) | |||
| 2889 | if success then | 3312 | if success then |
| 2890 | print(result) | 3313 | print(result) |
| 2891 | end | 3314 | end |
| 3315 | local a, b, c | ||
| 3316 | do | ||
| 3317 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 3318 | return func() | ||
| 3319 | end) | ||
| 3320 | if _ok_0 then | ||
| 3321 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 3322 | end | ||
| 3323 | end | ||
| 3324 | do | ||
| 3325 | local _exp_0 = ((function() | ||
| 3326 | return (function(_arg_0, ...) | ||
| 3327 | local _ok_0 = _arg_0 | ||
| 3328 | if _ok_0 then | ||
| 3329 | return ... | ||
| 3330 | end | ||
| 3331 | end)(pcall(function() | ||
| 3332 | return func() | ||
| 3333 | end)) | ||
| 3334 | end)()) | ||
| 3335 | if _exp_0 ~= nil then | ||
| 3336 | a = _exp_0 | ||
| 3337 | else | ||
| 3338 | a = "default" | ||
| 3339 | end | ||
| 3340 | end | ||
| 3341 | f((function() | ||
| 3342 | return (function(_arg_0, ...) | ||
| 3343 | local _ok_0 = _arg_0 | ||
| 3344 | if _ok_0 then | ||
| 3345 | return ... | ||
| 3346 | end | ||
| 3347 | end)(pcall(function() | ||
| 3348 | return func() | ||
| 3349 | end)) | ||
| 3350 | end)()) | ||
| 3351 | f((function() | ||
| 3352 | return (function(_arg_0, ...) | ||
| 3353 | local _ok_0 = _arg_0 | ||
| 3354 | if _ok_0 then | ||
| 3355 | return ... | ||
| 3356 | end | ||
| 3357 | end)(xpcall(function() | ||
| 3358 | print(123) | ||
| 3359 | return func() | ||
| 3360 | end, function(e) | ||
| 3361 | print(e) | ||
| 3362 | return e | ||
| 3363 | end)) | ||
| 3364 | end)()) | ||
| 2892 | local a <const> = 123 | 3365 | local a <const> = 123 |
| 2893 | local _ <close> = setmetatable({ }, { | 3366 | local _ <close> = setmetatable({ }, { |
| 2894 | __close = function() | 3367 | __close = function() |
| @@ -2903,6 +3376,14 @@ local some_string = "Here is a string\n that has a line break in it." | |||
| 2903 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 3376 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
| 2904 | local integer = 1000000 | 3377 | local integer = 1000000 |
| 2905 | local hex = 0xEFBBBF | 3378 | local hex = 0xEFBBBF |
| 3379 | local binary = 19 | ||
| 3380 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 3381 | local fn | ||
| 3382 | fn = function() | ||
| 3383 | local str = "foo:\n bar: baz" | ||
| 3384 | return str | ||
| 3385 | end | ||
| 3386 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 2906 | local my_function | 3387 | local my_function |
| 2907 | my_function = function() end | 3388 | my_function = function() end |
| 2908 | my_function() | 3389 | my_function() |
| @@ -2997,6 +3478,66 @@ if func(1, 2, 3, "hello", "world") then | |||
| 2997 | print("hello") | 3478 | print("hello") |
| 2998 | print("I am inside if") | 3479 | print("I am inside if") |
| 2999 | end | 3480 | end |
| 3481 | local f1 | ||
| 3482 | f1 = function(_arg_0) | ||
| 3483 | local a, b, c | ||
| 3484 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 3485 | return print(a, b, c) | ||
| 3486 | end | ||
| 3487 | f1({ | ||
| 3488 | a = 1, | ||
| 3489 | b = "2", | ||
| 3490 | c = { } | ||
| 3491 | }) | ||
| 3492 | local f2 | ||
| 3493 | f2 = function(_arg_0, c) | ||
| 3494 | local a1, b | ||
| 3495 | a1, b = _arg_0.a, _arg_0.b | ||
| 3496 | if a1 == nil then | ||
| 3497 | a1 = 123 | ||
| 3498 | end | ||
| 3499 | if b == nil then | ||
| 3500 | b = 'abc' | ||
| 3501 | end | ||
| 3502 | if c == nil then | ||
| 3503 | c = { } | ||
| 3504 | end | ||
| 3505 | end | ||
| 3506 | print(a1, b, c) | ||
| 3507 | local arg1 = { | ||
| 3508 | a = 0 | ||
| 3509 | } | ||
| 3510 | f2(arg1, arg2) | ||
| 3511 | local findFirstEven | ||
| 3512 | findFirstEven = function(list) | ||
| 3513 | for _index_0 = 1, #list do | ||
| 3514 | local item = list[_index_0] | ||
| 3515 | if type(item) == "table" then | ||
| 3516 | for _index_1 = 1, #item do | ||
| 3517 | local sub = item[_index_1] | ||
| 3518 | if sub % 2 == 0 then | ||
| 3519 | return sub | ||
| 3520 | end | ||
| 3521 | end | ||
| 3522 | end | ||
| 3523 | end | ||
| 3524 | return nil | ||
| 3525 | end | ||
| 3526 | local findFirstEven | ||
| 3527 | findFirstEven = function(list) | ||
| 3528 | for _index_0 = 1, #list do | ||
| 3529 | local item = list[_index_0] | ||
| 3530 | if type(item) == "table" then | ||
| 3531 | for _index_1 = 1, #item do | ||
| 3532 | local sub = item[_index_1] | ||
| 3533 | if sub % 2 == 0 then | ||
| 3534 | return sub | ||
| 3535 | end | ||
| 3536 | end | ||
| 3537 | end | ||
| 3538 | end | ||
| 3539 | return nil | ||
| 3540 | end | ||
| 3000 | f(function() | 3541 | f(function() |
| 3001 | return print("hello") | 3542 | return print("hello") |
| 3002 | end) | 3543 | end) |
| @@ -3122,6 +3663,28 @@ for _index_0 = 1, #_list_0 do | |||
| 3122 | _len_0 = _len_0 + 1 | 3663 | _len_0 = _len_0 + 1 |
| 3123 | end | 3664 | end |
| 3124 | doubled = _accum_0 | 3665 | doubled = _accum_0 |
| 3666 | local data = { | ||
| 3667 | a = { | ||
| 3668 | 1, | ||
| 3669 | 2, | ||
| 3670 | 3 | ||
| 3671 | }, | ||
| 3672 | b = { | ||
| 3673 | 4, | ||
| 3674 | 5, | ||
| 3675 | 6 | ||
| 3676 | } | ||
| 3677 | } | ||
| 3678 | local flat | ||
| 3679 | local _accum_0 = { } | ||
| 3680 | for k, v in pairs(data) do | ||
| 3681 | local _len_0 = #_accum_0 + 1 | ||
| 3682 | for _index_0 = 1, #v do | ||
| 3683 | local _elm_0 = v[_index_0] | ||
| 3684 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 3685 | end | ||
| 3686 | end | ||
| 3687 | flat = _accum_0 | ||
| 3125 | local x_coords = { | 3688 | local x_coords = { |
| 3126 | 4, | 3689 | 4, |
| 3127 | 5, | 3690 | 5, |
| @@ -3212,8 +3775,7 @@ local slice | |||
| 3212 | local _accum_0 = { } | 3775 | local _accum_0 = { } |
| 3213 | local _len_0 = 1 | 3776 | local _len_0 = 1 |
| 3214 | local _list_0 = items | 3777 | local _list_0 = items |
| 3215 | local _max_0 = 5 | 3778 | for _index_0 = 1, 5 do |
| 3216 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3217 | local item = _list_0[_index_0] | 3779 | local item = _list_0[_index_0] |
| 3218 | _accum_0[_len_0] = item | 3780 | _accum_0[_len_0] = item |
| 3219 | _len_0 = _len_0 + 1 | 3781 | _len_0 = _len_0 + 1 |
| @@ -3223,7 +3785,8 @@ local slice | |||
| 3223 | local _accum_0 = { } | 3785 | local _accum_0 = { } |
| 3224 | local _len_0 = 1 | 3786 | local _len_0 = 1 |
| 3225 | local _list_0 = items | 3787 | local _list_0 = items |
| 3226 | for _index_0 = 2, #_list_0 do | 3788 | local _max_0 = #_list_0 |
| 3789 | for _index_0 = 2, _max_0 do | ||
| 3227 | local item = _list_0[_index_0] | 3790 | local item = _list_0[_index_0] |
| 3228 | _accum_0[_len_0] = item | 3791 | _accum_0[_len_0] = item |
| 3229 | _len_0 = _len_0 + 1 | 3792 | _len_0 = _len_0 + 1 |
| @@ -3233,12 +3796,46 @@ local slice | |||
| 3233 | local _accum_0 = { } | 3796 | local _accum_0 = { } |
| 3234 | local _len_0 = 1 | 3797 | local _len_0 = 1 |
| 3235 | local _list_0 = items | 3798 | local _list_0 = items |
| 3236 | for _index_0 = 1, #_list_0, 2 do | 3799 | local _max_0 = #_list_0 |
| 3800 | for _index_0 = 1, _max_0, 2 do | ||
| 3237 | local item = _list_0[_index_0] | 3801 | local item = _list_0[_index_0] |
| 3238 | _accum_0[_len_0] = item | 3802 | _accum_0[_len_0] = item |
| 3239 | _len_0 = _len_0 + 1 | 3803 | _len_0 = _len_0 + 1 |
| 3240 | end | 3804 | end |
| 3241 | slice = _accum_0 | 3805 | slice = _accum_0 |
| 3806 | local slice | ||
| 3807 | local _accum_0 = { } | ||
| 3808 | local _len_0 = 1 | ||
| 3809 | local _list_0 = items | ||
| 3810 | local _min_0 = #_list_0 + -4 + 1 | ||
| 3811 | local _max_0 = #_list_0 + -1 + 1 | ||
| 3812 | for _index_0 = _min_0, _max_0 do | ||
| 3813 | local item = _list_0[_index_0] | ||
| 3814 | _accum_0[_len_0] = item | ||
| 3815 | _len_0 = _len_0 + 1 | ||
| 3816 | end | ||
| 3817 | slice = _accum_0 | ||
| 3818 | local reverse_slice | ||
| 3819 | local _accum_0 = { } | ||
| 3820 | local _len_0 = 1 | ||
| 3821 | local _list_0 = items | ||
| 3822 | local _min_0 = #_list_0 + -1 + 1 | ||
| 3823 | for _index_0 = _min_0, 1, -1 do | ||
| 3824 | local item = _list_0[_index_0] | ||
| 3825 | _accum_0[_len_0] = item | ||
| 3826 | _len_0 = _len_0 + 1 | ||
| 3827 | end | ||
| 3828 | reverse_slice = _accum_0 | ||
| 3829 | local sub_list | ||
| 3830 | local _accum_0 = { } | ||
| 3831 | local _len_0 = 1 | ||
| 3832 | local _list_0 = items | ||
| 3833 | for _index_0 = 2, 4 do | ||
| 3834 | local _item_0 = _list_0[_index_0] | ||
| 3835 | _accum_0[_len_0] = _item_0 | ||
| 3836 | _len_0 = _len_0 + 1 | ||
| 3837 | end | ||
| 3838 | sub_list = _accum_0 | ||
| 3242 | for i = 10, 20 do | 3839 | for i = 10, 20 do |
| 3243 | print(i) | 3840 | print(i) |
| 3244 | end | 3841 | end |
| @@ -3249,8 +3846,7 @@ for key, value in pairs(object) do | |||
| 3249 | print(key, value) | 3846 | print(key, value) |
| 3250 | end | 3847 | end |
| 3251 | local _list_0 = items | 3848 | local _list_0 = items |
| 3252 | local _max_0 = 4 | 3849 | for _index_0 = 2, 4 do |
| 3253 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3254 | local item = _list_0[_index_0] | 3850 | local item = _list_0[_index_0] |
| 3255 | print(item) | 3851 | print(item) |
| 3256 | end | 3852 | end |
| @@ -3434,7 +4030,7 @@ if "Robert" == name then | |||
| 3434 | elseif "Dan" == name or "Daniel" == name then | 4030 | elseif "Dan" == name or "Daniel" == name then |
| 3435 | print("Your name, it's Dan") | 4031 | print("Your name, it's Dan") |
| 3436 | else | 4032 | else |
| 3437 | print("I don't know about your name") | 4033 | print("I don't know about you with name " .. tostring(name)) |
| 3438 | end | 4034 | end |
| 3439 | local b = 1 | 4035 | local b = 1 |
| 3440 | local next_number | 4036 | local next_number |
| @@ -3691,6 +4287,35 @@ if _tab_0 then | |||
| 3691 | print("matched", fourth) | 4287 | print("matched", fourth) |
| 3692 | end | 4288 | end |
| 3693 | end | 4289 | end |
| 4290 | local segments = { | ||
| 4291 | "admin", | ||
| 4292 | "users", | ||
| 4293 | "logs", | ||
| 4294 | "view" | ||
| 4295 | } | ||
| 4296 | local _type_0 = type(segments) | ||
| 4297 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4298 | if _tab_0 then | ||
| 4299 | local groups | ||
| 4300 | do | ||
| 4301 | local _accum_0 = { } | ||
| 4302 | local _len_0 = 1 | ||
| 4303 | local _max_0 = #segments + -3 + 1 | ||
| 4304 | for _index_0 = 1, _max_0 do | ||
| 4305 | local _item_0 = segments[_index_0] | ||
| 4306 | _accum_0[_len_0] = _item_0 | ||
| 4307 | _len_0 = _len_0 + 1 | ||
| 4308 | end | ||
| 4309 | groups = _accum_0 | ||
| 4310 | end | ||
| 4311 | local resource = segments[#segments - 1] | ||
| 4312 | local action = segments[#segments] | ||
| 4313 | if resource ~= nil and action ~= nil then | ||
| 4314 | print("Group:", groups) | ||
| 4315 | print("Resource:", resource) | ||
| 4316 | print("Action:", action) | ||
| 4317 | end | ||
| 4318 | end | ||
| 3694 | local Inventory | 4319 | local Inventory |
| 3695 | local _class_0 | 4320 | local _class_0 |
| 3696 | local _base_0 = { | 4321 | local _base_0 = { |
| @@ -4347,6 +4972,10 @@ do | |||
| 4347 | _with_1["key-name"] = value | 4972 | _with_1["key-name"] = value |
| 4348 | end | 4973 | end |
| 4349 | _with_0[#_with_0 + 1] = "abc" | 4974 | _with_0[#_with_0 + 1] = "abc" |
| 4975 | local _with_0 = obj | ||
| 4976 | if _with_0 ~= nil then | ||
| 4977 | print(obj.name) | ||
| 4978 | end | ||
| 4350 | do | 4979 | do |
| 4351 | local var = "hello" | 4980 | local var = "hello" |
| 4352 | print(var) | 4981 | print(var) |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index 52204b7..6a6c38c 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
| @@ -73,8 +73,8 @@ local apple = setmetatable({ | |||
| 73 | if (getmetatable(apple) ~= nil) then | 73 | if (getmetatable(apple) ~= nil) then |
| 74 | p(apple.size, apple.color, getmetatable(apple).__index) | 74 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 75 | end | 75 | end |
| 76 | local _ud83c_udf1b = "月之脚本" | 76 | local _u1f31b = "月之脚本" |
| 77 | _module_0["🌛"] = _ud83c_udf1b | 77 | _module_0["🌛"] = _u1f31b |
| 78 | return _module_0 | 78 | return _module_0 |
| 79 | local area = 6.2831853071796 * 5 | 79 | local area = 6.2831853071796 * 5 |
| 80 | print('ä½ å¥½ 世界') | 80 | print('ä½ å¥½ 世界') |
| @@ -109,6 +109,12 @@ end | |||
| 109 | print("yuescript") | 109 | print("yuescript") |
| 110 | print(3) | 110 | print(3) |
| 111 | print("有效的枚举类型:", "Static") | 111 | print("有效的枚举类型:", "Static") |
| 112 | do | ||
| 113 | print(123, "hello") | ||
| 114 | end | ||
| 115 | do | ||
| 116 | print(123, "hello") | ||
| 117 | end | ||
| 112 | if tb ~= nil then | 118 | if tb ~= nil then |
| 113 | tb:func() | 119 | tb:func() |
| 114 | end | 120 | end |
| @@ -141,6 +147,21 @@ print((function() | |||
| 141 | end)()) | 147 | end)()) |
| 142 | local tab = { } | 148 | local tab = { } |
| 143 | tab[#tab + 1] = "Value" | 149 | tab[#tab + 1] = "Value" |
| 150 | local tbA = { | ||
| 151 | 1, | ||
| 152 | 2, | ||
| 153 | 3 | ||
| 154 | } | ||
| 155 | local tbB = { | ||
| 156 | 4, | ||
| 157 | 5, | ||
| 158 | 6 | ||
| 159 | } | ||
| 160 | local _len_0 = #tbA + 1 | ||
| 161 | for _index_0 = 1, #tbB do | ||
| 162 | local _elm_0 = tbB[_index_0] | ||
| 163 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 164 | end | ||
| 144 | local parts = { | 165 | local parts = { |
| 145 | "shoulders", | 166 | "shoulders", |
| 146 | "knees" | 167 | "knees" |
| @@ -209,6 +230,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 209 | end | 230 | end |
| 210 | end | 231 | end |
| 211 | merge = _tab_0 | 232 | merge = _tab_0 |
| 233 | local last | ||
| 234 | do | ||
| 235 | local _item_0 = data.items | ||
| 236 | last = _item_0[#_item_0] | ||
| 237 | end | ||
| 238 | local second_last | ||
| 239 | do | ||
| 240 | local _item_0 = data.items | ||
| 241 | second_last = _item_0[#_item_0 - 1] | ||
| 242 | end | ||
| 243 | local _obj_0 = data.items | ||
| 244 | _obj_0[#_obj_0] = 1 | ||
| 212 | local mt = { } | 245 | local mt = { } |
| 213 | local add | 246 | local add |
| 214 | add = function(self, right) | 247 | add = function(self, right) |
| @@ -339,6 +372,14 @@ func({ | |||
| 339 | 2, | 372 | 2, |
| 340 | 3 | 373 | 3 |
| 341 | }) | 374 | }) |
| 375 | local f | ||
| 376 | f = function() | ||
| 377 | return { | ||
| 378 | 1, | ||
| 379 | 2, | ||
| 380 | 3 | ||
| 381 | } | ||
| 382 | end | ||
| 342 | local tb = { | 383 | local tb = { |
| 343 | name = "abc", | 384 | name = "abc", |
| 344 | values = { | 385 | values = { |
| @@ -579,6 +620,59 @@ end | |||
| 579 | local two, four | 620 | local two, four |
| 580 | local _obj_0 = items | 621 | local _obj_0 = items |
| 581 | two, four = _obj_0[2], _obj_0[4] | 622 | two, four = _obj_0[2], _obj_0[4] |
| 623 | local orders = { | ||
| 624 | "first", | ||
| 625 | "second", | ||
| 626 | "third", | ||
| 627 | "fourth", | ||
| 628 | "last" | ||
| 629 | } | ||
| 630 | local first, bulk, last = orders[1], (function() | ||
| 631 | local _accum_0 = { } | ||
| 632 | local _len_0 = 1 | ||
| 633 | local _max_0 = #orders + -2 + 1 | ||
| 634 | for _index_0 = 2, _max_0 do | ||
| 635 | local _item_0 = orders[_index_0] | ||
| 636 | _accum_0[_len_0] = _item_0 | ||
| 637 | _len_0 = _len_0 + 1 | ||
| 638 | end | ||
| 639 | return _accum_0 | ||
| 640 | end)(), orders[#orders] | ||
| 641 | print(first) | ||
| 642 | print(bulk) | ||
| 643 | print(last) | ||
| 644 | local first, rest | ||
| 645 | do | ||
| 646 | local _obj_0 = orders | ||
| 647 | first, rest = _obj_0[1], (function() | ||
| 648 | local _accum_0 = { } | ||
| 649 | local _len_0 = 1 | ||
| 650 | local _max_0 = #_obj_0 | ||
| 651 | for _index_0 = 2, _max_0 do | ||
| 652 | local _item_0 = _obj_0[_index_0] | ||
| 653 | _accum_0[_len_0] = _item_0 | ||
| 654 | _len_0 = _len_0 + 1 | ||
| 655 | end | ||
| 656 | return _accum_0 | ||
| 657 | end)() | ||
| 658 | end | ||
| 659 | local start, last | ||
| 660 | do | ||
| 661 | local _obj_0 = orders | ||
| 662 | start, last = (function() | ||
| 663 | local _accum_0 = { } | ||
| 664 | local _len_0 = 1 | ||
| 665 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 666 | for _index_0 = 1, _max_0 do | ||
| 667 | local _item_0 = _obj_0[_index_0] | ||
| 668 | _accum_0[_len_0] = _item_0 | ||
| 669 | _len_0 = _len_0 + 1 | ||
| 670 | end | ||
| 671 | return _accum_0 | ||
| 672 | end)(), _obj_0[#_obj_0] | ||
| 673 | end | ||
| 674 | local _obj_0 = orders | ||
| 675 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 582 | local tuples = { | 676 | local tuples = { |
| 583 | { | 677 | { |
| 584 | "hello", | 678 | "hello", |
| @@ -643,6 +737,36 @@ end | |||
| 643 | local first = select(1, ...) | 737 | local first = select(1, ...) |
| 644 | return print(ok, count, first) | 738 | return print(ok, count, first) |
| 645 | end)(fn(true)) | 739 | end)(fn(true)) |
| 740 | local f | ||
| 741 | f = function(...) | ||
| 742 | local t = { | ||
| 743 | n = select("#", ...), | ||
| 744 | ... | ||
| 745 | } | ||
| 746 | print("傿•°ä¸ªæ•°:", t.n) | ||
| 747 | print("表长度:", #t) | ||
| 748 | for i = 1, t.n do | ||
| 749 | print(t[i]) | ||
| 750 | end | ||
| 751 | end | ||
| 752 | f(1, 2, 3) | ||
| 753 | f("a", "b", "c", "d") | ||
| 754 | f() | ||
| 755 | local process | ||
| 756 | process = function(...) | ||
| 757 | local args = { | ||
| 758 | n = select("#", ...), | ||
| 759 | ... | ||
| 760 | } | ||
| 761 | local sum = 0 | ||
| 762 | for i = 1, args.n do | ||
| 763 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 764 | sum = sum + args[i] | ||
| 765 | end | ||
| 766 | end | ||
| 767 | return sum | ||
| 768 | end | ||
| 769 | process(1, nil, 3, nil, 5) | ||
| 646 | Rx.Observable.fromRange(1, 8):filter(function(x) | 770 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 647 | return x % 2 == 0 | 771 | return x % 2 == 0 |
| 648 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 772 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -680,6 +804,56 @@ end) | |||
| 680 | if success then | 804 | if success then |
| 681 | print(result) | 805 | print(result) |
| 682 | end | 806 | end |
| 807 | local a, b, c | ||
| 808 | do | ||
| 809 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 810 | return func() | ||
| 811 | end) | ||
| 812 | if _ok_0 then | ||
| 813 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 814 | end | ||
| 815 | end | ||
| 816 | do | ||
| 817 | local _exp_0 = ((function() | ||
| 818 | return (function(_arg_0, ...) | ||
| 819 | local _ok_0 = _arg_0 | ||
| 820 | if _ok_0 then | ||
| 821 | return ... | ||
| 822 | end | ||
| 823 | end)(pcall(function() | ||
| 824 | return func() | ||
| 825 | end)) | ||
| 826 | end)()) | ||
| 827 | if _exp_0 ~= nil then | ||
| 828 | a = _exp_0 | ||
| 829 | else | ||
| 830 | a = "default" | ||
| 831 | end | ||
| 832 | end | ||
| 833 | f((function() | ||
| 834 | return (function(_arg_0, ...) | ||
| 835 | local _ok_0 = _arg_0 | ||
| 836 | if _ok_0 then | ||
| 837 | return ... | ||
| 838 | end | ||
| 839 | end)(pcall(function() | ||
| 840 | return func() | ||
| 841 | end)) | ||
| 842 | end)()) | ||
| 843 | f((function() | ||
| 844 | return (function(_arg_0, ...) | ||
| 845 | local _ok_0 = _arg_0 | ||
| 846 | if _ok_0 then | ||
| 847 | return ... | ||
| 848 | end | ||
| 849 | end)(xpcall(function() | ||
| 850 | print(123) | ||
| 851 | return func() | ||
| 852 | end, function(e) | ||
| 853 | print(e) | ||
| 854 | return e | ||
| 855 | end)) | ||
| 856 | end)()) | ||
| 683 | local a <const> = 123 | 857 | local a <const> = 123 |
| 684 | local _ <close> = setmetatable({ }, { | 858 | local _ <close> = setmetatable({ }, { |
| 685 | __close = function() | 859 | __close = function() |
| @@ -695,6 +869,13 @@ print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | |||
| 695 | local integer = 1000000 | 869 | local integer = 1000000 |
| 696 | local hex = 0xEFBBBF | 870 | local hex = 0xEFBBBF |
| 697 | local binary = 19 | 871 | local binary = 19 |
| 872 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 873 | local fn | ||
| 874 | fn = function() | ||
| 875 | local str = "foo:\n bar: baz" | ||
| 876 | return str | ||
| 877 | end | ||
| 878 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 698 | local my_function | 879 | local my_function |
| 699 | my_function = function() end | 880 | my_function = function() end |
| 700 | my_function() | 881 | my_function() |
| @@ -783,6 +964,36 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
| 783 | print("hello") | 964 | print("hello") |
| 784 | print("我在if内部") | 965 | print("我在if内部") |
| 785 | end | 966 | end |
| 967 | local f1 | ||
| 968 | f1 = function(_arg_0) | ||
| 969 | local a, b, c | ||
| 970 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 971 | return print(a, b, c) | ||
| 972 | end | ||
| 973 | f1({ | ||
| 974 | a = 1, | ||
| 975 | b = "2", | ||
| 976 | c = { } | ||
| 977 | }) | ||
| 978 | local f2 | ||
| 979 | f2 = function(_arg_0, c) | ||
| 980 | local a1, b | ||
| 981 | a1, b = _arg_0.a, _arg_0.b | ||
| 982 | if a1 == nil then | ||
| 983 | a1 = 123 | ||
| 984 | end | ||
| 985 | if b == nil then | ||
| 986 | b = 'abc' | ||
| 987 | end | ||
| 988 | if c == nil then | ||
| 989 | c = { } | ||
| 990 | end | ||
| 991 | return print(a1, b, c) | ||
| 992 | end | ||
| 993 | local arg1 = { | ||
| 994 | a = 0 | ||
| 995 | } | ||
| 996 | f2(arg1, arg2) | ||
| 786 | f(function() | 997 | f(function() |
| 787 | return print("hello") | 998 | return print("hello") |
| 788 | end) | 999 | end) |
| @@ -908,6 +1119,28 @@ for _index_0 = 1, #_list_0 do | |||
| 908 | _len_0 = _len_0 + 1 | 1119 | _len_0 = _len_0 + 1 |
| 909 | end | 1120 | end |
| 910 | doubled = _accum_0 | 1121 | doubled = _accum_0 |
| 1122 | local data = { | ||
| 1123 | a = { | ||
| 1124 | 1, | ||
| 1125 | 2, | ||
| 1126 | 3 | ||
| 1127 | }, | ||
| 1128 | b = { | ||
| 1129 | 4, | ||
| 1130 | 5, | ||
| 1131 | 6 | ||
| 1132 | } | ||
| 1133 | } | ||
| 1134 | local flat | ||
| 1135 | local _accum_0 = { } | ||
| 1136 | for k, v in pairs(data) do | ||
| 1137 | local _len_0 = #_accum_0 + 1 | ||
| 1138 | for _index_0 = 1, #v do | ||
| 1139 | local _elm_0 = v[_index_0] | ||
| 1140 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 1141 | end | ||
| 1142 | end | ||
| 1143 | flat = _accum_0 | ||
| 911 | local x_coords = { | 1144 | local x_coords = { |
| 912 | 4, | 1145 | 4, |
| 913 | 5, | 1146 | 5, |
| @@ -998,8 +1231,18 @@ local slice | |||
| 998 | local _accum_0 = { } | 1231 | local _accum_0 = { } |
| 999 | local _len_0 = 1 | 1232 | local _len_0 = 1 |
| 1000 | local _list_0 = items | 1233 | local _list_0 = items |
| 1001 | local _max_0 = 5 | 1234 | for _index_0 = 1, 5 do |
| 1002 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | 1235 | local item = _list_0[_index_0] |
| 1236 | _accum_0[_len_0] = item | ||
| 1237 | _len_0 = _len_0 + 1 | ||
| 1238 | end | ||
| 1239 | slice = _accum_0 | ||
| 1240 | local slice | ||
| 1241 | local _accum_0 = { } | ||
| 1242 | local _len_0 = 1 | ||
| 1243 | local _list_0 = items | ||
| 1244 | local _max_0 = #_list_0 | ||
| 1245 | for _index_0 = 2, _max_0 do | ||
| 1003 | local item = _list_0[_index_0] | 1246 | local item = _list_0[_index_0] |
| 1004 | _accum_0[_len_0] = item | 1247 | _accum_0[_len_0] = item |
| 1005 | _len_0 = _len_0 + 1 | 1248 | _len_0 = _len_0 + 1 |
| @@ -1009,7 +1252,8 @@ local slice | |||
| 1009 | local _accum_0 = { } | 1252 | local _accum_0 = { } |
| 1010 | local _len_0 = 1 | 1253 | local _len_0 = 1 |
| 1011 | local _list_0 = items | 1254 | local _list_0 = items |
| 1012 | for _index_0 = 2, #_list_0 do | 1255 | local _max_0 = #_list_0 |
| 1256 | for _index_0 = 1, _max_0, 2 do | ||
| 1013 | local item = _list_0[_index_0] | 1257 | local item = _list_0[_index_0] |
| 1014 | _accum_0[_len_0] = item | 1258 | _accum_0[_len_0] = item |
| 1015 | _len_0 = _len_0 + 1 | 1259 | _len_0 = _len_0 + 1 |
| @@ -1019,12 +1263,35 @@ local slice | |||
| 1019 | local _accum_0 = { } | 1263 | local _accum_0 = { } |
| 1020 | local _len_0 = 1 | 1264 | local _len_0 = 1 |
| 1021 | local _list_0 = items | 1265 | local _list_0 = items |
| 1022 | for _index_0 = 1, #_list_0, 2 do | 1266 | local _min_0 = #_list_0 + -4 + 1 |
| 1267 | local _max_0 = #_list_0 + -1 + 1 | ||
| 1268 | for _index_0 = _min_0, _max_0 do | ||
| 1023 | local item = _list_0[_index_0] | 1269 | local item = _list_0[_index_0] |
| 1024 | _accum_0[_len_0] = item | 1270 | _accum_0[_len_0] = item |
| 1025 | _len_0 = _len_0 + 1 | 1271 | _len_0 = _len_0 + 1 |
| 1026 | end | 1272 | end |
| 1027 | slice = _accum_0 | 1273 | slice = _accum_0 |
| 1274 | local reverse_slice | ||
| 1275 | local _accum_0 = { } | ||
| 1276 | local _len_0 = 1 | ||
| 1277 | local _list_0 = items | ||
| 1278 | local _min_0 = #_list_0 + -1 + 1 | ||
| 1279 | for _index_0 = _min_0, 1, -1 do | ||
| 1280 | local item = _list_0[_index_0] | ||
| 1281 | _accum_0[_len_0] = item | ||
| 1282 | _len_0 = _len_0 + 1 | ||
| 1283 | end | ||
| 1284 | reverse_slice = _accum_0 | ||
| 1285 | local sub_list | ||
| 1286 | local _accum_0 = { } | ||
| 1287 | local _len_0 = 1 | ||
| 1288 | local _list_0 = items | ||
| 1289 | for _index_0 = 2, 4 do | ||
| 1290 | local _item_0 = _list_0[_index_0] | ||
| 1291 | _accum_0[_len_0] = _item_0 | ||
| 1292 | _len_0 = _len_0 + 1 | ||
| 1293 | end | ||
| 1294 | sub_list = _accum_0 | ||
| 1028 | for i = 10, 20 do | 1295 | for i = 10, 20 do |
| 1029 | print(i) | 1296 | print(i) |
| 1030 | end | 1297 | end |
| @@ -1035,8 +1302,7 @@ for key, value in pairs(object) do | |||
| 1035 | print(key, value) | 1302 | print(key, value) |
| 1036 | end | 1303 | end |
| 1037 | local _list_0 = items | 1304 | local _list_0 = items |
| 1038 | local _max_0 = 4 | 1305 | for _index_0 = 2, 4 do |
| 1039 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 1040 | local item = _list_0[_index_0] | 1306 | local item = _list_0[_index_0] |
| 1041 | print(item) | 1307 | print(item) |
| 1042 | end | 1308 | end |
| @@ -1220,7 +1486,7 @@ if "Robert" == name then | |||
| 1220 | elseif "Dan" == name or "Daniel" == name then | 1486 | elseif "Dan" == name or "Daniel" == name then |
| 1221 | print("ä½ çš„åå—æ˜¯Dan") | 1487 | print("ä½ çš„åå—æ˜¯Dan") |
| 1222 | else | 1488 | else |
| 1223 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 1489 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
| 1224 | end | 1490 | end |
| 1225 | local b = 1 | 1491 | local b = 1 |
| 1226 | local next_number | 1492 | local next_number |
| @@ -1477,6 +1743,35 @@ if _tab_0 then | |||
| 1477 | print("åŒ¹é…æˆåŠŸ", fourth) | 1743 | print("åŒ¹é…æˆåŠŸ", fourth) |
| 1478 | end | 1744 | end |
| 1479 | end | 1745 | end |
| 1746 | local segments = { | ||
| 1747 | "admin", | ||
| 1748 | "users", | ||
| 1749 | "logs", | ||
| 1750 | "view" | ||
| 1751 | } | ||
| 1752 | local _type_0 = type(segments) | ||
| 1753 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1754 | if _tab_0 then | ||
| 1755 | local groups | ||
| 1756 | do | ||
| 1757 | local _accum_0 = { } | ||
| 1758 | local _len_0 = 1 | ||
| 1759 | local _max_0 = #segments + -3 + 1 | ||
| 1760 | for _index_0 = 1, _max_0 do | ||
| 1761 | local _item_0 = segments[_index_0] | ||
| 1762 | _accum_0[_len_0] = _item_0 | ||
| 1763 | _len_0 = _len_0 + 1 | ||
| 1764 | end | ||
| 1765 | groups = _accum_0 | ||
| 1766 | end | ||
| 1767 | local resource = segments[#segments - 1] | ||
| 1768 | local action = segments[#segments] | ||
| 1769 | if resource ~= nil and action ~= nil then | ||
| 1770 | print("Group:", groups) | ||
| 1771 | print("Resource:", resource) | ||
| 1772 | print("Action:", action) | ||
| 1773 | end | ||
| 1774 | end | ||
| 1480 | local Inventory | 1775 | local Inventory |
| 1481 | local _class_0 | 1776 | local _class_0 |
| 1482 | local _base_0 = { | 1777 | local _base_0 = { |
| @@ -2133,6 +2428,10 @@ do | |||
| 2133 | _with_1["key-name"] = value | 2428 | _with_1["key-name"] = value |
| 2134 | end | 2429 | end |
| 2135 | _with_0[#_with_0 + 1] = "abc" | 2430 | _with_0[#_with_0 + 1] = "abc" |
| 2431 | local _with_0 = obj | ||
| 2432 | if _with_0 ~= nil then | ||
| 2433 | print(obj.name) | ||
| 2434 | end | ||
| 2136 | do | 2435 | do |
| 2137 | local var = "hello" | 2436 | local var = "hello" |
| 2138 | print(var) | 2437 | print(var) |
| @@ -2276,8 +2575,8 @@ local apple = setmetatable({ | |||
| 2276 | if (getmetatable(apple) ~= nil) then | 2575 | if (getmetatable(apple) ~= nil) then |
| 2277 | p(apple.size, apple.color, getmetatable(apple).__index) | 2576 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 2278 | end | 2577 | end |
| 2279 | local _ud83c_udf1b = "月之脚本" | 2578 | local _u1f31b = "月之脚本" |
| 2280 | _module_0["🌛"] = _ud83c_udf1b | 2579 | _module_0["🌛"] = _u1f31b |
| 2281 | return _module_0 | 2580 | return _module_0 |
| 2282 | local area = 6.2831853071796 * 5 | 2581 | local area = 6.2831853071796 * 5 |
| 2283 | print('ä½ å¥½ 世界') | 2582 | print('ä½ å¥½ 世界') |
| @@ -2312,6 +2611,12 @@ end | |||
| 2312 | print("yuescript") | 2611 | print("yuescript") |
| 2313 | print(3) | 2612 | print(3) |
| 2314 | print("有效的枚举类型:", "Static") | 2613 | print("有效的枚举类型:", "Static") |
| 2614 | do | ||
| 2615 | print(123, "hello") | ||
| 2616 | end | ||
| 2617 | do | ||
| 2618 | print(123, "hello") | ||
| 2619 | end | ||
| 2315 | if tb ~= nil then | 2620 | if tb ~= nil then |
| 2316 | tb:func() | 2621 | tb:func() |
| 2317 | end | 2622 | end |
| @@ -2344,6 +2649,21 @@ print((function() | |||
| 2344 | end)()) | 2649 | end)()) |
| 2345 | local tab = { } | 2650 | local tab = { } |
| 2346 | tab[#tab + 1] = "Value" | 2651 | tab[#tab + 1] = "Value" |
| 2652 | local tbA = { | ||
| 2653 | 1, | ||
| 2654 | 2, | ||
| 2655 | 3 | ||
| 2656 | } | ||
| 2657 | local tbB = { | ||
| 2658 | 4, | ||
| 2659 | 5, | ||
| 2660 | 6 | ||
| 2661 | } | ||
| 2662 | local _len_0 = #tbA + 1 | ||
| 2663 | for _index_0 = 1, #tbB do | ||
| 2664 | local _elm_0 = tbB[_index_0] | ||
| 2665 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2666 | end | ||
| 2347 | local parts = { | 2667 | local parts = { |
| 2348 | "shoulders", | 2668 | "shoulders", |
| 2349 | "knees" | 2669 | "knees" |
| @@ -2412,6 +2732,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 2412 | end | 2732 | end |
| 2413 | end | 2733 | end |
| 2414 | merge = _tab_0 | 2734 | merge = _tab_0 |
| 2735 | local last | ||
| 2736 | do | ||
| 2737 | local _item_0 = data.items | ||
| 2738 | last = _item_0[#_item_0] | ||
| 2739 | end | ||
| 2740 | local second_last | ||
| 2741 | do | ||
| 2742 | local _item_0 = data.items | ||
| 2743 | second_last = _item_0[#_item_0 - 1] | ||
| 2744 | end | ||
| 2745 | local _obj_0 = data.items | ||
| 2746 | _obj_0[#_obj_0] = 1 | ||
| 2415 | local mt = { } | 2747 | local mt = { } |
| 2416 | local add | 2748 | local add |
| 2417 | add = function(self, right) | 2749 | add = function(self, right) |
| @@ -2542,6 +2874,14 @@ func({ | |||
| 2542 | 2, | 2874 | 2, |
| 2543 | 3 | 2875 | 3 |
| 2544 | }) | 2876 | }) |
| 2877 | local f | ||
| 2878 | f = function() | ||
| 2879 | return { | ||
| 2880 | 1, | ||
| 2881 | 2, | ||
| 2882 | 3 | ||
| 2883 | } | ||
| 2884 | end | ||
| 2545 | local tb = { | 2885 | local tb = { |
| 2546 | name = "abc", | 2886 | name = "abc", |
| 2547 | values = { | 2887 | values = { |
| @@ -2782,6 +3122,59 @@ end | |||
| 2782 | local two, four | 3122 | local two, four |
| 2783 | local _obj_0 = items | 3123 | local _obj_0 = items |
| 2784 | two, four = _obj_0[2], _obj_0[4] | 3124 | two, four = _obj_0[2], _obj_0[4] |
| 3125 | local orders = { | ||
| 3126 | "first", | ||
| 3127 | "second", | ||
| 3128 | "third", | ||
| 3129 | "fourth", | ||
| 3130 | "last" | ||
| 3131 | } | ||
| 3132 | local first, bulk, last = orders[1], (function() | ||
| 3133 | local _accum_0 = { } | ||
| 3134 | local _len_0 = 1 | ||
| 3135 | local _max_0 = #orders + -2 + 1 | ||
| 3136 | for _index_0 = 2, _max_0 do | ||
| 3137 | local _item_0 = orders[_index_0] | ||
| 3138 | _accum_0[_len_0] = _item_0 | ||
| 3139 | _len_0 = _len_0 + 1 | ||
| 3140 | end | ||
| 3141 | return _accum_0 | ||
| 3142 | end)(), orders[#orders] | ||
| 3143 | print(first) | ||
| 3144 | print(bulk) | ||
| 3145 | print(last) | ||
| 3146 | local first, rest | ||
| 3147 | do | ||
| 3148 | local _obj_0 = orders | ||
| 3149 | first, rest = _obj_0[1], (function() | ||
| 3150 | local _accum_0 = { } | ||
| 3151 | local _len_0 = 1 | ||
| 3152 | local _max_0 = #_obj_0 | ||
| 3153 | for _index_0 = 2, _max_0 do | ||
| 3154 | local _item_0 = _obj_0[_index_0] | ||
| 3155 | _accum_0[_len_0] = _item_0 | ||
| 3156 | _len_0 = _len_0 + 1 | ||
| 3157 | end | ||
| 3158 | return _accum_0 | ||
| 3159 | end)() | ||
| 3160 | end | ||
| 3161 | local start, last | ||
| 3162 | do | ||
| 3163 | local _obj_0 = orders | ||
| 3164 | start, last = (function() | ||
| 3165 | local _accum_0 = { } | ||
| 3166 | local _len_0 = 1 | ||
| 3167 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 3168 | for _index_0 = 1, _max_0 do | ||
| 3169 | local _item_0 = _obj_0[_index_0] | ||
| 3170 | _accum_0[_len_0] = _item_0 | ||
| 3171 | _len_0 = _len_0 + 1 | ||
| 3172 | end | ||
| 3173 | return _accum_0 | ||
| 3174 | end)(), _obj_0[#_obj_0] | ||
| 3175 | end | ||
| 3176 | local _obj_0 = orders | ||
| 3177 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 2785 | local tuples = { | 3178 | local tuples = { |
| 2786 | { | 3179 | { |
| 2787 | "hello", | 3180 | "hello", |
| @@ -2846,6 +3239,36 @@ end | |||
| 2846 | local first = select(1, ...) | 3239 | local first = select(1, ...) |
| 2847 | return print(ok, count, first) | 3240 | return print(ok, count, first) |
| 2848 | end)(fn(true)) | 3241 | end)(fn(true)) |
| 3242 | local f | ||
| 3243 | f = function(...) | ||
| 3244 | local t = { | ||
| 3245 | n = select("#", ...), | ||
| 3246 | ... | ||
| 3247 | } | ||
| 3248 | print("傿•°ä¸ªæ•°:", t.n) | ||
| 3249 | print("表长度:", #t) | ||
| 3250 | for i = 1, t.n do | ||
| 3251 | print(t[i]) | ||
| 3252 | end | ||
| 3253 | end | ||
| 3254 | f(1, 2, 3) | ||
| 3255 | f("a", "b", "c", "d") | ||
| 3256 | f() | ||
| 3257 | local process | ||
| 3258 | process = function(...) | ||
| 3259 | local args = { | ||
| 3260 | n = select("#", ...), | ||
| 3261 | ... | ||
| 3262 | } | ||
| 3263 | local sum = 0 | ||
| 3264 | for i = 1, args.n do | ||
| 3265 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 3266 | sum = sum + args[i] | ||
| 3267 | end | ||
| 3268 | end | ||
| 3269 | return sum | ||
| 3270 | end | ||
| 3271 | process(1, nil, 3, nil, 5) | ||
| 2849 | Rx.Observable.fromRange(1, 8):filter(function(x) | 3272 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 2850 | return x % 2 == 0 | 3273 | return x % 2 == 0 |
| 2851 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 3274 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -2883,6 +3306,56 @@ end) | |||
| 2883 | if success then | 3306 | if success then |
| 2884 | print(result) | 3307 | print(result) |
| 2885 | end | 3308 | end |
| 3309 | local a, b, c | ||
| 3310 | do | ||
| 3311 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 3312 | return func() | ||
| 3313 | end) | ||
| 3314 | if _ok_0 then | ||
| 3315 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 3316 | end | ||
| 3317 | end | ||
| 3318 | do | ||
| 3319 | local _exp_0 = ((function() | ||
| 3320 | return (function(_arg_0, ...) | ||
| 3321 | local _ok_0 = _arg_0 | ||
| 3322 | if _ok_0 then | ||
| 3323 | return ... | ||
| 3324 | end | ||
| 3325 | end)(pcall(function() | ||
| 3326 | return func() | ||
| 3327 | end)) | ||
| 3328 | end)()) | ||
| 3329 | if _exp_0 ~= nil then | ||
| 3330 | a = _exp_0 | ||
| 3331 | else | ||
| 3332 | a = "default" | ||
| 3333 | end | ||
| 3334 | end | ||
| 3335 | f((function() | ||
| 3336 | return (function(_arg_0, ...) | ||
| 3337 | local _ok_0 = _arg_0 | ||
| 3338 | if _ok_0 then | ||
| 3339 | return ... | ||
| 3340 | end | ||
| 3341 | end)(pcall(function() | ||
| 3342 | return func() | ||
| 3343 | end)) | ||
| 3344 | end)()) | ||
| 3345 | f((function() | ||
| 3346 | return (function(_arg_0, ...) | ||
| 3347 | local _ok_0 = _arg_0 | ||
| 3348 | if _ok_0 then | ||
| 3349 | return ... | ||
| 3350 | end | ||
| 3351 | end)(xpcall(function() | ||
| 3352 | print(123) | ||
| 3353 | return func() | ||
| 3354 | end, function(e) | ||
| 3355 | print(e) | ||
| 3356 | return e | ||
| 3357 | end)) | ||
| 3358 | end)()) | ||
| 2886 | local a <const> = 123 | 3359 | local a <const> = 123 |
| 2887 | local _ <close> = setmetatable({ }, { | 3360 | local _ <close> = setmetatable({ }, { |
| 2888 | __close = function() | 3361 | __close = function() |
| @@ -2897,6 +3370,14 @@ local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" | |||
| 2897 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | 3370 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") |
| 2898 | local integer = 1000000 | 3371 | local integer = 1000000 |
| 2899 | local hex = 0xEFBBBF | 3372 | local hex = 0xEFBBBF |
| 3373 | local binary = 19 | ||
| 3374 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 3375 | local fn | ||
| 3376 | fn = function() | ||
| 3377 | local str = "foo:\n bar: baz" | ||
| 3378 | return str | ||
| 3379 | end | ||
| 3380 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 2900 | local my_function | 3381 | local my_function |
| 2901 | my_function = function() end | 3382 | my_function = function() end |
| 2902 | my_function() | 3383 | my_function() |
| @@ -2985,6 +3466,66 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
| 2985 | print("ä½ å¥½") | 3466 | print("ä½ å¥½") |
| 2986 | print("我在if内部") | 3467 | print("我在if内部") |
| 2987 | end | 3468 | end |
| 3469 | local f1 | ||
| 3470 | f1 = function(_arg_0) | ||
| 3471 | local a, b, c | ||
| 3472 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 3473 | return print(a, b, c) | ||
| 3474 | end | ||
| 3475 | f1({ | ||
| 3476 | a = 1, | ||
| 3477 | b = "2", | ||
| 3478 | c = { } | ||
| 3479 | }) | ||
| 3480 | local f2 | ||
| 3481 | f2 = function(_arg_0, c) | ||
| 3482 | local a1, b | ||
| 3483 | a1, b = _arg_0.a, _arg_0.b | ||
| 3484 | if a1 == nil then | ||
| 3485 | a1 = 123 | ||
| 3486 | end | ||
| 3487 | if b == nil then | ||
| 3488 | b = 'abc' | ||
| 3489 | end | ||
| 3490 | if c == nil then | ||
| 3491 | c = { } | ||
| 3492 | end | ||
| 3493 | return print(a1, b, c) | ||
| 3494 | end | ||
| 3495 | local arg1 = { | ||
| 3496 | a = 0 | ||
| 3497 | } | ||
| 3498 | f2(arg1, arg2) | ||
| 3499 | local findFirstEven | ||
| 3500 | findFirstEven = function(list) | ||
| 3501 | for _index_0 = 1, #list do | ||
| 3502 | local item = list[_index_0] | ||
| 3503 | if type(item) == "table" then | ||
| 3504 | for _index_1 = 1, #item do | ||
| 3505 | local sub = item[_index_1] | ||
| 3506 | if sub % 2 == 0 then | ||
| 3507 | return sub | ||
| 3508 | end | ||
| 3509 | end | ||
| 3510 | end | ||
| 3511 | end | ||
| 3512 | return nil | ||
| 3513 | end | ||
| 3514 | local findFirstEven | ||
| 3515 | findFirstEven = function(list) | ||
| 3516 | for _index_0 = 1, #list do | ||
| 3517 | local item = list[_index_0] | ||
| 3518 | if type(item) == "table" then | ||
| 3519 | for _index_1 = 1, #item do | ||
| 3520 | local sub = item[_index_1] | ||
| 3521 | if sub % 2 == 0 then | ||
| 3522 | return sub | ||
| 3523 | end | ||
| 3524 | end | ||
| 3525 | end | ||
| 3526 | end | ||
| 3527 | return nil | ||
| 3528 | end | ||
| 2988 | f(function() | 3529 | f(function() |
| 2989 | return print("hello") | 3530 | return print("hello") |
| 2990 | end) | 3531 | end) |
| @@ -3110,6 +3651,28 @@ for _index_0 = 1, #_list_0 do | |||
| 3110 | _len_0 = _len_0 + 1 | 3651 | _len_0 = _len_0 + 1 |
| 3111 | end | 3652 | end |
| 3112 | doubled = _accum_0 | 3653 | doubled = _accum_0 |
| 3654 | local data = { | ||
| 3655 | a = { | ||
| 3656 | 1, | ||
| 3657 | 2, | ||
| 3658 | 3 | ||
| 3659 | }, | ||
| 3660 | b = { | ||
| 3661 | 4, | ||
| 3662 | 5, | ||
| 3663 | 6 | ||
| 3664 | } | ||
| 3665 | } | ||
| 3666 | local flat | ||
| 3667 | local _accum_0 = { } | ||
| 3668 | for k, v in pairs(data) do | ||
| 3669 | local _len_0 = #_accum_0 + 1 | ||
| 3670 | for _index_0 = 1, #v do | ||
| 3671 | local _elm_0 = v[_index_0] | ||
| 3672 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 3673 | end | ||
| 3674 | end | ||
| 3675 | flat = _accum_0 | ||
| 3113 | local x_coords = { | 3676 | local x_coords = { |
| 3114 | 4, | 3677 | 4, |
| 3115 | 5, | 3678 | 5, |
| @@ -3200,8 +3763,7 @@ local slice | |||
| 3200 | local _accum_0 = { } | 3763 | local _accum_0 = { } |
| 3201 | local _len_0 = 1 | 3764 | local _len_0 = 1 |
| 3202 | local _list_0 = items | 3765 | local _list_0 = items |
| 3203 | local _max_0 = 5 | 3766 | for _index_0 = 1, 5 do |
| 3204 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3205 | local item = _list_0[_index_0] | 3767 | local item = _list_0[_index_0] |
| 3206 | _accum_0[_len_0] = item | 3768 | _accum_0[_len_0] = item |
| 3207 | _len_0 = _len_0 + 1 | 3769 | _len_0 = _len_0 + 1 |
| @@ -3211,7 +3773,8 @@ local slice | |||
| 3211 | local _accum_0 = { } | 3773 | local _accum_0 = { } |
| 3212 | local _len_0 = 1 | 3774 | local _len_0 = 1 |
| 3213 | local _list_0 = items | 3775 | local _list_0 = items |
| 3214 | for _index_0 = 2, #_list_0 do | 3776 | local _max_0 = #_list_0 |
| 3777 | for _index_0 = 2, _max_0 do | ||
| 3215 | local item = _list_0[_index_0] | 3778 | local item = _list_0[_index_0] |
| 3216 | _accum_0[_len_0] = item | 3779 | _accum_0[_len_0] = item |
| 3217 | _len_0 = _len_0 + 1 | 3780 | _len_0 = _len_0 + 1 |
| @@ -3221,12 +3784,46 @@ local slice | |||
| 3221 | local _accum_0 = { } | 3784 | local _accum_0 = { } |
| 3222 | local _len_0 = 1 | 3785 | local _len_0 = 1 |
| 3223 | local _list_0 = items | 3786 | local _list_0 = items |
| 3224 | for _index_0 = 1, #_list_0, 2 do | 3787 | local _max_0 = #_list_0 |
| 3788 | for _index_0 = 1, _max_0, 2 do | ||
| 3225 | local item = _list_0[_index_0] | 3789 | local item = _list_0[_index_0] |
| 3226 | _accum_0[_len_0] = item | 3790 | _accum_0[_len_0] = item |
| 3227 | _len_0 = _len_0 + 1 | 3791 | _len_0 = _len_0 + 1 |
| 3228 | end | 3792 | end |
| 3229 | slice = _accum_0 | 3793 | slice = _accum_0 |
| 3794 | local slice | ||
| 3795 | local _accum_0 = { } | ||
| 3796 | local _len_0 = 1 | ||
| 3797 | local _list_0 = items | ||
| 3798 | local _min_0 = #_list_0 + -4 + 1 | ||
| 3799 | local _max_0 = #_list_0 + -1 + 1 | ||
| 3800 | for _index_0 = _min_0, _max_0 do | ||
| 3801 | local item = _list_0[_index_0] | ||
| 3802 | _accum_0[_len_0] = item | ||
| 3803 | _len_0 = _len_0 + 1 | ||
| 3804 | end | ||
| 3805 | slice = _accum_0 | ||
| 3806 | local reverse_slice | ||
| 3807 | local _accum_0 = { } | ||
| 3808 | local _len_0 = 1 | ||
| 3809 | local _list_0 = items | ||
| 3810 | local _min_0 = #_list_0 + -1 + 1 | ||
| 3811 | for _index_0 = _min_0, 1, -1 do | ||
| 3812 | local item = _list_0[_index_0] | ||
| 3813 | _accum_0[_len_0] = item | ||
| 3814 | _len_0 = _len_0 + 1 | ||
| 3815 | end | ||
| 3816 | reverse_slice = _accum_0 | ||
| 3817 | local sub_list | ||
| 3818 | local _accum_0 = { } | ||
| 3819 | local _len_0 = 1 | ||
| 3820 | local _list_0 = items | ||
| 3821 | for _index_0 = 2, 4 do | ||
| 3822 | local _item_0 = _list_0[_index_0] | ||
| 3823 | _accum_0[_len_0] = _item_0 | ||
| 3824 | _len_0 = _len_0 + 1 | ||
| 3825 | end | ||
| 3826 | sub_list = _accum_0 | ||
| 3230 | for i = 10, 20 do | 3827 | for i = 10, 20 do |
| 3231 | print(i) | 3828 | print(i) |
| 3232 | end | 3829 | end |
| @@ -3237,8 +3834,7 @@ for key, value in pairs(object) do | |||
| 3237 | print(key, value) | 3834 | print(key, value) |
| 3238 | end | 3835 | end |
| 3239 | local _list_0 = items | 3836 | local _list_0 = items |
| 3240 | local _max_0 = 4 | 3837 | for _index_0 = 2, 4 do |
| 3241 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3242 | local item = _list_0[_index_0] | 3838 | local item = _list_0[_index_0] |
| 3243 | print(item) | 3839 | print(item) |
| 3244 | end | 3840 | end |
| @@ -3422,7 +4018,7 @@ if "Robert" == name then | |||
| 3422 | elseif "Dan" == name or "Daniel" == name then | 4018 | elseif "Dan" == name or "Daniel" == name then |
| 3423 | print("ä½ çš„åå—æ˜¯Dan") | 4019 | print("ä½ çš„åå—æ˜¯Dan") |
| 3424 | else | 4020 | else |
| 3425 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 4021 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
| 3426 | end | 4022 | end |
| 3427 | local b = 1 | 4023 | local b = 1 |
| 3428 | local next_number | 4024 | local next_number |
| @@ -3679,6 +4275,35 @@ if _tab_0 then | |||
| 3679 | print("åŒ¹é…æˆåŠŸ", fourth) | 4275 | print("åŒ¹é…æˆåŠŸ", fourth) |
| 3680 | end | 4276 | end |
| 3681 | end | 4277 | end |
| 4278 | local segments = { | ||
| 4279 | "admin", | ||
| 4280 | "users", | ||
| 4281 | "logs", | ||
| 4282 | "view" | ||
| 4283 | } | ||
| 4284 | local _type_0 = type(segments) | ||
| 4285 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4286 | if _tab_0 then | ||
| 4287 | local groups | ||
| 4288 | do | ||
| 4289 | local _accum_0 = { } | ||
| 4290 | local _len_0 = 1 | ||
| 4291 | local _max_0 = #segments + -3 + 1 | ||
| 4292 | for _index_0 = 1, _max_0 do | ||
| 4293 | local _item_0 = segments[_index_0] | ||
| 4294 | _accum_0[_len_0] = _item_0 | ||
| 4295 | _len_0 = _len_0 + 1 | ||
| 4296 | end | ||
| 4297 | groups = _accum_0 | ||
| 4298 | end | ||
| 4299 | local resource = segments[#segments - 1] | ||
| 4300 | local action = segments[#segments] | ||
| 4301 | if resource ~= nil and action ~= nil then | ||
| 4302 | print("Group:", groups) | ||
| 4303 | print("Resource:", resource) | ||
| 4304 | print("Action:", action) | ||
| 4305 | end | ||
| 4306 | end | ||
| 3682 | local Inventory | 4307 | local Inventory |
| 3683 | local _class_0 | 4308 | local _class_0 |
| 3684 | local _base_0 = { | 4309 | local _base_0 = { |
| @@ -4335,6 +4960,10 @@ do | |||
| 4335 | _with_1["key-name"] = value | 4960 | _with_1["key-name"] = value |
| 4336 | end | 4961 | end |
| 4337 | _with_0[#_with_0 + 1] = "abc" | 4962 | _with_0[#_with_0 + 1] = "abc" |
| 4963 | local _with_0 = obj | ||
| 4964 | if _with_0 ~= nil then | ||
| 4965 | print(obj.name) | ||
| 4966 | end | ||
| 4338 | do | 4967 | do |
| 4339 | local var = "hello" | 4968 | local var = "hello" |
| 4340 | print(var) | 4969 | print(var) |
diff --git a/spec/outputs/comprehension.lua b/spec/outputs/comprehension.lua index 9a7c478..663bd44 100644 --- a/spec/outputs/comprehension.lua +++ b/spec/outputs/comprehension.lua | |||
| @@ -243,8 +243,11 @@ end | |||
| 243 | do | 243 | do |
| 244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
| 245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
| 246 | local _min_0 = 1 + 2 | ||
| 246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
| 247 | for _index_0 = 1 + 2, _max_0 < 0 and #items + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
| 249 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
| 250 | for _index_0 = _min_0, _max_0 do | ||
| 248 | local item = items[_index_0] | 251 | local item = items[_index_0] |
| 249 | _accum_0[_len_0] = item | 252 | _accum_0[_len_0] = item |
| 250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
| @@ -254,8 +257,11 @@ end | |||
| 254 | do | 257 | do |
| 255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
| 256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
| 260 | local _min_0 = hello() * 4 | ||
| 257 | local _max_0 = 2 - thing[4] | 261 | local _max_0 = 2 - thing[4] |
| 258 | for _index_0 = hello() * 4, _max_0 < 0 and #items + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #items + _min_0 + 1 or _min_0 |
| 263 | _max_0 = _max_0 < 0 and #items + _max_0 + 1 or _max_0 | ||
| 264 | for _index_0 = _min_0, _max_0 do | ||
| 259 | local item = items[_index_0] | 265 | local item = items[_index_0] |
| 260 | _accum_0[_len_0] = item | 266 | _accum_0[_len_0] = item |
| 261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/destructure.lua b/spec/outputs/destructure.lua index 44da58b..4e19aca 100644 --- a/spec/outputs/destructure.lua +++ b/spec/outputs/destructure.lua | |||
| @@ -621,4 +621,114 @@ do | |||
| 621 | print(meta_field, abc, def) | 621 | print(meta_field, abc, def) |
| 622 | end | 622 | end |
| 623 | end | 623 | end |
| 624 | do | ||
| 625 | local clients = { | ||
| 626 | "VIP_Alice", | ||
| 627 | "User_Bob", | ||
| 628 | "User_Clara", | ||
| 629 | "VIP_Eva" | ||
| 630 | } | ||
| 631 | local vipStart, regulars, vipEnd = clients[1], (function() | ||
| 632 | local _accum_0 = { } | ||
| 633 | local _len_0 = 1 | ||
| 634 | local _max_0 = #clients + -2 + 1 | ||
| 635 | for _index_0 = 2, _max_0 do | ||
| 636 | local _item_0 = clients[_index_0] | ||
| 637 | _accum_0[_len_0] = _item_0 | ||
| 638 | _len_0 = _len_0 + 1 | ||
| 639 | end | ||
| 640 | return _accum_0 | ||
| 641 | end)(), clients[#clients] | ||
| 642 | print(vipStart) | ||
| 643 | print(regulars) | ||
| 644 | print(vipEnd) | ||
| 645 | end | ||
| 646 | do | ||
| 647 | local setupMeeting | ||
| 648 | setupMeeting = function(participants) | ||
| 649 | local chair, secretary = participants[1], participants[#participants] | ||
| 650 | return print(chair, secretary) | ||
| 651 | end | ||
| 652 | setupMeeting({ | ||
| 653 | "Alice", | ||
| 654 | "Bob", | ||
| 655 | "Charlie", | ||
| 656 | "David" | ||
| 657 | }) | ||
| 658 | end | ||
| 659 | do | ||
| 660 | local getTransactions | ||
| 661 | getTransactions = function() | ||
| 662 | return { | ||
| 663 | { | ||
| 664 | id = "T1", | ||
| 665 | amount = 100 | ||
| 666 | }, | ||
| 667 | { | ||
| 668 | id = "T2", | ||
| 669 | amount = 200 | ||
| 670 | }, | ||
| 671 | { | ||
| 672 | id = "T3", | ||
| 673 | amount = 300 | ||
| 674 | } | ||
| 675 | } | ||
| 676 | end | ||
| 677 | local id, amount | ||
| 678 | do | ||
| 679 | local _item_0 = getTransactions() | ||
| 680 | local _obj_0 = _item_0[#_item_0] | ||
| 681 | id, amount = _obj_0.id, _obj_0.amount | ||
| 682 | end | ||
| 683 | assert(id == "T3") | ||
| 684 | assert(amount == 300) | ||
| 685 | end | ||
| 686 | do | ||
| 687 | local middle | ||
| 688 | local _accum_0 = { } | ||
| 689 | local _len_0 = 1 | ||
| 690 | local _list_0 = tb | ||
| 691 | local _max_0 = #_list_0 + -2 + 1 | ||
| 692 | for _index_0 = 2, _max_0 do | ||
| 693 | local _item_0 = _list_0[_index_0] | ||
| 694 | _accum_0[_len_0] = _item_0 | ||
| 695 | _len_0 = _len_0 + 1 | ||
| 696 | end | ||
| 697 | middle = _accum_0 | ||
| 698 | end | ||
| 699 | do | ||
| 700 | local a, abc, b, def, sub, d, e | ||
| 701 | local _obj_0 = tb | ||
| 702 | a, abc, b, def, sub, d, e = _obj_0[1], _obj_0.abc, _obj_0[2], _obj_0.def, (function() | ||
| 703 | local _accum_0 = { } | ||
| 704 | local _len_0 = 1 | ||
| 705 | local _max_0 = #_obj_0 + -3 + 1 | ||
| 706 | for _index_0 = 3, _max_0 do | ||
| 707 | local _item_0 = _obj_0[_index_0] | ||
| 708 | _accum_0[_len_0] = _item_0 | ||
| 709 | _len_0 = _len_0 + 1 | ||
| 710 | end | ||
| 711 | return _accum_0 | ||
| 712 | end)(), _obj_0[#_obj_0 - 1], _obj_0[#_obj_0] | ||
| 713 | end | ||
| 714 | do | ||
| 715 | local _list_0 = items | ||
| 716 | for _index_0 = 1, #_list_0 do | ||
| 717 | local _des_0 = _list_0[_index_0] | ||
| 718 | local a, b = _des_0.a, _des_0.b | ||
| 719 | print(a, b) | ||
| 720 | end | ||
| 721 | local _list_1 = items | ||
| 722 | for _index_0 = 1, #_list_1 do | ||
| 723 | local _des_0 = _list_1[_index_0] | ||
| 724 | local a, b = _des_0.a, _des_0.b | ||
| 725 | print(a, b) | ||
| 726 | end | ||
| 727 | for _des_0 in pairs(data) do | ||
| 728 | local body = _des_0.body | ||
| 729 | if body then | ||
| 730 | print(body) | ||
| 731 | end | ||
| 732 | end | ||
| 733 | end | ||
| 624 | return nil | 734 | return nil |
diff --git a/spec/outputs/funcs.lua b/spec/outputs/funcs.lua index c1735c4..db7ed67 100644 --- a/spec/outputs/funcs.lua +++ b/spec/outputs/funcs.lua | |||
| @@ -283,4 +283,157 @@ do | |||
| 283 | end | 283 | end |
| 284 | print(func()) | 284 | print(func()) |
| 285 | end | 285 | end |
| 286 | local _anon_func_0 = function(_arg_0) | ||
| 287 | local _accum_0 = { } | ||
| 288 | local _len_0 = 1 | ||
| 289 | local _max_0 = #_arg_0 | ||
| 290 | for _index_0 = 1, _max_0 do | ||
| 291 | local _item_0 = _arg_0[_index_0] | ||
| 292 | _accum_0[_len_0] = _item_0 | ||
| 293 | _len_0 = _len_0 + 1 | ||
| 294 | end | ||
| 295 | return _accum_0 | ||
| 296 | end | ||
| 297 | do | ||
| 298 | local f | ||
| 299 | f = function(_arg_0) | ||
| 300 | local a, b, c | ||
| 301 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 302 | return print(a, b, c) | ||
| 303 | end | ||
| 304 | f = function(_arg_0) | ||
| 305 | local a, b, c | ||
| 306 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 307 | return print(a, b, c) | ||
| 308 | end | ||
| 309 | local g | ||
| 310 | g = function(x, _arg_0) | ||
| 311 | local y | ||
| 312 | y = _arg_0.y | ||
| 313 | return print(x, y) | ||
| 314 | end | ||
| 315 | local i | ||
| 316 | i = function(_arg_0) | ||
| 317 | local ax, by | ||
| 318 | ax, by = _arg_0.a, _arg_0.b | ||
| 319 | if ax == nil then | ||
| 320 | ax = 0 | ||
| 321 | end | ||
| 322 | if by == nil then | ||
| 323 | by = 0 | ||
| 324 | end | ||
| 325 | return print(ax, by) | ||
| 326 | end | ||
| 327 | j = function(name, _arg_0) | ||
| 328 | local uid, role | ||
| 329 | uid, role = _arg_0.id, _arg_0.role | ||
| 330 | if uid == nil then | ||
| 331 | uid = "n/a" | ||
| 332 | end | ||
| 333 | if role == nil then | ||
| 334 | role = "guest" | ||
| 335 | end | ||
| 336 | return print(name, uid, role) | ||
| 337 | end | ||
| 338 | local m | ||
| 339 | m = function(_arg_0) | ||
| 340 | local name, age, ver | ||
| 341 | name, age, ver = _arg_0.user.name, _arg_0.user.age, _arg_0.meta.ver | ||
| 342 | if ver == nil then | ||
| 343 | ver = 1 | ||
| 344 | end | ||
| 345 | return print(name, age, ver) | ||
| 346 | end | ||
| 347 | local m1 | ||
| 348 | m1 = function(_arg_0) | ||
| 349 | local name, age, meta | ||
| 350 | name, age, meta = _arg_0.user.name, _arg_0.user.age, _arg_0.meta | ||
| 351 | if meta == nil then | ||
| 352 | meta = { } | ||
| 353 | end | ||
| 354 | return print(name, age, meta and meta.ver or "nil") | ||
| 355 | end | ||
| 356 | local new | ||
| 357 | new = function(self, _arg_0) | ||
| 358 | local name, age | ||
| 359 | name, age = _arg_0.name, _arg_0.age | ||
| 360 | if name == nil then | ||
| 361 | name = "anon" | ||
| 362 | end | ||
| 363 | if age == nil then | ||
| 364 | age = 0 | ||
| 365 | end | ||
| 366 | self.name = name | ||
| 367 | self.age = age | ||
| 368 | end | ||
| 369 | local set | ||
| 370 | set = function(self, _arg_0) | ||
| 371 | local name, age | ||
| 372 | name, age = _arg_0.name, _arg_0.age | ||
| 373 | if name == nil then | ||
| 374 | name = self.name | ||
| 375 | end | ||
| 376 | if age == nil then | ||
| 377 | age = self.age | ||
| 378 | end | ||
| 379 | self.name = name | ||
| 380 | self.age = age | ||
| 381 | end | ||
| 382 | local logKV | ||
| 383 | logKV = function(_arg_0, ...) | ||
| 384 | local k, v | ||
| 385 | k, v = _arg_0.k, _arg_0.v | ||
| 386 | print("kv:", k, v) | ||
| 387 | return print("rest count:", select("#", ...)) | ||
| 388 | end | ||
| 389 | do | ||
| 390 | local foo | ||
| 391 | foo = function(_arg_0) | ||
| 392 | local a, b | ||
| 393 | a, b = _arg_0.a, _arg_0.b | ||
| 394 | if b == nil then | ||
| 395 | b = 0 | ||
| 396 | end | ||
| 397 | return print(a, b) | ||
| 398 | end | ||
| 399 | end | ||
| 400 | local t1 | ||
| 401 | t1 = function(_arg_0, x) | ||
| 402 | local a | ||
| 403 | a = _arg_0.a | ||
| 404 | return print(a, x) | ||
| 405 | end | ||
| 406 | local t2 | ||
| 407 | t2 = function(_arg_0) | ||
| 408 | local a | ||
| 409 | a = _arg_0.a | ||
| 410 | return print(a) | ||
| 411 | end | ||
| 412 | local w | ||
| 413 | w = function(id, _arg_0, _arg_1) | ||
| 414 | local x, y | ||
| 415 | x, y = _arg_0.x, _arg_0.y | ||
| 416 | if x == nil then | ||
| 417 | x = 0 | ||
| 418 | end | ||
| 419 | if y == nil then | ||
| 420 | y = 0 | ||
| 421 | end | ||
| 422 | local flag | ||
| 423 | flag = _arg_1.flag | ||
| 424 | return print(id, x, y, flag) | ||
| 425 | end | ||
| 426 | local g1 | ||
| 427 | g1 = function(_arg_0) | ||
| 428 | local a, ax | ||
| 429 | a, ax = _arg_0.a, _arg_0.a | ||
| 430 | return print(a, ax) | ||
| 431 | end | ||
| 432 | local g4 | ||
| 433 | g4 = function(_arg_0) | ||
| 434 | local a, b, rest | ||
| 435 | a, b, rest = _arg_0.a, _arg_0.b, _anon_func_0(_arg_0) | ||
| 436 | return print(a, b) | ||
| 437 | end | ||
| 438 | end | ||
| 286 | return nil | 439 | return nil |
diff --git a/spec/outputs/import.lua b/spec/outputs/import.lua index 83c99e2..7aa130f 100644 --- a/spec/outputs/import.lua +++ b/spec/outputs/import.lua | |||
| @@ -166,3 +166,13 @@ do | |||
| 166 | local _obj_1 = require("m") | 166 | local _obj_1 = require("m") |
| 167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close | 167 | g, i = _obj_1[1], getmetatable(_obj_1[2]).__close |
| 168 | end | 168 | end |
| 169 | do | ||
| 170 | local require <const> = require | ||
| 171 | local stringlib <const> = string | ||
| 172 | local format <const> = string.format | ||
| 173 | local io_read <const> = io.read | ||
| 174 | local type | ||
| 175 | type = function() end | ||
| 176 | local tp <const> = _G.type | ||
| 177 | local yue <const> = _G["月"] | ||
| 178 | end | ||
diff --git a/spec/outputs/lists.lua b/spec/outputs/lists.lua index 48ec9c8..75f04fa 100644 --- a/spec/outputs/lists.lua +++ b/spec/outputs/lists.lua | |||
| @@ -230,31 +230,36 @@ x = { | |||
| 230 | 6, | 230 | 6, |
| 231 | 7 | 231 | 7 |
| 232 | } | 232 | } |
| 233 | local _max_0 = -5 | 233 | local _max_0 = #x + -5 + 1 |
| 234 | for _index_0 = 2, _max_0 < 0 and #x + _max_0 or _max_0, 2 do | 234 | for _index_0 = 2, _max_0, 2 do |
| 235 | local y = x[_index_0] | 235 | local y = x[_index_0] |
| 236 | print(y) | 236 | print(y) |
| 237 | end | 237 | end |
| 238 | local _max_1 = 3 | 238 | for _index_0 = 1, 3 do |
| 239 | for _index_0 = 1, _max_1 < 0 and #x + _max_1 or _max_1 do | ||
| 240 | local y = x[_index_0] | 239 | local y = x[_index_0] |
| 241 | print(y) | 240 | print(y) |
| 242 | end | 241 | end |
| 243 | for _index_0 = 2, #x do | 242 | local _max_1 = #x |
| 243 | for _index_0 = 2, _max_1 do | ||
| 244 | local y = x[_index_0] | 244 | local y = x[_index_0] |
| 245 | print(y) | 245 | print(y) |
| 246 | end | 246 | end |
| 247 | for _index_0 = 1, #x, 2 do | 247 | local _max_2 = #x |
| 248 | for _index_0 = 1, _max_2, 2 do | ||
| 248 | local y = x[_index_0] | 249 | local y = x[_index_0] |
| 249 | print(y) | 250 | print(y) |
| 250 | end | 251 | end |
| 251 | for _index_0 = 2, #x, 2 do | 252 | local _max_3 = #x |
| 253 | for _index_0 = 2, _max_3, 2 do | ||
| 252 | local y = x[_index_0] | 254 | local y = x[_index_0] |
| 253 | print(y) | 255 | print(y) |
| 254 | end | 256 | end |
| 255 | local a, b, c = 1, 5, 2 | 257 | local a, b, c = 1, 5, 2 |
| 256 | local _max_2 = b | 258 | local _min_0 = a |
| 257 | for _index_0 = a, _max_2 < 0 and #x + _max_2 or _max_2, c do | 259 | local _max_4 = b |
| 260 | _min_0 = _min_0 < 0 and #x + _min_0 + 1 or _min_0 | ||
| 261 | _max_4 = _max_4 < 0 and #x + _max_4 + 1 or _max_4 | ||
| 262 | for _index_0 = _min_0, _max_4, c do | ||
| 258 | local y = x[_index_0] | 263 | local y = x[_index_0] |
| 259 | print(y) | 264 | print(y) |
| 260 | end | 265 | end |
| @@ -287,7 +292,10 @@ do | |||
| 287 | a | 292 | a |
| 288 | }) | 293 | }) |
| 289 | local _list_0 = f | 294 | local _list_0 = f |
| 290 | for _index_0 = a, #_list_0 do | 295 | local _min_1 = a |
| 296 | local _max_5 = #_list_0 | ||
| 297 | _min_1 = _min_1 < 0 and #_list_0 + _min_1 + 1 or _min_1 | ||
| 298 | for _index_0 = _min_1, _max_5 do | ||
| 291 | local v = _list_0[_index_0] | 299 | local v = _list_0[_index_0] |
| 292 | print(v) | 300 | print(v) |
| 293 | end | 301 | end |
| @@ -327,4 +335,570 @@ do | |||
| 327 | job = "jobless" | 335 | job = "jobless" |
| 328 | end | 336 | end |
| 329 | end | 337 | end |
| 338 | do | ||
| 339 | local transactions = { | ||
| 340 | "T001", | ||
| 341 | "T002", | ||
| 342 | "T003", | ||
| 343 | "T004", | ||
| 344 | "T005" | ||
| 345 | } | ||
| 346 | local middleTransactions | ||
| 347 | do | ||
| 348 | local _accum_0 = { } | ||
| 349 | local _len_0 = 1 | ||
| 350 | local _max_5 = #transactions + -2 + 1 | ||
| 351 | for _index_0 = 2, _max_5 do | ||
| 352 | local _item_0 = transactions[_index_0] | ||
| 353 | _accum_0[_len_0] = _item_0 | ||
| 354 | _len_0 = _len_0 + 1 | ||
| 355 | end | ||
| 356 | middleTransactions = _accum_0 | ||
| 357 | end | ||
| 358 | print(middleTransactions) | ||
| 359 | end | ||
| 360 | do | ||
| 361 | local logs = { | ||
| 362 | { | ||
| 363 | start = 0, | ||
| 364 | ["end"] = 100 | ||
| 365 | }, | ||
| 366 | { | ||
| 367 | start = 100, | ||
| 368 | ["end"] = 200 | ||
| 369 | }, | ||
| 370 | { | ||
| 371 | start = 200, | ||
| 372 | ["end"] = 123 | ||
| 373 | } | ||
| 374 | } | ||
| 375 | print(logs[#logs]["end"]) | ||
| 376 | end | ||
| 377 | do | ||
| 378 | local pendingOrders = { | ||
| 379 | "O001", | ||
| 380 | "O002", | ||
| 381 | "O003", | ||
| 382 | "O004" | ||
| 383 | } | ||
| 384 | print(pendingOrders[#pendingOrders - 1]) | ||
| 385 | end | ||
| 386 | do | ||
| 387 | local getOrders | ||
| 388 | getOrders = function() | ||
| 389 | return { | ||
| 390 | { | ||
| 391 | id = "O1001", | ||
| 392 | status = "pending" | ||
| 393 | }, | ||
| 394 | { | ||
| 395 | id = "O1002", | ||
| 396 | status = "processing" | ||
| 397 | }, | ||
| 398 | { | ||
| 399 | id = "O1003", | ||
| 400 | status = "done" | ||
| 401 | } | ||
| 402 | } | ||
| 403 | end | ||
| 404 | local lastStatus | ||
| 405 | do | ||
| 406 | local _item_0 = getOrders() | ||
| 407 | lastStatus = _item_0[#_item_0].status | ||
| 408 | end | ||
| 409 | assert(lastStatus == "done") | ||
| 410 | end | ||
| 411 | do | ||
| 412 | local cloneList1 | ||
| 413 | cloneList1 = function(list) | ||
| 414 | local _accum_0 = { } | ||
| 415 | local _len_0 = 1 | ||
| 416 | local _max_5 = #list | ||
| 417 | for _index_0 = 1, _max_5 do | ||
| 418 | local _item_0 = list[_index_0] | ||
| 419 | _accum_0[_len_0] = _item_0 | ||
| 420 | _len_0 = _len_0 + 1 | ||
| 421 | end | ||
| 422 | return _accum_0 | ||
| 423 | end | ||
| 424 | local cloneList2 | ||
| 425 | cloneList2 = function(list) | ||
| 426 | local _tab_0 = { } | ||
| 427 | local _idx_0 = #_tab_0 + 1 | ||
| 428 | for _index_0 = 1, #list do | ||
| 429 | local _value_0 = list[_index_0] | ||
| 430 | _tab_0[_idx_0] = _value_0 | ||
| 431 | _idx_0 = _idx_0 + 1 | ||
| 432 | end | ||
| 433 | return _tab_0 | ||
| 434 | end | ||
| 435 | local cloneTable | ||
| 436 | cloneTable = function(tb) | ||
| 437 | local _tab_0 = { } | ||
| 438 | local _idx_0 = 1 | ||
| 439 | for _key_0, _value_0 in pairs(tb) do | ||
| 440 | if _idx_0 == _key_0 then | ||
| 441 | _tab_0[#_tab_0 + 1] = _value_0 | ||
| 442 | _idx_0 = _idx_0 + 1 | ||
| 443 | else | ||
| 444 | _tab_0[_key_0] = _value_0 | ||
| 445 | end | ||
| 446 | end | ||
| 447 | return _tab_0 | ||
| 448 | end | ||
| 449 | end | ||
| 450 | do | ||
| 451 | print((function() | ||
| 452 | local _item_0 = globalTB | ||
| 453 | return _item_0[#_item_0] | ||
| 454 | end)(), (function() | ||
| 455 | local _item_0 = a.b.c | ||
| 456 | return _item_0[#_item_0 - 2] | ||
| 457 | end)(), (function() | ||
| 458 | if x ~= nil then | ||
| 459 | local _obj_0 = x.y | ||
| 460 | if _obj_0 ~= nil then | ||
| 461 | local _obj_1 = _obj_0(x).z | ||
| 462 | if _obj_1 ~= nil then | ||
| 463 | return _obj_1[#_obj_1 - 3] | ||
| 464 | end | ||
| 465 | return nil | ||
| 466 | end | ||
| 467 | return nil | ||
| 468 | end | ||
| 469 | return nil | ||
| 470 | end)()) | ||
| 471 | end | ||
| 472 | local _anon_func_0 = function(globalTB) | ||
| 473 | local _call_0 | ||
| 474 | do | ||
| 475 | local _item_0 = globalTB | ||
| 476 | _call_0 = _item_0[#_item_0] | ||
| 477 | end | ||
| 478 | return _call_0["end"](_call_0, 123) | ||
| 479 | end | ||
| 480 | local _anon_func_1 = function(a) | ||
| 481 | local _item_0 | ||
| 482 | do | ||
| 483 | local _accum_0 = { } | ||
| 484 | local _len_0 = 1 | ||
| 485 | local _list_0 = a.b.c | ||
| 486 | local _max_5 = #_list_0 + -5 + 1 | ||
| 487 | for _index_0 = 5, _max_5 do | ||
| 488 | local _item_1 = _list_0[_index_0] | ||
| 489 | _accum_0[_len_0] = _item_1 | ||
| 490 | _len_0 = _len_0 + 1 | ||
| 491 | end | ||
| 492 | _item_0 = _accum_0 | ||
| 493 | end | ||
| 494 | return _item_0[#_item_0 - 2] | ||
| 495 | end | ||
| 496 | local _anon_func_2 = function(x) | ||
| 497 | if x ~= nil then | ||
| 498 | local _obj_0 = x.y | ||
| 499 | if _obj_0 ~= nil then | ||
| 500 | local _obj_1 = _obj_0(x).z | ||
| 501 | if _obj_1 ~= nil then | ||
| 502 | local _obj_2 = _obj_1[#_obj_1 - 3] | ||
| 503 | if _obj_2 ~= nil then | ||
| 504 | local _accum_0 = { } | ||
| 505 | local _len_0 = 1 | ||
| 506 | local _max_5 = #_obj_2 + -3 + 1 | ||
| 507 | for _index_0 = 1, _max_5 do | ||
| 508 | local _item_0 = _obj_2[_index_0] | ||
| 509 | _accum_0[_len_0] = _item_0 | ||
| 510 | _len_0 = _len_0 + 1 | ||
| 511 | end | ||
| 512 | return _accum_0 | ||
| 513 | end | ||
| 514 | return nil | ||
| 515 | end | ||
| 516 | return nil | ||
| 517 | end | ||
| 518 | return nil | ||
| 519 | end | ||
| 520 | return nil | ||
| 521 | end | ||
| 522 | do | ||
| 523 | local f | ||
| 524 | f = function() | ||
| 525 | return print(_anon_func_0(globalTB), _anon_func_1(a), _anon_func_2(x)) | ||
| 526 | end | ||
| 527 | end | ||
| 528 | do | ||
| 529 | local tb = { | ||
| 530 | 1, | ||
| 531 | 2, | ||
| 532 | 3 | ||
| 533 | } | ||
| 534 | tb[#tb] = 40 | ||
| 535 | tb[#tb - 1] = 20 | ||
| 536 | end | ||
| 537 | do | ||
| 538 | a = "x" | ||
| 539 | b = a | ||
| 540 | c = a | ||
| 541 | local lst = { } | ||
| 542 | lst[#lst] = a | ||
| 543 | lst[#lst - 1] = b | ||
| 544 | end | ||
| 545 | do | ||
| 546 | local y, z | ||
| 547 | x, y, z = 1, 2, 3 | ||
| 548 | local arr = { } | ||
| 549 | local head | ||
| 550 | arr[#arr], head = x, y | ||
| 551 | arr[#arr] = z | ||
| 552 | end | ||
| 553 | do | ||
| 554 | local triple = { | ||
| 555 | "keep", | ||
| 556 | "skip", | ||
| 557 | "tail" | ||
| 558 | } | ||
| 559 | local head, tailv = triple[1], triple[3] | ||
| 560 | local buf = { } | ||
| 561 | buf[#buf] = head | ||
| 562 | buf[#buf] = tailv | ||
| 563 | end | ||
| 564 | do | ||
| 565 | local src = { | ||
| 566 | "a", | ||
| 567 | "", | ||
| 568 | "c", | ||
| 569 | nil, | ||
| 570 | "d" | ||
| 571 | } | ||
| 572 | local collected = { } | ||
| 573 | for _index_0 = 1, #src do | ||
| 574 | local item = src[_index_0] | ||
| 575 | if item and #item > 0 then | ||
| 576 | collected[#collected] = item | ||
| 577 | end | ||
| 578 | end | ||
| 579 | end | ||
| 580 | do | ||
| 581 | local nums = { | ||
| 582 | 1, | ||
| 583 | 2, | ||
| 584 | 3, | ||
| 585 | 4, | ||
| 586 | 5 | ||
| 587 | } | ||
| 588 | local last_two | ||
| 589 | do | ||
| 590 | local _accum_0 = { } | ||
| 591 | local _len_0 = 1 | ||
| 592 | for _index_0 = 1, #nums do | ||
| 593 | local v = nums[_index_0] | ||
| 594 | if v > 3 then | ||
| 595 | _accum_0[_len_0] = v | ||
| 596 | _len_0 = _len_0 + 1 | ||
| 597 | end | ||
| 598 | end | ||
| 599 | last_two = _accum_0 | ||
| 600 | end | ||
| 601 | nums[#nums] = last_two[1] | ||
| 602 | nums[#nums] = last_two[2] | ||
| 603 | end | ||
| 604 | do | ||
| 605 | local store = { } | ||
| 606 | store[#store] = { | ||
| 607 | meta = { | ||
| 608 | id = 1, | ||
| 609 | ok = true | ||
| 610 | }, | ||
| 611 | payload = { | ||
| 612 | 10, | ||
| 613 | 20 | ||
| 614 | } | ||
| 615 | } | ||
| 616 | store[#store] = { | ||
| 617 | meta = { | ||
| 618 | id = 1, | ||
| 619 | ok = false | ||
| 620 | }, | ||
| 621 | payload = { | ||
| 622 | 10, | ||
| 623 | 20, | ||
| 624 | 30 | ||
| 625 | } | ||
| 626 | } | ||
| 627 | end | ||
| 628 | local _anon_func_3 = function(tb) | ||
| 629 | local _item_0 = tb.tmp | ||
| 630 | return _item_0[#_item_0] | ||
| 631 | end | ||
| 632 | do | ||
| 633 | local f | ||
| 634 | f = function() | ||
| 635 | local q = { } | ||
| 636 | do | ||
| 637 | local _accum_0 = { } | ||
| 638 | local _len_0 = 1 | ||
| 639 | for n = 1, 4 do | ||
| 640 | _accum_0[_len_0] = n | ||
| 641 | _len_0 = _len_0 + 1 | ||
| 642 | end | ||
| 643 | tb.tmp = _accum_0 | ||
| 644 | end | ||
| 645 | if #tb.tmp >= 3 then | ||
| 646 | q[#q] = { | ||
| 647 | head = tb.tmp[1], | ||
| 648 | tail = _anon_func_3(tb) | ||
| 649 | } | ||
| 650 | end | ||
| 651 | end | ||
| 652 | end | ||
| 653 | do | ||
| 654 | local make_pair | ||
| 655 | make_pair = function(a, b) | ||
| 656 | return { | ||
| 657 | a, | ||
| 658 | b | ||
| 659 | } | ||
| 660 | end | ||
| 661 | local pairs = { } | ||
| 662 | local p1 = make_pair(7, 8) | ||
| 663 | pairs[#pairs] = p1 | ||
| 664 | local k, v = "key", 42 | ||
| 665 | pairs[#pairs] = { | ||
| 666 | k = k, | ||
| 667 | v = v | ||
| 668 | } | ||
| 669 | end | ||
| 670 | do | ||
| 671 | local cfg = { | ||
| 672 | mode = "safe", | ||
| 673 | tags = { } | ||
| 674 | } | ||
| 675 | if cfg.mode == "safe" then | ||
| 676 | cfg.mode = "fast" | ||
| 677 | local _obj_0 = cfg.tags | ||
| 678 | _obj_0[#_obj_0] = "newbie" | ||
| 679 | end | ||
| 680 | end | ||
| 681 | do | ||
| 682 | local mat = { | ||
| 683 | { | ||
| 684 | 1, | ||
| 685 | 2 | ||
| 686 | }, | ||
| 687 | { | ||
| 688 | 3, | ||
| 689 | 4 | ||
| 690 | }, | ||
| 691 | { | ||
| 692 | 5, | ||
| 693 | 6 | ||
| 694 | } | ||
| 695 | } | ||
| 696 | local last_row = mat[#mat] | ||
| 697 | local rows = { } | ||
| 698 | rows[#rows] = last_row[1] | ||
| 699 | end | ||
| 700 | do | ||
| 701 | local kv = { } | ||
| 702 | kv[#kv] = { | ||
| 703 | k = "a", | ||
| 704 | v = 1 | ||
| 705 | } | ||
| 706 | kv[#kv] = { | ||
| 707 | k = "b", | ||
| 708 | v = 2 | ||
| 709 | } | ||
| 710 | local pair_last = kv[#kv] | ||
| 711 | local dict = { } | ||
| 712 | dict[pair_last.k] = pair_last.v | ||
| 713 | dict[pair_last.k] = 3 | ||
| 714 | end | ||
| 715 | do | ||
| 716 | local base | ||
| 717 | do | ||
| 718 | local _accum_0 = { } | ||
| 719 | local _len_0 = 1 | ||
| 720 | for i = 1, 4 do | ||
| 721 | _accum_0[_len_0] = i | ||
| 722 | _len_0 = _len_0 + 1 | ||
| 723 | end | ||
| 724 | base = _accum_0 | ||
| 725 | end | ||
| 726 | local pack = { } | ||
| 727 | pack[#pack] = { | ||
| 728 | base[1], | ||
| 729 | base[#base] | ||
| 730 | } | ||
| 731 | pack[#pack] = { | ||
| 732 | first = base[1], | ||
| 733 | last = base[#base] | ||
| 734 | } | ||
| 735 | end | ||
| 736 | do | ||
| 737 | local opts = { | ||
| 738 | limit = 10 | ||
| 739 | } | ||
| 740 | local limit, offset = opts.limit, opts.offset | ||
| 741 | if offset == nil then | ||
| 742 | offset = 0 | ||
| 743 | end | ||
| 744 | local pages = { } | ||
| 745 | pages[#pages] = { | ||
| 746 | limit = limit, | ||
| 747 | offset = offset | ||
| 748 | } | ||
| 749 | end | ||
| 750 | do | ||
| 751 | local chain = { | ||
| 752 | a = { | ||
| 753 | b = { | ||
| 754 | c = 0 | ||
| 755 | } | ||
| 756 | }, | ||
| 757 | list = { | ||
| 758 | { | ||
| 759 | x = 0 | ||
| 760 | }, | ||
| 761 | { | ||
| 762 | x = 0 | ||
| 763 | } | ||
| 764 | } | ||
| 765 | } | ||
| 766 | chain.a.b.c = 1 | ||
| 767 | chain.list[1].x = 10; | ||
| 768 | ((function() | ||
| 769 | local _item_0 = chain.list | ||
| 770 | return _item_0[#_item_0] | ||
| 771 | end)()).x = 20 | ||
| 772 | local _obj_0 = chain.list | ||
| 773 | _obj_0[#_obj_0 - 1] = { | ||
| 774 | x = 30 | ||
| 775 | } | ||
| 776 | end | ||
| 777 | do | ||
| 778 | local node = { | ||
| 779 | left = { | ||
| 780 | v = 0 | ||
| 781 | }, | ||
| 782 | right = { | ||
| 783 | v = 0 | ||
| 784 | } | ||
| 785 | } | ||
| 786 | local bag = { } | ||
| 787 | local left, right = node.left, node.right | ||
| 788 | bag[#bag], left.v, right.v = "k", 1, 2 | ||
| 789 | end | ||
| 790 | do | ||
| 791 | local a1, a2, a3 = 100, 200, 300 | ||
| 792 | local mix = { } | ||
| 793 | local meta | ||
| 794 | mix[#mix], mix[#mix], meta = a1, a2, { | ||
| 795 | tag = "ok" | ||
| 796 | } | ||
| 797 | end | ||
| 798 | do | ||
| 799 | local cfg2 = { | ||
| 800 | limit = 5, | ||
| 801 | opts = { | ||
| 802 | flag = false | ||
| 803 | } | ||
| 804 | } | ||
| 805 | local lim, opt2 = cfg2.limit, cfg2.opts | ||
| 806 | local bucket = { | ||
| 807 | xs = { } | ||
| 808 | } | ||
| 809 | local _obj_0 = bucket.xs | ||
| 810 | _obj_0[#_obj_0] = lim | ||
| 811 | bucket.flag = true | ||
| 812 | local _obj_1 = opt2.flags | ||
| 813 | _obj_1[#_obj_1 + 1] = 123 | ||
| 814 | end | ||
| 815 | do | ||
| 816 | local ret2 | ||
| 817 | ret2 = function() | ||
| 818 | return 7, 8 | ||
| 819 | end | ||
| 820 | local box = { } | ||
| 821 | local x1 | ||
| 822 | box[#box], x1 = ret2() | ||
| 823 | end | ||
| 824 | do | ||
| 825 | local q = { | ||
| 826 | 1, | ||
| 827 | 2 | ||
| 828 | } | ||
| 829 | local lastq = q[#q] | ||
| 830 | q[#q - 1] = lastq * 10 | ||
| 831 | end | ||
| 832 | do | ||
| 833 | local mat2 = [[9,8], [7,6]] | ||
| 834 | local t = { | ||
| 835 | hold = nil | ||
| 836 | } | ||
| 837 | t.hold = mat2[#mat2][1] | ||
| 838 | end | ||
| 839 | do | ||
| 840 | local f | ||
| 841 | f = function() | ||
| 842 | local _obj_0 | ||
| 843 | do | ||
| 844 | local _item_0 = globalTB | ||
| 845 | _obj_0 = _item_0[#_item_0] | ||
| 846 | end | ||
| 847 | _obj_0[#_obj_0] = 1 | ||
| 848 | end | ||
| 849 | local f1 | ||
| 850 | f1 = function() | ||
| 851 | do | ||
| 852 | local _item_0 = globalTB | ||
| 853 | do | ||
| 854 | local _item_1 = _item_0[#_item_0] | ||
| 855 | return _item_1[#_item_1 - 1] | ||
| 856 | end | ||
| 857 | end | ||
| 858 | end | ||
| 859 | end | ||
| 860 | do | ||
| 861 | do | ||
| 862 | local _obj_0 = tbA | ||
| 863 | local _len_0 = #_obj_0 + 1 | ||
| 864 | local _list_0 = tbB | ||
| 865 | for _index_0 = 1, #_list_0 do | ||
| 866 | local _elm_0 = _list_0[_index_0] | ||
| 867 | _obj_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 868 | end | ||
| 869 | end | ||
| 870 | a = 1 | ||
| 871 | do | ||
| 872 | local _obj_0 = tb | ||
| 873 | local _len_0 = #_obj_0 + 1 | ||
| 874 | for _index_0 = 1, #x do | ||
| 875 | local _elm_0 = x[_index_0] | ||
| 876 | _obj_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 877 | end | ||
| 878 | end | ||
| 879 | b[#b + 1] = 3 | ||
| 880 | c = 4 | ||
| 881 | local data = { | ||
| 882 | a = { | ||
| 883 | 1, | ||
| 884 | 2, | ||
| 885 | 3 | ||
| 886 | }, | ||
| 887 | b = { | ||
| 888 | 4, | ||
| 889 | 5, | ||
| 890 | 6 | ||
| 891 | } | ||
| 892 | } | ||
| 893 | local flat | ||
| 894 | local _accum_0 = { } | ||
| 895 | for k, v in pairs(data) do | ||
| 896 | local _len_0 = #_accum_0 + 1 | ||
| 897 | for _index_0 = 1, #v do | ||
| 898 | local _elm_0 = v[_index_0] | ||
| 899 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 900 | end | ||
| 901 | end | ||
| 902 | flat = _accum_0 | ||
| 903 | end | ||
| 330 | return nil | 904 | return nil |
diff --git a/spec/outputs/loops.lua b/spec/outputs/loops.lua index 9a47579..6ab4bbb 100644 --- a/spec/outputs/loops.lua +++ b/spec/outputs/loops.lua | |||
| @@ -468,3 +468,31 @@ do | |||
| 468 | end | 468 | end |
| 469 | list = _accum_0 | 469 | list = _accum_0 |
| 470 | end | 470 | end |
| 471 | do | ||
| 472 | repeat | ||
| 473 | print(1) | ||
| 474 | until true | ||
| 475 | do | ||
| 476 | local _accum_0 | ||
| 477 | repeat | ||
| 478 | a = func() | ||
| 479 | _accum_0 = a.x | ||
| 480 | break | ||
| 481 | until a.v | ||
| 482 | x = _accum_0 | ||
| 483 | end | ||
| 484 | local items | ||
| 485 | local _accum_0 = { } | ||
| 486 | local _len_0 = 1 | ||
| 487 | repeat | ||
| 488 | local item = getItem() | ||
| 489 | if not item then | ||
| 490 | break | ||
| 491 | end | ||
| 492 | if item.value > 0 then | ||
| 493 | _accum_0[_len_0] = item | ||
| 494 | _len_0 = _len_0 + 1 | ||
| 495 | end | ||
| 496 | until false | ||
| 497 | items = _accum_0 | ||
| 498 | end | ||
diff --git a/spec/outputs/macro.lua b/spec/outputs/macro.lua index 9f5507c..89c6e63 100644 --- a/spec/outputs/macro.lua +++ b/spec/outputs/macro.lua | |||
| @@ -26,6 +26,10 @@ print({ | |||
| 26 | 123, | 26 | 123, |
| 27 | 'xyz' | 27 | 'xyz' |
| 28 | }) | 28 | }) |
| 29 | print({ | ||
| 30 | 456, | ||
| 31 | 'abc' | ||
| 32 | }) | ||
| 29 | do | 33 | do |
| 30 | assert(item == nil) | 34 | assert(item == nil) |
| 31 | end | 35 | end |
| @@ -213,6 +217,13 @@ function tb:func() | |||
| 213 | end | 217 | end |
| 214 | end | 218 | end |
| 215 | print(x) | 219 | print(x) |
| 220 | local yue = require("yue") | ||
| 221 | do | ||
| 222 | local function f2(a) | ||
| 223 | return a + 1 | ||
| 224 | end | ||
| 225 | x = x + f2(3) | ||
| 226 | end | ||
| 216 | local sel | 227 | local sel |
| 217 | sel = function(a, b, c) | 228 | sel = function(a, b, c) |
| 218 | if a then | 229 | if a then |
| @@ -317,7 +328,7 @@ print((setmetatable({ | |||
| 317 | return 998 | 328 | return 998 |
| 318 | end | 329 | end |
| 319 | })) | 330 | })) |
| 320 | print("current line: " .. tostring(323)) | 331 | print("current line: " .. tostring(349)) |
| 321 | do | 332 | do |
| 322 | do | 333 | do |
| 323 | -- TODO | 334 | -- TODO |
diff --git a/spec/outputs/props.lua b/spec/outputs/props.lua new file mode 100644 index 0000000..2c282e0 --- /dev/null +++ b/spec/outputs/props.lua | |||
| @@ -0,0 +1,240 @@ | |||
| 1 | local Props | ||
| 2 | do | ||
| 3 | local _class_0 | ||
| 4 | local assignReadOnly | ||
| 5 | local _base_0 = { | ||
| 6 | __index = function(self, name) | ||
| 7 | local cls = getmetatable(self) | ||
| 8 | do | ||
| 9 | local item | ||
| 10 | do | ||
| 11 | local _obj_0 = cls.__getter | ||
| 12 | if _obj_0 ~= nil then | ||
| 13 | item = _obj_0[name] | ||
| 14 | end | ||
| 15 | end | ||
| 16 | if item then | ||
| 17 | return item(self) | ||
| 18 | else | ||
| 19 | item = rawget(cls, name) | ||
| 20 | if item then | ||
| 21 | return item | ||
| 22 | else | ||
| 23 | local c = cls | ||
| 24 | repeat | ||
| 25 | c = getmetatable(c) | ||
| 26 | if c then | ||
| 27 | local _obj_0 = c.__getter | ||
| 28 | if _obj_0 ~= nil then | ||
| 29 | item = _obj_0[name] | ||
| 30 | end | ||
| 31 | if item then | ||
| 32 | if cls.__getter == nil then | ||
| 33 | cls.__getter = { } | ||
| 34 | end | ||
| 35 | cls.__getter[name] = item | ||
| 36 | return item(self) | ||
| 37 | else | ||
| 38 | item = rawget(c, name) | ||
| 39 | if item then | ||
| 40 | rawset(cls, name, item) | ||
| 41 | return item | ||
| 42 | end | ||
| 43 | end | ||
| 44 | else | ||
| 45 | break | ||
| 46 | end | ||
| 47 | until false | ||
| 48 | end | ||
| 49 | end | ||
| 50 | end | ||
| 51 | return nil | ||
| 52 | end, | ||
| 53 | __newindex = function(self, name, value) | ||
| 54 | local cls = getmetatable(self) | ||
| 55 | local item | ||
| 56 | local _obj_0 = cls.__setter | ||
| 57 | if _obj_0 ~= nil then | ||
| 58 | item = _obj_0[name] | ||
| 59 | end | ||
| 60 | if item then | ||
| 61 | return item(self, value) | ||
| 62 | else | ||
| 63 | local c = cls | ||
| 64 | repeat | ||
| 65 | c = getmetatable(c) | ||
| 66 | if c then | ||
| 67 | local _obj_1 = c.__setter | ||
| 68 | if _obj_1 ~= nil then | ||
| 69 | item = _obj_1[name] | ||
| 70 | end | ||
| 71 | if item then | ||
| 72 | if cls.__setter == nil then | ||
| 73 | cls.__setter = { } | ||
| 74 | end | ||
| 75 | cls.__setter[name] = item | ||
| 76 | item(self, value) | ||
| 77 | return | ||
| 78 | end | ||
| 79 | else | ||
| 80 | break | ||
| 81 | end | ||
| 82 | until false | ||
| 83 | return rawset(self, name, value) | ||
| 84 | end | ||
| 85 | end, | ||
| 86 | prop = function(self, name, props) | ||
| 87 | local get, set = props.get, props.set | ||
| 88 | if set == nil then | ||
| 89 | set = assignReadOnly | ||
| 90 | end | ||
| 91 | do | ||
| 92 | local getter = rawget(self.__base, "__getter") | ||
| 93 | if getter then | ||
| 94 | getter[name] = get | ||
| 95 | else | ||
| 96 | rawset(self.__base, "__getter", { | ||
| 97 | [name] = get | ||
| 98 | }) | ||
| 99 | end | ||
| 100 | end | ||
| 101 | local setter = rawget(self.__base, "__setter") | ||
| 102 | if setter then | ||
| 103 | setter[name] = set | ||
| 104 | else | ||
| 105 | return rawset(self.__base, "__setter", { | ||
| 106 | [name] = set | ||
| 107 | }) | ||
| 108 | end | ||
| 109 | end | ||
| 110 | } | ||
| 111 | if _base_0.__index == nil then | ||
| 112 | _base_0.__index = _base_0 | ||
| 113 | end | ||
| 114 | _class_0 = setmetatable({ | ||
| 115 | __init = function() end, | ||
| 116 | __base = _base_0, | ||
| 117 | __name = "Props" | ||
| 118 | }, { | ||
| 119 | __index = _base_0, | ||
| 120 | __call = function(cls, ...) | ||
| 121 | local _self_0 = setmetatable({ }, _base_0) | ||
| 122 | cls.__init(_self_0, ...) | ||
| 123 | return _self_0 | ||
| 124 | end | ||
| 125 | }) | ||
| 126 | _base_0.__class = _class_0 | ||
| 127 | local self = _class_0; | ||
| 128 | assignReadOnly = function() | ||
| 129 | return error("assigning a readonly property") | ||
| 130 | end | ||
| 131 | Props = _class_0 | ||
| 132 | end | ||
| 133 | local A | ||
| 134 | do | ||
| 135 | local _class_0 | ||
| 136 | local _parent_0 = Props | ||
| 137 | local _base_0 = { } | ||
| 138 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
| 139 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
| 140 | _base_0[_key_0] = _val_0 | ||
| 141 | end | ||
| 142 | end | ||
| 143 | if _base_0.__index == nil then | ||
| 144 | _base_0.__index = _base_0 | ||
| 145 | end | ||
| 146 | setmetatable(_base_0, _parent_0.__base) | ||
| 147 | _class_0 = setmetatable({ | ||
| 148 | __init = function(self) | ||
| 149 | self._x = 0 | ||
| 150 | end, | ||
| 151 | __base = _base_0, | ||
| 152 | __name = "A", | ||
| 153 | __parent = _parent_0 | ||
| 154 | }, { | ||
| 155 | __index = function(cls, name) | ||
| 156 | local val = rawget(_base_0, name) | ||
| 157 | if val == nil then | ||
| 158 | local parent = rawget(cls, "__parent") | ||
| 159 | if parent then | ||
| 160 | return parent[name] | ||
| 161 | end | ||
| 162 | else | ||
| 163 | return val | ||
| 164 | end | ||
| 165 | end, | ||
| 166 | __call = function(cls, ...) | ||
| 167 | local _self_0 = setmetatable({ }, _base_0) | ||
| 168 | cls.__init(_self_0, ...) | ||
| 169 | return _self_0 | ||
| 170 | end | ||
| 171 | }) | ||
| 172 | _base_0.__class = _class_0 | ||
| 173 | local self = _class_0; | ||
| 174 | self:prop('x', { | ||
| 175 | get = function(self) | ||
| 176 | return self._x + 1000 | ||
| 177 | end, | ||
| 178 | set = function(self, v) | ||
| 179 | self._x = v | ||
| 180 | end | ||
| 181 | }) | ||
| 182 | if _parent_0.__inherited then | ||
| 183 | _parent_0.__inherited(_parent_0, _class_0) | ||
| 184 | end | ||
| 185 | A = _class_0 | ||
| 186 | end | ||
| 187 | local B | ||
| 188 | do | ||
| 189 | local _class_0 | ||
| 190 | local _parent_0 = A | ||
| 191 | local _base_0 = { } | ||
| 192 | for _key_0, _val_0 in pairs(_parent_0.__base) do | ||
| 193 | if _base_0[_key_0] == nil and _key_0:match("^__") and not (_key_0 == "__index" and _val_0 == _parent_0.__base) then | ||
| 194 | _base_0[_key_0] = _val_0 | ||
| 195 | end | ||
| 196 | end | ||
| 197 | if _base_0.__index == nil then | ||
| 198 | _base_0.__index = _base_0 | ||
| 199 | end | ||
| 200 | setmetatable(_base_0, _parent_0.__base) | ||
| 201 | _class_0 = setmetatable({ | ||
| 202 | __init = function(self, ...) | ||
| 203 | return _class_0.__parent.__init(self, ...) | ||
| 204 | end, | ||
| 205 | __base = _base_0, | ||
| 206 | __name = "B", | ||
| 207 | __parent = _parent_0 | ||
| 208 | }, { | ||
| 209 | __index = function(cls, name) | ||
| 210 | local val = rawget(_base_0, name) | ||
| 211 | if val == nil then | ||
| 212 | local parent = rawget(cls, "__parent") | ||
| 213 | if parent then | ||
| 214 | return parent[name] | ||
| 215 | end | ||
| 216 | else | ||
| 217 | return val | ||
| 218 | end | ||
| 219 | end, | ||
| 220 | __call = function(cls, ...) | ||
| 221 | local _self_0 = setmetatable({ }, _base_0) | ||
| 222 | cls.__init(_self_0, ...) | ||
| 223 | return _self_0 | ||
| 224 | end | ||
| 225 | }) | ||
| 226 | _base_0.__class = _class_0 | ||
| 227 | local self = _class_0; | ||
| 228 | self:prop('abc', { | ||
| 229 | get = function(self) | ||
| 230 | return "hello" | ||
| 231 | end | ||
| 232 | }) | ||
| 233 | if _parent_0.__inherited then | ||
| 234 | _parent_0.__inherited(_parent_0, _class_0) | ||
| 235 | end | ||
| 236 | B = _class_0 | ||
| 237 | end | ||
| 238 | local b = B() | ||
| 239 | b.x = 999 | ||
| 240 | return print(b.x, b.abc) | ||
diff --git a/spec/outputs/string.lua b/spec/outputs/string.lua index febea62..bdfd676 100644 --- a/spec/outputs/string.lua +++ b/spec/outputs/string.lua | |||
| @@ -1,3 +1,4 @@ | |||
| 1 | local _module_0 = { } | ||
| 1 | local hi = "hello" | 2 | local hi = "hello" |
| 2 | local hello = "what the heckyes" | 3 | local hello = "what the heckyes" |
| 3 | print(hi) | 4 | print(hi) |
| @@ -41,4 +42,42 @@ local _ = "hello"; | |||
| 41 | ("hello"):format().hello(1, 2, 3); | 42 | ("hello"):format().hello(1, 2, 3); |
| 42 | ("hello"):format(1, 2, 3) | 43 | ("hello"):format(1, 2, 3) |
| 43 | something("hello"):world() | 44 | something("hello"):world() |
| 44 | return something(("hello"):world()) | 45 | something(("hello"):world()) |
| 46 | do | ||
| 47 | local str = "key: value" | ||
| 48 | str = "config:\n\tenabled: true\n\tlevel: 5" | ||
| 49 | str = "header: start\nfooter: end" | ||
| 50 | str = "name: " .. tostring(username) | ||
| 51 | str = "count: " .. tostring(total) .. " items" | ||
| 52 | str = "user: " .. tostring(name) .. "\nid: " .. tostring(id) | ||
| 53 | str = "path: \"C:\\\\Program Files\\\\App\"\ndesc: 'single \"quote\" test'" | ||
| 54 | str = "key: value \nnext: 123 " | ||
| 55 | str = "list:\n\t- \"one\"\n\t- \"two\"" | ||
| 56 | str = "-- comment\ncontent text\n-- comment" | ||
| 57 | str = tostring(1 + 2) .. '\n' .. tostring(2 + 3) .. '\n' .. tostring("a" .. "b") | ||
| 58 | local obj = { | ||
| 59 | settings = "mode: " .. tostring(mode) .. "\nflags:\n\t- " .. tostring(flag1) .. "\n\t- default" | ||
| 60 | } | ||
| 61 | local fn | ||
| 62 | fn = function() | ||
| 63 | return "Hello\nname: " .. tostring(userName) | ||
| 64 | end | ||
| 65 | str = "result:\n\tstatus: " .. tostring((function() | ||
| 66 | if ok then | ||
| 67 | return "pass" | ||
| 68 | else | ||
| 69 | return "fail" | ||
| 70 | end | ||
| 71 | end)()) .. "\n\tcode: " .. tostring(code) | ||
| 72 | local summary = "date: " .. tostring(os.date()) .. "\nvalues:\n\t-\n\t\ta: " .. tostring(aVal) .. "\n\t\tb: " .. tostring(bVal or defaultB) | ||
| 73 | local msg = send("Hello, " .. tostring(user) .. "!\nToday is " .. tostring(os.date("%A")) .. ".") | ||
| 74 | local desc | ||
| 75 | do | ||
| 76 | local prefix = "Result" | ||
| 77 | desc = tostring(prefix) .. ":\nvalue: " .. tostring(compute()) | ||
| 78 | end | ||
| 79 | print(("1\n2\n3")) | ||
| 80 | end | ||
| 81 | local yaml = "version: " .. tostring(ver) .. "\nok: true" | ||
| 82 | _module_0["yaml"] = yaml | ||
| 83 | return _module_0 | ||
diff --git a/spec/outputs/switch.lua b/spec/outputs/switch.lua index 0f8bba2..7c1004b 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
| @@ -656,4 +656,125 @@ do | |||
| 656 | end | 656 | end |
| 657 | end | 657 | end |
| 658 | end | 658 | end |
| 659 | do | ||
| 660 | local v = "hello" | ||
| 661 | if "hello" == v then | ||
| 662 | print("matched hello") | ||
| 663 | else | ||
| 664 | print("not matched") | ||
| 665 | end | ||
| 666 | end | ||
| 667 | do | ||
| 668 | local f | ||
| 669 | f = function() | ||
| 670 | return "ok" | ||
| 671 | end | ||
| 672 | local val = f() | ||
| 673 | if "ok" == val then | ||
| 674 | print("it's ok") | ||
| 675 | end | ||
| 676 | end | ||
| 677 | do | ||
| 678 | local g | ||
| 679 | g = function() | ||
| 680 | return 42 | ||
| 681 | end | ||
| 682 | local result = g() | ||
| 683 | if 1 == result or 2 == result then | ||
| 684 | print("small") | ||
| 685 | elseif 42 == result then | ||
| 686 | print("life universe everything") | ||
| 687 | else | ||
| 688 | print("other " .. tostring(result)) | ||
| 689 | end | ||
| 690 | end | ||
| 691 | do | ||
| 692 | local check | ||
| 693 | check = function() | ||
| 694 | if true then | ||
| 695 | return "yes" | ||
| 696 | else | ||
| 697 | return "no" | ||
| 698 | end | ||
| 699 | end | ||
| 700 | local x = check() | ||
| 701 | if "yes" == x then | ||
| 702 | print("affirmative") | ||
| 703 | else | ||
| 704 | print("negative") | ||
| 705 | end | ||
| 706 | end | ||
| 707 | do | ||
| 708 | local t | ||
| 709 | t = function() | ||
| 710 | local tb = { | ||
| 711 | a = 1 | ||
| 712 | } | ||
| 713 | tb.a = 2 | ||
| 714 | return tb | ||
| 715 | end | ||
| 716 | local data = t() | ||
| 717 | local _type_0 = type(data) | ||
| 718 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 719 | local _match_0 = false | ||
| 720 | if _tab_0 then | ||
| 721 | if 2 == data.a then | ||
| 722 | _match_0 = true | ||
| 723 | print("matched") | ||
| 724 | end | ||
| 725 | end | ||
| 726 | if not _match_0 then | ||
| 727 | print("not matched") | ||
| 728 | end | ||
| 729 | end | ||
| 730 | do | ||
| 731 | local clientData = { | ||
| 732 | "Meta", | ||
| 733 | "CUST_1001", | ||
| 734 | "CHK123" | ||
| 735 | } | ||
| 736 | local _type_0 = type(clientData) | ||
| 737 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 738 | if _tab_0 then | ||
| 739 | local metadata | ||
| 740 | do | ||
| 741 | local _accum_0 = { } | ||
| 742 | local _len_0 = 1 | ||
| 743 | local _max_0 = #clientData + -3 + 1 | ||
| 744 | for _index_0 = 1, _max_0 do | ||
| 745 | local _item_0 = clientData[_index_0] | ||
| 746 | _accum_0[_len_0] = _item_0 | ||
| 747 | _len_0 = _len_0 + 1 | ||
| 748 | end | ||
| 749 | metadata = _accum_0 | ||
| 750 | end | ||
| 751 | local customerId = clientData[#clientData - 1] | ||
| 752 | local checksum = clientData[#clientData] | ||
| 753 | if customerId ~= nil and checksum ~= nil then | ||
| 754 | print(metadata) | ||
| 755 | print(customerId) | ||
| 756 | print(checksum) | ||
| 757 | end | ||
| 758 | end | ||
| 759 | end | ||
| 760 | do | ||
| 761 | local handlePath | ||
| 762 | handlePath = function(segments) | ||
| 763 | local _type_0 = type(segments) | ||
| 764 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 765 | if _tab_0 then | ||
| 766 | local resource = segments[#segments - 1] | ||
| 767 | local action = segments[#segments] | ||
| 768 | if resource ~= nil and action ~= nil then | ||
| 769 | print("Resource:", resource) | ||
| 770 | return print("Action:", action) | ||
| 771 | end | ||
| 772 | end | ||
| 773 | end | ||
| 774 | handlePath({ | ||
| 775 | "admin", | ||
| 776 | "logs", | ||
| 777 | "view" | ||
| 778 | }) | ||
| 779 | end | ||
| 659 | return nil | 780 | return nil |
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index 040a325..2df3473 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
| @@ -430,4 +430,15 @@ do | |||
| 430 | local f2 | 430 | local f2 |
| 431 | f2 = function() end | 431 | f2 = function() end |
| 432 | end | 432 | end |
| 433 | do | ||
| 434 | if res ~= "" then | ||
| 435 | return res | ||
| 436 | end | ||
| 437 | end | ||
| 438 | do | ||
| 439 | return res((function() | ||
| 440 | if res ~= "" then | ||
| 441 | end | ||
| 442 | end)()) | ||
| 443 | end | ||
| 433 | return nil | 444 | return nil |
diff --git a/spec/outputs/tables.lua b/spec/outputs/tables.lua index f358811..3f851de 100644 --- a/spec/outputs/tables.lua +++ b/spec/outputs/tables.lua | |||
| @@ -366,6 +366,28 @@ local menus = { | |||
| 366 | } | 366 | } |
| 367 | } | 367 | } |
| 368 | } | 368 | } |
| 369 | _ = { | ||
| 370 | boolean = { | ||
| 371 | true, | ||
| 372 | false | ||
| 373 | }, | ||
| 374 | float = { | ||
| 375 | 3.14, | ||
| 376 | -6.8523015e+5 | ||
| 377 | }, | ||
| 378 | int = { | ||
| 379 | 123, | ||
| 380 | -685230 | ||
| 381 | }, | ||
| 382 | null = { | ||
| 383 | nodeName = 'node', | ||
| 384 | parent = nil | ||
| 385 | }, | ||
| 386 | string = { | ||
| 387 | 'Hello world', | ||
| 388 | "newline\nnewline2" | ||
| 389 | } | ||
| 390 | } | ||
| 369 | local tb | 391 | local tb |
| 370 | do | 392 | do |
| 371 | local _tab_0 = { } | 393 | local _tab_0 = { } |
diff --git a/spec/outputs/test/format_spec.lua b/spec/outputs/test/format_spec.lua index ed0fbee..7aa85cd 100644 --- a/spec/outputs/test/format_spec.lua +++ b/spec/outputs/test/format_spec.lua | |||
| @@ -122,7 +122,7 @@ return describe("format", function() | |||
| 122 | local original_ast = yue.to_ast(code) | 122 | local original_ast = yue.to_ast(code) |
| 123 | assert.is_not_nil(original_ast) | 123 | assert.is_not_nil(original_ast) |
| 124 | rewriteLineCol(original_ast) | 124 | rewriteLineCol(original_ast) |
| 125 | local formated = yue.format(code) | 125 | local formated = yue.format(code, 0, false) |
| 126 | local ast = yue.to_ast(formated) | 126 | local ast = yue.to_ast(formated) |
| 127 | assert.is_not_nil(ast) | 127 | assert.is_not_nil(ast) |
| 128 | rewriteLineCol(ast) | 128 | rewriteLineCol(ast) |
diff --git a/spec/outputs/try_catch.lua b/spec/outputs/try_catch.lua index efd92c6..edb2341 100644 --- a/spec/outputs/try_catch.lua +++ b/spec/outputs/try_catch.lua | |||
| @@ -22,6 +22,44 @@ end | |||
| 22 | local _anon_func_7 = function(a, b, c, tb) | 22 | local _anon_func_7 = function(a, b, c, tb) |
| 23 | return tb.f(a, b, c) | 23 | return tb.f(a, b, c) |
| 24 | end | 24 | end |
| 25 | local _anon_func_8 = function(_arg_0, ...) | ||
| 26 | local ok = _arg_0 | ||
| 27 | return ... | ||
| 28 | end | ||
| 29 | local _anon_func_10 = function(_arg_0, ...) | ||
| 30 | local _ok_0 = _arg_0 | ||
| 31 | if _ok_0 then | ||
| 32 | return ... | ||
| 33 | end | ||
| 34 | end | ||
| 35 | local _anon_func_9 = function(func, pcall) | ||
| 36 | return _anon_func_10(pcall(func)) | ||
| 37 | end | ||
| 38 | local _anon_func_12 = function(_arg_0, ...) | ||
| 39 | local _ok_0 = _arg_0 | ||
| 40 | if _ok_0 then | ||
| 41 | return ... | ||
| 42 | end | ||
| 43 | end | ||
| 44 | local _anon_func_11 = function(func, pcall) | ||
| 45 | return _anon_func_12(pcall(func)) | ||
| 46 | end | ||
| 47 | local _anon_func_14 = function(_arg_0, ...) | ||
| 48 | local _ok_0 = _arg_0 | ||
| 49 | if _ok_0 then | ||
| 50 | return ... | ||
| 51 | end | ||
| 52 | end | ||
| 53 | local _anon_func_15 = function(func, print) | ||
| 54 | print(123) | ||
| 55 | return func() | ||
| 56 | end | ||
| 57 | local _anon_func_13 = function(func, print, xpcall) | ||
| 58 | return _anon_func_14(xpcall(_anon_func_15, function(e) | ||
| 59 | print(e) | ||
| 60 | return e | ||
| 61 | end, func, print)) | ||
| 62 | end | ||
| 25 | local f | 63 | local f |
| 26 | f = function() | 64 | f = function() |
| 27 | xpcall(function() | 65 | xpcall(function() |
| @@ -104,10 +142,236 @@ f = function() | |||
| 104 | do | 142 | do |
| 105 | x(function() | 143 | x(function() |
| 106 | local tb, a, b, c | 144 | local tb, a, b, c |
| 107 | f = function() | 145 | local f1 |
| 146 | f1 = function() | ||
| 108 | return pcall(_anon_func_7, a, b, c, tb) | 147 | return pcall(_anon_func_7, a, b, c, tb) |
| 109 | end | 148 | end |
| 110 | end) | 149 | end) |
| 111 | end | 150 | end |
| 151 | do | ||
| 152 | local f1 | ||
| 153 | f1 = function() | ||
| 154 | do | ||
| 155 | return _anon_func_8(pcall(function() | ||
| 156 | return func() | ||
| 157 | end)) | ||
| 158 | end | ||
| 159 | end | ||
| 160 | end | ||
| 161 | do | ||
| 162 | local func | ||
| 163 | local a, b, c | ||
| 164 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
| 165 | if _ok_0 then | ||
| 166 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 167 | end | ||
| 168 | end | ||
| 169 | do | ||
| 170 | local a, b, c | ||
| 171 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 172 | return func() | ||
| 173 | end) | ||
| 174 | if _ok_0 then | ||
| 175 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 176 | end | ||
| 177 | end | ||
| 178 | do | ||
| 179 | local a | ||
| 180 | local _exp_0 = (_anon_func_9(func, pcall)) | ||
| 181 | if _exp_0 ~= nil then | ||
| 182 | a = _exp_0 | ||
| 183 | else | ||
| 184 | a = "default" | ||
| 185 | end | ||
| 186 | end | ||
| 187 | do | ||
| 188 | f(_anon_func_11(func, pcall)) | ||
| 189 | end | ||
| 190 | do | ||
| 191 | f(_anon_func_13(func, print, xpcall)) | ||
| 192 | end | ||
| 112 | return nil | 193 | return nil |
| 113 | end | 194 | end |
| 195 | local _anon_func_16 = function(a, b, c, tb) | ||
| 196 | return tb.f(a, b, c) | ||
| 197 | end | ||
| 198 | local _anon_func_17 = function(_arg_0, ...) | ||
| 199 | local ok = _arg_0 | ||
| 200 | return ... | ||
| 201 | end | ||
| 202 | do | ||
| 203 | xpcall(function() | ||
| 204 | return func(1, 2, 3) | ||
| 205 | end, function(err) | ||
| 206 | return print(err) | ||
| 207 | end) | ||
| 208 | xpcall(function() | ||
| 209 | return func(1, 2, 3) | ||
| 210 | end, function(err) | ||
| 211 | return print(err) | ||
| 212 | end) | ||
| 213 | pcall(function() | ||
| 214 | print("trying") | ||
| 215 | return func(1, 2, 3) | ||
| 216 | end) | ||
| 217 | do | ||
| 218 | local success, result = xpcall(function() | ||
| 219 | return func(1, 2, 3) | ||
| 220 | end, function(err) | ||
| 221 | return print(err) | ||
| 222 | end) | ||
| 223 | success, result = pcall(function() | ||
| 224 | return func(1, 2, 3) | ||
| 225 | end) | ||
| 226 | end | ||
| 227 | local tb = { } | ||
| 228 | pcall(function() | ||
| 229 | return tb.func | ||
| 230 | end) | ||
| 231 | pcall(function() | ||
| 232 | return tb.func() | ||
| 233 | end) | ||
| 234 | pcall(function() | ||
| 235 | return tb.func() | ||
| 236 | end) | ||
| 237 | pcall(function() | ||
| 238 | return (tb.func()) | ||
| 239 | end) | ||
| 240 | pcall(function() | ||
| 241 | return (tb:func(1, 2, 3)) | ||
| 242 | end) | ||
| 243 | pcall(function() | ||
| 244 | return tb.func(1) | ||
| 245 | end) | ||
| 246 | pcall(function() | ||
| 247 | return tb.func(1) | ||
| 248 | end) | ||
| 249 | if (xpcall(function() | ||
| 250 | return func(1) | ||
| 251 | end, function(err) | ||
| 252 | return print(err) | ||
| 253 | end)) then | ||
| 254 | print("OK") | ||
| 255 | end | ||
| 256 | if xpcall(function() | ||
| 257 | return (func(1)) | ||
| 258 | end, function(err) | ||
| 259 | return print(err) | ||
| 260 | end) then | ||
| 261 | print("OK") | ||
| 262 | end | ||
| 263 | do | ||
| 264 | do | ||
| 265 | local success, result = pcall(function() | ||
| 266 | return func("abc", 123) | ||
| 267 | end) | ||
| 268 | if success then | ||
| 269 | print(result) | ||
| 270 | end | ||
| 271 | end | ||
| 272 | local success, result = xpcall(function() | ||
| 273 | return func("abc", 123) | ||
| 274 | end, function(err) | ||
| 275 | return print(err) | ||
| 276 | end) | ||
| 277 | success, result = xpcall(function() | ||
| 278 | return func("abc", 123) | ||
| 279 | end, function(err) | ||
| 280 | return print(err) | ||
| 281 | end) | ||
| 282 | if success then | ||
| 283 | print(result) | ||
| 284 | end | ||
| 285 | end | ||
| 286 | do | ||
| 287 | pcall(function() | ||
| 288 | return func(1, 2, 3) | ||
| 289 | end) | ||
| 290 | pcall(function() | ||
| 291 | return func(1, 2, 3) | ||
| 292 | end) | ||
| 293 | end | ||
| 294 | do | ||
| 295 | x(function() | ||
| 296 | local tb, a, b, c | ||
| 297 | local f1 | ||
| 298 | f1 = function() | ||
| 299 | return pcall(_anon_func_16, a, b, c, tb) | ||
| 300 | end | ||
| 301 | end) | ||
| 302 | end | ||
| 303 | do | ||
| 304 | local f1 | ||
| 305 | f1 = function() | ||
| 306 | do | ||
| 307 | return _anon_func_17(pcall(function() | ||
| 308 | return func() | ||
| 309 | end)) | ||
| 310 | end | ||
| 311 | end | ||
| 312 | end | ||
| 313 | do | ||
| 314 | local func | ||
| 315 | local a, b, c | ||
| 316 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(func) | ||
| 317 | if _ok_0 then | ||
| 318 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 319 | end | ||
| 320 | end | ||
| 321 | do | ||
| 322 | local a, b, c | ||
| 323 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 324 | return func() | ||
| 325 | end) | ||
| 326 | if _ok_0 then | ||
| 327 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 328 | end | ||
| 329 | end | ||
| 330 | do | ||
| 331 | local a | ||
| 332 | local _exp_0 = ((function() | ||
| 333 | return (function(_arg_0, ...) | ||
| 334 | local _ok_0 = _arg_0 | ||
| 335 | if _ok_0 then | ||
| 336 | return ... | ||
| 337 | end | ||
| 338 | end)(pcall(function() | ||
| 339 | return func() | ||
| 340 | end)) | ||
| 341 | end)()) | ||
| 342 | if _exp_0 ~= nil then | ||
| 343 | a = _exp_0 | ||
| 344 | else | ||
| 345 | a = "default" | ||
| 346 | end | ||
| 347 | end | ||
| 348 | do | ||
| 349 | f((function() | ||
| 350 | return (function(_arg_0, ...) | ||
| 351 | local _ok_0 = _arg_0 | ||
| 352 | if _ok_0 then | ||
| 353 | return ... | ||
| 354 | end | ||
| 355 | end)(pcall(function() | ||
| 356 | return func() | ||
| 357 | end)) | ||
| 358 | end)()) | ||
| 359 | end | ||
| 360 | do | ||
| 361 | f((function() | ||
| 362 | return (function(_arg_0, ...) | ||
| 363 | local _ok_0 = _arg_0 | ||
| 364 | if _ok_0 then | ||
| 365 | return ... | ||
| 366 | end | ||
| 367 | end)(xpcall(function() | ||
| 368 | print(123) | ||
| 369 | return func() | ||
| 370 | end, function(e) | ||
| 371 | print(e) | ||
| 372 | return e | ||
| 373 | end)) | ||
| 374 | end)()) | ||
| 375 | end | ||
| 376 | end | ||
| 377 | return nil | ||
diff --git a/spec/outputs/unicode/assign.lua b/spec/outputs/unicode/assign.lua index d4ad56a..e00d016 100644 --- a/spec/outputs/unicode/assign.lua +++ b/spec/outputs/unicode/assign.lua | |||
| @@ -43,10 +43,8 @@ do | |||
| 43 | end | 43 | end |
| 44 | end | 44 | end |
| 45 | local _anon_func_0 = function(_u6253_u5370) | 45 | local _anon_func_0 = function(_u6253_u5370) |
| 46 | do | 46 | _u6253_u5370(123) |
| 47 | _u6253_u5370(123) | 47 | return { } |
| 48 | return { } | ||
| 49 | end | ||
| 50 | end | 48 | end |
| 51 | return __u65e0_u6548_u53d8_u91cf(function() | 49 | return __u65e0_u6548_u53d8_u91cf(function() |
| 52 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) | 50 | setmetatable(a_u53d8_u91cf, _anon_func_0(_u6253_u5370)) |
diff --git a/spec/outputs/unicode/comprehension.lua b/spec/outputs/unicode/comprehension.lua index 60e490f..92bce69 100644 --- a/spec/outputs/unicode/comprehension.lua +++ b/spec/outputs/unicode/comprehension.lua | |||
| @@ -243,8 +243,11 @@ end | |||
| 243 | do | 243 | do |
| 244 | local _accum_0 = { } | 244 | local _accum_0 = { } |
| 245 | local _len_0 = 1 | 245 | local _len_0 = 1 |
| 246 | local _min_0 = 1 + 2 | ||
| 246 | local _max_0 = 3 + 4 | 247 | local _max_0 = 3 + 4 |
| 247 | for _index_0 = 1 + 2, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 248 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
| 249 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
| 250 | for _index_0 = _min_0, _max_0 do | ||
| 248 | local _u9879_u76ee = _u5217_u8868[_index_0] | 251 | local _u9879_u76ee = _u5217_u8868[_index_0] |
| 249 | _accum_0[_len_0] = _u9879_u76ee | 252 | _accum_0[_len_0] = _u9879_u76ee |
| 250 | _len_0 = _len_0 + 1 | 253 | _len_0 = _len_0 + 1 |
| @@ -254,8 +257,11 @@ end | |||
| 254 | do | 257 | do |
| 255 | local _accum_0 = { } | 258 | local _accum_0 = { } |
| 256 | local _len_0 = 1 | 259 | local _len_0 = 1 |
| 260 | local _min_0 = _u4f60_u597d() * 4 | ||
| 257 | local _max_0 = 2 - _u4e1c_u897f[4] | 261 | local _max_0 = 2 - _u4e1c_u897f[4] |
| 258 | for _index_0 = _u4f60_u597d() * 4, _max_0 < 0 and #_u5217_u8868 + _max_0 or _max_0 do | 262 | _min_0 = _min_0 < 0 and #_u5217_u8868 + _min_0 + 1 or _min_0 |
| 263 | _max_0 = _max_0 < 0 and #_u5217_u8868 + _max_0 + 1 or _max_0 | ||
| 264 | for _index_0 = _min_0, _max_0 do | ||
| 259 | local _u9879_u76ee = _u5217_u8868[_index_0] | 265 | local _u9879_u76ee = _u5217_u8868[_index_0] |
| 260 | _accum_0[_len_0] = _u9879_u76ee | 266 | _accum_0[_len_0] = _u9879_u76ee |
| 261 | _len_0 = _len_0 + 1 | 267 | _len_0 = _len_0 + 1 |
diff --git a/spec/outputs/unicode/funcs.lua b/spec/outputs/unicode/funcs.lua index 6e94587..06b24b1 100644 --- a/spec/outputs/unicode/funcs.lua +++ b/spec/outputs/unicode/funcs.lua | |||
| @@ -24,7 +24,7 @@ _u5f00(function() | |||
| 24 | end) | 24 | end) |
| 25 | local _u53d8_u91cfh | 25 | local _u53d8_u91cfh |
| 26 | _u53d8_u91cfh = function() | 26 | _u53d8_u91cfh = function() |
| 27 | return _ud83d_udc4b | 27 | return _u1f44b |
| 28 | end | 28 | end |
| 29 | _u5403(function() end, _u4e16_u754c); | 29 | _u5403(function() end, _u4e16_u754c); |
| 30 | (function() end)() | 30 | (function() end)() |
diff --git a/spec/outputs/unicode/import.lua b/spec/outputs/unicode/import.lua index 7c31ceb..e055c81 100644 --- a/spec/outputs/unicode/import.lua +++ b/spec/outputs/unicode/import.lua | |||
| @@ -11,10 +11,10 @@ local _u5b57_u6bb5x, _u5b57_u6bb5y, _u5b57_u6bb5z = _u9053_u5177_u7ec4["å—æ®µx" | |||
| 11 | return _fn_0(_base_0, ...) | 11 | return _fn_0(_base_0, ...) |
| 12 | end | 12 | end |
| 13 | end)(), _u9053_u5177_u7ec4["å—æ®µz"] | 13 | end)(), _u9053_u5177_u7ec4["å—æ®µz"] |
| 14 | local _u9886_u4e3b, _ud83d_udc7b | 14 | local _u9886_u4e3b, _u1f47b |
| 15 | do | 15 | do |
| 16 | local _obj_1 = _u627e_u5230("我的表") | 16 | local _obj_1 = _u627e_u5230("我的表") |
| 17 | _u9886_u4e3b, _ud83d_udc7b = _obj_1["领主"], (function() | 17 | _u9886_u4e3b, _u1f47b = _obj_1["领主"], (function() |
| 18 | local _base_0 = _obj_1 | 18 | local _base_0 = _obj_1 |
| 19 | local _fn_0 = _base_0["👻"] | 19 | local _fn_0 = _base_0["👻"] |
| 20 | return _fn_0 and function(...) | 20 | return _fn_0 and function(...) |
diff --git a/spec/outputs/unicode/lists.lua b/spec/outputs/unicode/lists.lua index aafd516..3bf6f50 100644 --- a/spec/outputs/unicode/lists.lua +++ b/spec/outputs/unicode/lists.lua | |||
| @@ -229,31 +229,36 @@ _u53d8_u91cfx = { | |||
| 229 | 6, | 229 | 6, |
| 230 | 7 | 230 | 7 |
| 231 | } | 231 | } |
| 232 | local _max_0 = -5 | 232 | local _max_0 = #_u53d8_u91cfx + -5 + 1 |
| 233 | for _index_0 = 2, _max_0 < 0 and #_u53d8_u91cfx + _max_0 or _max_0, 2 do | 233 | for _index_0 = 2, _max_0, 2 do |
| 234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 234 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 235 | _u6253_u5370(_u53d8_u91cfy) | 235 | _u6253_u5370(_u53d8_u91cfy) |
| 236 | end | 236 | end |
| 237 | local _max_1 = 3 | 237 | for _index_0 = 1, 3 do |
| 238 | for _index_0 = 1, _max_1 < 0 and #_u53d8_u91cfx + _max_1 or _max_1 do | ||
| 239 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 238 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 240 | _u6253_u5370(_u53d8_u91cfy) | 239 | _u6253_u5370(_u53d8_u91cfy) |
| 241 | end | 240 | end |
| 242 | for _index_0 = 2, #_u53d8_u91cfx do | 241 | local _max_1 = #_u53d8_u91cfx |
| 242 | for _index_0 = 2, _max_1 do | ||
| 243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 243 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 244 | _u6253_u5370(_u53d8_u91cfy) | 244 | _u6253_u5370(_u53d8_u91cfy) |
| 245 | end | 245 | end |
| 246 | for _index_0 = 1, #_u53d8_u91cfx, 2 do | 246 | local _max_2 = #_u53d8_u91cfx |
| 247 | for _index_0 = 1, _max_2, 2 do | ||
| 247 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 248 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 248 | _u6253_u5370(_u53d8_u91cfy) | 249 | _u6253_u5370(_u53d8_u91cfy) |
| 249 | end | 250 | end |
| 250 | for _index_0 = 2, #_u53d8_u91cfx, 2 do | 251 | local _max_3 = #_u53d8_u91cfx |
| 252 | for _index_0 = 2, _max_3, 2 do | ||
| 251 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 253 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 252 | _u6253_u5370(_u53d8_u91cfy) | 254 | _u6253_u5370(_u53d8_u91cfy) |
| 253 | end | 255 | end |
| 254 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 | 256 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc = 1, 5, 2 |
| 255 | local _max_2 = _u53d8_u91cfb | 257 | local _min_0 = _u53d8_u91cfa |
| 256 | for _index_0 = _u53d8_u91cfa, _max_2 < 0 and #_u53d8_u91cfx + _max_2 or _max_2, _u53d8_u91cfc do | 258 | local _max_4 = _u53d8_u91cfb |
| 259 | _min_0 = _min_0 < 0 and #_u53d8_u91cfx + _min_0 + 1 or _min_0 | ||
| 260 | _max_4 = _max_4 < 0 and #_u53d8_u91cfx + _max_4 + 1 or _max_4 | ||
| 261 | for _index_0 = _min_0, _max_4, _u53d8_u91cfc do | ||
| 257 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] | 262 | local _u53d8_u91cfy = _u53d8_u91cfx[_index_0] |
| 258 | _u6253_u5370(_u53d8_u91cfy) | 263 | _u6253_u5370(_u53d8_u91cfy) |
| 259 | end | 264 | end |
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua index 3b9327a..b4e78cd 100644 --- a/spec/outputs/unicode/macro.lua +++ b/spec/outputs/unicode/macro.lua | |||
| @@ -216,17 +216,15 @@ do | |||
| 216 | end | 216 | end |
| 217 | local _ = require('下划线') | 217 | local _ = require('下划线') |
| 218 | local _anon_func_0 = function(_) | 218 | local _anon_func_0 = function(_) |
| 219 | do | 219 | local _call_0 = (_({ |
| 220 | local _call_0 = (_({ | 220 | 1, |
| 221 | 1, | 221 | 2, |
| 222 | 2, | 222 | 3, |
| 223 | 3, | 223 | 4, |
| 224 | 4, | 224 | -2, |
| 225 | -2, | 225 | 3 |
| 226 | 3 | 226 | })) |
| 227 | })) | 227 | return _call_0["链"](_call_0) |
| 228 | return _call_0["链"](_call_0) | ||
| 229 | end | ||
| 230 | end | 228 | end |
| 231 | local _call_0 = ((function() | 229 | local _call_0 = ((function() |
| 232 | local _call_0 = ((function() | 230 | local _call_0 = ((function() |
| @@ -241,17 +239,15 @@ local _call_0 = ((function() | |||
| 241 | end)()) | 239 | end)()) |
| 242 | local _u7ed3_u679ca = _call_0["å–值"](_call_0) | 240 | local _u7ed3_u679ca = _call_0["å–值"](_call_0) |
| 243 | local _anon_func_1 = function(_) | 241 | local _anon_func_1 = function(_) |
| 244 | do | 242 | local _call_1 = (_({ |
| 245 | local _call_1 = (_({ | 243 | 1, |
| 246 | 1, | 244 | 2, |
| 247 | 2, | 245 | 3, |
| 248 | 3, | 246 | 4, |
| 249 | 4, | 247 | -2, |
| 250 | -2, | 248 | 3 |
| 251 | 3 | 249 | })) |
| 252 | })) | 250 | return _call_1["链"](_call_1) |
| 253 | return _call_1["链"](_call_1) | ||
| 254 | end | ||
| 255 | end | 251 | end |
| 256 | do | 252 | do |
| 257 | local _call_1 = ((function() | 253 | local _call_1 = ((function() |
| @@ -270,10 +266,8 @@ do | |||
| 270 | end) | 266 | end) |
| 271 | end | 267 | end |
| 272 | local _anon_func_2 = function(_u539f_u70b9) | 268 | local _anon_func_2 = function(_u539f_u70b9) |
| 273 | do | 269 | local _call_1 = _u539f_u70b9["å˜æ¢"]["æ ¹èŠ‚ç‚¹"]["游æˆå¯¹è±¡"] |
| 274 | local _call_1 = _u539f_u70b9["å˜æ¢"]["æ ¹èŠ‚ç‚¹"]["游æˆå¯¹è±¡"] | 270 | return _call_1["父节点"](_call_1) |
| 275 | return _call_1["父节点"](_call_1) | ||
| 276 | end | ||
| 277 | end | 271 | end |
| 278 | local _call_1 = ((function() | 272 | local _call_1 = ((function() |
| 279 | local _call_1 = ((function() | 273 | local _call_1 = ((function() |
diff --git a/spec/outputs/unicode/multiline_chain.lua b/spec/outputs/unicode/multiline_chain.lua index c1da13f..61e7057 100644 --- a/spec/outputs/unicode/multiline_chain.lua +++ b/spec/outputs/unicode/multiline_chain.lua | |||
| @@ -59,10 +59,8 @@ _u51fd_u6570 = function() | |||
| 59 | return _accum_0 | 59 | return _accum_0 |
| 60 | end | 60 | end |
| 61 | local _anon_func_0 = function(_u53d8_u91cfa) | 61 | local _anon_func_0 = function(_u53d8_u91cfa) |
| 62 | do | 62 | local _call_1 = _u53d8_u91cfa |
| 63 | local _call_1 = _u53d8_u91cfa | 63 | return (_call_1["å˜é‡b"](_call_1, 123))["å˜é‡c"]("abc") |
| 64 | return (_call_1["å˜é‡b"](_call_1, 123))["å˜é‡c"]("abc") | ||
| 65 | end | ||
| 66 | end | 64 | end |
| 67 | local _u51fd_u65701 | 65 | local _u51fd_u65701 |
| 68 | _u51fd_u65701 = function() | 66 | _u51fd_u65701 = function() |
diff --git a/spec/outputs/unicode/syntax.lua b/spec/outputs/unicode/syntax.lua index 1984f40..a13302b 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua | |||
| @@ -286,10 +286,8 @@ _ = 5 - _u4ec0_u4e48(_u65e0_u804a) | |||
| 286 | _u4ec0_u4e48(_u65e0_u804a - 5) | 286 | _u4ec0_u4e48(_u65e0_u804a - 5) |
| 287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 | 287 | _u53d8_u91cfx = _u4f60_u597d - _u4e16_u754c - _u67d0_u7269 |
| 288 | local _anon_func_0 = function(_u4ec0_u4e48) | 288 | local _anon_func_0 = function(_u4ec0_u4e48) |
| 289 | do | 289 | local _call_8 = _u4ec0_u4e48 |
| 290 | local _call_8 = _u4ec0_u4e48 | 290 | return _call_8["é…·"](_call_8, 100) |
| 291 | return _call_8["é…·"](_call_8, 100) | ||
| 292 | end | ||
| 293 | end | 291 | end |
| 294 | (function(_u67d0_u7269) | 292 | (function(_u67d0_u7269) |
| 295 | if _u67d0_u7269 == nil then | 293 | if _u67d0_u7269 == nil then |
diff --git a/spec/outputs/unicode/vararg.lua b/spec/outputs/unicode/vararg.lua index b837006..fc894ff 100644 --- a/spec/outputs/unicode/vararg.lua +++ b/spec/outputs/unicode/vararg.lua | |||
| @@ -125,14 +125,10 @@ local _anon_func_11 = function(_u9879_u76ee, ...) | |||
| 125 | return _tbl_0 | 125 | return _tbl_0 |
| 126 | end | 126 | end |
| 127 | local _anon_func_12 = function(_u51fd_u6570) | 127 | local _anon_func_12 = function(_u51fd_u6570) |
| 128 | do | 128 | return _u51fd_u6570() |
| 129 | return _u51fd_u6570() | ||
| 130 | end | ||
| 131 | end | 129 | end |
| 132 | local _anon_func_13 = function(_u51fd_u6570, ...) | 130 | local _anon_func_13 = function(_u51fd_u6570, ...) |
| 133 | do | 131 | return _u51fd_u6570(...) |
| 134 | return _u51fd_u6570(...) | ||
| 135 | end | ||
| 136 | end | 132 | end |
| 137 | local _anon_func_14 = function(_u51fd_u6570) | 133 | local _anon_func_14 = function(_u51fd_u6570) |
| 138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
| @@ -195,15 +191,11 @@ local _anon_func_23 = function(_u51fd_u6570, ...) | |||
| 195 | return nil | 191 | return nil |
| 196 | end | 192 | end |
| 197 | local _anon_func_24 = function(_u6253_u5370, select, ...) | 193 | local _anon_func_24 = function(_u6253_u5370, select, ...) |
| 198 | do | 194 | _u6253_u5370(select("#", ...)) |
| 199 | _u6253_u5370(select("#", ...)) | 195 | return _u6253_u5370(...) |
| 200 | return _u6253_u5370(...) | ||
| 201 | end | ||
| 202 | end | 196 | end |
| 203 | local _anon_func_25 = function(_u6253_u5370, ...) | 197 | local _anon_func_25 = function(_u6253_u5370, ...) |
| 204 | do | 198 | return _u6253_u5370(...) |
| 205 | return _u6253_u5370(...) | ||
| 206 | end | ||
| 207 | end | 199 | end |
| 208 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | 200 | local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) |
| 209 | if 1 == _u53d8_u91cfx then | 201 | if 1 == _u53d8_u91cfx then |
| @@ -214,9 +206,7 @@ local _anon_func_26 = function(_u53d8_u91cfx, _u8868, _u88682) | |||
| 214 | end | 206 | end |
| 215 | end | 207 | end |
| 216 | local _anon_func_27 = function(_u6253_u5370, ...) | 208 | local _anon_func_27 = function(_u6253_u5370, ...) |
| 217 | do | 209 | return _u6253_u5370(...) |
| 218 | return _u6253_u5370(...) | ||
| 219 | end | ||
| 220 | end | 210 | end |
| 221 | local _anon_func_28 = function(_u6761_u4ef6) | 211 | local _anon_func_28 = function(_u6761_u4ef6) |
| 222 | if _u6761_u4ef6 then | 212 | if _u6761_u4ef6 then |
| @@ -224,10 +214,8 @@ local _anon_func_28 = function(_u6761_u4ef6) | |||
| 224 | end | 214 | end |
| 225 | end | 215 | end |
| 226 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) | 216 | local _anon_func_29 = function(_u6253_u5370, _arg_0, ...) |
| 227 | do | 217 | local _u8868 = _arg_0 |
| 228 | local _u8868 = _arg_0 | 218 | return _u6253_u5370(...) |
| 229 | return _u6253_u5370(...) | ||
| 230 | end | ||
| 231 | end | 219 | end |
| 232 | local _u8fde_u63a5 | 220 | local _u8fde_u63a5 |
| 233 | _u8fde_u63a5 = function(...) | 221 | _u8fde_u63a5 = function(...) |
diff --git a/spec/outputs/upvalue_func.lua b/spec/outputs/upvalue_func.lua index 3181adf..3e088be 100644 --- a/spec/outputs/upvalue_func.lua +++ b/spec/outputs/upvalue_func.lua | |||
| @@ -214,10 +214,8 @@ local _anon_func_1 = function(valueB) | |||
| 214 | end | 214 | end |
| 215 | end | 215 | end |
| 216 | local _anon_func_2 = function(print, select, _arg_0, ...) | 216 | local _anon_func_2 = function(print, select, _arg_0, ...) |
| 217 | do | 217 | local ok = _arg_0 |
| 218 | local ok = _arg_0 | 218 | return print(select(3, ...)) |
| 219 | return print(select(3, ...)) | ||
| 220 | end | ||
| 221 | end | 219 | end |
| 222 | local _anon_func_3 = function(tb) | 220 | local _anon_func_3 = function(tb) |
| 223 | if tb ~= nil then | 221 | if tb ~= nil then |
| @@ -242,11 +240,9 @@ local _anon_func_5 = function(getmetatable, tb) | |||
| 242 | return _obj_0[1 + 1](_obj_0, "abc") | 240 | return _obj_0[1 + 1](_obj_0, "abc") |
| 243 | end | 241 | end |
| 244 | local _anon_func_6 = function(tb) | 242 | local _anon_func_6 = function(tb) |
| 245 | do | 243 | local _call_0 = tb |
| 246 | local _call_0 = tb | 244 | local _call_1 = _call_0["end"](_call_0) |
| 247 | local _call_1 = _call_0["end"](_call_0) | 245 | return _call_1["🤣"](_call_1, 123) |
| 248 | return _call_1["🤣"](_call_1, 123) | ||
| 249 | end | ||
| 250 | end | 246 | end |
| 251 | local _anon_func_7 = function(itemA, listA) | 247 | local _anon_func_7 = function(itemA, listA) |
| 252 | for _index_0 = 1, #listA do | 248 | for _index_0 = 1, #listA do |
| @@ -354,17 +350,13 @@ local _anon_func_16 = function(pairs, tb, tostring) | |||
| 354 | return _tbl_0 | 350 | return _tbl_0 |
| 355 | end | 351 | end |
| 356 | local _anon_func_17 = function(print) | 352 | local _anon_func_17 = function(print) |
| 357 | do | 353 | print(123) |
| 358 | print(123) | 354 | return "abc" |
| 359 | return "abc" | ||
| 360 | end | ||
| 361 | end | 355 | end |
| 362 | local _anon_func_18 = function(print, select, _arg_0, ...) | 356 | local _anon_func_18 = function(print, select, _arg_0, ...) |
| 363 | do | 357 | local success = _arg_0 |
| 364 | local success = _arg_0 | 358 | if success then |
| 365 | if success then | 359 | return print(select('#', ...)) |
| 366 | return print(select('#', ...)) | ||
| 367 | end | ||
| 368 | end | 360 | end |
| 369 | end | 361 | end |
| 370 | local _anon_func_19 = function(cond, i) | 362 | local _anon_func_19 = function(cond, i) |
| @@ -459,11 +451,9 @@ local _anon_func_25 = function(itemA, listA) | |||
| 459 | return false | 451 | return false |
| 460 | end | 452 | end |
| 461 | local _anon_func_24 = function(itemA, listA, tb) | 453 | local _anon_func_24 = function(itemA, listA, tb) |
| 462 | do | 454 | local _call_0 = tb |
| 463 | local _call_0 = tb | 455 | local _call_1 = _call_0["end"](_call_0) |
| 464 | local _call_1 = _call_0["end"](_call_0) | 456 | return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) |
| 465 | return _call_1["🤣"](_call_1, 123 and (#listA > 0 and _anon_func_25(itemA, listA))) | ||
| 466 | end | ||
| 467 | end | 457 | end |
| 468 | GameEngine:onEvent("SomeEvent", function() | 458 | GameEngine:onEvent("SomeEvent", function() |
| 469 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) | 459 | return func(value + (_anon_func_21(cond)) + (_anon_func_22(valueB)) > _anon_func_23(tb) + _anon_func_24(itemA, listA, tb)) |
| @@ -503,13 +493,11 @@ local _anon_func_27 = function(char) | |||
| 503 | return nil | 493 | return nil |
| 504 | end | 494 | end |
| 505 | local _anon_func_28 = function(os, _arg_0, ...) | 495 | local _anon_func_28 = function(os, _arg_0, ...) |
| 506 | do | 496 | local ok = _arg_0 |
| 507 | local ok = _arg_0 | 497 | if ok then |
| 508 | if ok then | 498 | return ... |
| 509 | return ... | 499 | else |
| 510 | else | 500 | return os.exit(1) |
| 511 | return os.exit(1) | ||
| 512 | end | ||
| 513 | end | 501 | end |
| 514 | end | 502 | end |
| 515 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) | 503 | local _anon_func_29 = function(debug_env_after, debug_env_before, env, func) |
diff --git a/spec/outputs/vararg.lua b/spec/outputs/vararg.lua index dabba44..9f97681 100644 --- a/spec/outputs/vararg.lua +++ b/spec/outputs/vararg.lua | |||
| @@ -125,14 +125,10 @@ local _anon_func_11 = function(items, ...) | |||
| 125 | return _tbl_0 | 125 | return _tbl_0 |
| 126 | end | 126 | end |
| 127 | local _anon_func_12 = function(func) | 127 | local _anon_func_12 = function(func) |
| 128 | do | 128 | return func() |
| 129 | return func() | ||
| 130 | end | ||
| 131 | end | 129 | end |
| 132 | local _anon_func_13 = function(func, ...) | 130 | local _anon_func_13 = function(func, ...) |
| 133 | do | 131 | return func(...) |
| 134 | return func(...) | ||
| 135 | end | ||
| 136 | end | 132 | end |
| 137 | local _anon_func_14 = function(func) | 133 | local _anon_func_14 = function(func) |
| 138 | local _accum_0 = { } | 134 | local _accum_0 = { } |
| @@ -195,15 +191,11 @@ local _anon_func_23 = function(func, ...) | |||
| 195 | return nil | 191 | return nil |
| 196 | end | 192 | end |
| 197 | local _anon_func_24 = function(print, select, ...) | 193 | local _anon_func_24 = function(print, select, ...) |
| 198 | do | 194 | print(select("#", ...)) |
| 199 | print(select("#", ...)) | 195 | return print(...) |
| 200 | return print(...) | ||
| 201 | end | ||
| 202 | end | 196 | end |
| 203 | local _anon_func_25 = function(print, ...) | 197 | local _anon_func_25 = function(print, ...) |
| 204 | do | 198 | return print(...) |
| 205 | return print(...) | ||
| 206 | end | ||
| 207 | end | 199 | end |
| 208 | local _anon_func_26 = function(tb, tb2, x) | 200 | local _anon_func_26 = function(tb, tb2, x) |
| 209 | if 1 == x then | 201 | if 1 == x then |
| @@ -214,9 +206,7 @@ local _anon_func_26 = function(tb, tb2, x) | |||
| 214 | end | 206 | end |
| 215 | end | 207 | end |
| 216 | local _anon_func_27 = function(print, ...) | 208 | local _anon_func_27 = function(print, ...) |
| 217 | do | 209 | return print(...) |
| 218 | return print(...) | ||
| 219 | end | ||
| 220 | end | 210 | end |
| 221 | local _anon_func_28 = function(cond) | 211 | local _anon_func_28 = function(cond) |
| 222 | if cond then | 212 | if cond then |
| @@ -224,10 +214,8 @@ local _anon_func_28 = function(cond) | |||
| 224 | end | 214 | end |
| 225 | end | 215 | end |
| 226 | local _anon_func_29 = function(print, _arg_0, ...) | 216 | local _anon_func_29 = function(print, _arg_0, ...) |
| 227 | do | 217 | local tb = _arg_0 |
| 228 | local tb = _arg_0 | 218 | return print(...) |
| 229 | return print(...) | ||
| 230 | end | ||
| 231 | end | 219 | end |
| 232 | local join | 220 | local join |
| 233 | join = function(...) | 221 | join = function(...) |
| @@ -306,3 +294,75 @@ join = function(...) | |||
| 306 | end | 294 | end |
| 307 | return nil | 295 | return nil |
| 308 | end | 296 | end |
| 297 | do | ||
| 298 | local f1 | ||
| 299 | f1 = function(...) | ||
| 300 | local t = { | ||
| 301 | n = select("#", ...), | ||
| 302 | ... | ||
| 303 | } | ||
| 304 | print(t.n) | ||
| 305 | print(#t) | ||
| 306 | for i = 1, t.n do | ||
| 307 | print(t[i]) | ||
| 308 | end | ||
| 309 | end | ||
| 310 | f1(1, 2, 3) | ||
| 311 | f1("a", "b", "c", "d") | ||
| 312 | f1() | ||
| 313 | local f2 | ||
| 314 | f2 = function(...) | ||
| 315 | local args = { | ||
| 316 | n = select("#", ...), | ||
| 317 | ... | ||
| 318 | } | ||
| 319 | print("args count:", args.n) | ||
| 320 | print("args length:", #args) | ||
| 321 | for i = 1, args.n do | ||
| 322 | if args[i] == nil then | ||
| 323 | print("position", i, "is nil") | ||
| 324 | else | ||
| 325 | print("position", i, ":", args[i]) | ||
| 326 | end | ||
| 327 | end | ||
| 328 | end | ||
| 329 | f2(1, nil, 3, nil, 5) | ||
| 330 | local f3 | ||
| 331 | f3 = function(prefix, ...) | ||
| 332 | local items = { | ||
| 333 | n = select("#", ...), | ||
| 334 | ... | ||
| 335 | } | ||
| 336 | local result = { } | ||
| 337 | for i = 1, items.n do | ||
| 338 | result[i] = prefix .. tostring(items[i]) | ||
| 339 | end | ||
| 340 | return result | ||
| 341 | end | ||
| 342 | f3("item_", 1, 2, 3) | ||
| 343 | local f4 | ||
| 344 | f4 = function(...) | ||
| 345 | local empty = { | ||
| 346 | n = select("#", ...), | ||
| 347 | ... | ||
| 348 | } | ||
| 349 | print("empty count:", empty.n) | ||
| 350 | return print("empty length:", #empty) | ||
| 351 | end | ||
| 352 | f4() | ||
| 353 | local process | ||
| 354 | process = function(...) | ||
| 355 | local data = { | ||
| 356 | n = select("#", ...), | ||
| 357 | ... | ||
| 358 | } | ||
| 359 | local sum = 0 | ||
| 360 | for i = 1, data.n do | ||
| 361 | if type(data[i]) == "number" then | ||
| 362 | sum = sum + data[i] | ||
| 363 | end | ||
| 364 | end | ||
| 365 | return sum | ||
| 366 | end | ||
| 367 | return process(1, 2, 3, "skip", 5) | ||
| 368 | end | ||
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua index 20c5d44..530915e 100644 --- a/spec/outputs/with.lua +++ b/spec/outputs/with.lua | |||
| @@ -192,26 +192,61 @@ do | |||
| 192 | local _with_0 = item | 192 | local _with_0 = item |
| 193 | do | 193 | do |
| 194 | local _accum_0 | 194 | local _accum_0 |
| 195 | while true do | 195 | repeat |
| 196 | if _with_0.id > 0 then | 196 | if _with_0.id > 0 then |
| 197 | _accum_0 = _with_0.content | 197 | _accum_0 = _with_0.content |
| 198 | break | 198 | break |
| 199 | end | 199 | end |
| 200 | end | 200 | until true |
| 201 | _with_0 = _accum_0 | 201 | _with_0 = _accum_0 |
| 202 | end | 202 | end |
| 203 | return _with_0 | 203 | return _with_0 |
| 204 | end)()) | 204 | end)()) |
| 205 | local a | 205 | local a |
| 206 | local _with_0 = tb | 206 | do |
| 207 | local _with_0 = tb | ||
| 208 | do | ||
| 209 | local _accum_0 | ||
| 210 | repeat | ||
| 211 | if _with_0.v then | ||
| 212 | _accum_0 = _with_0.a | ||
| 213 | break | ||
| 214 | end | ||
| 215 | until true | ||
| 216 | _with_0 = _accum_0 | ||
| 217 | end | ||
| 218 | a = _with_0 | ||
| 219 | end | ||
| 207 | local _accum_0 | 220 | local _accum_0 |
| 208 | while true do | 221 | while true do |
| 209 | if _with_0.v then | 222 | local _with_0 = tb |
| 210 | _accum_0 = _with_0.a | 223 | local _accum_1 |
| 211 | break | 224 | repeat |
| 225 | if _with_0 ~= nil then | ||
| 226 | _accum_1 = 1 | ||
| 227 | break | ||
| 228 | end | ||
| 229 | until true | ||
| 230 | _with_0 = _accum_1 | ||
| 231 | _accum_0 = _with_0 | ||
| 232 | break | ||
| 233 | end | ||
| 234 | a = _accum_0 | ||
| 235 | end | ||
| 236 | do | ||
| 237 | local a | ||
| 238 | local _accum_0 | ||
| 239 | for i = 1, 100 do | ||
| 240 | local x = tb[i] | ||
| 241 | if x ~= nil then | ||
| 242 | local _des_0 = 1 | ||
| 243 | if _des_0 then | ||
| 244 | x.id = _des_0 | ||
| 245 | _accum_0 = x | ||
| 246 | break | ||
| 247 | end | ||
| 212 | end | 248 | end |
| 213 | end | 249 | end |
| 214 | _with_0 = _accum_0 | 250 | a = _accum_0 |
| 215 | a = _with_0 | ||
| 216 | end | 251 | end |
| 217 | return nil | 252 | return nil |
diff --git a/src/3rdParty/colib/LICENSE b/src/3rdParty/colib/LICENSE new file mode 100755 index 0000000..e0eddeb --- /dev/null +++ b/src/3rdParty/colib/LICENSE | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | MIT License | ||
| 2 | |||
| 3 | Copyright (c) 2020 colin | ||
| 4 | |||
| 5 | Permission is hereby granted, free of charge, to any person obtaining a copy | ||
| 6 | of this software and associated documentation files (the "Software"), to deal | ||
| 7 | in the Software without restriction, including without limitation the rights | ||
| 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||
| 9 | copies of the Software, and to permit persons to whom the Software is | ||
| 10 | furnished to do so, subject to the following conditions: | ||
| 11 | |||
| 12 | The above copyright notice and this permission notice shall be included in all | ||
| 13 | copies or substantial portions of the Software. | ||
| 14 | |||
| 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||
| 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||
| 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||
| 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE | ||
| 21 | SOFTWARE. | ||
diff --git a/src/3rdParty/colib/ljson.c b/src/3rdParty/colib/ljson.c new file mode 100644 index 0000000..4daba07 --- /dev/null +++ b/src/3rdParty/colib/ljson.c | |||
| @@ -0,0 +1,925 @@ | |||
| 1 | /** | ||
| 2 | * jsonè§£æžå™¨ï¼šåªæ”¯æŒutf-8æ ¼å¼ï¼ŒLuaåªæ”¯æŒ64ä½çš„æ•°å— | ||
| 3 | */ | ||
| 4 | #define LUA_LIB | ||
| 5 | #include <stdlib.h> | ||
| 6 | #include <string.h> | ||
| 7 | #include <stdint.h> | ||
| 8 | #include <stdio.h> | ||
| 9 | #include <ctype.h> | ||
| 10 | #include <assert.h> | ||
| 11 | #include <errno.h> | ||
| 12 | #include <setjmp.h> | ||
| 13 | #include <ctype.h> | ||
| 14 | #include <limits.h> | ||
| 15 | #include <float.h> | ||
| 16 | #include <math.h> | ||
| 17 | #include "lua.h" | ||
| 18 | #include "lauxlib.h" | ||
| 19 | |||
| 20 | #if LUA_VERSION_NUM > 501 | ||
| 21 | #ifndef LUA_COMPAT_5_1 | ||
| 22 | #ifndef lua_objlen | ||
| 23 | #define lua_objlen lua_rawlen | ||
| 24 | #endif // lua_objlen | ||
| 25 | #endif // LUA_COMPAT_5_1 | ||
| 26 | #endif // LUA_VERSION_NUM | ||
| 27 | |||
| 28 | // 内å˜åˆ†é…å‡½æ•°ï¼Œæ–¹ä¾¿æ›¿æ¢ | ||
| 29 | #define co_malloc malloc | ||
| 30 | #define co_free free | ||
| 31 | #define co_realloc realloc | ||
| 32 | #define co_calloc calloc | ||
| 33 | |||
| 34 | |||
| 35 | #if !defined(likely) | ||
| 36 | #if defined(__GNUC__) | ||
| 37 | #define likely(x) (__builtin_expect(((x) != 0), 1)) | ||
| 38 | #define unlikely(x) (__builtin_expect(((x) != 0), 0)) | ||
| 39 | #else | ||
| 40 | #define likely(x) (x) | ||
| 41 | #define unlikely(x) (x) | ||
| 42 | #endif | ||
| 43 | |||
| 44 | #endif | ||
| 45 | |||
| 46 | //----------------------------------------------------------------------------- | ||
| 47 | // membuffer | ||
| 48 | |||
| 49 | #define STACK_BUFF_SIZE 512 | ||
| 50 | |||
| 51 | typedef struct membuffer { | ||
| 52 | char *b; // 内å˜buffer | ||
| 53 | size_t sz; // buffer已用长度 | ||
| 54 | size_t cap; // bufferå®žé™…å¤§å° | ||
| 55 | char s[STACK_BUFF_SIZE]; | ||
| 56 | } membuffer_t; | ||
| 57 | |||
| 58 | // åˆå§‹åŒ–buffer | ||
| 59 | static inline void membuffer_init(membuffer_t *buff) { | ||
| 60 | buff->b = buff->s; | ||
| 61 | buff->cap = STACK_BUFF_SIZE; | ||
| 62 | buff->sz = 0; | ||
| 63 | } | ||
| 64 | |||
| 65 | static inline void membuffer_add_size(membuffer_t *buff, size_t sz) { | ||
| 66 | buff->sz += sz; | ||
| 67 | } | ||
| 68 | |||
| 69 | static inline void membuffer_reset(membuffer_t *buff) { | ||
| 70 | buff->sz = 0; | ||
| 71 | } | ||
| 72 | |||
| 73 | static inline void membuffer_free(membuffer_t *buff) { | ||
| 74 | if (buff->b && buff->b != buff->s) { | ||
| 75 | co_free(buff->b); | ||
| 76 | buff->b = NULL; | ||
| 77 | } | ||
| 78 | } | ||
| 79 | |||
| 80 | static inline void _membuffer_grow(membuffer_t *buff, size_t needsz) { | ||
| 81 | if (buff->cap < needsz) { | ||
| 82 | size_t newcap = buff->cap * 2; | ||
| 83 | if (newcap < needsz) | ||
| 84 | newcap = needsz; | ||
| 85 | if (buff->b == buff->s) { | ||
| 86 | buff->b = (char*)co_malloc(newcap); | ||
| 87 | memcpy(buff->b, buff->s, buff->sz); | ||
| 88 | } else { | ||
| 89 | buff->b = (char*)co_realloc(buff->b, newcap); | ||
| 90 | } | ||
| 91 | buff->cap = newcap; | ||
| 92 | } | ||
| 93 | } | ||
| 94 | |||
| 95 | // ç¡®ä¿ç¼“å˜ä¸è¿˜æœ‰szçš„å¯ç”¨ç©ºé—´ | ||
| 96 | static inline void membuffer_ensure_space(membuffer_t *buff, size_t sz) { | ||
| 97 | if (buff->sz + sz > buff->cap) { | ||
| 98 | _membuffer_grow(buff, buff->sz+sz); | ||
| 99 | } | ||
| 100 | } | ||
| 101 | |||
| 102 | // 压入一个å—符 | ||
| 103 | static inline void membuffer_putc(membuffer_t *buff, char c) { | ||
| 104 | membuffer_ensure_space(buff, 1); | ||
| 105 | buff->b[buff->sz++] = c; | ||
| 106 | } | ||
| 107 | |||
| 108 | // å†™å…¥ä¸€æ®µå†…å˜ | ||
| 109 | static inline void membuffer_putb(membuffer_t *buff, const void *b, size_t sz) { | ||
| 110 | membuffer_ensure_space(buff, sz); | ||
| 111 | memcpy(buff->b + buff->sz, b, sz); | ||
| 112 | buff->sz += sz; | ||
| 113 | } | ||
| 114 | |||
| 115 | // 压入一个å—ç¬¦ï¼šä¸æ£€æŸ¥ç©ºé—´(ä¸å®‰å…¨ç‰ˆæœ¬) | ||
| 116 | static inline void membuffer_putc_unsafe(membuffer_t *buff, char c) { | ||
| 117 | buff->b[buff->sz++] = c; | ||
| 118 | } | ||
| 119 | |||
| 120 | #if LUA_VERSION_NUM > 501 | ||
| 121 | // 写入一段内å˜ï¼šä¸æ£€æŸ¥ç©ºé—´(ä¸å®‰å…¨ç‰ˆæœ¬) | ||
| 122 | static inline void membuffer_putb_unsafe(membuffer_t *buff, const void *b, size_t sz) { | ||
| 123 | memcpy(buff->b + buff->sz, b, sz); | ||
| 124 | buff->sz += sz; | ||
| 125 | } | ||
| 126 | #endif | ||
| 127 | |||
| 128 | // å–当å‰çš„æŒ‡é’ˆ | ||
| 129 | static inline char* membuffer_getp(membuffer_t *buff) { | ||
| 130 | return buff->b + buff->sz; | ||
| 131 | } | ||
| 132 | |||
| 133 | //----------------------------------------------------------------------------- | ||
| 134 | // parser | ||
| 135 | |||
| 136 | //------------------------------------- | ||
| 137 | // 与Lua相关的代ç | ||
| 138 | |||
| 139 | static inline void l_add_object(lua_State *L) { | ||
| 140 | luaL_checkstack(L, 6, NULL); | ||
| 141 | lua_createtable(L, 0, 4); | ||
| 142 | } | ||
| 143 | static inline void l_begin_pair(lua_State *L, const char *k, size_t sz) { | ||
| 144 | lua_pushlstring(L, k, sz); | ||
| 145 | } | ||
| 146 | static inline void l_end_pair(lua_State *L) { | ||
| 147 | lua_rawset(L, -3); | ||
| 148 | } | ||
| 149 | static inline void l_add_array(lua_State *L) { | ||
| 150 | luaL_checkstack(L, 6, NULL); | ||
| 151 | lua_createtable(L, 4, 0); | ||
| 152 | } | ||
| 153 | static inline void l_add_index(lua_State *L, int i) { | ||
| 154 | lua_rawseti(L, -2, i+1); | ||
| 155 | } | ||
| 156 | static inline void l_add_string(lua_State *L, const char *s, size_t sz) { | ||
| 157 | lua_pushlstring(L, s, sz); | ||
| 158 | } | ||
| 159 | static inline void l_add_float(lua_State *L, double f) { | ||
| 160 | lua_pushnumber(L, (lua_Number)f); | ||
| 161 | } | ||
| 162 | static inline void l_add_integer(lua_State *L, int64_t i) { | ||
| 163 | lua_pushinteger(L, (lua_Integer)i); | ||
| 164 | } | ||
| 165 | static inline void l_add_boolean(lua_State *L, int b) { | ||
| 166 | lua_pushboolean(L, b); | ||
| 167 | } | ||
| 168 | static inline void l_add_null(lua_State *L) { | ||
| 169 | lua_pushlightuserdata(L, NULL); | ||
| 170 | } | ||
| 171 | static inline void l_error(lua_State *L, const char *msg) { | ||
| 172 | luaL_error(L, msg); | ||
| 173 | } | ||
| 174 | |||
| 175 | // è§£æžäº‹ä»¶ | ||
| 176 | #define ON_ADD_OBJECT(ud) l_add_object((lua_State*)(ud)) | ||
| 177 | #define ON_BEGIN_PAIR(ud, k, sz) l_begin_pair((lua_State*)(ud), k, sz) | ||
| 178 | #define ON_END_PAIR(ud) l_end_pair((lua_State*)(ud)) | ||
| 179 | #define ON_ADD_ARRAY(ud) l_add_array((lua_State*)(ud)) | ||
| 180 | #define ON_ADD_INDEX(ud, i) l_add_index((lua_State*)(ud), i) | ||
| 181 | #define ON_ADD_STRING(ud, s, sz) l_add_string((lua_State*)(ud), s, sz) | ||
| 182 | #define ON_ADD_FLOAT(ud, f) l_add_float((lua_State*)(ud), f) | ||
| 183 | #define ON_ADD_INTEGER(ud, i) l_add_integer((lua_State*)(ud), i) | ||
| 184 | #define ON_ADD_BOOLEAN(ud, b) l_add_boolean((lua_State*)(ud), b) | ||
| 185 | #define ON_ADD_NULL(ud) l_add_null((lua_State*)(ud)) | ||
| 186 | #define ON_ERROR(ud, msg) l_error((lua_State*)(ud), msg) | ||
| 187 | |||
| 188 | //------------------------------------- | ||
| 189 | // è§£æžjson,这部分代ç 与Luaæ— å…³ï¼Œæ˜¯é€šç”¨çš„è§£æžå™¨ï¼›å¦‚æžœè¦ç§»æ¤è¿™éƒ¨åˆ†ä»£ç ï¼Œéœ€è¦æŠŠ //>>> 开头的注释去掉 | ||
| 190 | |||
| 191 | // 错误消æ¯çš„å¤§å° | ||
| 192 | #define ERRMSG_SIZE 256 | ||
| 193 | |||
| 194 | // jsonè§£æžå™¨ | ||
| 195 | typedef struct { | ||
| 196 | const char *str; // jsonå—符串 | ||
| 197 | const char *ptr; // jsonå—ç¬¦ä¸²è§£æžæŒ‡é’ˆ | ||
| 198 | void *ud; // è§£æžäº‹ä»¶çš„ç”¨æˆ·æ•°æ® | ||
| 199 | membuffer_t buff; // ä¸´æ—¶ç¼“å˜ | ||
| 200 | int curdepth; // 当å‰å±‚次 | ||
| 201 | int maxdepth; // 最大层次 | ||
| 202 | int allowcomment; // 是å¦å…许注释 | ||
| 203 | char errmsg[ERRMSG_SIZE]; // ä¿å˜é”™è¯¯æ¶ˆæ¯ | ||
| 204 | //>>>jmp_buf jb; // 用于实现从解æžä¸å‡ºé”™ç›´æŽ¥è·³å‡º | ||
| 205 | } json_parser_t; | ||
| 206 | |||
| 207 | static inline void parser_init(json_parser_t *parser, const char *str, size_t size, void *ud, | ||
| 208 | int maxdepth, int allowcomment) { | ||
| 209 | membuffer_init(&parser->buff); | ||
| 210 | membuffer_ensure_space(&parser->buff, size); | ||
| 211 | parser->str = str; | ||
| 212 | parser->ptr = str; | ||
| 213 | parser->ud = ud; | ||
| 214 | parser->maxdepth = maxdepth; | ||
| 215 | parser->curdepth = 0; | ||
| 216 | parser->allowcomment = allowcomment; | ||
| 217 | } | ||
| 218 | |||
| 219 | static inline void parser_free(json_parser_t *parser) { | ||
| 220 | membuffer_free(&parser->buff); | ||
| 221 | } | ||
| 222 | |||
| 223 | // 抛出错误 | ||
| 224 | static void parser_throw_error(json_parser_t *parser, const char *fmt, ...) { | ||
| 225 | membuffer_free(&parser->buff); | ||
| 226 | va_list arg; | ||
| 227 | va_start(arg, fmt); | ||
| 228 | vsnprintf(parser->errmsg, ERRMSG_SIZE, fmt, arg); | ||
| 229 | va_end(arg); | ||
| 230 | ON_ERROR(parser->ud, parser->errmsg); | ||
| 231 | // 直接跳出解æžä»£ç ,由于Luaçš„lua_error也是用longjmp,所以下é¢çš„ä»£ç æ²¡æœ‰æœºä¼šæ‰§è¡Œåˆ°ã€‚但其他è¯è¨€å°±ä¸ä¸€å®šã€‚ | ||
| 232 | //>>>longjmp(parser->jb, 1); | ||
| 233 | } | ||
| 234 | |||
| 235 | // è¾…åŠ©å® | ||
| 236 | #define peekchar(p) (*(p)->ptr) | ||
| 237 | #define skipchar(p) (++(p)->ptr) | ||
| 238 | #define get_and_next(p) (*(p)->ptr++) | ||
| 239 | #define next_and_get(p) (*(++(p)->ptr)) | ||
| 240 | #define savechar(p, c) membuffer_putc_unsafe(&(p)->buff, (c)) | ||
| 241 | #define currpos(p) (size_t)((p)->ptr - (p)->str) | ||
| 242 | |||
| 243 | // å–è§£æžåˆ°çš„错误内容 | ||
| 244 | static const char* parser_error_content(json_parser_t *p) { | ||
| 245 | size_t n = currpos(p); | ||
| 246 | if (n > 50) n = 50; // 调整这个数获得更长的内容 | ||
| 247 | membuffer_reset(&p->buff); | ||
| 248 | membuffer_putb(&p->buff, p->ptr - n, n); | ||
| 249 | membuffer_putc(&p->buff, '\0'); | ||
| 250 | return p->buff.b; | ||
| 251 | } | ||
| 252 | |||
| 253 | // å¢žåŠ æ·±åº¦ | ||
| 254 | static inline void parser_add_depth(json_parser_t *p) { | ||
| 255 | p->curdepth++; | ||
| 256 | if (p->curdepth >= p->maxdepth) | ||
| 257 | parser_throw_error(p, "Too many nested data, max depth is %d, at: %s[:%lu]", p->maxdepth, | ||
| 258 | parser_error_content(p), currpos(p)); | ||
| 259 | } | ||
| 260 | |||
| 261 | static inline void parser_skip_whitespaces(json_parser_t *p) { | ||
| 262 | // colin: è¦æ”¯æŒæ³¨é‡Šï¼Œè¯·å°†ä¸‹é¢æ³¨é‡ŠåŽ»æŽ‰ | ||
| 263 | // if (likely(!p->allowcomment)) { | ||
| 264 | char ch = peekchar(p); | ||
| 265 | while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') | ||
| 266 | ch = next_and_get(p); | ||
| 267 | // } else { | ||
| 268 | // char ch = peekchar(p); | ||
| 269 | // for (;;) { | ||
| 270 | // while (ch == ' ' || ch == '\t' || ch == '\n' || ch == '\r') | ||
| 271 | // ch = next_and_get(p); | ||
| 272 | // if (ch == '/') { | ||
| 273 | // ch = next_and_get(p); | ||
| 274 | // if (ch == '/') { | ||
| 275 | // ch = next_and_get(p); | ||
| 276 | // while (ch != '\n' && ch != '\r' && ch != '\0') | ||
| 277 | // ch = next_and_get(p); | ||
| 278 | // continue; | ||
| 279 | // } else { | ||
| 280 | // parser_throw_error(p, "Invalid comment, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 281 | // } | ||
| 282 | // } | ||
| 283 | // break; | ||
| 284 | // } | ||
| 285 | // } | ||
| 286 | } | ||
| 287 | |||
| 288 | static inline void parser_expect_char(json_parser_t *p, char c) { | ||
| 289 | if (likely(peekchar(p) == c)) | ||
| 290 | skipchar(p); | ||
| 291 | else | ||
| 292 | parser_throw_error(p, "Expect '%c' at: %s[:%lu]", c, parser_error_content(p), currpos(p)); | ||
| 293 | } | ||
| 294 | |||
| 295 | static inline void parser_process_false(json_parser_t *p) { | ||
| 296 | if (likely(p->ptr[0] == 'a' && p->ptr[1] == 'l' && p->ptr[2] == 's' && p->ptr[3] == 'e')) { | ||
| 297 | p->ptr += 4; | ||
| 298 | ON_ADD_BOOLEAN(p->ud, 0); | ||
| 299 | } else { | ||
| 300 | parser_throw_error(p, "Invalid boolean, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 301 | } | ||
| 302 | } | ||
| 303 | |||
| 304 | static inline void parser_process_true(json_parser_t *p) { | ||
| 305 | if (likely(p->ptr[0] == 'r' && p->ptr[1] == 'u' && p->ptr[2] == 'e')) { | ||
| 306 | p->ptr += 3; | ||
| 307 | ON_ADD_BOOLEAN(p->ud, 1); | ||
| 308 | } else { | ||
| 309 | parser_throw_error(p, "Invalid boolean, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 310 | } | ||
| 311 | } | ||
| 312 | |||
| 313 | static inline void parser_process_null(json_parser_t *p) { | ||
| 314 | if (likely(p->ptr[0] == 'u' && p->ptr[1] == 'l' && p->ptr[2] == 'l')) { | ||
| 315 | p->ptr += 3; | ||
| 316 | ON_ADD_NULL(p->ud); | ||
| 317 | } else { | ||
| 318 | parser_throw_error(p, "Invalid null, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 319 | } | ||
| 320 | } | ||
| 321 | |||
| 322 | static inline uint32_t parser_read_hex(json_parser_t *p) { | ||
| 323 | uint32_t cp = 0; | ||
| 324 | unsigned char ch; | ||
| 325 | int i = 4; | ||
| 326 | while (i--) { | ||
| 327 | ch = (unsigned char)get_and_next(p); | ||
| 328 | if ('0' <= ch && ch <= '9') | ||
| 329 | ch -= '0'; | ||
| 330 | else if (ch >= 'a' && ch <= 'f') | ||
| 331 | ch = ch - 'a' + 10; | ||
| 332 | else if (ch >= 'A' && ch <= 'F') | ||
| 333 | ch = ch - 'A' + 10; | ||
| 334 | else { | ||
| 335 | parser_throw_error(p, "Invalid utf8 escape sequence, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 336 | return cp; | ||
| 337 | } | ||
| 338 | cp = (cp << 4) + ch; | ||
| 339 | } | ||
| 340 | return cp; | ||
| 341 | } | ||
| 342 | |||
| 343 | static inline void parser_process_utf8esc(json_parser_t *p) { | ||
| 344 | uint32_t cp = parser_read_hex(p); | ||
| 345 | // UTF-16 surrogate pairs, see https://unicodebook.readthedocs.io/unicode_encodings.html#utf-16-surrogate-pairs | ||
| 346 | if (cp >= 0xD800 && cp <= 0xDBFF) { | ||
| 347 | char p0 = p->ptr[0]; | ||
| 348 | char p1 = p->ptr[1]; | ||
| 349 | if (p0 != '\\' || p1 != 'u') | ||
| 350 | parser_throw_error(p, "Invalid utf8 escape sequence, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 351 | p->ptr += 2; | ||
| 352 | uint32_t cp2 = parser_read_hex(p); | ||
| 353 | if (cp2 < 0xDC00 || cp2 > 0xDFFF) | ||
| 354 | parser_throw_error(p, "Invalid utf8 escape sequence, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 355 | cp = 0x10000 + (((cp & 0x03FF) << 10) | (cp2 & 0x03FF)); | ||
| 356 | } | ||
| 357 | if (cp < 0x80) { | ||
| 358 | membuffer_putc_unsafe(&p->buff, (char)cp); | ||
| 359 | } else if (cp < 0x800) { | ||
| 360 | membuffer_putc_unsafe(&p->buff, 0xC0 | (cp >> 6)); | ||
| 361 | membuffer_putc_unsafe(&p->buff, 0x80 | (cp & 0x3F)); | ||
| 362 | } else if (cp < 0x10000) { | ||
| 363 | membuffer_putc_unsafe(&p->buff, 0xE0 | (cp >> 12)); | ||
| 364 | membuffer_putc_unsafe(&p->buff, 0x80 | ((cp >> 6) & 0x3F)); | ||
| 365 | membuffer_putc_unsafe(&p->buff, 0x80 | (cp & 0x3F)); | ||
| 366 | } else { | ||
| 367 | membuffer_putc_unsafe(&p->buff, 0xF0 | (cp >> 18)); | ||
| 368 | membuffer_putc_unsafe(&p->buff, 0x80 | ((cp >> 12) & 0x3F)); | ||
| 369 | membuffer_putc_unsafe(&p->buff, 0x80 | ((cp >> 6) & 0x3F)); | ||
| 370 | membuffer_putc_unsafe(&p->buff, 0x80 | (cp & 0x3F)); | ||
| 371 | } | ||
| 372 | } | ||
| 373 | |||
| 374 | static const char escape2char[256] = { | ||
| 375 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 0~19 | ||
| 376 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\"',0, 0, 0, 0, 0, // 20~39 | ||
| 377 | 0, 0, 0, 0, 0, 0, 0, '/', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40~59 | ||
| 378 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60~79 | ||
| 379 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\',0, 0, 0, 0, 0, '\b',0, // 80~99 | ||
| 380 | 0, 0, '\f',0, 0, 0, 0, 0, 0, 0, '\n',0, 0, 0, '\r',0, '\t',0, 0, 0, // 100~119 | ||
| 381 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120~139 | ||
| 382 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140~159 | ||
| 383 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160~179 | ||
| 384 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180~199 | ||
| 385 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200~219 | ||
| 386 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220~239 | ||
| 387 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240~256 | ||
| 388 | }; | ||
| 389 | |||
| 390 | static inline void parser_process_string(json_parser_t *p) { | ||
| 391 | membuffer_reset(&p->buff); | ||
| 392 | char ch = get_and_next(p); | ||
| 393 | for (;;) { | ||
| 394 | if (ch == '\\') { | ||
| 395 | unsigned char nch = (unsigned char)peekchar(p); | ||
| 396 | if (likely(escape2char[nch])) { | ||
| 397 | savechar(p, escape2char[nch]); | ||
| 398 | skipchar(p); | ||
| 399 | } else if (nch == 'u') { | ||
| 400 | skipchar(p); | ||
| 401 | parser_process_utf8esc(p); | ||
| 402 | } else { | ||
| 403 | parser_throw_error(p, "Invalid escape sequence, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 404 | } | ||
| 405 | } else if (ch == '"') { | ||
| 406 | break; | ||
| 407 | } else if ((unsigned char)ch < 0x20) { | ||
| 408 | parser_throw_error(p, "Invalid string, at: %s[:%lu]", parser_error_content(p), currpos(p)); | ||
| 409 | } else { | ||
| 410 | savechar(p, ch); | ||
| 411 | } | ||
| 412 | ch = get_and_next(p); | ||
| 413 | } | ||
| 414 | } | ||
| 415 | |||
| 416 | #define invalid_number(p) parser_throw_error(p, "Invalid value, at: %s[:%lu]", parser_error_content(p), currpos(p)) | ||
| 417 | #define MAXBY10 (int64_t)(922337203685477580) | ||
| 418 | #define MAXLASTD (int)(7) | ||
| 419 | static double powersOf10[] = {10., 100., 1.0e4, 1.0e8, 1.0e16, 1.0e32, 1.0e64, 1.0e128, 1.0e256}; | ||
| 420 | static inline void parser_process_number(json_parser_t *p, char ch) { | ||
| 421 | double db; // 浮点数 | ||
| 422 | int64_t in = 0; // 整型值 | ||
| 423 | int isdouble = 0; // æ˜¯å¦æ˜¯æµ®ç‚¹æ•° | ||
| 424 | int neg = 0; // æ˜¯å¦æ˜¯è´Ÿæ•° | ||
| 425 | int exponent = 0; // æŒ‡æ•°ä½æ•° | ||
| 426 | |||
| 427 | if (ch == '-') { // 负值 | ||
| 428 | neg = 1; | ||
| 429 | ch = get_and_next(p); | ||
| 430 | } | ||
| 431 | if (unlikely(ch == '0')) { // 0开头的åŽé¢åªèƒ½æ˜¯ï¼š.eE或\0 | ||
| 432 | ch = peekchar(p); | ||
| 433 | } else if (likely(ch >= '1' && ch <= '9')) { | ||
| 434 | in = ch - '0'; | ||
| 435 | ch = peekchar(p); | ||
| 436 | while (ch >= '0' && ch <= '9') { | ||
| 437 | if (unlikely(in >= MAXBY10 && (in > MAXBY10 || (ch - '0') > MAXLASTD + neg))) { // 更大的数å—就用浮点数表示 | ||
| 438 | isdouble = 1; | ||
| 439 | db = (double)in; | ||
| 440 | do { | ||
| 441 | db = db * 10.0 + (ch - '0'); | ||
| 442 | ch = next_and_get(p); | ||
| 443 | } while (ch >= '0' && ch <= '9'); | ||
| 444 | break; | ||
| 445 | } | ||
| 446 | in = in * 10 + (ch - '0'); | ||
| 447 | ch = next_and_get(p); | ||
| 448 | } | ||
| 449 | } else { | ||
| 450 | invalid_number(p); | ||
| 451 | } | ||
| 452 | |||
| 453 | if (ch == '.') { // å°æ•°ç‚¹éƒ¨åˆ† | ||
| 454 | if (likely(!isdouble)) { | ||
| 455 | isdouble = 1; | ||
| 456 | db = (double)in; | ||
| 457 | } | ||
| 458 | ch = next_and_get(p); | ||
| 459 | if (unlikely(!(ch >= '0' && ch <= '9'))) | ||
| 460 | invalid_number(p); // .åŽé¢ä¸€å®šæ˜¯æ•°å— | ||
| 461 | do { | ||
| 462 | db = db * 10. + (ch - '0'); | ||
| 463 | exponent--; | ||
| 464 | ch = next_and_get(p); | ||
| 465 | } while (ch >= '0' && ch <= '9'); | ||
| 466 | } | ||
| 467 | |||
| 468 | if (ch == 'e' || ch == 'E') { // 指数部分 | ||
| 469 | if (!isdouble) { // 有e强制认为是浮点数 | ||
| 470 | isdouble = 1; | ||
| 471 | db = (double)in; | ||
| 472 | } | ||
| 473 | ch = next_and_get(p); | ||
| 474 | int eneg = 0; | ||
| 475 | if (ch == '-') { | ||
| 476 | eneg = 1; | ||
| 477 | ch = next_and_get(p); | ||
| 478 | } else if (ch == '+') { | ||
| 479 | ch = next_and_get(p); | ||
| 480 | } | ||
| 481 | if (unlikely(!(ch >= '0' && ch <= '9'))) | ||
| 482 | invalid_number(p); // åŽé¢ä¸€å®šæ˜¯æ•°å— | ||
| 483 | int exp = 0; | ||
| 484 | do { | ||
| 485 | exp = exp * 10. + (ch - '0'); | ||
| 486 | ch = next_and_get(p); | ||
| 487 | } while (ch >= '0' && ch <= '9'); | ||
| 488 | exponent += eneg ? (-exp) : (exp); | ||
| 489 | } | ||
| 490 | |||
| 491 | if (isdouble) { | ||
| 492 | int n = exponent < 0 ? -exponent : exponent; | ||
| 493 | if (unlikely(n>511)) | ||
| 494 | n = 511; // inf | ||
| 495 | double p10 = 1.0; | ||
| 496 | double *d; | ||
| 497 | for (d = powersOf10; n != 0; n >>= 1, d += 1) { | ||
| 498 | if (n & 1) p10 *= *d; | ||
| 499 | } | ||
| 500 | if (exponent < 0) | ||
| 501 | db /= p10; | ||
| 502 | else | ||
| 503 | db *= p10; | ||
| 504 | if (neg) db = -db; | ||
| 505 | ON_ADD_FLOAT(p->ud, db); | ||
| 506 | } else { | ||
| 507 | if (neg) in = -in; | ||
| 508 | ON_ADD_INTEGER(p->ud, in); | ||
| 509 | } | ||
| 510 | } | ||
| 511 | |||
| 512 | static void parser_process_value(json_parser_t *p); | ||
| 513 | |||
| 514 | static inline void parser_process_object(json_parser_t *p) { | ||
| 515 | parser_add_depth(p); | ||
| 516 | ON_ADD_OBJECT(p->ud); | ||
| 517 | parser_skip_whitespaces(p); | ||
| 518 | char ch = peekchar(p); | ||
| 519 | if (ch == '}') { | ||
| 520 | skipchar(p); | ||
| 521 | p->curdepth--; | ||
| 522 | return; | ||
| 523 | } | ||
| 524 | for (;;) { | ||
| 525 | parser_expect_char(p, '"'); | ||
| 526 | parser_process_string(p); // key | ||
| 527 | ON_BEGIN_PAIR(p->ud, p->buff.b, p->buff.sz); | ||
| 528 | |||
| 529 | parser_skip_whitespaces(p); | ||
| 530 | parser_expect_char(p, ':'); | ||
| 531 | |||
| 532 | parser_process_value(p); // value | ||
| 533 | ON_END_PAIR(p->ud); | ||
| 534 | |||
| 535 | parser_skip_whitespaces(p); | ||
| 536 | if (peekchar(p) == '}') { | ||
| 537 | skipchar(p); | ||
| 538 | p->curdepth--; | ||
| 539 | return; | ||
| 540 | } | ||
| 541 | else { | ||
| 542 | parser_expect_char(p, ','); | ||
| 543 | parser_skip_whitespaces(p); | ||
| 544 | } | ||
| 545 | } | ||
| 546 | } | ||
| 547 | |||
| 548 | static inline void parser_process_array(json_parser_t *p) { | ||
| 549 | parser_add_depth(p); | ||
| 550 | ON_ADD_ARRAY(p->ud); | ||
| 551 | parser_skip_whitespaces(p); | ||
| 552 | char ch = peekchar(p); | ||
| 553 | if (ch == ']') { | ||
| 554 | skipchar(p); | ||
| 555 | p->curdepth--; | ||
| 556 | return; | ||
| 557 | } | ||
| 558 | int i; | ||
| 559 | for (i = 0; ;++i) { | ||
| 560 | parser_process_value(p); | ||
| 561 | ON_ADD_INDEX(p->ud, i); | ||
| 562 | |||
| 563 | parser_skip_whitespaces(p); | ||
| 564 | if (peekchar(p) == ']') { | ||
| 565 | skipchar(p); | ||
| 566 | p->curdepth--; | ||
| 567 | return; | ||
| 568 | } | ||
| 569 | else { | ||
| 570 | parser_expect_char(p, ','); | ||
| 571 | } | ||
| 572 | } | ||
| 573 | } | ||
| 574 | |||
| 575 | static void parser_process_value(json_parser_t *p) { | ||
| 576 | parser_skip_whitespaces(p); | ||
| 577 | char ch = get_and_next(p); | ||
| 578 | switch (ch) { | ||
| 579 | case 'f': | ||
| 580 | parser_process_false(p); | ||
| 581 | break; | ||
| 582 | case 't': | ||
| 583 | parser_process_true(p); | ||
| 584 | break; | ||
| 585 | case 'n': | ||
| 586 | parser_process_null(p); | ||
| 587 | break; | ||
| 588 | case '"': | ||
| 589 | parser_process_string(p); | ||
| 590 | ON_ADD_STRING(p->ud, p->buff.b, p->buff.sz); | ||
| 591 | break; | ||
| 592 | case '{': | ||
| 593 | parser_process_object(p); | ||
| 594 | break; | ||
| 595 | case '[': | ||
| 596 | parser_process_array(p); | ||
| 597 | break; | ||
| 598 | default: | ||
| 599 | parser_process_number(p, ch); | ||
| 600 | break; | ||
| 601 | } | ||
| 602 | } | ||
| 603 | |||
| 604 | // è§£æžjson文本 | ||
| 605 | static void parser_do_parse(const char *str, size_t size, void *ud, int maxdepth, int allowcomment) { | ||
| 606 | json_parser_t p; | ||
| 607 | parser_init(&p, str, size, ud, maxdepth, allowcomment); | ||
| 608 | //>>>if (setjmp(p.jb) == 0) { | ||
| 609 | parser_process_value(&p); | ||
| 610 | parser_skip_whitespaces(&p); | ||
| 611 | if (peekchar(&p) != '\0') { | ||
| 612 | parser_throw_error(&p, "Expect '<eof>' but got '%c', at: %s[:%lu]", peekchar(&p), | ||
| 613 | parser_error_content(&p), currpos(&p)); | ||
| 614 | } | ||
| 615 | parser_free(&p); | ||
| 616 | //>>>} | ||
| 617 | } | ||
| 618 | |||
| 619 | //----------------------------------------------------------------------------- | ||
| 620 | // dumpper | ||
| 621 | |||
| 622 | typedef struct { | ||
| 623 | membuffer_t buff; // ä¸´æ—¶ç¼“å˜ | ||
| 624 | int maxdepth; // 最大层次 | ||
| 625 | int format; // æ˜¯å¦æ ¼å¼åŒ– | ||
| 626 | int empty_as_array; // 空表是å¦å½“æˆæ•°ç»„ | ||
| 627 | int num_as_str; // æ•°å—Key转为å—符串 | ||
| 628 | char errmsg[ERRMSG_SIZE]; // ä¿å˜é”™è¯¯æ¶ˆæ¯ | ||
| 629 | } json_dumpper_t; | ||
| 630 | |||
| 631 | // è¶³å¤Ÿè½¬æ¢æ•°å—的缓å˜å¤§å° | ||
| 632 | #define NUMBER_BUFF_SZ 44 | ||
| 633 | #define INTEGER_BUFF_SZ 24 | ||
| 634 | |||
| 635 | // 抛出错误 | ||
| 636 | static void dumpper_throw_error(json_dumpper_t *d, lua_State *L, const char *fmt, ...) { | ||
| 637 | membuffer_free(&d->buff); | ||
| 638 | va_list arg; | ||
| 639 | va_start(arg, fmt); | ||
| 640 | vsnprintf(d->errmsg, ERRMSG_SIZE, fmt, arg); | ||
| 641 | va_end(arg); | ||
| 642 | luaL_error(L, d->errmsg); | ||
| 643 | } | ||
| 644 | |||
| 645 | #if LUA_VERSION_NUM > 501 | ||
| 646 | static void dumpper_process_integer(json_dumpper_t *d, lua_State *L, int idx) { | ||
| 647 | char nbuff[INTEGER_BUFF_SZ]; | ||
| 648 | int i = INTEGER_BUFF_SZ; | ||
| 649 | membuffer_ensure_space(&d->buff, INTEGER_BUFF_SZ); | ||
| 650 | int64_t x = (int64_t)lua_tointeger(L, idx); | ||
| 651 | uint64_t ux = (uint64_t)x; | ||
| 652 | if (x < 0) { | ||
| 653 | membuffer_putc_unsafe(&d->buff, '-'); | ||
| 654 | ux = ~ux + 1; | ||
| 655 | } | ||
| 656 | do { | ||
| 657 | nbuff[--i] = (ux % 10) + '0'; | ||
| 658 | } while (ux /= 10); | ||
| 659 | membuffer_putb_unsafe(&d->buff, nbuff+i, INTEGER_BUFF_SZ-i); | ||
| 660 | } | ||
| 661 | #endif | ||
| 662 | |||
| 663 | static void dumpper_process_number(json_dumpper_t *d, lua_State *L, int idx) { | ||
| 664 | lua_Number num = lua_tonumber(L, idx); | ||
| 665 | if (isinf(num) || isnan(num)) | ||
| 666 | dumpper_throw_error(d, L, "The number is NaN or Infinity"); | ||
| 667 | membuffer_ensure_space(&d->buff, NUMBER_BUFF_SZ); | ||
| 668 | char *p = membuffer_getp(&d->buff); | ||
| 669 | int len = sprintf(p, LUA_NUMBER_FMT, num); | ||
| 670 | membuffer_add_size(&d->buff, len); | ||
| 671 | } | ||
| 672 | |||
| 673 | // å—符转义表 | ||
| 674 | static const char char2escape[256] = { | ||
| 675 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'b', 't', 'n', 'u', 'f', 'r', 'u', 'u', 'u', 'u', 'u', 'u', // 0~19 | ||
| 676 | 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 'u', 0, 0, '"', 0, 0, 0, 0, 0, // 20~39 | ||
| 677 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 40~59 | ||
| 678 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 60~79 | ||
| 679 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, '\\', 0, 0, 0, 0, 0, 0, 0, // 80~99 | ||
| 680 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 100~119 | ||
| 681 | 0, 0, 0, 0, 0, 0, 0, 'u', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 120~139 | ||
| 682 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 140~159 | ||
| 683 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 160~179 | ||
| 684 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 180~199 | ||
| 685 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 200~219 | ||
| 686 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 220~239 | ||
| 687 | 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // 240~256 | ||
| 688 | }; | ||
| 689 | static const char hex_digits[16] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' }; | ||
| 690 | |||
| 691 | static void dumpper_process_string(json_dumpper_t *d, lua_State *L, int idx) { | ||
| 692 | membuffer_t *buff = &d->buff; | ||
| 693 | size_t len, i; | ||
| 694 | const char *str = lua_tolstring(L, idx, &len); | ||
| 695 | membuffer_ensure_space(buff, len * 6 + 2); | ||
| 696 | membuffer_putc_unsafe(buff, '\"'); | ||
| 697 | char esc; | ||
| 698 | unsigned char ch; | ||
| 699 | for (i = 0; i < len; ++i) { | ||
| 700 | ch = (unsigned char)str[i]; | ||
| 701 | esc = char2escape[ch]; | ||
| 702 | if (likely(!esc)) | ||
| 703 | membuffer_putc_unsafe(buff, (char)ch); | ||
| 704 | else { | ||
| 705 | membuffer_putc_unsafe(buff, '\\'); | ||
| 706 | membuffer_putc_unsafe(buff, esc); | ||
| 707 | if (esc == 'u') { | ||
| 708 | membuffer_putc_unsafe(buff, '0'); | ||
| 709 | membuffer_putc_unsafe(buff, '0'); | ||
| 710 | membuffer_putc_unsafe(buff, hex_digits[(unsigned char)esc >> 4]); | ||
| 711 | membuffer_putc_unsafe(buff, hex_digits[(unsigned char)esc & 0xF]); | ||
| 712 | } | ||
| 713 | } | ||
| 714 | } | ||
| 715 | membuffer_putc_unsafe(buff, '\"'); | ||
| 716 | } | ||
| 717 | |||
| 718 | static void dumpper_process_value(json_dumpper_t *d, lua_State *L, int depth); | ||
| 719 | |||
| 720 | static int dumpper_check_array(json_dumpper_t *d, lua_State *L, int *len) { | ||
| 721 | int asize = lua_objlen(L, -1); | ||
| 722 | if (asize > 0) { | ||
| 723 | lua_pushinteger(L, asize); | ||
| 724 | if (lua_next(L, -2) == 0) { | ||
| 725 | *len = asize; | ||
| 726 | return 1; | ||
| 727 | } else { | ||
| 728 | lua_pop(L, 2); | ||
| 729 | return 0; | ||
| 730 | } | ||
| 731 | } else { | ||
| 732 | lua_pushnil(L); | ||
| 733 | if (lua_next(L, -2) == 0) { | ||
| 734 | *len = asize; | ||
| 735 | return d->empty_as_array; | ||
| 736 | } else { | ||
| 737 | lua_pop(L, 2); | ||
| 738 | return 0; | ||
| 739 | } | ||
| 740 | } | ||
| 741 | } | ||
| 742 | |||
| 743 | static inline void dumpper_add_indent(json_dumpper_t *d, int count) { | ||
| 744 | membuffer_ensure_space(&d->buff, count); | ||
| 745 | int i; | ||
| 746 | for (i = 0; i < count; ++i) | ||
| 747 | membuffer_putc_unsafe(&d->buff, '\t'); | ||
| 748 | } | ||
| 749 | |||
| 750 | static void dumpper_process_array(json_dumpper_t *d, lua_State *L, int len, int depth) { | ||
| 751 | membuffer_t *buff = &d->buff; | ||
| 752 | membuffer_putc(buff, '['); | ||
| 753 | |||
| 754 | int i; | ||
| 755 | for (i = 1; i <= len; ++i) { | ||
| 756 | if (unlikely(d->format && i == 1)) membuffer_putc(buff, '\n'); | ||
| 757 | lua_rawgeti(L, -1, i); | ||
| 758 | if (unlikely(d->format)) dumpper_add_indent(d, depth); | ||
| 759 | dumpper_process_value(d, L, depth); | ||
| 760 | lua_pop(L, 1); | ||
| 761 | if (i < len) | ||
| 762 | membuffer_putc(buff, ','); | ||
| 763 | if (unlikely(d->format)) membuffer_putc(buff, '\n'); | ||
| 764 | } | ||
| 765 | |||
| 766 | if (unlikely(d->format && i > 1)) dumpper_add_indent(d, depth-1); | ||
| 767 | membuffer_putc(buff, ']'); | ||
| 768 | } | ||
| 769 | |||
| 770 | static void dumpper_process_object(json_dumpper_t *d, lua_State *L, int depth) { | ||
| 771 | membuffer_t *buff = &d->buff; | ||
| 772 | membuffer_putc(buff, '{'); | ||
| 773 | |||
| 774 | int ktp; | ||
| 775 | int comma = 0; | ||
| 776 | lua_pushnil(L); // t nil | ||
| 777 | while (lua_next(L, -2) != 0) { // t k v | ||
| 778 | if (comma) { | ||
| 779 | membuffer_putc(buff, ','); | ||
| 780 | if (unlikely(d->format)) membuffer_putc(buff, '\n'); | ||
| 781 | } else { | ||
| 782 | comma = 1; | ||
| 783 | if (unlikely(d->format)) membuffer_putc(buff, '\n'); | ||
| 784 | } | ||
| 785 | // key | ||
| 786 | ktp = lua_type(L, -2); | ||
| 787 | if (ktp == LUA_TSTRING) { | ||
| 788 | if (unlikely(d->format)) dumpper_add_indent(d, depth); | ||
| 789 | dumpper_process_string(d, L, -2); | ||
| 790 | if (likely(!d->format)) | ||
| 791 | membuffer_putc(buff, ':'); | ||
| 792 | else | ||
| 793 | membuffer_putb(buff, " : ", 3); | ||
| 794 | } else if (ktp == LUA_TNUMBER && d->num_as_str) { | ||
| 795 | if (unlikely(d->format)) dumpper_add_indent(d, depth); | ||
| 796 | membuffer_putc(buff, '\"'); | ||
| 797 | #if LUA_VERSION_NUM > 501 | ||
| 798 | if (lua_isinteger(L, -2)) | ||
| 799 | dumpper_process_integer(d, L, -2); | ||
| 800 | else | ||
| 801 | #endif | ||
| 802 | dumpper_process_number(d, L, -2); | ||
| 803 | if (likely(!d->format)) | ||
| 804 | membuffer_putb(buff, "\":", 2); | ||
| 805 | else | ||
| 806 | membuffer_putb(buff, "\" : ", 4); | ||
| 807 | } else { | ||
| 808 | dumpper_throw_error(d, L, "Table key must be a string"); | ||
| 809 | } | ||
| 810 | // value | ||
| 811 | dumpper_process_value(d, L, depth); | ||
| 812 | lua_pop(L, 1); | ||
| 813 | } | ||
| 814 | if (unlikely(d->format && comma)) { | ||
| 815 | membuffer_putc(buff, '\n'); | ||
| 816 | dumpper_add_indent(d, depth-1); | ||
| 817 | } | ||
| 818 | membuffer_putc(buff, '}'); | ||
| 819 | } | ||
| 820 | |||
| 821 | static inline void dumpper_process_table(json_dumpper_t *d, lua_State *L, int depth) { | ||
| 822 | depth++; | ||
| 823 | if (depth > d->maxdepth) | ||
| 824 | dumpper_throw_error(d, L, "Too many nested data, max depth is %d", d->maxdepth); | ||
| 825 | luaL_checkstack(L, 6, NULL); | ||
| 826 | |||
| 827 | int len; | ||
| 828 | if (dumpper_check_array(d, L, &len)) | ||
| 829 | dumpper_process_array(d, L, len, depth); | ||
| 830 | else | ||
| 831 | dumpper_process_object(d, L, depth); | ||
| 832 | } | ||
| 833 | |||
| 834 | static void dumpper_process_value(json_dumpper_t *d, lua_State *L, int depth) { | ||
| 835 | int tp = lua_type(L, -1); | ||
| 836 | switch (tp) { | ||
| 837 | case LUA_TSTRING: | ||
| 838 | dumpper_process_string(d, L, -1); | ||
| 839 | break; | ||
| 840 | case LUA_TNUMBER: | ||
| 841 | #if LUA_VERSION_NUM > 501 | ||
| 842 | if (lua_isinteger(L, -1)) | ||
| 843 | dumpper_process_integer(d, L, -1); | ||
| 844 | else | ||
| 845 | #endif | ||
| 846 | dumpper_process_number(d, L, -1); | ||
| 847 | break; | ||
| 848 | case LUA_TBOOLEAN: | ||
| 849 | if (lua_toboolean(L, -1)) | ||
| 850 | membuffer_putb(&d->buff, "true", 4); | ||
| 851 | else | ||
| 852 | membuffer_putb(&d->buff, "false", 5); | ||
| 853 | break; | ||
| 854 | case LUA_TTABLE: | ||
| 855 | dumpper_process_table(d, L, depth); | ||
| 856 | break; | ||
| 857 | case LUA_TNIL: | ||
| 858 | membuffer_putb(&d->buff, "null", 4); | ||
| 859 | break; | ||
| 860 | case LUA_TLIGHTUSERDATA: | ||
| 861 | if (lua_touserdata(L, -1) == NULL) { | ||
| 862 | membuffer_putb(&d->buff, "null", 4); | ||
| 863 | break; | ||
| 864 | } | ||
| 865 | goto error; | ||
| 866 | default: | ||
| 867 | error: | ||
| 868 | dumpper_throw_error(d, L, "Unsupport type %s", lua_typename(L, tp)); | ||
| 869 | } | ||
| 870 | } | ||
| 871 | |||
| 872 | //----------------------------------------------------------------------------- | ||
| 873 | // æŽ¥å£ | ||
| 874 | #define DEF_MAX_DEPTH 128 | ||
| 875 | |||
| 876 | // 从å—ç¬¦ä¸²åŠ è½½ï¼šjson.decode(str, maxdepth) -> obj | ||
| 877 | // è¦æ±‚å—符串必须以0结尾 | ||
| 878 | int colibc_json_decode(lua_State *L) { | ||
| 879 | size_t size; | ||
| 880 | const char *str = luaL_checklstring(L, 1, &size); | ||
| 881 | int maxdepth = (int)luaL_optinteger(L, 2, DEF_MAX_DEPTH); | ||
| 882 | int allowcomment = lua_toboolean(L, 3); | ||
| 883 | parser_do_parse(str, size, L, maxdepth, allowcomment); | ||
| 884 | return 1; | ||
| 885 | } | ||
| 886 | |||
| 887 | // ä¿å˜åˆ°å—符串: json.encode(obj) -> str | ||
| 888 | int colibc_json_encode(lua_State *L) { | ||
| 889 | luaL_checkany(L, 1); | ||
| 890 | json_dumpper_t dumpper; | ||
| 891 | membuffer_init(&dumpper.buff); | ||
| 892 | dumpper.format = lua_toboolean(L, 2); | ||
| 893 | dumpper.empty_as_array = lua_toboolean(L, 3); | ||
| 894 | dumpper.num_as_str = lua_toboolean(L, 4); | ||
| 895 | dumpper.maxdepth = (int)luaL_optinteger(L, 5, DEF_MAX_DEPTH); | ||
| 896 | |||
| 897 | lua_settop(L, 1); | ||
| 898 | dumpper_process_value(&dumpper, L, 0); | ||
| 899 | lua_pushlstring(L, dumpper.buff.b, dumpper.buff.sz); | ||
| 900 | membuffer_free(&dumpper.buff); | ||
| 901 | return 1; | ||
| 902 | } | ||
| 903 | |||
| 904 | static const luaL_Reg lib[] = { | ||
| 905 | {"decode", colibc_json_decode}, | ||
| 906 | {"encode", colibc_json_encode}, | ||
| 907 | {NULL, NULL}, | ||
| 908 | }; | ||
| 909 | |||
| 910 | LUALIB_API int luaopen_colibc_json(lua_State* L) { | ||
| 911 | #if LUA_VERSION_NUM > 501 | ||
| 912 | luaL_newlib(L, lib); // json | ||
| 913 | #else | ||
| 914 | lua_getglobal(L, "package"); // package | ||
| 915 | lua_getfield(L, -1, "loaded"); // package loaded | ||
| 916 | lua_createtable(L, 0, 0); // package loaded json | ||
| 917 | lua_pushvalue(L, -1); // package loaded json json | ||
| 918 | lua_setfield(L, -3, "cojson"); // loaded["cojson"] = json, package loaded json | ||
| 919 | luaL_register(L, NULL, lib); // package loaded json | ||
| 920 | #endif | ||
| 921 | // json.null | ||
| 922 | lua_pushlightuserdata(L, NULL); | ||
| 923 | lua_setfield(L, -2, "null"); | ||
| 924 | return 1; | ||
| 925 | } | ||
diff --git a/src/3rdParty/utf8cpp.h b/src/3rdParty/utf8cpp.h new file mode 100755 index 0000000..76f0fa1 --- /dev/null +++ b/src/3rdParty/utf8cpp.h | |||
| @@ -0,0 +1,1277 @@ | |||
| 1 | // Copyright 2006 Nemanja Trifunovic | ||
| 2 | |||
| 3 | /* | ||
| 4 | Permission is hereby granted, free of charge, to any person or organization | ||
| 5 | obtaining a copy of the software and accompanying documentation covered by | ||
| 6 | this license (the "Software") to use, reproduce, display, distribute, | ||
| 7 | execute, and transmit the Software, and to prepare derivative works of the | ||
| 8 | Software, and to permit third-parties to whom the Software is furnished to | ||
| 9 | do so, all subject to the following: | ||
| 10 | |||
| 11 | The copyright notices in the Software and this entire statement, including | ||
| 12 | the above license grant, this restriction and the following disclaimer, | ||
| 13 | must be included in all copies of the Software, in whole or in part, and | ||
| 14 | all derivative works of the Software, unless such copies or derivative | ||
| 15 | works are solely in the form of machine-executable object code generated by | ||
| 16 | a source language processor. | ||
| 17 | |||
| 18 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||
| 19 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||
| 20 | FITNESS FOR A PARTICULAR PURPOSE, TITLE AND NON-INFRINGEMENT. IN NO EVENT | ||
| 21 | SHALL THE COPYRIGHT HOLDERS OR ANYONE DISTRIBUTING THE SOFTWARE BE LIABLE | ||
| 22 | FOR ANY DAMAGES OR OTHER LIABILITY, WHETHER IN CONTRACT, TORT OR OTHERWISE, | ||
| 23 | ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER | ||
| 24 | DEALINGS IN THE SOFTWARE. | ||
| 25 | */ | ||
| 26 | |||
| 27 | |||
| 28 | #ifndef UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 | ||
| 29 | #define UTF8_FOR_CPP_2675DCD0_9480_4c0c_B92A_CC14C027B731 | ||
| 30 | |||
| 31 | /* | ||
| 32 | To control the C++ language version used by the library, you can define UTF_CPP_CPLUSPLUS macro | ||
| 33 | and set it to one of the values used by the __cplusplus predefined macro. | ||
| 34 | |||
| 35 | For instance, | ||
| 36 | #define UTF_CPP_CPLUSPLUS 199711L | ||
| 37 | will cause the UTF-8 CPP library to use only types and language features available in the C++ 98 standard. | ||
| 38 | Some library features will be disabled. | ||
| 39 | |||
| 40 | If you leave UTF_CPP_CPLUSPLUS undefined, it will be internally assigned to __cplusplus. | ||
| 41 | */ | ||
| 42 | |||
| 43 | #include <iterator> | ||
| 44 | #include <cstring> | ||
| 45 | #include <string> | ||
| 46 | |||
| 47 | // Determine the C++ standard version. | ||
| 48 | // If the user defines UTF_CPP_CPLUSPLUS, use that. | ||
| 49 | // Otherwise, trust the unreliable predefined macro __cplusplus | ||
| 50 | |||
| 51 | #if !defined UTF_CPP_CPLUSPLUS | ||
| 52 | #define UTF_CPP_CPLUSPLUS __cplusplus | ||
| 53 | #endif | ||
| 54 | |||
| 55 | #if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later | ||
| 56 | #define UTF_CPP_OVERRIDE override | ||
| 57 | #define UTF_CPP_NOEXCEPT noexcept | ||
| 58 | #define UTF_CPP_STATIC_ASSERT(condition) static_assert(condition, "UTFCPP static assert"); | ||
| 59 | #else // C++ 98/03 | ||
| 60 | #define UTF_CPP_OVERRIDE | ||
| 61 | #define UTF_CPP_NOEXCEPT throw() | ||
| 62 | // Simulate static_assert: | ||
| 63 | template<bool> struct UtfCppCompileTimeAssert; | ||
| 64 | template<> struct UtfCppCompileTimeAssert <true> { }; | ||
| 65 | #define UTF_CPP_STATIC_ASSERT(condition) (UtfCppCompileTimeAssert <(condition) != 0>()) | ||
| 66 | #endif // C++ 11 or later | ||
| 67 | |||
| 68 | |||
| 69 | namespace utf8 | ||
| 70 | { | ||
| 71 | // The typedefs for 8-bit, 16-bit and 32-bit code units | ||
| 72 | #if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later | ||
| 73 | #if UTF_CPP_CPLUSPLUS >= 202002L // C++ 20 or later | ||
| 74 | typedef char8_t utfchar8_t; | ||
| 75 | #else // C++ 11/14/17 | ||
| 76 | typedef unsigned char utfchar8_t; | ||
| 77 | #endif | ||
| 78 | typedef char16_t utfchar16_t; | ||
| 79 | typedef char32_t utfchar32_t; | ||
| 80 | #else // C++ 98/03 | ||
| 81 | typedef unsigned char utfchar8_t; | ||
| 82 | typedef unsigned short utfchar16_t; | ||
| 83 | typedef unsigned int utfchar32_t; | ||
| 84 | #endif // C++ 11 or later | ||
| 85 | |||
| 86 | // Helper code - not intended to be directly called by the library users. May be changed at any time | ||
| 87 | namespace internal | ||
| 88 | { | ||
| 89 | // Unicode constants | ||
| 90 | // Leading (high) surrogates: 0xd800 - 0xdbff | ||
| 91 | // Trailing (low) surrogates: 0xdc00 - 0xdfff | ||
| 92 | const utfchar16_t LEAD_SURROGATE_MIN = 0xd800u; | ||
| 93 | const utfchar16_t LEAD_SURROGATE_MAX = 0xdbffu; | ||
| 94 | const utfchar16_t TRAIL_SURROGATE_MIN = 0xdc00u; | ||
| 95 | const utfchar16_t TRAIL_SURROGATE_MAX = 0xdfffu; | ||
| 96 | const utfchar16_t LEAD_OFFSET = 0xd7c0u; // LEAD_SURROGATE_MIN - (0x10000 >> 10) | ||
| 97 | const utfchar32_t SURROGATE_OFFSET = 0xfca02400u; // 0x10000u - (LEAD_SURROGATE_MIN << 10) - TRAIL_SURROGATE_MIN | ||
| 98 | |||
| 99 | // Maximum valid value for a Unicode code point | ||
| 100 | const utfchar32_t CODE_POINT_MAX = 0x0010ffffu; | ||
| 101 | |||
| 102 | template<typename octet_type> | ||
| 103 | inline utfchar8_t mask8(octet_type oc) | ||
| 104 | { | ||
| 105 | return static_cast<utfchar8_t>(0xff & oc); | ||
| 106 | } | ||
| 107 | |||
| 108 | template<typename u16_type> | ||
| 109 | inline utfchar16_t mask16(u16_type oc) | ||
| 110 | { | ||
| 111 | return static_cast<utfchar16_t>(0xffff & oc); | ||
| 112 | } | ||
| 113 | |||
| 114 | template<typename octet_type> | ||
| 115 | inline bool is_trail(octet_type oc) | ||
| 116 | { | ||
| 117 | return ((utf8::internal::mask8(oc) >> 6) == 0x2); | ||
| 118 | } | ||
| 119 | |||
| 120 | inline bool is_lead_surrogate(utfchar32_t cp) | ||
| 121 | { | ||
| 122 | return (cp >= static_cast<utfchar32_t>(LEAD_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(LEAD_SURROGATE_MAX)); | ||
| 123 | } | ||
| 124 | |||
| 125 | inline bool is_trail_surrogate(utfchar32_t cp) | ||
| 126 | { | ||
| 127 | return (cp >= static_cast<utfchar32_t>(TRAIL_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(TRAIL_SURROGATE_MAX)); | ||
| 128 | } | ||
| 129 | |||
| 130 | inline bool is_surrogate(utfchar32_t cp) | ||
| 131 | { | ||
| 132 | return (cp >= static_cast<utfchar32_t>(LEAD_SURROGATE_MIN) && cp <= static_cast<utfchar32_t>(TRAIL_SURROGATE_MAX)); | ||
| 133 | } | ||
| 134 | |||
| 135 | inline bool is_code_point_valid(utfchar32_t cp) | ||
| 136 | { | ||
| 137 | return (cp <= CODE_POINT_MAX && !utf8::internal::is_surrogate(cp)); | ||
| 138 | } | ||
| 139 | |||
| 140 | inline bool is_in_bmp(utfchar32_t cp) | ||
| 141 | { | ||
| 142 | return cp < utfchar32_t(0x10000); | ||
| 143 | } | ||
| 144 | |||
| 145 | template <typename octet_iterator> | ||
| 146 | int sequence_length(octet_iterator lead_it) | ||
| 147 | { | ||
| 148 | const utfchar8_t lead = utf8::internal::mask8(*lead_it); | ||
| 149 | if (lead < 0x80) | ||
| 150 | return 1; | ||
| 151 | else if ((lead >> 5) == 0x6) | ||
| 152 | return 2; | ||
| 153 | else if ((lead >> 4) == 0xe) | ||
| 154 | return 3; | ||
| 155 | else if ((lead >> 3) == 0x1e) | ||
| 156 | return 4; | ||
| 157 | else | ||
| 158 | return 0; | ||
| 159 | } | ||
| 160 | |||
| 161 | inline bool is_overlong_sequence(utfchar32_t cp, int length) | ||
| 162 | { | ||
| 163 | if (cp < 0x80) { | ||
| 164 | if (length != 1) | ||
| 165 | return true; | ||
| 166 | } | ||
| 167 | else if (cp < 0x800) { | ||
| 168 | if (length != 2) | ||
| 169 | return true; | ||
| 170 | } | ||
| 171 | else if (cp < 0x10000) { | ||
| 172 | if (length != 3) | ||
| 173 | return true; | ||
| 174 | } | ||
| 175 | return false; | ||
| 176 | } | ||
| 177 | |||
| 178 | enum utf_error {UTF8_OK, NOT_ENOUGH_ROOM, INVALID_LEAD, INCOMPLETE_SEQUENCE, OVERLONG_SEQUENCE, INVALID_CODE_POINT}; | ||
| 179 | |||
| 180 | /// Helper for get_sequence_x | ||
| 181 | template <typename octet_iterator> | ||
| 182 | utf_error increase_safely(octet_iterator& it, const octet_iterator end) | ||
| 183 | { | ||
| 184 | if (++it == end) | ||
| 185 | return NOT_ENOUGH_ROOM; | ||
| 186 | |||
| 187 | if (!utf8::internal::is_trail(*it)) | ||
| 188 | return INCOMPLETE_SEQUENCE; | ||
| 189 | |||
| 190 | return UTF8_OK; | ||
| 191 | } | ||
| 192 | |||
| 193 | #define UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(IT, END) {utf_error ret = increase_safely(IT, END); if (ret != UTF8_OK) return ret;} | ||
| 194 | |||
| 195 | /// get_sequence_x functions decode utf-8 sequences of the length x | ||
| 196 | template <typename octet_iterator> | ||
| 197 | utf_error get_sequence_1(octet_iterator& it, octet_iterator end, utfchar32_t& code_point) | ||
| 198 | { | ||
| 199 | if (it == end) | ||
| 200 | return NOT_ENOUGH_ROOM; | ||
| 201 | |||
| 202 | code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it)); | ||
| 203 | |||
| 204 | return UTF8_OK; | ||
| 205 | } | ||
| 206 | |||
| 207 | template <typename octet_iterator> | ||
| 208 | utf_error get_sequence_2(octet_iterator& it, octet_iterator end, utfchar32_t& code_point) | ||
| 209 | { | ||
| 210 | if (it == end) | ||
| 211 | return NOT_ENOUGH_ROOM; | ||
| 212 | |||
| 213 | code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it)); | ||
| 214 | |||
| 215 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 216 | |||
| 217 | code_point = ((code_point << 6) & 0x7ff) + ((*it) & 0x3f); | ||
| 218 | |||
| 219 | return UTF8_OK; | ||
| 220 | } | ||
| 221 | |||
| 222 | template <typename octet_iterator> | ||
| 223 | utf_error get_sequence_3(octet_iterator& it, octet_iterator end, utfchar32_t& code_point) | ||
| 224 | { | ||
| 225 | if (it == end) | ||
| 226 | return NOT_ENOUGH_ROOM; | ||
| 227 | |||
| 228 | code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it)); | ||
| 229 | |||
| 230 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 231 | |||
| 232 | code_point = ((code_point << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); | ||
| 233 | |||
| 234 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 235 | |||
| 236 | code_point = static_cast<utfchar32_t>(code_point + ((*it) & 0x3f)); | ||
| 237 | |||
| 238 | return UTF8_OK; | ||
| 239 | } | ||
| 240 | |||
| 241 | template <typename octet_iterator> | ||
| 242 | utf_error get_sequence_4(octet_iterator& it, octet_iterator end, utfchar32_t& code_point) | ||
| 243 | { | ||
| 244 | if (it == end) | ||
| 245 | return NOT_ENOUGH_ROOM; | ||
| 246 | |||
| 247 | code_point = static_cast<utfchar32_t>(utf8::internal::mask8(*it)); | ||
| 248 | |||
| 249 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 250 | |||
| 251 | code_point = ((code_point << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); | ||
| 252 | |||
| 253 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 254 | |||
| 255 | code_point = static_cast<utfchar32_t>(code_point + ((utf8::internal::mask8(*it) << 6) & 0xfff)); | ||
| 256 | |||
| 257 | UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR(it, end) | ||
| 258 | |||
| 259 | code_point = static_cast<utfchar32_t>(code_point + ((*it) & 0x3f)); | ||
| 260 | |||
| 261 | return UTF8_OK; | ||
| 262 | } | ||
| 263 | |||
| 264 | #undef UTF8_CPP_INCREASE_AND_RETURN_ON_ERROR | ||
| 265 | |||
| 266 | template <typename octet_iterator> | ||
| 267 | utf_error validate_next(octet_iterator& it, octet_iterator end, utfchar32_t& code_point) | ||
| 268 | { | ||
| 269 | if (it == end) | ||
| 270 | return NOT_ENOUGH_ROOM; | ||
| 271 | |||
| 272 | // Save the original value of it so we can go back in case of failure | ||
| 273 | // Of course, it does not make much sense with i.e. stream iterators | ||
| 274 | octet_iterator original_it = it; | ||
| 275 | |||
| 276 | utfchar32_t cp = 0; | ||
| 277 | // Determine the sequence length based on the lead octet | ||
| 278 | const int length = utf8::internal::sequence_length(it); | ||
| 279 | |||
| 280 | // Get trail octets and calculate the code point | ||
| 281 | utf_error err = UTF8_OK; | ||
| 282 | switch (length) { | ||
| 283 | case 0: | ||
| 284 | return INVALID_LEAD; | ||
| 285 | case 1: | ||
| 286 | err = utf8::internal::get_sequence_1(it, end, cp); | ||
| 287 | break; | ||
| 288 | case 2: | ||
| 289 | err = utf8::internal::get_sequence_2(it, end, cp); | ||
| 290 | break; | ||
| 291 | case 3: | ||
| 292 | err = utf8::internal::get_sequence_3(it, end, cp); | ||
| 293 | break; | ||
| 294 | case 4: | ||
| 295 | err = utf8::internal::get_sequence_4(it, end, cp); | ||
| 296 | break; | ||
| 297 | } | ||
| 298 | |||
| 299 | if (err == UTF8_OK) { | ||
| 300 | // Decoding succeeded. Now, security checks... | ||
| 301 | if (utf8::internal::is_code_point_valid(cp)) { | ||
| 302 | if (!utf8::internal::is_overlong_sequence(cp, length)){ | ||
| 303 | // Passed! Return here. | ||
| 304 | code_point = cp; | ||
| 305 | ++it; | ||
| 306 | return UTF8_OK; | ||
| 307 | } | ||
| 308 | else | ||
| 309 | err = OVERLONG_SEQUENCE; | ||
| 310 | } | ||
| 311 | else | ||
| 312 | err = INVALID_CODE_POINT; | ||
| 313 | } | ||
| 314 | |||
| 315 | // Failure branch - restore the original value of the iterator | ||
| 316 | it = original_it; | ||
| 317 | return err; | ||
| 318 | } | ||
| 319 | |||
| 320 | template <typename octet_iterator> | ||
| 321 | inline utf_error validate_next(octet_iterator& it, octet_iterator end) { | ||
| 322 | utfchar32_t ignored; | ||
| 323 | return utf8::internal::validate_next(it, end, ignored); | ||
| 324 | } | ||
| 325 | |||
| 326 | template <typename word_iterator> | ||
| 327 | utf_error validate_next16(word_iterator& it, word_iterator end, utfchar32_t& code_point) | ||
| 328 | { | ||
| 329 | // Make sure the iterator dereferences a large enough type | ||
| 330 | typedef typename std::iterator_traits<word_iterator>::value_type word_type; | ||
| 331 | UTF_CPP_STATIC_ASSERT(sizeof(word_type) >= sizeof(utfchar16_t)); | ||
| 332 | // Check the edge case: | ||
| 333 | if (it == end) | ||
| 334 | return NOT_ENOUGH_ROOM; | ||
| 335 | // Save the original value of it so we can go back in case of failure | ||
| 336 | // Of course, it does not make much sense with i.e. stream iterators | ||
| 337 | word_iterator original_it = it; | ||
| 338 | |||
| 339 | utf_error err = UTF8_OK; | ||
| 340 | |||
| 341 | const utfchar16_t first_word = *it++; | ||
| 342 | if (!is_surrogate(first_word)) { | ||
| 343 | code_point = first_word; | ||
| 344 | return UTF8_OK; | ||
| 345 | } | ||
| 346 | else { | ||
| 347 | if (it == end) | ||
| 348 | err = NOT_ENOUGH_ROOM; | ||
| 349 | else if (is_lead_surrogate(first_word)) { | ||
| 350 | const utfchar16_t second_word = *it++; | ||
| 351 | if (is_trail_surrogate(static_cast<utfchar32_t>(second_word))) { | ||
| 352 | code_point = static_cast<utfchar32_t>(first_word << 10) + static_cast<utfchar32_t>(second_word) + SURROGATE_OFFSET; | ||
| 353 | return UTF8_OK; | ||
| 354 | } else | ||
| 355 | err = INCOMPLETE_SEQUENCE; | ||
| 356 | |||
| 357 | } else { | ||
| 358 | err = INVALID_LEAD; | ||
| 359 | } | ||
| 360 | } | ||
| 361 | // error branch | ||
| 362 | it = original_it; | ||
| 363 | return err; | ||
| 364 | } | ||
| 365 | |||
| 366 | // Internal implementation of both checked and unchecked append() function | ||
| 367 | // This function will be invoked by the overloads below, as they will know | ||
| 368 | // the octet_type. | ||
| 369 | template <typename octet_iterator, typename octet_type> | ||
| 370 | octet_iterator append(utfchar32_t cp, octet_iterator result) { | ||
| 371 | if (cp < 0x80) // one octet | ||
| 372 | *(result++) = static_cast<octet_type>(cp); | ||
| 373 | else if (cp < 0x800) { // two octets | ||
| 374 | *(result++) = static_cast<octet_type>((cp >> 6) | 0xc0); | ||
| 375 | *(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80); | ||
| 376 | } | ||
| 377 | else if (cp < 0x10000) { // three octets | ||
| 378 | *(result++) = static_cast<octet_type>((cp >> 12) | 0xe0); | ||
| 379 | *(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80); | ||
| 380 | *(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80); | ||
| 381 | } | ||
| 382 | else { // four octets | ||
| 383 | *(result++) = static_cast<octet_type>((cp >> 18) | 0xf0); | ||
| 384 | *(result++) = static_cast<octet_type>(((cp >> 12) & 0x3f)| 0x80); | ||
| 385 | *(result++) = static_cast<octet_type>(((cp >> 6) & 0x3f) | 0x80); | ||
| 386 | *(result++) = static_cast<octet_type>((cp & 0x3f) | 0x80); | ||
| 387 | } | ||
| 388 | return result; | ||
| 389 | } | ||
| 390 | |||
| 391 | // One of the following overloads will be invoked from the API calls | ||
| 392 | |||
| 393 | // A simple (but dangerous) case: the caller appends byte(s) to a char array | ||
| 394 | inline char* append(utfchar32_t cp, char* result) { | ||
| 395 | return append<char*, char>(cp, result); | ||
| 396 | } | ||
| 397 | |||
| 398 | // Hopefully, most common case: the caller uses back_inserter | ||
| 399 | // i.e. append(cp, std::back_inserter(str)); | ||
| 400 | template<typename container_type> | ||
| 401 | std::back_insert_iterator<container_type> append | ||
| 402 | (utfchar32_t cp, std::back_insert_iterator<container_type> result) { | ||
| 403 | return append<std::back_insert_iterator<container_type>, | ||
| 404 | typename container_type::value_type>(cp, result); | ||
| 405 | } | ||
| 406 | |||
| 407 | // The caller uses some other kind of output operator - not covered above | ||
| 408 | // Note that in this case we are not able to determine octet_type | ||
| 409 | // so we assume it's utfchar8_t; that can cause a conversion warning if we are wrong. | ||
| 410 | template <typename octet_iterator> | ||
| 411 | octet_iterator append(utfchar32_t cp, octet_iterator result) { | ||
| 412 | return append<octet_iterator, utfchar8_t>(cp, result); | ||
| 413 | } | ||
| 414 | |||
| 415 | // Internal implementation of both checked and unchecked append16() function | ||
| 416 | // This function will be invoked by the overloads below, as they will know | ||
| 417 | // the word_type. | ||
| 418 | template <typename word_iterator, typename word_type> | ||
| 419 | word_iterator append16(utfchar32_t cp, word_iterator result) { | ||
| 420 | UTF_CPP_STATIC_ASSERT(sizeof(word_type) >= sizeof(utfchar16_t)); | ||
| 421 | if (is_in_bmp(cp)) | ||
| 422 | *(result++) = static_cast<word_type>(cp); | ||
| 423 | else { | ||
| 424 | // Code points from the supplementary planes are encoded via surrogate pairs | ||
| 425 | *(result++) = static_cast<word_type>(LEAD_OFFSET + (cp >> 10)); | ||
| 426 | *(result++) = static_cast<word_type>(TRAIL_SURROGATE_MIN + (cp & 0x3FF)); | ||
| 427 | } | ||
| 428 | return result; | ||
| 429 | } | ||
| 430 | |||
| 431 | // Hopefully, most common case: the caller uses back_inserter | ||
| 432 | // i.e. append16(cp, std::back_inserter(str)); | ||
| 433 | template<typename container_type> | ||
| 434 | std::back_insert_iterator<container_type> append16 | ||
| 435 | (utfchar32_t cp, std::back_insert_iterator<container_type> result) { | ||
| 436 | return append16<std::back_insert_iterator<container_type>, | ||
| 437 | typename container_type::value_type>(cp, result); | ||
| 438 | } | ||
| 439 | |||
| 440 | // The caller uses some other kind of output operator - not covered above | ||
| 441 | // Note that in this case we are not able to determine word_type | ||
| 442 | // so we assume it's utfchar16_t; that can cause a conversion warning if we are wrong. | ||
| 443 | template <typename word_iterator> | ||
| 444 | word_iterator append16(utfchar32_t cp, word_iterator result) { | ||
| 445 | return append16<word_iterator, utfchar16_t>(cp, result); | ||
| 446 | } | ||
| 447 | |||
| 448 | } // namespace internal | ||
| 449 | |||
| 450 | /// The library API - functions intended to be called by the users | ||
| 451 | |||
| 452 | // Byte order mark | ||
| 453 | const utfchar8_t bom[] = {0xef, 0xbb, 0xbf}; | ||
| 454 | |||
| 455 | template <typename octet_iterator> | ||
| 456 | octet_iterator find_invalid(octet_iterator start, octet_iterator end) | ||
| 457 | { | ||
| 458 | octet_iterator result = start; | ||
| 459 | while (result != end) { | ||
| 460 | utf8::internal::utf_error err_code = utf8::internal::validate_next(result, end); | ||
| 461 | if (err_code != internal::UTF8_OK) | ||
| 462 | return result; | ||
| 463 | } | ||
| 464 | return result; | ||
| 465 | } | ||
| 466 | |||
| 467 | inline const char* find_invalid(const char* str) | ||
| 468 | { | ||
| 469 | const char* end = str + std::strlen(str); | ||
| 470 | return find_invalid(str, end); | ||
| 471 | } | ||
| 472 | |||
| 473 | inline std::size_t find_invalid(const std::string& s) | ||
| 474 | { | ||
| 475 | std::string::const_iterator invalid = find_invalid(s.begin(), s.end()); | ||
| 476 | return (invalid == s.end()) ? std::string::npos : static_cast<std::size_t>(invalid - s.begin()); | ||
| 477 | } | ||
| 478 | |||
| 479 | template <typename octet_iterator> | ||
| 480 | inline bool is_valid(octet_iterator start, octet_iterator end) | ||
| 481 | { | ||
| 482 | return (utf8::find_invalid(start, end) == end); | ||
| 483 | } | ||
| 484 | |||
| 485 | inline bool is_valid(const char* str) | ||
| 486 | { | ||
| 487 | return (*(utf8::find_invalid(str)) == '\0'); | ||
| 488 | } | ||
| 489 | |||
| 490 | inline bool is_valid(const std::string& s) | ||
| 491 | { | ||
| 492 | return is_valid(s.begin(), s.end()); | ||
| 493 | } | ||
| 494 | |||
| 495 | |||
| 496 | |||
| 497 | template <typename octet_iterator> | ||
| 498 | inline bool starts_with_bom (octet_iterator it, octet_iterator end) | ||
| 499 | { | ||
| 500 | return ( | ||
| 501 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[0]) && | ||
| 502 | ((it != end) && (utf8::internal::mask8(*it++)) == bom[1]) && | ||
| 503 | ((it != end) && (utf8::internal::mask8(*it)) == bom[2]) | ||
| 504 | ); | ||
| 505 | } | ||
| 506 | |||
| 507 | inline bool starts_with_bom(const std::string& s) | ||
| 508 | { | ||
| 509 | return starts_with_bom(s.begin(), s.end()); | ||
| 510 | } | ||
| 511 | } // namespace utf8 | ||
| 512 | |||
| 513 | #include <stdexcept> | ||
| 514 | |||
| 515 | namespace utf8 | ||
| 516 | { | ||
| 517 | // Base for the exceptions that may be thrown from the library | ||
| 518 | class exception : public ::std::exception { | ||
| 519 | }; | ||
| 520 | |||
| 521 | // Exceptions that may be thrown from the library functions. | ||
| 522 | class invalid_code_point : public exception { | ||
| 523 | utfchar32_t cp; | ||
| 524 | public: | ||
| 525 | invalid_code_point(utfchar32_t codepoint) : cp(codepoint) {} | ||
| 526 | virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid code point"; } | ||
| 527 | utfchar32_t code_point() const {return cp;} | ||
| 528 | }; | ||
| 529 | |||
| 530 | class invalid_utf8 : public exception { | ||
| 531 | utfchar8_t u8; | ||
| 532 | public: | ||
| 533 | invalid_utf8 (utfchar8_t u) : u8(u) {} | ||
| 534 | invalid_utf8 (char c) : u8(static_cast<utfchar8_t>(c)) {} | ||
| 535 | virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-8"; } | ||
| 536 | utfchar8_t utf8_octet() const {return u8;} | ||
| 537 | }; | ||
| 538 | |||
| 539 | class invalid_utf16 : public exception { | ||
| 540 | utfchar16_t u16; | ||
| 541 | public: | ||
| 542 | invalid_utf16 (utfchar16_t u) : u16(u) {} | ||
| 543 | virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Invalid UTF-16"; } | ||
| 544 | utfchar16_t utf16_word() const {return u16;} | ||
| 545 | }; | ||
| 546 | |||
| 547 | class not_enough_room : public exception { | ||
| 548 | public: | ||
| 549 | virtual const char* what() const UTF_CPP_NOEXCEPT UTF_CPP_OVERRIDE { return "Not enough space"; } | ||
| 550 | }; | ||
| 551 | |||
| 552 | /// The library API - functions intended to be called by the users | ||
| 553 | |||
| 554 | template <typename octet_iterator> | ||
| 555 | octet_iterator append(utfchar32_t cp, octet_iterator result) | ||
| 556 | { | ||
| 557 | if (!utf8::internal::is_code_point_valid(cp)) | ||
| 558 | throw invalid_code_point(cp); | ||
| 559 | |||
| 560 | return internal::append(cp, result); | ||
| 561 | } | ||
| 562 | |||
| 563 | inline void append(utfchar32_t cp, std::string& s) | ||
| 564 | { | ||
| 565 | append(cp, std::back_inserter(s)); | ||
| 566 | } | ||
| 567 | |||
| 568 | template <typename word_iterator> | ||
| 569 | word_iterator append16(utfchar32_t cp, word_iterator result) | ||
| 570 | { | ||
| 571 | if (!utf8::internal::is_code_point_valid(cp)) | ||
| 572 | throw invalid_code_point(cp); | ||
| 573 | |||
| 574 | return internal::append16(cp, result); | ||
| 575 | } | ||
| 576 | |||
| 577 | template <typename octet_iterator, typename output_iterator> | ||
| 578 | output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, utfchar32_t replacement) | ||
| 579 | { | ||
| 580 | while (start != end) { | ||
| 581 | octet_iterator sequence_start = start; | ||
| 582 | internal::utf_error err_code = utf8::internal::validate_next(start, end); | ||
| 583 | switch (err_code) { | ||
| 584 | case internal::UTF8_OK : | ||
| 585 | for (octet_iterator it = sequence_start; it != start; ++it) | ||
| 586 | *out++ = *it; | ||
| 587 | break; | ||
| 588 | case internal::NOT_ENOUGH_ROOM: | ||
| 589 | out = utf8::append (replacement, out); | ||
| 590 | start = end; | ||
| 591 | break; | ||
| 592 | case internal::INVALID_LEAD: | ||
| 593 | out = utf8::append (replacement, out); | ||
| 594 | ++start; | ||
| 595 | break; | ||
| 596 | case internal::INCOMPLETE_SEQUENCE: | ||
| 597 | case internal::OVERLONG_SEQUENCE: | ||
| 598 | case internal::INVALID_CODE_POINT: | ||
| 599 | out = utf8::append (replacement, out); | ||
| 600 | ++start; | ||
| 601 | // just one replacement mark for the sequence | ||
| 602 | while (start != end && utf8::internal::is_trail(*start)) | ||
| 603 | ++start; | ||
| 604 | break; | ||
| 605 | } | ||
| 606 | } | ||
| 607 | return out; | ||
| 608 | } | ||
| 609 | |||
| 610 | template <typename octet_iterator, typename output_iterator> | ||
| 611 | inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) | ||
| 612 | { | ||
| 613 | static const utfchar32_t replacement_marker = static_cast<utfchar32_t>(utf8::internal::mask16(0xfffd)); | ||
| 614 | return utf8::replace_invalid(start, end, out, replacement_marker); | ||
| 615 | } | ||
| 616 | |||
| 617 | inline std::string replace_invalid(const std::string& s, utfchar32_t replacement) | ||
| 618 | { | ||
| 619 | std::string result; | ||
| 620 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); | ||
| 621 | return result; | ||
| 622 | } | ||
| 623 | |||
| 624 | inline std::string replace_invalid(const std::string& s) | ||
| 625 | { | ||
| 626 | std::string result; | ||
| 627 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); | ||
| 628 | return result; | ||
| 629 | } | ||
| 630 | |||
| 631 | template <typename octet_iterator> | ||
| 632 | utfchar32_t next(octet_iterator& it, octet_iterator end) | ||
| 633 | { | ||
| 634 | utfchar32_t cp = 0; | ||
| 635 | internal::utf_error err_code = utf8::internal::validate_next(it, end, cp); | ||
| 636 | switch (err_code) { | ||
| 637 | case internal::UTF8_OK : | ||
| 638 | break; | ||
| 639 | case internal::NOT_ENOUGH_ROOM : | ||
| 640 | throw not_enough_room(); | ||
| 641 | case internal::INVALID_LEAD : | ||
| 642 | case internal::INCOMPLETE_SEQUENCE : | ||
| 643 | case internal::OVERLONG_SEQUENCE : | ||
| 644 | throw invalid_utf8(static_cast<utfchar8_t>(*it)); | ||
| 645 | case internal::INVALID_CODE_POINT : | ||
| 646 | throw invalid_code_point(cp); | ||
| 647 | } | ||
| 648 | return cp; | ||
| 649 | } | ||
| 650 | |||
| 651 | template <typename word_iterator> | ||
| 652 | utfchar32_t next16(word_iterator& it, word_iterator end) | ||
| 653 | { | ||
| 654 | utfchar32_t cp = 0; | ||
| 655 | internal::utf_error err_code = utf8::internal::validate_next16(it, end, cp); | ||
| 656 | if (err_code == internal::NOT_ENOUGH_ROOM) | ||
| 657 | throw not_enough_room(); | ||
| 658 | return cp; | ||
| 659 | } | ||
| 660 | |||
| 661 | template <typename octet_iterator> | ||
| 662 | utfchar32_t peek_next(octet_iterator it, octet_iterator end) | ||
| 663 | { | ||
| 664 | return utf8::next(it, end); | ||
| 665 | } | ||
| 666 | |||
| 667 | template <typename octet_iterator> | ||
| 668 | utfchar32_t prior(octet_iterator& it, octet_iterator start) | ||
| 669 | { | ||
| 670 | // can't do much if it == start | ||
| 671 | if (it == start) | ||
| 672 | throw not_enough_room(); | ||
| 673 | |||
| 674 | octet_iterator end = it; | ||
| 675 | // Go back until we hit either a lead octet or start | ||
| 676 | while (utf8::internal::is_trail(*(--it))) | ||
| 677 | if (it == start) | ||
| 678 | throw invalid_utf8(*it); // error - no lead byte in the sequence | ||
| 679 | return utf8::peek_next(it, end); | ||
| 680 | } | ||
| 681 | |||
| 682 | template <typename octet_iterator, typename distance_type> | ||
| 683 | void advance (octet_iterator& it, distance_type n, octet_iterator end) | ||
| 684 | { | ||
| 685 | const distance_type zero(0); | ||
| 686 | if (n < zero) { | ||
| 687 | // backward | ||
| 688 | for (distance_type i = n; i < zero; ++i) | ||
| 689 | utf8::prior(it, end); | ||
| 690 | } else { | ||
| 691 | // forward | ||
| 692 | for (distance_type i = zero; i < n; ++i) | ||
| 693 | utf8::next(it, end); | ||
| 694 | } | ||
| 695 | } | ||
| 696 | |||
| 697 | template <typename octet_iterator> | ||
| 698 | typename std::iterator_traits<octet_iterator>::difference_type | ||
| 699 | distance (octet_iterator first, octet_iterator last) | ||
| 700 | { | ||
| 701 | typename std::iterator_traits<octet_iterator>::difference_type dist; | ||
| 702 | for (dist = 0; first < last; ++dist) | ||
| 703 | utf8::next(first, last); | ||
| 704 | return dist; | ||
| 705 | } | ||
| 706 | |||
| 707 | template <typename u16bit_iterator, typename octet_iterator> | ||
| 708 | octet_iterator utf16to8 (u16bit_iterator start, u16bit_iterator end, octet_iterator result) | ||
| 709 | { | ||
| 710 | while (start != end) { | ||
| 711 | utfchar32_t cp = static_cast<utfchar32_t>(utf8::internal::mask16(*start++)); | ||
| 712 | // Take care of surrogate pairs first | ||
| 713 | if (utf8::internal::is_lead_surrogate(cp)) { | ||
| 714 | if (start != end) { | ||
| 715 | const utfchar32_t trail_surrogate = static_cast<utfchar32_t>(utf8::internal::mask16(*start++)); | ||
| 716 | if (utf8::internal::is_trail_surrogate(trail_surrogate)) | ||
| 717 | cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; | ||
| 718 | else | ||
| 719 | throw invalid_utf16(static_cast<utfchar16_t>(trail_surrogate)); | ||
| 720 | } | ||
| 721 | else | ||
| 722 | throw invalid_utf16(static_cast<utfchar16_t>(cp)); | ||
| 723 | |||
| 724 | } | ||
| 725 | // Lone trail surrogate | ||
| 726 | else if (utf8::internal::is_trail_surrogate(cp)) | ||
| 727 | throw invalid_utf16(static_cast<utfchar16_t>(cp)); | ||
| 728 | |||
| 729 | result = utf8::append(cp, result); | ||
| 730 | } | ||
| 731 | return result; | ||
| 732 | } | ||
| 733 | |||
| 734 | template <typename u16bit_iterator, typename octet_iterator> | ||
| 735 | u16bit_iterator utf8to16 (octet_iterator start, octet_iterator end, u16bit_iterator result) | ||
| 736 | { | ||
| 737 | while (start < end) { | ||
| 738 | const utfchar32_t cp = utf8::next(start, end); | ||
| 739 | if (cp > 0xffff) { //make a surrogate pair | ||
| 740 | *result++ = static_cast<utfchar16_t>((cp >> 10) + internal::LEAD_OFFSET); | ||
| 741 | *result++ = static_cast<utfchar16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); | ||
| 742 | } | ||
| 743 | else | ||
| 744 | *result++ = static_cast<utfchar16_t>(cp); | ||
| 745 | } | ||
| 746 | return result; | ||
| 747 | } | ||
| 748 | |||
| 749 | template <typename octet_iterator, typename u32bit_iterator> | ||
| 750 | octet_iterator utf32to8 (u32bit_iterator start, u32bit_iterator end, octet_iterator result) | ||
| 751 | { | ||
| 752 | while (start != end) | ||
| 753 | result = utf8::append(*(start++), result); | ||
| 754 | |||
| 755 | return result; | ||
| 756 | } | ||
| 757 | |||
| 758 | template <typename octet_iterator, typename u32bit_iterator> | ||
| 759 | u32bit_iterator utf8to32 (octet_iterator start, octet_iterator end, u32bit_iterator result) | ||
| 760 | { | ||
| 761 | while (start < end) | ||
| 762 | (*result++) = utf8::next(start, end); | ||
| 763 | |||
| 764 | return result; | ||
| 765 | } | ||
| 766 | |||
| 767 | // The iterator class | ||
| 768 | template <typename octet_iterator> | ||
| 769 | class iterator { | ||
| 770 | octet_iterator it; | ||
| 771 | octet_iterator range_start; | ||
| 772 | octet_iterator range_end; | ||
| 773 | public: | ||
| 774 | typedef utfchar32_t value_type; | ||
| 775 | typedef utfchar32_t* pointer; | ||
| 776 | typedef utfchar32_t& reference; | ||
| 777 | typedef std::ptrdiff_t difference_type; | ||
| 778 | typedef std::bidirectional_iterator_tag iterator_category; | ||
| 779 | iterator () {} | ||
| 780 | explicit iterator (const octet_iterator& octet_it, | ||
| 781 | const octet_iterator& rangestart, | ||
| 782 | const octet_iterator& rangeend) : | ||
| 783 | it(octet_it), range_start(rangestart), range_end(rangeend) | ||
| 784 | { | ||
| 785 | if (it < range_start || it > range_end) | ||
| 786 | throw std::out_of_range("Invalid utf-8 iterator position"); | ||
| 787 | } | ||
| 788 | // the default "big three" are OK | ||
| 789 | octet_iterator base () const { return it; } | ||
| 790 | utfchar32_t operator * () const | ||
| 791 | { | ||
| 792 | octet_iterator temp = it; | ||
| 793 | return utf8::next(temp, range_end); | ||
| 794 | } | ||
| 795 | bool operator == (const iterator& rhs) const | ||
| 796 | { | ||
| 797 | if (range_start != rhs.range_start || range_end != rhs.range_end) | ||
| 798 | throw std::logic_error("Comparing utf-8 iterators defined with different ranges"); | ||
| 799 | return (it == rhs.it); | ||
| 800 | } | ||
| 801 | bool operator != (const iterator& rhs) const | ||
| 802 | { | ||
| 803 | return !(operator == (rhs)); | ||
| 804 | } | ||
| 805 | iterator& operator ++ () | ||
| 806 | { | ||
| 807 | utf8::next(it, range_end); | ||
| 808 | return *this; | ||
| 809 | } | ||
| 810 | iterator operator ++ (int) | ||
| 811 | { | ||
| 812 | iterator temp = *this; | ||
| 813 | utf8::next(it, range_end); | ||
| 814 | return temp; | ||
| 815 | } | ||
| 816 | iterator& operator -- () | ||
| 817 | { | ||
| 818 | utf8::prior(it, range_start); | ||
| 819 | return *this; | ||
| 820 | } | ||
| 821 | iterator operator -- (int) | ||
| 822 | { | ||
| 823 | iterator temp = *this; | ||
| 824 | utf8::prior(it, range_start); | ||
| 825 | return temp; | ||
| 826 | } | ||
| 827 | }; // class iterator | ||
| 828 | |||
| 829 | } // namespace utf8 | ||
| 830 | |||
| 831 | #if UTF_CPP_CPLUSPLUS >= 201103L // C++ 11 or later | ||
| 832 | namespace utf8 | ||
| 833 | { | ||
| 834 | inline void append16(utfchar32_t cp, std::u16string& s) | ||
| 835 | { | ||
| 836 | append16(cp, std::back_inserter(s)); | ||
| 837 | } | ||
| 838 | |||
| 839 | inline std::string utf16to8(const std::u16string& s) | ||
| 840 | { | ||
| 841 | std::string result; | ||
| 842 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 843 | return result; | ||
| 844 | } | ||
| 845 | |||
| 846 | inline std::u16string utf8to16(const std::string& s) | ||
| 847 | { | ||
| 848 | std::u16string result; | ||
| 849 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); | ||
| 850 | return result; | ||
| 851 | } | ||
| 852 | |||
| 853 | inline std::string utf32to8(const std::u32string& s) | ||
| 854 | { | ||
| 855 | std::string result; | ||
| 856 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 857 | return result; | ||
| 858 | } | ||
| 859 | |||
| 860 | inline std::u32string utf8to32(const std::string& s) | ||
| 861 | { | ||
| 862 | std::u32string result; | ||
| 863 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); | ||
| 864 | return result; | ||
| 865 | } | ||
| 866 | } // namespace utf8 | ||
| 867 | #endif // C++ 11 or later | ||
| 868 | |||
| 869 | #if UTF_CPP_CPLUSPLUS >= 201703L // C++ 17 or later | ||
| 870 | namespace utf8 | ||
| 871 | { | ||
| 872 | inline std::string utf16to8(std::u16string_view s) | ||
| 873 | { | ||
| 874 | std::string result; | ||
| 875 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 876 | return result; | ||
| 877 | } | ||
| 878 | |||
| 879 | inline std::u16string utf8to16(std::string_view s) | ||
| 880 | { | ||
| 881 | std::u16string result; | ||
| 882 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); | ||
| 883 | return result; | ||
| 884 | } | ||
| 885 | |||
| 886 | inline std::string utf32to8(std::u32string_view s) | ||
| 887 | { | ||
| 888 | std::string result; | ||
| 889 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 890 | return result; | ||
| 891 | } | ||
| 892 | |||
| 893 | inline std::u32string utf8to32(std::string_view s) | ||
| 894 | { | ||
| 895 | std::u32string result; | ||
| 896 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); | ||
| 897 | return result; | ||
| 898 | } | ||
| 899 | |||
| 900 | inline std::size_t find_invalid(std::string_view s) | ||
| 901 | { | ||
| 902 | std::string_view::const_iterator invalid = find_invalid(s.begin(), s.end()); | ||
| 903 | return (invalid == s.end()) ? std::string_view::npos : static_cast<std::size_t>(invalid - s.begin()); | ||
| 904 | } | ||
| 905 | |||
| 906 | inline bool is_valid(std::string_view s) | ||
| 907 | { | ||
| 908 | return is_valid(s.begin(), s.end()); | ||
| 909 | } | ||
| 910 | |||
| 911 | inline std::string replace_invalid(std::string_view s, char32_t replacement) | ||
| 912 | { | ||
| 913 | std::string result; | ||
| 914 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); | ||
| 915 | return result; | ||
| 916 | } | ||
| 917 | |||
| 918 | inline std::string replace_invalid(std::string_view s) | ||
| 919 | { | ||
| 920 | std::string result; | ||
| 921 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); | ||
| 922 | return result; | ||
| 923 | } | ||
| 924 | |||
| 925 | inline bool starts_with_bom(std::string_view s) | ||
| 926 | { | ||
| 927 | return starts_with_bom(s.begin(), s.end()); | ||
| 928 | } | ||
| 929 | |||
| 930 | } // namespace utf8 | ||
| 931 | #endif // C++ 17 or later | ||
| 932 | |||
| 933 | #if UTF_CPP_CPLUSPLUS >= 202002L // C++ 20 or later | ||
| 934 | namespace utf8 | ||
| 935 | { | ||
| 936 | inline std::u8string utf16tou8(const std::u16string& s) | ||
| 937 | { | ||
| 938 | std::u8string result; | ||
| 939 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 940 | return result; | ||
| 941 | } | ||
| 942 | |||
| 943 | inline std::u8string utf16tou8(std::u16string_view s) | ||
| 944 | { | ||
| 945 | std::u8string result; | ||
| 946 | utf16to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 947 | return result; | ||
| 948 | } | ||
| 949 | |||
| 950 | inline std::u16string utf8to16(const std::u8string& s) | ||
| 951 | { | ||
| 952 | std::u16string result; | ||
| 953 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); | ||
| 954 | return result; | ||
| 955 | } | ||
| 956 | |||
| 957 | inline std::u16string utf8to16(const std::u8string_view& s) | ||
| 958 | { | ||
| 959 | std::u16string result; | ||
| 960 | utf8to16(s.begin(), s.end(), std::back_inserter(result)); | ||
| 961 | return result; | ||
| 962 | } | ||
| 963 | |||
| 964 | inline std::u8string utf32tou8(const std::u32string& s) | ||
| 965 | { | ||
| 966 | std::u8string result; | ||
| 967 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 968 | return result; | ||
| 969 | } | ||
| 970 | |||
| 971 | inline std::u8string utf32tou8(const std::u32string_view& s) | ||
| 972 | { | ||
| 973 | std::u8string result; | ||
| 974 | utf32to8(s.begin(), s.end(), std::back_inserter(result)); | ||
| 975 | return result; | ||
| 976 | } | ||
| 977 | |||
| 978 | inline std::u32string utf8to32(const std::u8string& s) | ||
| 979 | { | ||
| 980 | std::u32string result; | ||
| 981 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); | ||
| 982 | return result; | ||
| 983 | } | ||
| 984 | |||
| 985 | inline std::u32string utf8to32(const std::u8string_view& s) | ||
| 986 | { | ||
| 987 | std::u32string result; | ||
| 988 | utf8to32(s.begin(), s.end(), std::back_inserter(result)); | ||
| 989 | return result; | ||
| 990 | } | ||
| 991 | |||
| 992 | inline std::size_t find_invalid(const std::u8string& s) | ||
| 993 | { | ||
| 994 | std::u8string::const_iterator invalid = find_invalid(s.begin(), s.end()); | ||
| 995 | return (invalid == s.end()) ? std::string_view::npos : static_cast<std::size_t>(invalid - s.begin()); | ||
| 996 | } | ||
| 997 | |||
| 998 | inline bool is_valid(const std::u8string& s) | ||
| 999 | { | ||
| 1000 | return is_valid(s.begin(), s.end()); | ||
| 1001 | } | ||
| 1002 | |||
| 1003 | inline std::u8string replace_invalid(const std::u8string& s, char32_t replacement) | ||
| 1004 | { | ||
| 1005 | std::u8string result; | ||
| 1006 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); | ||
| 1007 | return result; | ||
| 1008 | } | ||
| 1009 | |||
| 1010 | inline std::u8string replace_invalid(const std::u8string& s) | ||
| 1011 | { | ||
| 1012 | std::u8string result; | ||
| 1013 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); | ||
| 1014 | return result; | ||
| 1015 | } | ||
| 1016 | |||
| 1017 | inline bool starts_with_bom(const std::u8string& s) | ||
| 1018 | { | ||
| 1019 | return starts_with_bom(s.begin(), s.end()); | ||
| 1020 | } | ||
| 1021 | |||
| 1022 | } // namespace utf8 | ||
| 1023 | #endif // C++ 20 or later | ||
| 1024 | |||
| 1025 | namespace utf8 | ||
| 1026 | { | ||
| 1027 | namespace unchecked | ||
| 1028 | { | ||
| 1029 | template <typename octet_iterator> | ||
| 1030 | octet_iterator append(utfchar32_t cp, octet_iterator result) | ||
| 1031 | { | ||
| 1032 | return internal::append(cp, result); | ||
| 1033 | } | ||
| 1034 | |||
| 1035 | template <typename word_iterator> | ||
| 1036 | word_iterator append16(utfchar32_t cp, word_iterator result) | ||
| 1037 | { | ||
| 1038 | return internal::append16(cp, result); | ||
| 1039 | } | ||
| 1040 | |||
| 1041 | template <typename octet_iterator, typename output_iterator> | ||
| 1042 | output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out, utfchar32_t replacement) | ||
| 1043 | { | ||
| 1044 | while (start != end) { | ||
| 1045 | octet_iterator sequence_start = start; | ||
| 1046 | internal::utf_error err_code = utf8::internal::validate_next(start, end); | ||
| 1047 | switch (err_code) { | ||
| 1048 | case internal::UTF8_OK : | ||
| 1049 | for (octet_iterator it = sequence_start; it != start; ++it) | ||
| 1050 | *out++ = *it; | ||
| 1051 | break; | ||
| 1052 | case internal::NOT_ENOUGH_ROOM: | ||
| 1053 | out = utf8::unchecked::append(replacement, out); | ||
| 1054 | start = end; | ||
| 1055 | break; | ||
| 1056 | case internal::INVALID_LEAD: | ||
| 1057 | out = utf8::unchecked::append(replacement, out); | ||
| 1058 | ++start; | ||
| 1059 | break; | ||
| 1060 | case internal::INCOMPLETE_SEQUENCE: | ||
| 1061 | case internal::OVERLONG_SEQUENCE: | ||
| 1062 | case internal::INVALID_CODE_POINT: | ||
| 1063 | out = utf8::unchecked::append(replacement, out); | ||
| 1064 | ++start; | ||
| 1065 | // just one replacement mark for the sequence | ||
| 1066 | while (start != end && utf8::internal::is_trail(*start)) | ||
| 1067 | ++start; | ||
| 1068 | break; | ||
| 1069 | } | ||
| 1070 | } | ||
| 1071 | return out; | ||
| 1072 | } | ||
| 1073 | |||
| 1074 | template <typename octet_iterator, typename output_iterator> | ||
| 1075 | inline output_iterator replace_invalid(octet_iterator start, octet_iterator end, output_iterator out) | ||
| 1076 | { | ||
| 1077 | static const utfchar32_t replacement_marker = static_cast<utfchar32_t>(utf8::internal::mask16(0xfffd)); | ||
| 1078 | return utf8::unchecked::replace_invalid(start, end, out, replacement_marker); | ||
| 1079 | } | ||
| 1080 | |||
| 1081 | inline std::string replace_invalid(const std::string& s, utfchar32_t replacement) | ||
| 1082 | { | ||
| 1083 | std::string result; | ||
| 1084 | replace_invalid(s.begin(), s.end(), std::back_inserter(result), replacement); | ||
| 1085 | return result; | ||
| 1086 | } | ||
| 1087 | |||
| 1088 | inline std::string replace_invalid(const std::string& s) | ||
| 1089 | { | ||
| 1090 | std::string result; | ||
| 1091 | replace_invalid(s.begin(), s.end(), std::back_inserter(result)); | ||
| 1092 | return result; | ||
| 1093 | } | ||
| 1094 | |||
| 1095 | template <typename octet_iterator> | ||
| 1096 | utfchar32_t next(octet_iterator& it) | ||
| 1097 | { | ||
| 1098 | utfchar32_t cp = utf8::internal::mask8(*it); | ||
| 1099 | switch (utf8::internal::sequence_length(it)) { | ||
| 1100 | case 1: | ||
| 1101 | break; | ||
| 1102 | case 2: | ||
| 1103 | ++it; | ||
| 1104 | cp = ((cp << 6) & 0x7ff) + ((*it) & 0x3f); | ||
| 1105 | break; | ||
| 1106 | case 3: | ||
| 1107 | ++it; | ||
| 1108 | cp = ((cp << 12) & 0xffff) + ((utf8::internal::mask8(*it) << 6) & 0xfff); | ||
| 1109 | ++it; | ||
| 1110 | cp = static_cast<utfchar32_t>(cp + ((*it) & 0x3f)); | ||
| 1111 | break; | ||
| 1112 | case 4: | ||
| 1113 | ++it; | ||
| 1114 | cp = ((cp << 18) & 0x1fffff) + ((utf8::internal::mask8(*it) << 12) & 0x3ffff); | ||
| 1115 | ++it; | ||
| 1116 | cp = static_cast<utfchar32_t>(cp + ((utf8::internal::mask8(*it) << 6) & 0xfff)); | ||
| 1117 | ++it; | ||
| 1118 | cp = static_cast<utfchar32_t>(cp + ((*it) & 0x3f)); | ||
| 1119 | break; | ||
| 1120 | } | ||
| 1121 | ++it; | ||
| 1122 | return cp; | ||
| 1123 | } | ||
| 1124 | |||
| 1125 | template <typename octet_iterator> | ||
| 1126 | utfchar32_t peek_next(octet_iterator it) | ||
| 1127 | { | ||
| 1128 | return utf8::unchecked::next(it); | ||
| 1129 | } | ||
| 1130 | |||
| 1131 | template <typename word_iterator> | ||
| 1132 | utfchar32_t next16(word_iterator& it) | ||
| 1133 | { | ||
| 1134 | utfchar32_t cp = utf8::internal::mask16(*it++); | ||
| 1135 | if (utf8::internal::is_lead_surrogate(cp)) | ||
| 1136 | return (cp << 10) + *it++ + utf8::internal::SURROGATE_OFFSET; | ||
| 1137 | return cp; | ||
| 1138 | } | ||
| 1139 | |||
| 1140 | template <typename octet_iterator> | ||
| 1141 | utfchar32_t prior(octet_iterator& it) | ||
| 1142 | { | ||
| 1143 | while (utf8::internal::is_trail(*(--it))) ; | ||
| 1144 | octet_iterator temp = it; | ||
| 1145 | return utf8::unchecked::next(temp); | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | template <typename octet_iterator, typename distance_type> | ||
| 1149 | void advance(octet_iterator& it, distance_type n) | ||
| 1150 | { | ||
| 1151 | const distance_type zero(0); | ||
| 1152 | if (n < zero) { | ||
| 1153 | // backward | ||
| 1154 | for (distance_type i = n; i < zero; ++i) | ||
| 1155 | utf8::unchecked::prior(it); | ||
| 1156 | } else { | ||
| 1157 | // forward | ||
| 1158 | for (distance_type i = zero; i < n; ++i) | ||
| 1159 | utf8::unchecked::next(it); | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | |||
| 1163 | template <typename octet_iterator> | ||
| 1164 | typename std::iterator_traits<octet_iterator>::difference_type | ||
| 1165 | distance(octet_iterator first, octet_iterator last) | ||
| 1166 | { | ||
| 1167 | typename std::iterator_traits<octet_iterator>::difference_type dist; | ||
| 1168 | for (dist = 0; first < last; ++dist) | ||
| 1169 | utf8::unchecked::next(first); | ||
| 1170 | return dist; | ||
| 1171 | } | ||
| 1172 | |||
| 1173 | template <typename u16bit_iterator, typename octet_iterator> | ||
| 1174 | octet_iterator utf16to8(u16bit_iterator start, u16bit_iterator end, octet_iterator result) | ||
| 1175 | { | ||
| 1176 | while (start != end) { | ||
| 1177 | utfchar32_t cp = utf8::internal::mask16(*start++); | ||
| 1178 | // Take care of surrogate pairs first | ||
| 1179 | if (utf8::internal::is_lead_surrogate(cp)) { | ||
| 1180 | if (start == end) | ||
| 1181 | return result; | ||
| 1182 | utfchar32_t trail_surrogate = utf8::internal::mask16(*start++); | ||
| 1183 | cp = (cp << 10) + trail_surrogate + internal::SURROGATE_OFFSET; | ||
| 1184 | } | ||
| 1185 | result = utf8::unchecked::append(cp, result); | ||
| 1186 | } | ||
| 1187 | return result; | ||
| 1188 | } | ||
| 1189 | |||
| 1190 | template <typename u16bit_iterator, typename octet_iterator> | ||
| 1191 | u16bit_iterator utf8to16(octet_iterator start, octet_iterator end, u16bit_iterator result) | ||
| 1192 | { | ||
| 1193 | while (start < end) { | ||
| 1194 | utfchar32_t cp = utf8::unchecked::next(start); | ||
| 1195 | if (cp > 0xffff) { //make a surrogate pair | ||
| 1196 | *result++ = static_cast<utfchar16_t>((cp >> 10) + internal::LEAD_OFFSET); | ||
| 1197 | *result++ = static_cast<utfchar16_t>((cp & 0x3ff) + internal::TRAIL_SURROGATE_MIN); | ||
| 1198 | } | ||
| 1199 | else | ||
| 1200 | *result++ = static_cast<utfchar16_t>(cp); | ||
| 1201 | } | ||
| 1202 | return result; | ||
| 1203 | } | ||
| 1204 | |||
| 1205 | template <typename octet_iterator, typename u32bit_iterator> | ||
| 1206 | octet_iterator utf32to8(u32bit_iterator start, u32bit_iterator end, octet_iterator result) | ||
| 1207 | { | ||
| 1208 | while (start != end) | ||
| 1209 | result = utf8::unchecked::append(*(start++), result); | ||
| 1210 | |||
| 1211 | return result; | ||
| 1212 | } | ||
| 1213 | |||
| 1214 | template <typename octet_iterator, typename u32bit_iterator> | ||
| 1215 | u32bit_iterator utf8to32(octet_iterator start, octet_iterator end, u32bit_iterator result) | ||
| 1216 | { | ||
| 1217 | while (start < end) | ||
| 1218 | (*result++) = utf8::unchecked::next(start); | ||
| 1219 | |||
| 1220 | return result; | ||
| 1221 | } | ||
| 1222 | |||
| 1223 | // The iterator class | ||
| 1224 | template <typename octet_iterator> | ||
| 1225 | class iterator { | ||
| 1226 | octet_iterator it; | ||
| 1227 | public: | ||
| 1228 | typedef utfchar32_t value_type; | ||
| 1229 | typedef utfchar32_t* pointer; | ||
| 1230 | typedef utfchar32_t& reference; | ||
| 1231 | typedef std::ptrdiff_t difference_type; | ||
| 1232 | typedef std::bidirectional_iterator_tag iterator_category; | ||
| 1233 | iterator () {} | ||
| 1234 | explicit iterator (const octet_iterator& octet_it): it(octet_it) {} | ||
| 1235 | // the default "big three" are OK | ||
| 1236 | octet_iterator base () const { return it; } | ||
| 1237 | utfchar32_t operator * () const | ||
| 1238 | { | ||
| 1239 | octet_iterator temp = it; | ||
| 1240 | return utf8::unchecked::next(temp); | ||
| 1241 | } | ||
| 1242 | bool operator == (const iterator& rhs) const | ||
| 1243 | { | ||
| 1244 | return (it == rhs.it); | ||
| 1245 | } | ||
| 1246 | bool operator != (const iterator& rhs) const | ||
| 1247 | { | ||
| 1248 | return !(operator == (rhs)); | ||
| 1249 | } | ||
| 1250 | iterator& operator ++ () | ||
| 1251 | { | ||
| 1252 | ::std::advance(it, utf8::internal::sequence_length(it)); | ||
| 1253 | return *this; | ||
| 1254 | } | ||
| 1255 | iterator operator ++ (int) | ||
| 1256 | { | ||
| 1257 | iterator temp = *this; | ||
| 1258 | ::std::advance(it, utf8::internal::sequence_length(it)); | ||
| 1259 | return temp; | ||
| 1260 | } | ||
| 1261 | iterator& operator -- () | ||
| 1262 | { | ||
| 1263 | utf8::unchecked::prior(it); | ||
| 1264 | return *this; | ||
| 1265 | } | ||
| 1266 | iterator operator -- (int) | ||
| 1267 | { | ||
| 1268 | iterator temp = *this; | ||
| 1269 | utf8::unchecked::prior(it); | ||
| 1270 | return temp; | ||
| 1271 | } | ||
| 1272 | }; // class iterator | ||
| 1273 | |||
| 1274 | } // namespace utf8::unchecked | ||
| 1275 | } // namespace utf8 | ||
| 1276 | |||
| 1277 | #endif // header guard | ||
diff --git a/src/yue.cpp b/src/yue.cpp index fc57767..b93f75e 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -30,6 +30,38 @@ using namespace std::chrono_literals; | |||
| 30 | #include "ghc/fs_std.hpp" | 30 | #include "ghc/fs_std.hpp" |
| 31 | #include "linenoise.hpp" | 31 | #include "linenoise.hpp" |
| 32 | 32 | ||
| 33 | #if __has_include(<pthread.h>) | ||
| 34 | #include <pthread.h> | ||
| 35 | template<class R> | ||
| 36 | std::future<R> async(const std::function<R()>& f) { | ||
| 37 | using Fn = std::packaged_task<R()>; | ||
| 38 | auto task = new Fn(f); | ||
| 39 | std::future<R> fut = task->get_future(); | ||
| 40 | |||
| 41 | pthread_attr_t attr; | ||
| 42 | pthread_attr_init(&attr); | ||
| 43 | pthread_attr_setstacksize(&attr, 8 * 1024 * 1024); | ||
| 44 | |||
| 45 | pthread_t th; | ||
| 46 | pthread_create(&th, &attr, | ||
| 47 | [](void* p)->void* { | ||
| 48 | std::unique_ptr<Fn> fn(static_cast<Fn*>(p)); | ||
| 49 | (*fn)(); | ||
| 50 | return nullptr; | ||
| 51 | }, | ||
| 52 | task); | ||
| 53 | pthread_attr_destroy(&attr); | ||
| 54 | pthread_detach(th); | ||
| 55 | return fut; | ||
| 56 | } | ||
| 57 | #else | ||
| 58 | template<class R> | ||
| 59 | std::future<R> async(const std::function<R()>& f) { | ||
| 60 | // fallback: ignore stack size | ||
| 61 | return std::async(std::launch::async, f); | ||
| 62 | } | ||
| 63 | #endif | ||
| 64 | |||
| 33 | #if not(defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) | 65 | #if not(defined YUE_NO_MACRO && defined YUE_COMPILER_ONLY) |
| 34 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { \ | 66 | #define _DEFER(code, line) std::shared_ptr<void> _defer_##line(nullptr, [&](auto) { \ |
| 35 | code; \ | 67 | code; \ |
| @@ -40,18 +72,23 @@ extern "C" { | |||
| 40 | #include "lua.h" | 72 | #include "lua.h" |
| 41 | #include "lualib.h" | 73 | #include "lualib.h" |
| 42 | int luaopen_yue(lua_State* L); | 74 | int luaopen_yue(lua_State* L); |
| 75 | int luaopen_colibc_json(lua_State* L); | ||
| 43 | } // extern "C" | 76 | } // extern "C" |
| 44 | 77 | ||
| 45 | static void openlibs(void* state) { | 78 | static void openlibs(void* state) { |
| 46 | lua_State* L = static_cast<lua_State*>(state); | 79 | lua_State* L = static_cast<lua_State*>(state); |
| 80 | int top = lua_gettop(L); | ||
| 81 | DEFER(lua_settop(L, top)); | ||
| 47 | luaL_openlibs(L); | 82 | luaL_openlibs(L); |
| 48 | #if LUA_VERSION_NUM > 501 | 83 | #if LUA_VERSION_NUM > 501 |
| 49 | luaL_requiref(L, "yue", luaopen_yue, 0); | 84 | luaL_requiref(L, "yue", luaopen_yue, 0); |
| 85 | luaL_requiref(L, "cojson", luaopen_colibc_json, 0); | ||
| 50 | #else | 86 | #else |
| 51 | lua_pushcfunction(L, luaopen_yue); | 87 | lua_pushcfunction(L, luaopen_yue); |
| 52 | lua_call(L, 0, 0); | 88 | lua_call(L, 0, 0); |
| 89 | lua_pushcfunction(L, luaopen_colibc_json); | ||
| 90 | lua_call(L, 0, 0); | ||
| 53 | #endif | 91 | #endif |
| 54 | lua_pop(L, 1); | ||
| 55 | } | 92 | } |
| 56 | 93 | ||
| 57 | void pushYue(lua_State* L, std::string_view name) { | 94 | void pushYue(lua_State* L, std::string_view name) { |
| @@ -699,7 +736,7 @@ int main(int narg, const char** args) { | |||
| 699 | } | 736 | } |
| 700 | std::list<std::future<std::string>> results; | 737 | std::list<std::future<std::string>> results; |
| 701 | for (const auto& file : files) { | 738 | for (const auto& file : files) { |
| 702 | auto task = std::async(std::launch::async, [=]() { | 739 | auto task = async<std::string>([=]() { |
| 703 | #ifndef YUE_COMPILER_ONLY | 740 | #ifndef YUE_COMPILER_ONLY |
| 704 | return compileFile(fs::absolute(file.first), config, fullWorkPath, fullTargetPath, minify, rewrite); | 741 | return compileFile(fs::absolute(file.first), config, fullWorkPath, fullTargetPath, minify, rewrite); |
| 705 | #else | 742 | #else |
| @@ -737,7 +774,7 @@ int main(int narg, const char** args) { | |||
| 737 | #endif // YUE_NO_WATCHER | 774 | #endif // YUE_NO_WATCHER |
| 738 | std::list<std::future<std::tuple<int, std::string, std::string>>> results; | 775 | std::list<std::future<std::tuple<int, std::string, std::string>>> results; |
| 739 | for (const auto& file : files) { | 776 | for (const auto& file : files) { |
| 740 | auto task = std::async(std::launch::async, [=]() { | 777 | auto task = async<std::tuple<int, std::string, std::string>>([=]() { |
| 741 | std::ifstream input(file.first, std::ios::in); | 778 | std::ifstream input(file.first, std::ios::in); |
| 742 | if (input) { | 779 | if (input) { |
| 743 | std::string s( | 780 | std::string s( |
diff --git a/src/yue_wasm.cpp b/src/yue_wasm.cpp index 20f3794..abb291e 100644 --- a/src/yue_wasm.cpp +++ b/src/yue_wasm.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
diff --git a/src/yuescript/parser.cpp b/src/yuescript/parser.cpp index f0ddd06..5910348 100644 --- a/src/yuescript/parser.cpp +++ b/src/yuescript/parser.cpp | |||
| @@ -18,8 +18,33 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
| 18 | 18 | ||
| 19 | #include "yuescript/parser.hpp" | 19 | #include "yuescript/parser.hpp" |
| 20 | 20 | ||
| 21 | #ifndef YUE_UTF8_IMPL | ||
| 22 | namespace CodeCvt { | ||
| 23 | std::u32string utf8to32(const std::string& str); | ||
| 24 | std::string utf32to8(const std::u32string& str); | ||
| 25 | } // namespace CodeCvt | ||
| 26 | #else | ||
| 27 | #include "utf8cpp.h" | ||
| 28 | namespace CodeCvt { | ||
| 29 | std::u32string utf8to32(const std::string& str) { | ||
| 30 | return utf8::utf8to32(str); | ||
| 31 | } | ||
| 32 | std::string utf32to8(const std::u32string& str) { | ||
| 33 | return utf8::utf32to8(str); | ||
| 34 | } | ||
| 35 | } // namespace CodeCvt | ||
| 36 | #endif // YUE_UTF8_IMPL | ||
| 37 | |||
| 21 | namespace parserlib { | 38 | namespace parserlib { |
| 22 | 39 | ||
| 40 | input utf8_decode(const std::string& str) { | ||
| 41 | return CodeCvt::utf8to32(str); | ||
| 42 | } | ||
| 43 | |||
| 44 | std::string utf8_encode(const input& str) { | ||
| 45 | return CodeCvt::utf32to8(str); | ||
| 46 | } | ||
| 47 | |||
| 23 | // internal private class that manages access to the public classes' internals. | 48 | // internal private class that manages access to the public classes' internals. |
| 24 | class _private { | 49 | class _private { |
| 25 | public: | 50 | public: |
| @@ -241,7 +266,7 @@ class _string : public _expr { | |||
| 241 | public: | 266 | public: |
| 242 | // constructor from ansi string. | 267 | // constructor from ansi string. |
| 243 | _string(const char* s) | 268 | _string(const char* s) |
| 244 | : m_string(Converter{}.from_bytes(s)) { | 269 | : m_string(utf8_decode(s)) { |
| 245 | } | 270 | } |
| 246 | 271 | ||
| 247 | // parse with whitespace | 272 | // parse with whitespace |
| @@ -279,7 +304,7 @@ class _set : public _expr { | |||
| 279 | public: | 304 | public: |
| 280 | // constructor from ansi string. | 305 | // constructor from ansi string. |
| 281 | _set(const char* s) { | 306 | _set(const char* s) { |
| 282 | auto str = Converter{}.from_bytes(s); | 307 | auto str = utf8_decode(s); |
| 283 | for (auto ch : str) { | 308 | for (auto ch : str) { |
| 284 | _add(ch); | 309 | _add(ch); |
| 285 | } | 310 | } |
diff --git a/src/yuescript/parser.hpp b/src/yuescript/parser.hpp index c544785..4742539 100644 --- a/src/yuescript/parser.hpp +++ b/src/yuescript/parser.hpp | |||
| @@ -17,7 +17,6 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
| 17 | #pragma warning(disable : 4521) | 17 | #pragma warning(disable : 4521) |
| 18 | #endif | 18 | #endif |
| 19 | 19 | ||
| 20 | #include <codecvt> | ||
| 21 | #include <functional> | 20 | #include <functional> |
| 22 | #include <list> | 21 | #include <list> |
| 23 | #include <locale> | 22 | #include <locale> |
| @@ -27,9 +26,11 @@ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND | |||
| 27 | namespace parserlib { | 26 | namespace parserlib { |
| 28 | 27 | ||
| 29 | /// type of the parser's input. | 28 | /// type of the parser's input. |
| 30 | typedef std::basic_string<wchar_t> input; | 29 | typedef std::basic_string<char32_t> input; |
| 31 | typedef input::iterator input_it; | 30 | typedef input::iterator input_it; |
| 32 | typedef std::wstring_convert<std::codecvt_utf8_utf16<input::value_type>> Converter; | 31 | |
| 32 | input utf8_decode(const std::string& str); | ||
| 33 | std::string utf8_encode(const input& str); | ||
| 33 | 34 | ||
| 34 | class _private; | 35 | class _private; |
| 35 | class _expr; | 36 | class _expr; |
diff --git a/src/yuescript/yue_ast.cpp b/src/yuescript/yue_ast.cpp index fdb1d20..14d8db8 100644 --- a/src/yuescript/yue_ast.cpp +++ b/src/yuescript/yue_ast.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -30,7 +30,7 @@ std::string YueFormat::ind() const { | |||
| 30 | } | 30 | } |
| 31 | 31 | ||
| 32 | std::string YueFormat::convert(const ast_node* node) { | 32 | std::string YueFormat::convert(const ast_node* node) { |
| 33 | return converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | 33 | return utf8_encode({node->m_begin.m_it, node->m_end.m_it}); |
| 34 | } | 34 | } |
| 35 | 35 | ||
| 36 | std::string YueFormat::toString(ast_node* node) { | 36 | std::string YueFormat::toString(ast_node* node) { |
| @@ -82,6 +82,13 @@ std::string SelfClass_t::to_string(void*) const { | |||
| 82 | std::string VarArg_t::to_string(void*) const { | 82 | std::string VarArg_t::to_string(void*) const { |
| 83 | return "..."s; | 83 | return "..."s; |
| 84 | } | 84 | } |
| 85 | std::string VarArgDef_t::to_string(void* ud) const { | ||
| 86 | if (name) { | ||
| 87 | return "..."s + name->to_string(ud); | ||
| 88 | } else { | ||
| 89 | return "..."s; | ||
| 90 | } | ||
| 91 | } | ||
| 85 | std::string Seperator_t::to_string(void*) const { | 92 | std::string Seperator_t::to_string(void*) const { |
| 86 | return {}; | 93 | return {}; |
| 87 | } | 94 | } |
| @@ -167,7 +174,7 @@ std::string ExistentialOp_t::to_string(void*) const { | |||
| 167 | std::string TableAppendingOp_t::to_string(void*) const { | 174 | std::string TableAppendingOp_t::to_string(void*) const { |
| 168 | return "[]"s; | 175 | return "[]"s; |
| 169 | } | 176 | } |
| 170 | std::string PlainItem_t::to_string(void *) const { | 177 | std::string PlainItem_t::to_string(void*) const { |
| 171 | return {}; | 178 | return {}; |
| 172 | } | 179 | } |
| 173 | std::string GlobalOp_t::to_string(void*) const { | 180 | std::string GlobalOp_t::to_string(void*) const { |
| @@ -203,14 +210,18 @@ std::string YueLineComment_t::to_string(void* ud) const { | |||
| 203 | auto info = reinterpret_cast<YueFormat*>(ud); | 210 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 204 | return "--"s + info->convert(this); | 211 | return "--"s + info->convert(this); |
| 205 | } | 212 | } |
| 206 | std::string MultilineCommentInner_t::to_string(void* ud) const { | 213 | std::string YueMultilineComment_t::to_string(void* ud) const { |
| 207 | auto info = reinterpret_cast<YueFormat*>(ud); | 214 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 208 | return info->convert(this); | 215 | return "--[["s + info->convert(this) + "]]"s; |
| 209 | } | 216 | } |
| 210 | std::string Variable_t::to_string(void* ud) const { | 217 | std::string YueComment_t::to_string(void* ud) const { |
| 211 | return name->to_string(ud); | 218 | if (comment) { |
| 219 | return comment->to_string(ud); | ||
| 220 | } else { | ||
| 221 | return {}; | ||
| 222 | } | ||
| 212 | } | 223 | } |
| 213 | std::string LabelName_t::to_string(void* ud) const { | 224 | std::string Variable_t::to_string(void* ud) const { |
| 214 | return name->to_string(ud); | 225 | return name->to_string(ud); |
| 215 | } | 226 | } |
| 216 | std::string LuaKeyword_t::to_string(void* ud) const { | 227 | std::string LuaKeyword_t::to_string(void* ud) const { |
| @@ -304,6 +315,17 @@ std::string ImportAs_t::to_string(void* ud) const { | |||
| 304 | } | 315 | } |
| 305 | return join(temp, " "s); | 316 | return join(temp, " "s); |
| 306 | } | 317 | } |
| 318 | std::string ImportGlobal_t::to_string(void* ud) const { | ||
| 319 | str_list temp; | ||
| 320 | for (auto seg : segs.objects()) { | ||
| 321 | temp.emplace_back(seg->to_string(ud)); | ||
| 322 | } | ||
| 323 | auto item = join(temp, "."s); | ||
| 324 | if (target) { | ||
| 325 | return item + " as "s + target->to_string(ud); | ||
| 326 | } | ||
| 327 | return item; | ||
| 328 | } | ||
| 307 | std::string Import_t::to_string(void* ud) const { | 329 | std::string Import_t::to_string(void* ud) const { |
| 308 | if (ast_is<FromImport_t>(content)) { | 330 | if (ast_is<FromImport_t>(content)) { |
| 309 | return content->to_string(ud); | 331 | return content->to_string(ud); |
| @@ -372,8 +394,8 @@ std::string With_t::to_string(void* ud) const { | |||
| 372 | str_list temp{ | 394 | str_list temp{ |
| 373 | eop ? "with?"s : "with"s, | 395 | eop ? "with?"s : "with"s, |
| 374 | valueList->to_string(ud)}; | 396 | valueList->to_string(ud)}; |
| 375 | if (assigns) { | 397 | if (assign) { |
| 376 | temp.push_back(assigns->to_string(ud)); | 398 | temp.push_back(':' + assign->to_string(ud)); |
| 377 | } | 399 | } |
| 378 | if (body.is<Statement_t>()) { | 400 | if (body.is<Statement_t>()) { |
| 379 | return join(temp, " "sv) + " do "s + body->to_string(ud); | 401 | return join(temp, " "sv) + " do "s + body->to_string(ud); |
| @@ -419,6 +441,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
| 419 | std::string Switch_t::to_string(void* ud) const { | 441 | std::string Switch_t::to_string(void* ud) const { |
| 420 | auto info = reinterpret_cast<YueFormat*>(ud); | 442 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 421 | str_list temp{"switch "s + target->to_string(ud)}; | 443 | str_list temp{"switch "s + target->to_string(ud)}; |
| 444 | if (assignment) { | ||
| 445 | temp.back().append(assignment->to_string(ud)); | ||
| 446 | } | ||
| 422 | info->pushScope(); | 447 | info->pushScope(); |
| 423 | for (auto branch : branches.objects()) { | 448 | for (auto branch : branches.objects()) { |
| 424 | temp.emplace_back(info->ind() + branch->to_string(ud)); | 449 | temp.emplace_back(info->ind() + branch->to_string(ud)); |
| @@ -462,41 +487,75 @@ std::string If_t::to_string(void* ud) const { | |||
| 462 | temp.back() += " then"s; | 487 | temp.back() += " then"s; |
| 463 | } | 488 | } |
| 464 | ++it; | 489 | ++it; |
| 465 | bool condition = true; | 490 | enum class NType { |
| 491 | Cond, | ||
| 492 | Stat, | ||
| 493 | Block | ||
| 494 | }; | ||
| 495 | NType lastType = NType::Cond; | ||
| 466 | for (; it != nodes.objects().end(); ++it) { | 496 | for (; it != nodes.objects().end(); ++it) { |
| 467 | auto node = *it; | 497 | auto node = *it; |
| 468 | switch (node->get_id()) { | 498 | switch (node->get_id()) { |
| 469 | case id<IfCond_t>(): | 499 | case id<IfCond_t>(): |
| 470 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); | 500 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); |
| 471 | condition = true; | 501 | lastType = NType::Cond; |
| 472 | break; | 502 | break; |
| 473 | case id<Statement_t>(): { | 503 | case id<Statement_t>(): { |
| 474 | if (condition) { | 504 | switch (lastType) { |
| 475 | temp.back() += " then "s + node->to_string(ud); | 505 | case NType::Cond: |
| 476 | } else { | 506 | temp.back() += " then "s + node->to_string(ud); |
| 477 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | 507 | break; |
| 508 | case NType::Stat: | ||
| 509 | if (temp.back().back() == '\n') { | ||
| 510 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
| 511 | } else { | ||
| 512 | temp.back() += " else "s + node->to_string(ud); | ||
| 513 | } | ||
| 514 | break; | ||
| 515 | case NType::Block: | ||
| 516 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
| 517 | break; | ||
| 478 | } | 518 | } |
| 479 | condition = false; | 519 | lastType = NType::Stat; |
| 480 | break; | 520 | break; |
| 481 | } | 521 | } |
| 482 | case id<Block_t>(): { | 522 | case id<Block_t>(): { |
| 483 | if (condition) { | 523 | switch (lastType) { |
| 484 | info->pushScope(); | 524 | case NType::Cond: { |
| 485 | temp.emplace_back(node->to_string(ud)); | 525 | info->pushScope(); |
| 486 | if (temp.back().empty()) { | 526 | temp.emplace_back(node->to_string(ud)); |
| 487 | temp.back() = info->ind() + "--"s; | 527 | if (temp.back().empty()) { |
| 528 | temp.back() = info->ind() + "--"s; | ||
| 529 | } | ||
| 530 | info->popScope(); | ||
| 531 | break; | ||
| 532 | } | ||
| 533 | case NType::Stat: { | ||
| 534 | if (temp.back().back() == '\n') { | ||
| 535 | temp.emplace_back(info->ind() + "else"s); | ||
| 536 | } else { | ||
| 537 | temp.back() += " else"s; | ||
| 538 | } | ||
| 539 | info->pushScope(); | ||
| 540 | temp.emplace_back(node->to_string(ud)); | ||
| 541 | if (temp.back().empty()) { | ||
| 542 | temp.back() = info->ind() + "--"s; | ||
| 543 | } | ||
| 544 | info->popScope(); | ||
| 545 | break; | ||
| 488 | } | 546 | } |
| 489 | info->popScope(); | 547 | case NType::Block: { |
| 490 | } else { | 548 | temp.emplace_back(info->ind() + "else"s); |
| 491 | temp.emplace_back(info->ind() + "else"s); | 549 | info->pushScope(); |
| 492 | info->pushScope(); | 550 | temp.emplace_back(node->to_string(ud)); |
| 493 | temp.emplace_back(node->to_string(ud)); | 551 | if (temp.back().empty()) { |
| 494 | if (temp.back().empty()) { | 552 | temp.back() = info->ind() + "--"s; |
| 495 | temp.back() = info->ind() + "--"s; | 553 | } |
| 554 | info->popScope(); | ||
| 555 | break; | ||
| 496 | } | 556 | } |
| 497 | info->popScope(); | ||
| 498 | } | 557 | } |
| 499 | condition = false; | 558 | lastType = NType::Block; |
| 500 | break; | 559 | break; |
| 501 | } | 560 | } |
| 502 | } | 561 | } |
| @@ -524,10 +583,10 @@ std::string While_t::to_string(void* ud) const { | |||
| 524 | } | 583 | } |
| 525 | std::string Repeat_t::to_string(void* ud) const { | 584 | std::string Repeat_t::to_string(void* ud) const { |
| 526 | auto info = reinterpret_cast<YueFormat*>(ud); | 585 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 527 | str_list temp; | 586 | if (body.is<Statement_t>()) { |
| 528 | if (body->content.is<Statement_t>()) { | 587 | return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud); |
| 529 | temp.emplace_back("repeat "s + body->to_string(ud)); | ||
| 530 | } else { | 588 | } else { |
| 589 | str_list temp; | ||
| 531 | temp.emplace_back("repeat"s); | 590 | temp.emplace_back("repeat"s); |
| 532 | info->pushScope(); | 591 | info->pushScope(); |
| 533 | temp.emplace_back(body->to_string(ud)); | 592 | temp.emplace_back(body->to_string(ud)); |
| @@ -535,14 +594,14 @@ std::string Repeat_t::to_string(void* ud) const { | |||
| 535 | temp.back() = info->ind() + "--"s; | 594 | temp.back() = info->ind() + "--"s; |
| 536 | } | 595 | } |
| 537 | info->popScope(); | 596 | info->popScope(); |
| 597 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 598 | return join(temp, "\n"sv); | ||
| 538 | } | 599 | } |
| 539 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 540 | return join(temp, "\n"sv); | ||
| 541 | } | 600 | } |
| 542 | std::string ForStepValue_t::to_string(void* ud) const { | 601 | std::string ForStepValue_t::to_string(void* ud) const { |
| 543 | return value->to_string(ud); | 602 | return value->to_string(ud); |
| 544 | } | 603 | } |
| 545 | std::string For_t::to_string(void* ud) const { | 604 | std::string ForNum_t::to_string(void* ud) const { |
| 546 | auto info = reinterpret_cast<YueFormat*>(ud); | 605 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 547 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); | 606 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); |
| 548 | if (stepValue) { | 607 | if (stepValue) { |
| @@ -581,6 +640,9 @@ std::string ForEach_t::to_string(void* ud) const { | |||
| 581 | return line + '\n' + block; | 640 | return line + '\n' + block; |
| 582 | } | 641 | } |
| 583 | } | 642 | } |
| 643 | std::string For_t::to_string(void* ud) const { | ||
| 644 | return forLoop->to_string(ud); | ||
| 645 | } | ||
| 584 | std::string Do_t::to_string(void* ud) const { | 646 | std::string Do_t::to_string(void* ud) const { |
| 585 | auto info = reinterpret_cast<YueFormat*>(ud); | 647 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 586 | if (body->content.is<Statement_t>()) { | 648 | if (body->content.is<Statement_t>()) { |
| @@ -609,10 +671,13 @@ std::string CatchBlock_t::to_string(void* ud) const { | |||
| 609 | std::string Try_t::to_string(void* ud) const { | 671 | std::string Try_t::to_string(void* ud) const { |
| 610 | auto info = reinterpret_cast<YueFormat*>(ud); | 672 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 611 | str_list temp; | 673 | str_list temp; |
| 674 | temp.emplace_back("try"s); | ||
| 675 | if (eop) { | ||
| 676 | temp.back() += eop->to_string(ud); | ||
| 677 | } | ||
| 612 | if (func.is<Exp_t>()) { | 678 | if (func.is<Exp_t>()) { |
| 613 | temp.emplace_back("try "s + func->to_string(ud)); | 679 | temp.back() += (" "s + func->to_string(ud)); |
| 614 | } else { | 680 | } else { |
| 615 | temp.emplace_back("try"s); | ||
| 616 | info->pushScope(); | 681 | info->pushScope(); |
| 617 | temp.emplace_back(func->to_string(ud)); | 682 | temp.emplace_back(func->to_string(ud)); |
| 618 | if (temp.back().empty()) { | 683 | if (temp.back().empty()) { |
| @@ -729,7 +794,7 @@ static bool isInBlockExp(ast_node* node, bool last = false) { | |||
| 729 | return false; | 794 | return false; |
| 730 | } | 795 | } |
| 731 | std::string Comprehension_t::to_string(void* ud) const { | 796 | std::string Comprehension_t::to_string(void* ud) const { |
| 732 | if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { | 797 | if (items.size() != 2 || !ast_is<CompFor_t>(items.back())) { |
| 733 | if (items.size() == 1) { | 798 | if (items.size() == 1) { |
| 734 | str_list temp; | 799 | str_list temp; |
| 735 | for (const auto& item : items.objects()) { | 800 | for (const auto& item : items.objects()) { |
| @@ -796,14 +861,14 @@ std::string StarExp_t::to_string(void* ud) const { | |||
| 796 | std::string CompForEach_t::to_string(void* ud) const { | 861 | std::string CompForEach_t::to_string(void* ud) const { |
| 797 | return "for "s + nameList->to_string(ud) + " in "s + loopValue->to_string(ud); | 862 | return "for "s + nameList->to_string(ud) + " in "s + loopValue->to_string(ud); |
| 798 | } | 863 | } |
| 799 | std::string CompFor_t::to_string(void* ud) const { | 864 | std::string CompForNum_t::to_string(void* ud) const { |
| 800 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); | 865 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); |
| 801 | if (stepValue) { | 866 | if (stepValue) { |
| 802 | line += stepValue->to_string(ud); | 867 | line += stepValue->to_string(ud); |
| 803 | } | 868 | } |
| 804 | return line; | 869 | return line; |
| 805 | } | 870 | } |
| 806 | std::string CompInner_t::to_string(void* ud) const { | 871 | std::string CompFor_t::to_string(void* ud) const { |
| 807 | str_list temp; | 872 | str_list temp; |
| 808 | for (auto item : items.objects()) { | 873 | for (auto item : items.objects()) { |
| 809 | if (ast_is<Exp_t>(item)) { | 874 | if (ast_is<Exp_t>(item)) { |
| @@ -864,6 +929,12 @@ std::string Exp_t::to_string(void* ud) const { | |||
| 864 | } | 929 | } |
| 865 | return join(temp, " "sv); | 930 | return join(temp, " "sv); |
| 866 | } | 931 | } |
| 932 | std::string ReversedIndex_t::to_string(void* ud) const { | ||
| 933 | if (modifier) { | ||
| 934 | return "[# - "s + modifier->to_string(ud) + ']'; | ||
| 935 | } | ||
| 936 | return "[#]"s; | ||
| 937 | } | ||
| 867 | std::string Callable_t::to_string(void* ud) const { | 938 | std::string Callable_t::to_string(void* ud) const { |
| 868 | return item->to_string(ud); | 939 | return item->to_string(ud); |
| 869 | } | 940 | } |
| @@ -950,6 +1021,51 @@ std::string DoubleString_t::to_string(void* ud) const { | |||
| 950 | } | 1021 | } |
| 951 | return '"' + join(temp) + '"'; | 1022 | return '"' + join(temp) + '"'; |
| 952 | } | 1023 | } |
| 1024 | std::string YAMLIndent_t::to_string(void* ud) const { | ||
| 1025 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1026 | return info->convert(this); | ||
| 1027 | } | ||
| 1028 | std::string YAMLLineInner_t::to_string(void* ud) const { | ||
| 1029 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1030 | return info->convert(this); | ||
| 1031 | } | ||
| 1032 | std::string YAMLLineContent_t::to_string(void* ud) const { | ||
| 1033 | if (content.is<Exp_t>()) { | ||
| 1034 | return "#{"s + content->to_string(ud) + '}'; | ||
| 1035 | } | ||
| 1036 | return content->to_string(ud); | ||
| 1037 | } | ||
| 1038 | std::string YAMLLine_t::to_string(void* ud) const { | ||
| 1039 | str_list temp; | ||
| 1040 | for (auto seg : segments.objects()) { | ||
| 1041 | temp.emplace_back(seg->to_string(ud)); | ||
| 1042 | } | ||
| 1043 | return join(temp); | ||
| 1044 | } | ||
| 1045 | std::string YAMLMultiline_t::to_string(void* ud) const { | ||
| 1046 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1047 | int currentIndent = info->indent; | ||
| 1048 | str_list temp; | ||
| 1049 | int lastIndent = -1; | ||
| 1050 | for (auto line_ : lines.objects()) { | ||
| 1051 | auto line = static_cast<YAMLLine_t*>(line_); | ||
| 1052 | auto indent = line->indent->to_string(ud); | ||
| 1053 | int ind = 0; | ||
| 1054 | for (auto c : indent) { | ||
| 1055 | if (c == ' ') ind++; | ||
| 1056 | if (c == '\t') ind += 4; | ||
| 1057 | } | ||
| 1058 | if (lastIndent < ind) { | ||
| 1059 | info->pushScope(); | ||
| 1060 | } else if (lastIndent > ind) { | ||
| 1061 | info->popScope(); | ||
| 1062 | } | ||
| 1063 | lastIndent = ind; | ||
| 1064 | temp.emplace_back(indent + line->to_string(ud)); | ||
| 1065 | } | ||
| 1066 | info->indent = currentIndent; | ||
| 1067 | return "|\n" + join(temp, "\n"sv) + '\n'; | ||
| 1068 | } | ||
| 953 | std::string String_t::to_string(void* ud) const { | 1069 | std::string String_t::to_string(void* ud) const { |
| 954 | return str->to_string(ud); | 1070 | return str->to_string(ud); |
| 955 | } | 1071 | } |
| @@ -1248,6 +1364,9 @@ std::string FnArgDef_t::to_string(void* ud) const { | |||
| 1248 | if (op) { | 1364 | if (op) { |
| 1249 | line += op->to_string(ud); | 1365 | line += op->to_string(ud); |
| 1250 | } | 1366 | } |
| 1367 | if (label) { | ||
| 1368 | line += '`' + label->to_string(ud); | ||
| 1369 | } | ||
| 1251 | if (defaultValue) { | 1370 | if (defaultValue) { |
| 1252 | line += " = "s + defaultValue->to_string(ud); | 1371 | line += " = "s + defaultValue->to_string(ud); |
| 1253 | } | 1372 | } |
| @@ -1270,6 +1389,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
| 1270 | } | 1389 | } |
| 1271 | if (varArg) { | 1390 | if (varArg) { |
| 1272 | temp.emplace_back(info->ind() + varArg->to_string(ud)); | 1391 | temp.emplace_back(info->ind() + varArg->to_string(ud)); |
| 1392 | if (label) { | ||
| 1393 | temp.back().append('`' + label->to_string(ud)); | ||
| 1394 | } | ||
| 1273 | } | 1395 | } |
| 1274 | return join(temp, "\n"sv); | 1396 | return join(temp, "\n"sv); |
| 1275 | } else { | 1397 | } else { |
| @@ -1278,6 +1400,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
| 1278 | } | 1400 | } |
| 1279 | if (varArg) { | 1401 | if (varArg) { |
| 1280 | temp.emplace_back(varArg->to_string(ud)); | 1402 | temp.emplace_back(varArg->to_string(ud)); |
| 1403 | if (label) { | ||
| 1404 | temp.back().append('`' + label->to_string(ud)); | ||
| 1405 | } | ||
| 1281 | } | 1406 | } |
| 1282 | return join(temp, ", "sv); | 1407 | return join(temp, ", "sv); |
| 1283 | } | 1408 | } |
| @@ -1488,37 +1613,17 @@ std::string StatementAppendix_t::to_string(void* ud) const { | |||
| 1488 | return item->to_string(ud); | 1613 | return item->to_string(ud); |
| 1489 | } | 1614 | } |
| 1490 | std::string Statement_t::to_string(void* ud) const { | 1615 | std::string Statement_t::to_string(void* ud) const { |
| 1491 | std::string line; | 1616 | if (appendix) { |
| 1492 | if (!comments.empty()) { | 1617 | return content->to_string(ud) + ' ' + appendix->to_string(ud); |
| 1493 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1494 | str_list temp; | ||
| 1495 | for (ast_node* comment : comments.objects()) { | ||
| 1496 | if (comment == comments.front()) { | ||
| 1497 | temp.push_back(comment->to_string(ud)); | ||
| 1498 | } else { | ||
| 1499 | temp.push_back(info->ind() + comment->to_string(ud)); | ||
| 1500 | } | ||
| 1501 | } | ||
| 1502 | if (appendix) { | ||
| 1503 | temp.push_back(info->ind() + content->to_string(ud) + ' ' + appendix->to_string(ud)); | ||
| 1504 | return join(temp, "\n"sv); | ||
| 1505 | } else { | ||
| 1506 | temp.push_back(info->ind() + content->to_string(ud)); | ||
| 1507 | return join(temp, "\n"sv); | ||
| 1508 | } | ||
| 1509 | } else { | 1618 | } else { |
| 1510 | if (appendix) { | 1619 | return content->to_string(ud); |
| 1511 | return content->to_string(ud) + ' ' + appendix->to_string(ud); | ||
| 1512 | } else { | ||
| 1513 | return content->to_string(ud); | ||
| 1514 | } | ||
| 1515 | } | 1620 | } |
| 1516 | } | 1621 | } |
| 1517 | std::string StatementSep_t::to_string(void*) const { | 1622 | std::string StatementSep_t::to_string(void*) const { |
| 1518 | return {}; | 1623 | return {}; |
| 1519 | } | 1624 | } |
| 1520 | std::string YueMultilineComment_t::to_string(void* ud) const { | 1625 | std::string EmptyLine_t::to_string(void*) const { |
| 1521 | return "--[["s + inner->to_string(ud) + "]]"s; | 1626 | return {}; |
| 1522 | } | 1627 | } |
| 1523 | std::string ChainAssign_t::to_string(void* ud) const { | 1628 | std::string ChainAssign_t::to_string(void* ud) const { |
| 1524 | str_list temp; | 1629 | str_list temp; |
| @@ -1533,14 +1638,22 @@ std::string Body_t::to_string(void* ud) const { | |||
| 1533 | std::string Block_t::to_string(void* ud) const { | 1638 | std::string Block_t::to_string(void* ud) const { |
| 1534 | auto info = reinterpret_cast<YueFormat*>(ud); | 1639 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 1535 | str_list temp; | 1640 | str_list temp; |
| 1536 | for (auto stmt_ : statements.objects()) { | 1641 | for (auto stmt_ : statementOrComments.objects()) { |
| 1537 | auto stmt = static_cast<Statement_t*>(stmt_); | 1642 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { |
| 1538 | if (stmt->content.is<PipeBody_t>()) { | 1643 | if (stmt->content.is<PipeBody_t>()) { |
| 1539 | info->pushScope(); | 1644 | info->pushScope(); |
| 1540 | temp.emplace_back(stmt->to_string(ud)); | 1645 | temp.emplace_back(stmt->to_string(ud)); |
| 1541 | info->popScope(); | 1646 | info->popScope(); |
| 1542 | } else { | 1647 | } else { |
| 1543 | temp.emplace_back(info->ind() + stmt->to_string(ud)); | 1648 | temp.emplace_back(info->ind() + stmt->to_string(ud)); |
| 1649 | } | ||
| 1650 | } else if (info->reserveComment) { | ||
| 1651 | if (auto comment = ast_cast<YueComment_t>(stmt_)) { | ||
| 1652 | temp.emplace_back(info->ind() + comment->to_string(ud)); | ||
| 1653 | } else { | ||
| 1654 | auto empty = ast_to<EmptyLine_t>(stmt_); | ||
| 1655 | temp.emplace_back(empty->to_string(ud)); | ||
| 1656 | } | ||
| 1544 | } | 1657 | } |
| 1545 | } | 1658 | } |
| 1546 | return join(temp, "\n"sv); | 1659 | return join(temp, "\n"sv); |
| @@ -1559,3 +1672,4 @@ std::string File_t::to_string(void* ud) const { | |||
| 1559 | } // namespace yue | 1672 | } // namespace yue |
| 1560 | 1673 | ||
| 1561 | } // namespace parserlib | 1674 | } // namespace parserlib |
| 1675 | |||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 0c15fac..ba4186d 100644 --- a/src/yuescript/yue_ast.h +++ b/src/yuescript/yue_ast.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -68,7 +68,7 @@ class Statement_t; | |||
| 68 | class Body_t; | 68 | class Body_t; |
| 69 | class AssignableNameList_t; | 69 | class AssignableNameList_t; |
| 70 | class StarExp_t; | 70 | class StarExp_t; |
| 71 | class CompInner_t; | 71 | class CompFor_t; |
| 72 | class AssignableChain_t; | 72 | class AssignableChain_t; |
| 73 | class UnaryExp_t; | 73 | class UnaryExp_t; |
| 74 | class Parens_t; | 74 | class Parens_t; |
| @@ -103,11 +103,6 @@ AST_NODE(Variable) | |||
| 103 | AST_MEMBER(Variable, &name) | 103 | AST_MEMBER(Variable, &name) |
| 104 | AST_END(Variable) | 104 | AST_END(Variable) |
| 105 | 105 | ||
| 106 | AST_NODE(LabelName) | ||
| 107 | ast_ptr<true, UnicodeName_t> name; | ||
| 108 | AST_MEMBER(LabelName, &name) | ||
| 109 | AST_END(LabelName) | ||
| 110 | |||
| 111 | AST_NODE(LuaKeyword) | 106 | AST_NODE(LuaKeyword) |
| 112 | ast_ptr<true, Name_t> name; | 107 | ast_ptr<true, Name_t> name; |
| 113 | AST_MEMBER(LuaKeyword, &name) | 108 | AST_MEMBER(LuaKeyword, &name) |
| @@ -139,6 +134,11 @@ AST_NODE(KeyName) | |||
| 139 | AST_MEMBER(KeyName, &name) | 134 | AST_MEMBER(KeyName, &name) |
| 140 | AST_END(KeyName) | 135 | AST_END(KeyName) |
| 141 | 136 | ||
| 137 | AST_NODE(VarArgDef) | ||
| 138 | ast_ptr<false, Variable_t> name; | ||
| 139 | AST_MEMBER(VarArgDef, &name) | ||
| 140 | AST_END(VarArgDef) | ||
| 141 | |||
| 142 | AST_LEAF(VarArg) | 142 | AST_LEAF(VarArg) |
| 143 | AST_END(VarArg) | 143 | AST_END(VarArg) |
| 144 | 144 | ||
| @@ -233,18 +233,25 @@ AST_NODE(ImportAs) | |||
| 233 | AST_MEMBER(ImportAs, &literal, &target) | 233 | AST_MEMBER(ImportAs, &literal, &target) |
| 234 | AST_END(ImportAs) | 234 | AST_END(ImportAs) |
| 235 | 235 | ||
| 236 | AST_NODE(ImportGlobal) | ||
| 237 | ast_ptr<true, Seperator_t> sep; | ||
| 238 | ast_list<true, UnicodeName_t> segs; | ||
| 239 | ast_ptr<false, Variable_t> target; | ||
| 240 | AST_MEMBER(ImportGlobal, &sep, &segs, &target) | ||
| 241 | AST_END(ImportGlobal) | ||
| 242 | |||
| 236 | AST_NODE(Import) | 243 | AST_NODE(Import) |
| 237 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t> content; | 244 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t> content; |
| 238 | AST_MEMBER(Import, &content) | 245 | AST_MEMBER(Import, &content) |
| 239 | AST_END(Import) | 246 | AST_END(Import) |
| 240 | 247 | ||
| 241 | AST_NODE(Label) | 248 | AST_NODE(Label) |
| 242 | ast_ptr<true, LabelName_t> label; | 249 | ast_ptr<true, UnicodeName_t> label; |
| 243 | AST_MEMBER(Label, &label) | 250 | AST_MEMBER(Label, &label) |
| 244 | AST_END(Label) | 251 | AST_END(Label) |
| 245 | 252 | ||
| 246 | AST_NODE(Goto) | 253 | AST_NODE(Goto) |
| 247 | ast_ptr<true, LabelName_t> label; | 254 | ast_ptr<true, UnicodeName_t> label; |
| 248 | AST_MEMBER(Goto, &label) | 255 | AST_MEMBER(Goto, &label) |
| 249 | AST_END(Goto) | 256 | AST_END(Goto) |
| 250 | 257 | ||
| @@ -287,9 +294,9 @@ AST_END(Return) | |||
| 287 | AST_NODE(With) | 294 | AST_NODE(With) |
| 288 | ast_ptr<false, ExistentialOp_t> eop; | 295 | ast_ptr<false, ExistentialOp_t> eop; |
| 289 | ast_ptr<true, ExpList_t> valueList; | 296 | ast_ptr<true, ExpList_t> valueList; |
| 290 | ast_ptr<false, Assign_t> assigns; | 297 | ast_ptr<false, Assign_t> assign; |
| 291 | ast_sel<true, Block_t, Statement_t> body; | 298 | ast_sel<true, Block_t, Statement_t> body; |
| 292 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 299 | AST_MEMBER(With, &eop, &valueList, &assign, &body) |
| 293 | AST_END(With) | 300 | AST_END(With) |
| 294 | 301 | ||
| 295 | AST_NODE(SwitchList) | 302 | AST_NODE(SwitchList) |
| @@ -304,20 +311,21 @@ AST_NODE(SwitchCase) | |||
| 304 | AST_MEMBER(SwitchCase, &condition, &body) | 311 | AST_MEMBER(SwitchCase, &condition, &body) |
| 305 | AST_END(SwitchCase) | 312 | AST_END(SwitchCase) |
| 306 | 313 | ||
| 314 | AST_NODE(Assignment) | ||
| 315 | ast_ptr<false, ExpList_t> expList; | ||
| 316 | ast_ptr<true, Assign_t> assign; | ||
| 317 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 318 | AST_END(Assignment) | ||
| 319 | |||
| 307 | AST_NODE(Switch) | 320 | AST_NODE(Switch) |
| 308 | ast_ptr<true, Exp_t> target; | 321 | ast_ptr<true, Exp_t> target; |
| 322 | ast_ptr<false, Assignment_t> assignment; | ||
| 309 | ast_ptr<true, Seperator_t> sep; | 323 | ast_ptr<true, Seperator_t> sep; |
| 310 | ast_list<true, SwitchCase_t> branches; | 324 | ast_list<true, SwitchCase_t> branches; |
| 311 | ast_sel<false, Block_t, Statement_t> lastBranch; | 325 | ast_sel<false, Block_t, Statement_t> lastBranch; |
| 312 | AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) | 326 | AST_MEMBER(Switch, &target, &assignment, &sep, &branches, &lastBranch) |
| 313 | AST_END(Switch) | 327 | AST_END(Switch) |
| 314 | 328 | ||
| 315 | AST_NODE(Assignment) | ||
| 316 | ast_ptr<false, ExpList_t> expList; | ||
| 317 | ast_ptr<true, Assign_t> assign; | ||
| 318 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 319 | AST_END(Assignment) | ||
| 320 | |||
| 321 | AST_NODE(IfCond) | 329 | AST_NODE(IfCond) |
| 322 | ast_ptr<true, Exp_t> condition; | 330 | ast_ptr<true, Exp_t> condition; |
| 323 | ast_ptr<false, Assignment_t> assignment; | 331 | ast_ptr<false, Assignment_t> assignment; |
| @@ -345,7 +353,7 @@ AST_NODE(While) | |||
| 345 | AST_END(While) | 353 | AST_END(While) |
| 346 | 354 | ||
| 347 | AST_NODE(Repeat) | 355 | AST_NODE(Repeat) |
| 348 | ast_ptr<true, Body_t> body; | 356 | ast_sel<true, Block_t, Statement_t> body; |
| 349 | ast_ptr<true, Exp_t> condition; | 357 | ast_ptr<true, Exp_t> condition; |
| 350 | AST_MEMBER(Repeat, &body, &condition) | 358 | AST_MEMBER(Repeat, &body, &condition) |
| 351 | AST_END(Repeat) | 359 | AST_END(Repeat) |
| @@ -355,14 +363,14 @@ AST_NODE(ForStepValue) | |||
| 355 | AST_MEMBER(ForStepValue, &value) | 363 | AST_MEMBER(ForStepValue, &value) |
| 356 | AST_END(ForStepValue) | 364 | AST_END(ForStepValue) |
| 357 | 365 | ||
| 358 | AST_NODE(For) | 366 | AST_NODE(ForNum) |
| 359 | ast_ptr<true, Variable_t> varName; | 367 | ast_ptr<true, Variable_t> varName; |
| 360 | ast_ptr<true, Exp_t> startValue; | 368 | ast_ptr<true, Exp_t> startValue; |
| 361 | ast_ptr<true, Exp_t> stopValue; | 369 | ast_ptr<true, Exp_t> stopValue; |
| 362 | ast_ptr<false, ForStepValue_t> stepValue; | 370 | ast_ptr<false, ForStepValue_t> stepValue; |
| 363 | ast_sel<true, Block_t, Statement_t> body; | 371 | ast_sel<true, Block_t, Statement_t> body; |
| 364 | AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) | 372 | AST_MEMBER(ForNum, &varName, &startValue, &stopValue, &stepValue, &body) |
| 365 | AST_END(For) | 373 | AST_END(ForNum) |
| 366 | 374 | ||
| 367 | AST_NODE(ForEach) | 375 | AST_NODE(ForEach) |
| 368 | ast_ptr<true, AssignableNameList_t> nameList; | 376 | ast_ptr<true, AssignableNameList_t> nameList; |
| @@ -371,6 +379,11 @@ AST_NODE(ForEach) | |||
| 371 | AST_MEMBER(ForEach, &nameList, &loopValue, &body) | 379 | AST_MEMBER(ForEach, &nameList, &loopValue, &body) |
| 372 | AST_END(ForEach) | 380 | AST_END(ForEach) |
| 373 | 381 | ||
| 382 | AST_NODE(For) | ||
| 383 | ast_sel<true, ForEach_t, ForNum_t> forLoop; | ||
| 384 | AST_MEMBER(For, &forLoop) | ||
| 385 | AST_END(For) | ||
| 386 | |||
| 374 | AST_NODE(Do) | 387 | AST_NODE(Do) |
| 375 | ast_ptr<true, Body_t> body; | 388 | ast_ptr<true, Body_t> body; |
| 376 | AST_MEMBER(Do, &body) | 389 | AST_MEMBER(Do, &body) |
| @@ -383,14 +396,15 @@ AST_NODE(CatchBlock) | |||
| 383 | AST_END(CatchBlock) | 396 | AST_END(CatchBlock) |
| 384 | 397 | ||
| 385 | AST_NODE(Try) | 398 | AST_NODE(Try) |
| 399 | ast_ptr<false, ExistentialOp_t> eop; | ||
| 386 | ast_sel<true, Block_t, Exp_t> func; | 400 | ast_sel<true, Block_t, Exp_t> func; |
| 387 | ast_ptr<false, CatchBlock_t> catchBlock; | 401 | ast_ptr<false, CatchBlock_t> catchBlock; |
| 388 | AST_MEMBER(Try, &func, &catchBlock) | 402 | AST_MEMBER(Try, &eop, &func, &catchBlock) |
| 389 | AST_END(Try) | 403 | AST_END(Try) |
| 390 | 404 | ||
| 391 | AST_NODE(Comprehension) | 405 | AST_NODE(Comprehension) |
| 392 | ast_ptr<true, Seperator_t> sep; | 406 | ast_ptr<true, Seperator_t> sep; |
| 393 | ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompInner_t, | 407 | ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompFor_t, |
| 394 | /*non-syntax-rule*/ Statement_t> items; | 408 | /*non-syntax-rule*/ Statement_t> items; |
| 395 | AST_MEMBER(Comprehension, &sep, &items) | 409 | AST_MEMBER(Comprehension, &sep, &items) |
| 396 | AST_END(Comprehension) | 410 | AST_END(Comprehension) |
| @@ -403,7 +417,7 @@ AST_END(CompValue) | |||
| 403 | AST_NODE(TblComprehension) | 417 | AST_NODE(TblComprehension) |
| 404 | ast_ptr<true, Exp_t> key; | 418 | ast_ptr<true, Exp_t> key; |
| 405 | ast_ptr<false, CompValue_t> value; | 419 | ast_ptr<false, CompValue_t> value; |
| 406 | ast_ptr<true, CompInner_t> forLoop; | 420 | ast_ptr<true, CompFor_t> forLoop; |
| 407 | AST_MEMBER(TblComprehension, &key, &value, &forLoop) | 421 | AST_MEMBER(TblComprehension, &key, &value, &forLoop) |
| 408 | AST_END(TblComprehension) | 422 | AST_END(TblComprehension) |
| 409 | 423 | ||
| @@ -418,23 +432,23 @@ AST_NODE(CompForEach) | |||
| 418 | AST_MEMBER(CompForEach, &nameList, &loopValue) | 432 | AST_MEMBER(CompForEach, &nameList, &loopValue) |
| 419 | AST_END(CompForEach) | 433 | AST_END(CompForEach) |
| 420 | 434 | ||
| 421 | AST_NODE(CompFor) | 435 | AST_NODE(CompForNum) |
| 422 | ast_ptr<true, Variable_t> varName; | 436 | ast_ptr<true, Variable_t> varName; |
| 423 | ast_ptr<true, Exp_t> startValue; | 437 | ast_ptr<true, Exp_t> startValue; |
| 424 | ast_ptr<true, Exp_t> stopValue; | 438 | ast_ptr<true, Exp_t> stopValue; |
| 425 | ast_ptr<false, ForStepValue_t> stepValue; | 439 | ast_ptr<false, ForStepValue_t> stepValue; |
| 426 | AST_MEMBER(CompFor, &varName, &startValue, &stopValue, &stepValue) | 440 | AST_MEMBER(CompForNum, &varName, &startValue, &stopValue, &stepValue) |
| 427 | AST_END(CompFor) | 441 | AST_END(CompForNum) |
| 428 | 442 | ||
| 429 | AST_NODE(CompInner) | 443 | AST_NODE(CompFor) |
| 430 | ast_ptr<true, Seperator_t> sep; | 444 | ast_ptr<true, Seperator_t> sep; |
| 431 | ast_sel_list<true, CompFor_t, CompForEach_t, Exp_t> items; | 445 | ast_sel_list<true, CompForNum_t, CompForEach_t, Exp_t> items; |
| 432 | AST_MEMBER(CompInner, &sep, &items) | 446 | AST_MEMBER(CompFor, &sep, &items) |
| 433 | AST_END(CompInner) | 447 | AST_END(CompFor) |
| 434 | 448 | ||
| 435 | AST_NODE(Assign) | 449 | AST_NODE(Assign) |
| 436 | ast_ptr<true, Seperator_t> sep; | 450 | ast_ptr<true, Seperator_t> sep; |
| 437 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; | 451 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t, SpreadListExp_t> values; |
| 438 | AST_MEMBER(Assign, &sep, &values) | 452 | AST_MEMBER(Assign, &sep, &values) |
| 439 | AST_END(Assign) | 453 | AST_END(Assign) |
| 440 | 454 | ||
| @@ -549,8 +563,8 @@ AST_NODE(SimpleValue) | |||
| 549 | ast_sel<true, | 563 | ast_sel<true, |
| 550 | TableLit_t, ConstValue_t, | 564 | TableLit_t, ConstValue_t, |
| 551 | If_t, Switch_t, With_t, ClassDecl_t, | 565 | If_t, Switch_t, With_t, ClassDecl_t, |
| 552 | ForEach_t, For_t, While_t, Do_t, Try_t, | 566 | For_t, While_t, Repeat_t, |
| 553 | UnaryValue_t, | 567 | Do_t, Try_t, UnaryValue_t, |
| 554 | TblComprehension_t, Comprehension_t, | 568 | TblComprehension_t, Comprehension_t, |
| 555 | FunLit_t, Num_t, VarArg_t> value; | 569 | FunLit_t, Num_t, VarArg_t> value; |
| 556 | AST_MEMBER(SimpleValue, &value) | 570 | AST_MEMBER(SimpleValue, &value) |
| @@ -589,8 +603,31 @@ AST_NODE(DoubleString) | |||
| 589 | AST_MEMBER(DoubleString, &sep, &segments) | 603 | AST_MEMBER(DoubleString, &sep, &segments) |
| 590 | AST_END(DoubleString) | 604 | AST_END(DoubleString) |
| 591 | 605 | ||
| 606 | AST_LEAF(YAMLIndent) | ||
| 607 | AST_END(YAMLIndent) | ||
| 608 | |||
| 609 | AST_LEAF(YAMLLineInner) | ||
| 610 | AST_END(YAMLLineInner) | ||
| 611 | |||
| 612 | AST_NODE(YAMLLineContent) | ||
| 613 | ast_sel<true, YAMLLineInner_t, Exp_t> content; | ||
| 614 | AST_MEMBER(YAMLLineContent, &content) | ||
| 615 | AST_END(YAMLLineContent) | ||
| 616 | |||
| 617 | AST_NODE(YAMLLine) | ||
| 618 | ast_ptr<true, YAMLIndent_t> indent; | ||
| 619 | ast_list<true, YAMLLineContent_t> segments; | ||
| 620 | AST_MEMBER(YAMLLine, &indent, &segments) | ||
| 621 | AST_END(YAMLLine) | ||
| 622 | |||
| 623 | AST_NODE(YAMLMultiline) | ||
| 624 | ast_ptr<true, Seperator_t> sep; | ||
| 625 | ast_list<true, YAMLLine_t> lines; | ||
| 626 | AST_MEMBER(YAMLMultiline, &sep, &lines) | ||
| 627 | AST_END(YAMLMultiline) | ||
| 628 | |||
| 592 | AST_NODE(String) | 629 | AST_NODE(String) |
| 593 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t> str; | 630 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t, YAMLMultiline_t> str; |
| 594 | AST_MEMBER(String, &str) | 631 | AST_MEMBER(String, &str) |
| 595 | AST_END(String) | 632 | AST_END(String) |
| 596 | 633 | ||
| @@ -641,9 +678,14 @@ AST_END(TableAppendingOp) | |||
| 641 | AST_LEAF(PlainItem) | 678 | AST_LEAF(PlainItem) |
| 642 | AST_END(PlainItem) | 679 | AST_END(PlainItem) |
| 643 | 680 | ||
| 681 | AST_NODE(ReversedIndex) | ||
| 682 | ast_ptr<false, Exp_t> modifier; | ||
| 683 | AST_MEMBER(ReversedIndex, &modifier) | ||
| 684 | AST_END(ReversedIndex) | ||
| 685 | |||
| 644 | AST_NODE(ChainValue) | 686 | AST_NODE(ChainValue) |
| 645 | ast_ptr<true, Seperator_t> sep; | 687 | ast_ptr<true, Seperator_t> sep; |
| 646 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, | 688 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, ReversedIndex_t, |
| 647 | /*non-syntax-rule*/ PlainItem_t> items; | 689 | /*non-syntax-rule*/ PlainItem_t> items; |
| 648 | AST_MEMBER(ChainValue, &sep, &items) | 690 | AST_MEMBER(ChainValue, &sep, &items) |
| 649 | AST_END(ChainValue) | 691 | AST_END(ChainValue) |
| @@ -743,17 +785,19 @@ AST_NODE(Export) | |||
| 743 | AST_END(Export) | 785 | AST_END(Export) |
| 744 | 786 | ||
| 745 | AST_NODE(FnArgDef) | 787 | AST_NODE(FnArgDef) |
| 746 | ast_sel<true, Variable_t, SelfItem_t> name; | 788 | ast_sel<true, Variable_t, SelfItem_t, SimpleTable_t, TableLit_t> name; |
| 747 | ast_ptr<false, ExistentialOp_t> op; | 789 | ast_ptr<false, ExistentialOp_t> op; |
| 790 | ast_ptr<false, Name_t> label; | ||
| 748 | ast_ptr<false, Exp_t> defaultValue; | 791 | ast_ptr<false, Exp_t> defaultValue; |
| 749 | AST_MEMBER(FnArgDef, &name, &op, &defaultValue) | 792 | AST_MEMBER(FnArgDef, &name, &op, &label, &defaultValue) |
| 750 | AST_END(FnArgDef) | 793 | AST_END(FnArgDef) |
| 751 | 794 | ||
| 752 | AST_NODE(FnArgDefList) | 795 | AST_NODE(FnArgDefList) |
| 753 | ast_ptr<true, Seperator_t> sep; | 796 | ast_ptr<true, Seperator_t> sep; |
| 754 | ast_list<false, FnArgDef_t> definitions; | 797 | ast_list<false, FnArgDef_t> definitions; |
| 755 | ast_ptr<false, VarArg_t> varArg; | 798 | ast_ptr<false, VarArgDef_t> varArg; |
| 756 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) | 799 | ast_ptr<false, Name_t> label; |
| 800 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg, &label) | ||
| 757 | AST_END(FnArgDefList) | 801 | AST_END(FnArgDefList) |
| 758 | 802 | ||
| 759 | AST_NODE(OuterVarShadow) | 803 | AST_NODE(OuterVarShadow) |
| @@ -809,7 +853,7 @@ AST_NODE(Macro) | |||
| 809 | AST_END(Macro) | 853 | AST_END(Macro) |
| 810 | 854 | ||
| 811 | AST_NODE(NameOrDestructure) | 855 | AST_NODE(NameOrDestructure) |
| 812 | ast_sel<true, Variable_t, TableLit_t, Comprehension_t> item; | 856 | ast_sel<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> item; |
| 813 | AST_MEMBER(NameOrDestructure, &item) | 857 | AST_MEMBER(NameOrDestructure, &item) |
| 814 | AST_END(NameOrDestructure) | 858 | AST_END(NameOrDestructure) |
| 815 | 859 | ||
| @@ -885,7 +929,7 @@ AST_NODE(PipeBody) | |||
| 885 | AST_END(PipeBody) | 929 | AST_END(PipeBody) |
| 886 | 930 | ||
| 887 | AST_NODE(StatementAppendix) | 931 | AST_NODE(StatementAppendix) |
| 888 | ast_sel<true, IfLine_t, WhileLine_t, CompInner_t> item; | 932 | ast_sel<true, IfLine_t, WhileLine_t, CompFor_t> item; |
| 889 | AST_MEMBER(StatementAppendix, &item) | 933 | AST_MEMBER(StatementAppendix, &item) |
| 890 | AST_END(StatementAppendix) | 934 | AST_END(StatementAppendix) |
| 891 | 935 | ||
| @@ -895,14 +939,17 @@ AST_END(StatementSep) | |||
| 895 | AST_LEAF(YueLineComment) | 939 | AST_LEAF(YueLineComment) |
| 896 | AST_END(YueLineComment) | 940 | AST_END(YueLineComment) |
| 897 | 941 | ||
| 898 | AST_LEAF(MultilineCommentInner) | 942 | AST_LEAF(YueMultilineComment) |
| 899 | AST_END(MultilineCommentInner) | ||
| 900 | |||
| 901 | AST_NODE(YueMultilineComment) | ||
| 902 | ast_ptr<true, MultilineCommentInner_t> inner; | ||
| 903 | AST_MEMBER(YueMultilineComment, &inner) | ||
| 904 | AST_END(YueMultilineComment) | 943 | AST_END(YueMultilineComment) |
| 905 | 944 | ||
| 945 | AST_NODE(YueComment) | ||
| 946 | ast_sel<true, YueLineComment_t, YueMultilineComment_t> comment; | ||
| 947 | AST_MEMBER(YueComment, &comment) | ||
| 948 | AST_END(YueComment) | ||
| 949 | |||
| 950 | AST_LEAF(EmptyLine) | ||
| 951 | AST_END(EmptyLine) | ||
| 952 | |||
| 906 | AST_NODE(ChainAssign) | 953 | AST_NODE(ChainAssign) |
| 907 | ast_ptr<true, Seperator_t> sep; | 954 | ast_ptr<true, Seperator_t> sep; |
| 908 | ast_list<true, Exp_t> exprs; | 955 | ast_list<true, Exp_t> exprs; |
| @@ -911,16 +958,14 @@ AST_NODE(ChainAssign) | |||
| 911 | AST_END(ChainAssign) | 958 | AST_END(ChainAssign) |
| 912 | 959 | ||
| 913 | AST_NODE(Statement) | 960 | AST_NODE(Statement) |
| 914 | ast_ptr<true, Seperator_t> sep; | ||
| 915 | ast_sel_list<false, YueLineComment_t, YueMultilineComment_t> comments; | ||
| 916 | ast_sel<true, | 961 | ast_sel<true, |
| 917 | Import_t, While_t, Repeat_t, For_t, ForEach_t, | 962 | Import_t, While_t, Repeat_t, For_t, |
| 918 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, | 963 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, |
| 919 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, | 964 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, |
| 920 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t | 965 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t |
| 921 | > content; | 966 | > content; |
| 922 | ast_ptr<false, StatementAppendix_t> appendix; | 967 | ast_ptr<false, StatementAppendix_t> appendix; |
| 923 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix) | 968 | AST_MEMBER(Statement, &content, &appendix) |
| 924 | AST_END(Statement) | 969 | AST_END(Statement) |
| 925 | 970 | ||
| 926 | AST_NODE(Body) | 971 | AST_NODE(Body) |
| @@ -930,8 +975,8 @@ AST_END(Body) | |||
| 930 | 975 | ||
| 931 | AST_NODE(Block) | 976 | AST_NODE(Block) |
| 932 | ast_ptr<true, Seperator_t> sep; | 977 | ast_ptr<true, Seperator_t> sep; |
| 933 | ast_list<false, Statement_t> statements; | 978 | ast_sel_list<false, Statement_t, YueComment_t, EmptyLine_t> statementOrComments; |
| 934 | AST_MEMBER(Block, &sep, &statements) | 979 | AST_MEMBER(Block, &sep, &statementOrComments) |
| 935 | AST_END(Block) | 980 | AST_END(Block) |
| 936 | 981 | ||
| 937 | AST_NODE(BlockEnd) | 982 | AST_NODE(BlockEnd) |
| @@ -950,9 +995,9 @@ struct YueFormat { | |||
| 950 | int indent = 0; | 995 | int indent = 0; |
| 951 | bool spaceOverTab = false; | 996 | bool spaceOverTab = false; |
| 952 | int tabSpaces = 4; | 997 | int tabSpaces = 4; |
| 998 | bool reserveComment = true; | ||
| 953 | std::string toString(ast_node* node); | 999 | std::string toString(ast_node* node); |
| 954 | 1000 | ||
| 955 | Converter converter{}; | ||
| 956 | void pushScope(); | 1001 | void pushScope(); |
| 957 | void popScope(); | 1002 | void popScope(); |
| 958 | std::string convert(const ast_node* node); | 1003 | std::string convert(const ast_node* node); |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 7abc929..cffa7a8 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -78,7 +78,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 78 | "close"s // Lua 5.4 | 78 | "close"s // Lua 5.4 |
| 79 | }; | 79 | }; |
| 80 | 80 | ||
| 81 | const std::string_view version = "0.28.3"sv; | 81 | const std::string_view version = "0.30.4"sv; |
| 82 | const std::string_view extension = "yue"sv; | 82 | const std::string_view extension = "yue"sv; |
| 83 | 83 | ||
| 84 | class CompileError : public std::logic_error { | 84 | class CompileError : public std::logic_error { |
| @@ -165,12 +165,12 @@ public: | |||
| 165 | double compileTime = 0.0; | 165 | double compileTime = 0.0; |
| 166 | if (config.profiling) { | 166 | if (config.profiling) { |
| 167 | auto start = std::chrono::high_resolution_clock::now(); | 167 | auto start = std::chrono::high_resolution_clock::now(); |
| 168 | _info = _parser.parse<File_t>(codes); | 168 | _info = _parser.parse<File_t>(codes, config.lax); |
| 169 | auto stop = std::chrono::high_resolution_clock::now(); | 169 | auto stop = std::chrono::high_resolution_clock::now(); |
| 170 | std::chrono::duration<double> diff = stop - start; | 170 | std::chrono::duration<double> diff = stop - start; |
| 171 | parseTime = diff.count(); | 171 | parseTime = diff.count(); |
| 172 | } else { | 172 | } else { |
| 173 | _info = _parser.parse<File_t>(codes); | 173 | _info = _parser.parse<File_t>(codes, config.lax); |
| 174 | } | 174 | } |
| 175 | std::unique_ptr<GlobalVars> globals; | 175 | std::unique_ptr<GlobalVars> globals; |
| 176 | std::unique_ptr<Options> options; | 176 | std::unique_ptr<Options> options; |
| @@ -182,8 +182,9 @@ public: | |||
| 182 | try { | 182 | try { |
| 183 | auto block = _info.node.to<File_t>()->block.get(); | 183 | auto block = _info.node.to<File_t>()->block.get(); |
| 184 | if (_info.exportMacro) { | 184 | if (_info.exportMacro) { |
| 185 | for (auto stmt_ : block->statements.objects()) { | 185 | for (auto stmt_ : block->statementOrComments.objects()) { |
| 186 | auto stmt = static_cast<Statement_t*>(stmt_); | 186 | auto stmt = ast_cast<Statement_t>(stmt_); |
| 187 | if (!stmt) continue; | ||
| 187 | switch (stmt->content->get_id()) { | 188 | switch (stmt->content->get_id()) { |
| 188 | case id<MacroInPlace_t>(): | 189 | case id<MacroInPlace_t>(): |
| 189 | case id<Macro_t>(): | 190 | case id<Macro_t>(): |
| @@ -258,8 +259,8 @@ public: | |||
| 258 | if (config.lintGlobalVariable) { | 259 | if (config.lintGlobalVariable) { |
| 259 | globals = std::make_unique<GlobalVars>(); | 260 | globals = std::make_unique<GlobalVars>(); |
| 260 | for (const auto& var : _globals) { | 261 | for (const auto& var : _globals) { |
| 261 | auto [name, line, col, accessType] = var.second; | 262 | auto [name, line, col, accessType, defined] = var.second; |
| 262 | globals->push_back({name, line + _config.lineOffset, col, accessType}); | 263 | globals->push_back({name, line + _config.lineOffset, col, accessType, defined}); |
| 263 | } | 264 | } |
| 264 | std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) { | 265 | std::sort(globals->begin(), globals->end(), [](const GlobalVar& varA, const GlobalVar& varB) { |
| 265 | if (varA.line < varB.line) { | 266 | if (varA.line < varB.line) { |
| @@ -396,7 +397,7 @@ private: | |||
| 396 | }; | 397 | }; |
| 397 | std::stack<ContinueVar> _continueVars; | 398 | std::stack<ContinueVar> _continueVars; |
| 398 | std::list<std::unique_ptr<input>> _codeCache; | 399 | std::list<std::unique_ptr<input>> _codeCache; |
| 399 | std::unordered_map<std::string, std::tuple<std::string, int, int, AccessType>> _globals; | 400 | std::unordered_map<std::string, std::tuple<std::string, int, int, AccessType, bool>> _globals; |
| 400 | std::ostringstream _buf; | 401 | std::ostringstream _buf; |
| 401 | std::ostringstream _joinBuf; | 402 | std::ostringstream _joinBuf; |
| 402 | const std::string _newLine = "\n"; | 403 | const std::string _newLine = "\n"; |
| @@ -875,6 +876,10 @@ private: | |||
| 875 | return false; | 876 | return false; |
| 876 | } | 877 | } |
| 877 | 878 | ||
| 879 | bool isListComp(Comprehension_t* comp) const { | ||
| 880 | return comp->items.size() == 2 && ast_is<CompFor_t>(comp->items.back()); | ||
| 881 | } | ||
| 882 | |||
| 878 | void markVarLocalConst(const std::string& name) { | 883 | void markVarLocalConst(const std::string& name) { |
| 879 | auto& scope = _scopes.back(); | 884 | auto& scope = _scopes.back(); |
| 880 | scope.vars->insert_or_assign(name, VarType::LocalConst); | 885 | scope.vars->insert_or_assign(name, VarType::LocalConst); |
| @@ -967,7 +972,7 @@ private: | |||
| 967 | } | 972 | } |
| 968 | } | 973 | } |
| 969 | 974 | ||
| 970 | const std::string nll(ast_node* node) const { | 975 | const std::string nl(ast_node* node) const { |
| 971 | if (_config.reserveLineNumber) { | 976 | if (_config.reserveLineNumber) { |
| 972 | return " -- "s + std::to_string(node->m_begin.m_line + _config.lineOffset) + _newLine; | 977 | return " -- "s + std::to_string(node->m_begin.m_line + _config.lineOffset) + _newLine; |
| 973 | } else { | 978 | } else { |
| @@ -975,14 +980,6 @@ private: | |||
| 975 | } | 980 | } |
| 976 | } | 981 | } |
| 977 | 982 | ||
| 978 | const std::string nlr(ast_node* node) const { | ||
| 979 | if (_config.reserveLineNumber) { | ||
| 980 | return " -- "s + std::to_string(node->m_end.m_line + _config.lineOffset) + _newLine; | ||
| 981 | } else { | ||
| 982 | return _newLine; | ||
| 983 | } | ||
| 984 | } | ||
| 985 | |||
| 986 | void incIndentOffset() { | 983 | void incIndentOffset() { |
| 987 | _indentOffset++; | 984 | _indentOffset++; |
| 988 | } | 985 | } |
| @@ -1169,14 +1166,22 @@ private: | |||
| 1169 | return nullptr; | 1166 | return nullptr; |
| 1170 | } | 1167 | } |
| 1171 | 1168 | ||
| 1172 | Statement_t* lastStatementFrom(const node_container& stmts) const { | 1169 | Statement_t* lastStatementFrom(const node_container& statementOrComments) const { |
| 1173 | if (!stmts.empty()) { | 1170 | if (!statementOrComments.empty()) { |
| 1174 | auto it = stmts.end(); | 1171 | for (auto it = statementOrComments.rbegin(); it != statementOrComments.rend(); ++it) { |
| 1175 | --it; | 1172 | if (auto stmt = ast_cast<Statement_t>(*it)) { |
| 1176 | while (!static_cast<Statement_t*>(*it)->content && it != stmts.begin()) { | 1173 | return stmt; |
| 1177 | --it; | 1174 | } |
| 1175 | } | ||
| 1176 | } | ||
| 1177 | return nullptr; | ||
| 1178 | } | ||
| 1179 | |||
| 1180 | Statement_t* firstStatementFrom(Block_t* block) const { | ||
| 1181 | for (auto stmt_ : block->statementOrComments.objects()) { | ||
| 1182 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { | ||
| 1183 | return stmt; | ||
| 1178 | } | 1184 | } |
| 1179 | return static_cast<Statement_t*>(*it); | ||
| 1180 | } | 1185 | } |
| 1181 | return nullptr; | 1186 | return nullptr; |
| 1182 | } | 1187 | } |
| @@ -1185,16 +1190,26 @@ private: | |||
| 1185 | if (auto stmt = body->content.as<Statement_t>()) { | 1190 | if (auto stmt = body->content.as<Statement_t>()) { |
| 1186 | return stmt; | 1191 | return stmt; |
| 1187 | } else { | 1192 | } else { |
| 1188 | const auto& stmts = body->content.to<Block_t>()->statements.objects(); | 1193 | const auto& stmts = body->content.to<Block_t>()->statementOrComments.objects(); |
| 1189 | return lastStatementFrom(stmts); | 1194 | return lastStatementFrom(stmts); |
| 1190 | } | 1195 | } |
| 1191 | } | 1196 | } |
| 1192 | 1197 | ||
| 1193 | Statement_t* lastStatementFrom(Block_t* block) const { | 1198 | Statement_t* lastStatementFrom(Block_t* block) const { |
| 1194 | const auto& stmts = block->statements.objects(); | 1199 | const auto& stmts = block->statementOrComments.objects(); |
| 1195 | return lastStatementFrom(stmts); | 1200 | return lastStatementFrom(stmts); |
| 1196 | } | 1201 | } |
| 1197 | 1202 | ||
| 1203 | int countStatementFrom(Block_t* block) const { | ||
| 1204 | int count = 0; | ||
| 1205 | for (auto stmt_ : block->statementOrComments.objects()) { | ||
| 1206 | if (ast_is<Statement_t>(stmt_)) { | ||
| 1207 | count++; | ||
| 1208 | } | ||
| 1209 | } | ||
| 1210 | return count; | ||
| 1211 | } | ||
| 1212 | |||
| 1198 | Exp_t* lastExpFromAssign(ast_node* action) { | 1213 | Exp_t* lastExpFromAssign(ast_node* action) { |
| 1199 | switch (action->get_id()) { | 1214 | switch (action->get_id()) { |
| 1200 | case id<Update_t>(): { | 1215 | case id<Update_t>(): { |
| @@ -1258,7 +1273,7 @@ private: | |||
| 1258 | 1273 | ||
| 1259 | template <class T> | 1274 | template <class T> |
| 1260 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 1275 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
| 1261 | auto res = _parser.parse<T>(std::string(codes)); | 1276 | auto res = _parser.parse<T>(std::string(codes), false); |
| 1262 | if (res.error) { | 1277 | if (res.error) { |
| 1263 | throw CompileError(res.error.value().msg, parent); | 1278 | throw CompileError(res.error.value().msg, parent); |
| 1264 | } | 1279 | } |
| @@ -1281,6 +1296,8 @@ private: | |||
| 1281 | Common, | 1296 | Common, |
| 1282 | EndWithColon, | 1297 | EndWithColon, |
| 1283 | EndWithEOP, | 1298 | EndWithEOP, |
| 1299 | EndWithSlice, | ||
| 1300 | HasRIndex, | ||
| 1284 | HasEOP, | 1301 | HasEOP, |
| 1285 | HasKeyword, | 1302 | HasKeyword, |
| 1286 | HasUnicode, | 1303 | HasUnicode, |
| @@ -1299,6 +1316,9 @@ private: | |||
| 1299 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { | 1316 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { |
| 1300 | return ChainType::EndWithEOP; | 1317 | return ChainType::EndWithEOP; |
| 1301 | } | 1318 | } |
| 1319 | if (ast_is<Slice_t>(chainValue->items.back())) { | ||
| 1320 | return ChainType::EndWithSlice; | ||
| 1321 | } | ||
| 1302 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 1322 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { |
| 1303 | if (dot->name.is<Metatable_t>()) { | 1323 | if (dot->name.is<Metatable_t>()) { |
| 1304 | return ChainType::Metatable; | 1324 | return ChainType::Metatable; |
| @@ -1324,6 +1344,8 @@ private: | |||
| 1324 | } | 1344 | } |
| 1325 | } else if (ast_is<ExistentialOp_t>(item)) { | 1345 | } else if (ast_is<ExistentialOp_t>(item)) { |
| 1326 | return ChainType::HasEOP; | 1346 | return ChainType::HasEOP; |
| 1347 | } else if (ast_is<ReversedIndex_t>(item)) { | ||
| 1348 | return ChainType::HasRIndex; | ||
| 1327 | } | 1349 | } |
| 1328 | } | 1350 | } |
| 1329 | return type; | 1351 | return type; |
| @@ -1353,10 +1375,10 @@ private: | |||
| 1353 | std::ostringstream buf; | 1375 | std::ostringstream buf; |
| 1354 | for (auto it = uname->m_begin.m_it; it != uname->m_end.m_it; ++it) { | 1376 | for (auto it = uname->m_begin.m_it; it != uname->m_end.m_it; ++it) { |
| 1355 | auto ch = *it; | 1377 | auto ch = *it; |
| 1356 | if (ch > 255) { | 1378 | if (ch <= 0x7F && ((ch == '_') || ((ch | 0x20) >= 'a' && (ch | 0x20) <= 'z') || (ch >= '0' && ch <= '9'))) { |
| 1357 | buf << "_u"sv << std::hex << static_cast<int>(ch); | ||
| 1358 | } else { | ||
| 1359 | buf << static_cast<char>(ch); | 1379 | buf << static_cast<char>(ch); |
| 1380 | } else { | ||
| 1381 | buf << "_u"sv << std::hex << static_cast<uint32_t>(ch); | ||
| 1360 | } | 1382 | } |
| 1361 | } | 1383 | } |
| 1362 | return buf.str(); | 1384 | return buf.str(); |
| @@ -1438,6 +1460,7 @@ private: | |||
| 1438 | case id<DotChainItem_t>(): | 1460 | case id<DotChainItem_t>(): |
| 1439 | case id<Exp_t>(): | 1461 | case id<Exp_t>(): |
| 1440 | case id<TableAppendingOp_t>(): | 1462 | case id<TableAppendingOp_t>(): |
| 1463 | case id<ReversedIndex_t>(): | ||
| 1441 | return true; | 1464 | return true; |
| 1442 | } | 1465 | } |
| 1443 | } | 1466 | } |
| @@ -1455,7 +1478,7 @@ private: | |||
| 1455 | if (simpleValue->value.is<TableLit_t>()) { | 1478 | if (simpleValue->value.is<TableLit_t>()) { |
| 1456 | return true; | 1479 | return true; |
| 1457 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { | 1480 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { |
| 1458 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 1481 | if (!isListComp(comp)) { |
| 1459 | return true; | 1482 | return true; |
| 1460 | } | 1483 | } |
| 1461 | } | 1484 | } |
| @@ -1596,7 +1619,7 @@ private: | |||
| 1596 | if (accessType == AccessType::Read && _funcLevel > 1) { | 1619 | if (accessType == AccessType::Read && _funcLevel > 1) { |
| 1597 | accessType = AccessType::Capture; | 1620 | accessType = AccessType::Capture; |
| 1598 | } | 1621 | } |
| 1599 | _globals[key] = {str, x->m_begin.m_line, x->m_begin.m_col, accessType}; | 1622 | _globals[key] = {str, x->m_begin.m_line, x->m_begin.m_col, accessType, isSolidDefined(str)}; |
| 1600 | } | 1623 | } |
| 1601 | } | 1624 | } |
| 1602 | } | 1625 | } |
| @@ -1638,24 +1661,31 @@ private: | |||
| 1638 | return; | 1661 | return; |
| 1639 | } | 1662 | } |
| 1640 | 1663 | ||
| 1641 | void transformStatement(Statement_t* statement, str_list& out) { | 1664 | void transformComment(YueComment_t* comment, str_list& out) { |
| 1642 | auto x = statement; | 1665 | if (!_config.reserveComment) { |
| 1643 | if (_config.reserveComment && !x->comments.empty()) { | 1666 | return; |
| 1644 | for (ast_node* node : x->comments.objects()) { | 1667 | } |
| 1645 | switch (node->get_id()) { | 1668 | auto node = comment->comment.get(); |
| 1646 | case id<YueLineComment_t>(): { | 1669 | if (!node) { |
| 1647 | auto comment = ast_cast<YueLineComment_t>(node); | 1670 | out.push_back("\n"s); |
| 1648 | out.push_back(indent() + "--"s + _parser.toString(comment) + '\n'); | 1671 | return; |
| 1649 | break; | 1672 | } |
| 1650 | } | 1673 | switch (node->get_id()) { |
| 1651 | case id<YueMultilineComment_t>(): { | 1674 | case id<YueLineComment_t>(): { |
| 1652 | auto comment = ast_cast<YueMultilineComment_t>(node); | 1675 | auto content = static_cast<YueLineComment_t*>(node); |
| 1653 | out.push_back(indent() + _parser.toString(comment) + '\n'); | 1676 | out.push_back(indent() + "--"s + _parser.toString(content) + '\n'); |
| 1654 | break; | 1677 | break; |
| 1655 | } | 1678 | } |
| 1656 | } | 1679 | case id<YueMultilineComment_t>(): { |
| 1680 | auto content = static_cast<YueMultilineComment_t*>(node); | ||
| 1681 | out.push_back(indent() + "--[["s + _parser.toString(content) + "]]\n"s); | ||
| 1682 | break; | ||
| 1657 | } | 1683 | } |
| 1658 | } | 1684 | } |
| 1685 | } | ||
| 1686 | |||
| 1687 | void transformStatement(Statement_t* statement, str_list& out) { | ||
| 1688 | auto x = statement; | ||
| 1659 | if (statement->appendix) { | 1689 | if (statement->appendix) { |
| 1660 | if (auto assignment = assignmentFrom(statement)) { | 1690 | if (auto assignment = assignmentFrom(statement)) { |
| 1661 | auto preDefine = getPreDefineLine(assignment); | 1691 | auto preDefine = getPreDefineLine(assignment); |
| @@ -1719,7 +1749,7 @@ private: | |||
| 1719 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); | 1749 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); |
| 1720 | break; | 1750 | break; |
| 1721 | } | 1751 | } |
| 1722 | case id<CompInner_t>(): { | 1752 | case id<CompFor_t>(): { |
| 1723 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); | 1753 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); |
| 1724 | break; | 1754 | break; |
| 1725 | } | 1755 | } |
| @@ -1780,8 +1810,8 @@ private: | |||
| 1780 | statement->content.set(expListAssign); | 1810 | statement->content.set(expListAssign); |
| 1781 | break; | 1811 | break; |
| 1782 | } | 1812 | } |
| 1783 | case id<CompInner_t>(): { | 1813 | case id<CompFor_t>(): { |
| 1784 | auto compInner = appendix->item.to<CompInner_t>(); | 1814 | auto compInner = appendix->item.to<CompFor_t>(); |
| 1785 | auto comp = x->new_ptr<Comprehension_t>(); | 1815 | auto comp = x->new_ptr<Comprehension_t>(); |
| 1786 | auto stmt = x->new_ptr<Statement_t>(); | 1816 | auto stmt = x->new_ptr<Statement_t>(); |
| 1787 | stmt->content.set(statement->content); | 1817 | stmt->content.set(statement->content); |
| @@ -1846,11 +1876,12 @@ private: | |||
| 1846 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; | 1876 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; |
| 1847 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; | 1877 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; |
| 1848 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; | 1878 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; |
| 1879 | case id<Repeat_t>(): transformRepeat(static_cast<Repeat_t*>(value), out); break; | ||
| 1849 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; | 1880 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; |
| 1850 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; | 1881 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; |
| 1851 | case id<Comprehension_t>(): { | 1882 | case id<Comprehension_t>(): { |
| 1852 | auto comp = static_cast<Comprehension_t*>(value); | 1883 | auto comp = static_cast<Comprehension_t*>(value); |
| 1853 | if (comp->items.size() == 2 && ast_is<CompInner_t>(comp->items.back())) { | 1884 | if (isListComp(comp)) { |
| 1854 | transformCompCommon(comp, out); | 1885 | transformCompCommon(comp, out); |
| 1855 | } else { | 1886 | } else { |
| 1856 | specialSingleValue = false; | 1887 | specialSingleValue = false; |
| @@ -1974,7 +2005,7 @@ private: | |||
| 1974 | return indent() + "local "s + join(defs, ", "sv); | 2005 | return indent() + "local "s + join(defs, ", "sv); |
| 1975 | } | 2006 | } |
| 1976 | 2007 | ||
| 1977 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 2008 | std::string getDestructureDefine(ExpListAssign_t* assignment) { |
| 1978 | auto info = extractDestructureInfo(assignment, true, false); | 2009 | auto info = extractDestructureInfo(assignment, true, false); |
| 1979 | if (!info.destructures.empty()) { | 2010 | if (!info.destructures.empty()) { |
| 1980 | str_list defs; | 2011 | str_list defs; |
| @@ -2005,8 +2036,31 @@ private: | |||
| 2005 | return clearBuf(); | 2036 | return clearBuf(); |
| 2006 | } | 2037 | } |
| 2007 | 2038 | ||
| 2039 | str_list getArgDestructureList(ExpListAssign_t* assignment) { | ||
| 2040 | str_list defs; | ||
| 2041 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 2042 | if (!info.destructures.empty()) { | ||
| 2043 | for (const auto& des : info.destructures) { | ||
| 2044 | if (std::holds_alternative<Destructure>(des)) { | ||
| 2045 | const auto& destruct = std::get<Destructure>(des); | ||
| 2046 | for (const auto& item : destruct.items) { | ||
| 2047 | if (item.targetVar.empty()) { | ||
| 2048 | throw CompileError("can only destruct argument to variable"sv, item.target); | ||
| 2049 | } else { | ||
| 2050 | defs.push_back(item.targetVar); | ||
| 2051 | } | ||
| 2052 | } | ||
| 2053 | } else { | ||
| 2054 | const auto& assignment = std::get<AssignmentPtr>(des); | ||
| 2055 | YUEE("AST node mismatch", assignment.ptr); | ||
| 2056 | } | ||
| 2057 | } | ||
| 2058 | } | ||
| 2059 | return defs; | ||
| 2060 | } | ||
| 2061 | |||
| 2008 | std::string getPreDefine(ExpListAssign_t* assignment) { | 2062 | std::string getPreDefine(ExpListAssign_t* assignment) { |
| 2009 | auto preDefine = getDestrucureDefine(assignment); | 2063 | auto preDefine = getDestructureDefine(assignment); |
| 2010 | if (preDefine.empty()) { | 2064 | if (preDefine.empty()) { |
| 2011 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); | 2065 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); |
| 2012 | } | 2066 | } |
| @@ -2015,7 +2069,7 @@ private: | |||
| 2015 | 2069 | ||
| 2016 | std::string getPreDefineLine(ExpListAssign_t* assignment) { | 2070 | std::string getPreDefineLine(ExpListAssign_t* assignment) { |
| 2017 | auto preDefine = getPreDefine(assignment); | 2071 | auto preDefine = getPreDefine(assignment); |
| 2018 | if (!preDefine.empty()) preDefine += nll(assignment); | 2072 | if (!preDefine.empty()) preDefine += nl(assignment); |
| 2019 | return preDefine; | 2073 | return preDefine; |
| 2020 | } | 2074 | } |
| 2021 | 2075 | ||
| @@ -2171,14 +2225,14 @@ private: | |||
| 2171 | temp.push_back(getPreDefineLine(assignment)); | 2225 | temp.push_back(getPreDefineLine(assignment)); |
| 2172 | bool needScope = !currentScope().lastStatement; | 2226 | bool needScope = !currentScope().lastStatement; |
| 2173 | if (needScope) { | 2227 | if (needScope) { |
| 2174 | temp.push_back(indent() + "do"s + nll(assignment)); | 2228 | temp.push_back(indent() + "do"s + nl(assignment)); |
| 2175 | pushScope(); | 2229 | pushScope(); |
| 2176 | } | 2230 | } |
| 2177 | transformAssignment(preAssignment, temp); | 2231 | transformAssignment(preAssignment, temp); |
| 2178 | transformAssignment(assignment, temp); | 2232 | transformAssignment(assignment, temp); |
| 2179 | if (needScope) { | 2233 | if (needScope) { |
| 2180 | popScope(); | 2234 | popScope(); |
| 2181 | temp.push_back(indent() + "end"s + nll(assignment)); | 2235 | temp.push_back(indent() + "end"s + nl(assignment)); |
| 2182 | } | 2236 | } |
| 2183 | out.push_back(join(temp)); | 2237 | out.push_back(join(temp)); |
| 2184 | return false; | 2238 | return false; |
| @@ -2223,7 +2277,8 @@ private: | |||
| 2223 | BREAK_IF(!value); | 2277 | BREAK_IF(!value); |
| 2224 | auto chainValue = value->item.as<ChainValue_t>(); | 2278 | auto chainValue = value->item.as<ChainValue_t>(); |
| 2225 | BREAK_IF(!chainValue); | 2279 | BREAK_IF(!chainValue); |
| 2226 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 2280 | auto last = chainValue->items.back(); |
| 2281 | if (auto dot = ast_cast<DotChainItem_t>(last)) { | ||
| 2227 | BREAK_IF(!dot->name.is<Metatable_t>()); | 2282 | BREAK_IF(!dot->name.is<Metatable_t>()); |
| 2228 | str_list temp; | 2283 | str_list temp; |
| 2229 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | 2284 | auto [beforeAssignment, afterAssignment] = splitAssignment(); |
| @@ -2247,14 +2302,14 @@ private: | |||
| 2247 | throw CompileError("right value missing"sv, values.front()); | 2302 | throw CompileError("right value missing"sv, values.front()); |
| 2248 | } | 2303 | } |
| 2249 | transformAssignItem(*vit, args); | 2304 | transformAssignItem(*vit, args); |
| 2250 | _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nll(x); | 2305 | _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nl(x); |
| 2251 | temp.push_back(clearBuf()); | 2306 | temp.push_back(clearBuf()); |
| 2252 | if (!afterAssignment->expList->exprs.empty()) { | 2307 | if (!afterAssignment->expList->exprs.empty()) { |
| 2253 | transformAssignment(afterAssignment, temp); | 2308 | transformAssignment(afterAssignment, temp); |
| 2254 | } | 2309 | } |
| 2255 | out.push_back(join(temp)); | 2310 | out.push_back(join(temp)); |
| 2256 | return false; | 2311 | return false; |
| 2257 | } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) { | 2312 | } else if (ast_is<TableAppendingOp_t>(last)) { |
| 2258 | str_list temp; | 2313 | str_list temp; |
| 2259 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | 2314 | auto [beforeAssignment, afterAssignment] = splitAssignment(); |
| 2260 | if (!beforeAssignment->expList->exprs.empty()) { | 2315 | if (!beforeAssignment->expList->exprs.empty()) { |
| @@ -2276,7 +2331,7 @@ private: | |||
| 2276 | if (varName.empty() || !isLocal(varName)) { | 2331 | if (varName.empty() || !isLocal(varName)) { |
| 2277 | if (needScope) { | 2332 | if (needScope) { |
| 2278 | extraScoped = true; | 2333 | extraScoped = true; |
| 2279 | temp.push_back(indent() + "do"s + nll(x)); | 2334 | temp.push_back(indent() + "do"s + nl(x)); |
| 2280 | pushScope(); | 2335 | pushScope(); |
| 2281 | } | 2336 | } |
| 2282 | auto objVar = getUnusedName("_obj_"sv); | 2337 | auto objVar = getUnusedName("_obj_"sv); |
| @@ -2288,19 +2343,69 @@ private: | |||
| 2288 | transformAssignment(newAssignment, temp); | 2343 | transformAssignment(newAssignment, temp); |
| 2289 | varName = objVar; | 2344 | varName = objVar; |
| 2290 | } | 2345 | } |
| 2291 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2346 | if (auto spread = ast_cast<SpreadListExp_t>(*vit)) { |
| 2292 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | 2347 | auto lenVar = getUnusedName("_len_"sv); |
| 2293 | auto assign = x->new_ptr<Assign_t>(); | 2348 | forceAddToScope(lenVar); |
| 2294 | if (vit == values.end()) { | 2349 | temp.push_back(indent() + "local "s + lenVar + " = #"s + varName + " + 1"s + nl(spread)); |
| 2295 | throw CompileError("right value missing"sv, values.front()); | 2350 | auto elmVar = getUnusedName("_elm_"sv); |
| 2351 | _buf << varName << '[' << lenVar << "],"s << lenVar << "="s << elmVar << ',' << lenVar << "+1 for "s << elmVar << " in *nil"s; | ||
| 2352 | auto stmt = toAst<Statement_t>(clearBuf(), spread); | ||
| 2353 | auto comp = stmt->appendix->item.to<CompFor_t>(); | ||
| 2354 | ast_to<CompForEach_t>(comp->items.front())->loopValue.to<StarExp_t>()->value.set(spread->exp); | ||
| 2355 | transformStatement(stmt, temp); | ||
| 2356 | } else { | ||
| 2357 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 2358 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | ||
| 2359 | auto assign = x->new_ptr<Assign_t>(); | ||
| 2360 | if (vit == values.end()) { | ||
| 2361 | throw CompileError("right value missing"sv, values.front()); | ||
| 2362 | } | ||
| 2363 | assign->values.push_back(*vit); | ||
| 2364 | newAssignment->action.set(assign); | ||
| 2365 | transformAssignment(newAssignment, temp); | ||
| 2296 | } | 2366 | } |
| 2297 | assign->values.push_back(*vit); | ||
| 2298 | newAssignment->action.set(assign); | ||
| 2299 | transformAssignment(newAssignment, temp); | ||
| 2300 | if (extraScoped) { | 2367 | if (extraScoped) { |
| 2301 | popScope(); | 2368 | popScope(); |
| 2302 | temp.push_back(indent() + "end"s + nlr(x)); | 2369 | temp.push_back(indent() + "end"s + nl(x)); |
| 2370 | } | ||
| 2371 | if (!afterAssignment->expList->exprs.empty()) { | ||
| 2372 | transformAssignment(afterAssignment, temp); | ||
| 2373 | } | ||
| 2374 | out.push_back(join(temp)); | ||
| 2375 | return false; | ||
| 2376 | } else if (ast_is<ReversedIndex_t>(last)) { | ||
| 2377 | if (chainValue->items.size() == 1) { | ||
| 2378 | if (_withVars.empty()) { | ||
| 2379 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); | ||
| 2380 | } else { | ||
| 2381 | break; | ||
| 2382 | } | ||
| 2383 | } | ||
| 2384 | auto tmpChain = chainValue->new_ptr<ChainValue_t>(); | ||
| 2385 | tmpChain->items.dup(chainValue->items); | ||
| 2386 | tmpChain->items.pop_back(); | ||
| 2387 | auto tmpLeft = newExp(tmpChain, tmpChain); | ||
| 2388 | auto leftVar = singleVariableFrom(tmpLeft, AccessType::Read); | ||
| 2389 | if (!leftVar.empty() && isLocal(leftVar)) { | ||
| 2390 | break; | ||
| 2391 | } | ||
| 2392 | leftVar = getUnusedName("_obj_"sv); | ||
| 2393 | auto tmpAsmt = assignmentFrom(toAst<Exp_t>(leftVar, tmpLeft), tmpLeft, tmpLeft); | ||
| 2394 | str_list temp; | ||
| 2395 | transformAssignment(tmpAsmt, temp); | ||
| 2396 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | ||
| 2397 | if (!beforeAssignment->expList->exprs.empty()) { | ||
| 2398 | transformAssignment(beforeAssignment, temp); | ||
| 2303 | } | 2399 | } |
| 2400 | if (vit == values.end()) { | ||
| 2401 | throw CompileError("right value missing"sv, values.front()); | ||
| 2402 | } | ||
| 2403 | auto newChain = chainValue->new_ptr<ChainValue_t>(); | ||
| 2404 | newChain->items.push_back(toAst<Callable_t>(leftVar, newChain)); | ||
| 2405 | newChain->items.push_back(chainValue->items.back()); | ||
| 2406 | auto newLeft = newExp(newChain, newChain); | ||
| 2407 | auto newAsmt = assignmentFrom(newLeft, *vit, newLeft); | ||
| 2408 | transformAssignment(newAsmt, temp); | ||
| 2304 | if (!afterAssignment->expList->exprs.empty()) { | 2409 | if (!afterAssignment->expList->exprs.empty()) { |
| 2305 | transformAssignment(afterAssignment, temp); | 2410 | transformAssignment(afterAssignment, temp); |
| 2306 | } | 2411 | } |
| @@ -2329,6 +2434,17 @@ private: | |||
| 2329 | out.back().insert(0, preDefine); | 2434 | out.back().insert(0, preDefine); |
| 2330 | return false; | 2435 | return false; |
| 2331 | } | 2436 | } |
| 2437 | case id<Try_t>(): { | ||
| 2438 | auto tryNode = static_cast<Try_t*>(value); | ||
| 2439 | if (tryNode->eop) { | ||
| 2440 | auto assignList = assignment->expList.get(); | ||
| 2441 | std::string preDefine = getPreDefineLine(assignment); | ||
| 2442 | transformTry(tryNode, out, ExpUsage::Assignment, assignList); | ||
| 2443 | out.back().insert(0, preDefine); | ||
| 2444 | return false; | ||
| 2445 | } | ||
| 2446 | break; | ||
| 2447 | } | ||
| 2332 | case id<Switch_t>(): { | 2448 | case id<Switch_t>(): { |
| 2333 | auto switchNode = static_cast<Switch_t*>(value); | 2449 | auto switchNode = static_cast<Switch_t*>(value); |
| 2334 | auto assignList = assignment->expList.get(); | 2450 | auto assignList = assignment->expList.get(); |
| @@ -2356,7 +2472,7 @@ private: | |||
| 2356 | case id<Comprehension_t>(): { | 2472 | case id<Comprehension_t>(): { |
| 2357 | auto comp = static_cast<Comprehension_t*>(value); | 2473 | auto comp = static_cast<Comprehension_t*>(value); |
| 2358 | auto expList = assignment->expList.get(); | 2474 | auto expList = assignment->expList.get(); |
| 2359 | if (comp->items.size() == 2 && ast_is<CompInner_t>(comp->items.back())) { | 2475 | if (isListComp(comp)) { |
| 2360 | std::string preDefine = getPreDefineLine(assignment); | 2476 | std::string preDefine = getPreDefineLine(assignment); |
| 2361 | transformComprehension(comp, out, ExpUsage::Assignment, expList); | 2477 | transformComprehension(comp, out, ExpUsage::Assignment, expList); |
| 2362 | out.back().insert(0, preDefine); | 2478 | out.back().insert(0, preDefine); |
| @@ -2400,6 +2516,13 @@ private: | |||
| 2400 | out.back().insert(0, preDefine); | 2516 | out.back().insert(0, preDefine); |
| 2401 | return false; | 2517 | return false; |
| 2402 | } | 2518 | } |
| 2519 | case id<Repeat_t>(): { | ||
| 2520 | auto expList = assignment->expList.get(); | ||
| 2521 | std::string preDefine = getPreDefineLine(assignment); | ||
| 2522 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out, expList); | ||
| 2523 | out.back().insert(0, preDefine); | ||
| 2524 | return false; | ||
| 2525 | } | ||
| 2403 | case id<TableLit_t>(): { | 2526 | case id<TableLit_t>(): { |
| 2404 | auto tableLit = static_cast<TableLit_t*>(value); | 2527 | auto tableLit = static_cast<TableLit_t*>(value); |
| 2405 | if (hasSpreadExp(tableLit->values.objects())) { | 2528 | if (hasSpreadExp(tableLit->values.objects())) { |
| @@ -2452,12 +2575,14 @@ private: | |||
| 2452 | switch (type) { | 2575 | switch (type) { |
| 2453 | case ChainType::HasEOP: | 2576 | case ChainType::HasEOP: |
| 2454 | case ChainType::EndWithColon: | 2577 | case ChainType::EndWithColon: |
| 2578 | case ChainType::EndWithSlice: | ||
| 2455 | case ChainType::MetaFieldInvocation: { | 2579 | case ChainType::MetaFieldInvocation: { |
| 2456 | std::string preDefine = getPreDefineLine(assignment); | 2580 | std::string preDefine = getPreDefineLine(assignment); |
| 2457 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); | 2581 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); |
| 2458 | out.back().insert(0, preDefine); | 2582 | out.back().insert(0, preDefine); |
| 2459 | return false; | 2583 | return false; |
| 2460 | } | 2584 | } |
| 2585 | case ChainType::HasRIndex: | ||
| 2461 | case ChainType::HasKeyword: | 2586 | case ChainType::HasKeyword: |
| 2462 | case ChainType::HasUnicode: | 2587 | case ChainType::HasUnicode: |
| 2463 | case ChainType::Macro: | 2588 | case ChainType::Macro: |
| @@ -2512,11 +2637,11 @@ private: | |||
| 2512 | checkConst(def, x); | 2637 | checkConst(def, x); |
| 2513 | addToScope(def); | 2638 | addToScope(def); |
| 2514 | } | 2639 | } |
| 2515 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2640 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2516 | } | 2641 | } |
| 2517 | if (needScope) { | 2642 | if (needScope) { |
| 2518 | extraScope = true; | 2643 | extraScope = true; |
| 2519 | temp.push_back(indent() + "do"s + nll(x)); | 2644 | temp.push_back(indent() + "do"s + nl(x)); |
| 2520 | pushScope(); | 2645 | pushScope(); |
| 2521 | } | 2646 | } |
| 2522 | } | 2647 | } |
| @@ -2568,13 +2693,13 @@ private: | |||
| 2568 | continue; | 2693 | continue; |
| 2569 | } | 2694 | } |
| 2570 | if (extraScope) { | 2695 | if (extraScope) { |
| 2571 | temp.push_back(indent() + "do"s + nll(x)); | 2696 | temp.push_back(indent() + "do"s + nl(x)); |
| 2572 | pushScope(); | 2697 | pushScope(); |
| 2573 | } | 2698 | } |
| 2574 | if (!pair.targetVar.empty()) { | 2699 | if (!pair.targetVar.empty()) { |
| 2575 | checkConst(pair.targetVar, x); | 2700 | checkConst(pair.targetVar, x); |
| 2576 | if (addToScope(pair.targetVar)) { | 2701 | if (addToScope(pair.targetVar)) { |
| 2577 | _buf << indent() << "local "sv << pair.targetVar << nll(x); | 2702 | _buf << indent() << "local "sv << pair.targetVar << nl(x); |
| 2578 | temp.push_back(clearBuf()); | 2703 | temp.push_back(clearBuf()); |
| 2579 | } | 2704 | } |
| 2580 | } | 2705 | } |
| @@ -2584,7 +2709,7 @@ private: | |||
| 2584 | objVar = destruct.valueVar; | 2709 | objVar = destruct.valueVar; |
| 2585 | } else { | 2710 | } else { |
| 2586 | if (needScope) { | 2711 | if (needScope) { |
| 2587 | temp.push_back(indent() + "do"s + nll(x)); | 2712 | temp.push_back(indent() + "do"s + nl(x)); |
| 2588 | pushScope(); | 2713 | pushScope(); |
| 2589 | } | 2714 | } |
| 2590 | objVar = getUnusedName("_obj_"sv); | 2715 | objVar = getUnusedName("_obj_"sv); |
| @@ -2600,7 +2725,7 @@ private: | |||
| 2600 | if (!isLocalValue) { | 2725 | if (!isLocalValue) { |
| 2601 | if (needScope) { | 2726 | if (needScope) { |
| 2602 | popScope(); | 2727 | popScope(); |
| 2603 | _buf << indent() << "end"sv << nlr(x); | 2728 | _buf << indent() << "end"sv << nl(x); |
| 2604 | temp.push_back(clearBuf()); | 2729 | temp.push_back(clearBuf()); |
| 2605 | } | 2730 | } |
| 2606 | } | 2731 | } |
| @@ -2638,9 +2763,9 @@ private: | |||
| 2638 | checkConst(def, x); | 2763 | checkConst(def, x); |
| 2639 | addToScope(def); | 2764 | addToScope(def); |
| 2640 | } | 2765 | } |
| 2641 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2766 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2642 | } | 2767 | } |
| 2643 | temp.push_back(indent() + "do"s + nll(x)); | 2768 | temp.push_back(indent() + "do"s + nl(x)); |
| 2644 | pushScope(); | 2769 | pushScope(); |
| 2645 | } | 2770 | } |
| 2646 | } else { | 2771 | } else { |
| @@ -2649,11 +2774,11 @@ private: | |||
| 2649 | checkConst(def, x); | 2774 | checkConst(def, x); |
| 2650 | addToScope(def); | 2775 | addToScope(def); |
| 2651 | } | 2776 | } |
| 2652 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2777 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2653 | } | 2778 | } |
| 2654 | if (needScope) { | 2779 | if (needScope) { |
| 2655 | extraScope = true; | 2780 | extraScope = true; |
| 2656 | temp.push_back(indent() + "do"s + nll(x)); | 2781 | temp.push_back(indent() + "do"s + nl(x)); |
| 2657 | pushScope(); | 2782 | pushScope(); |
| 2658 | } | 2783 | } |
| 2659 | auto valVar = getUnusedName("_obj_"sv); | 2784 | auto valVar = getUnusedName("_obj_"sv); |
| @@ -2668,7 +2793,7 @@ private: | |||
| 2668 | if (destruct.inlineAssignment) { | 2793 | if (destruct.inlineAssignment) { |
| 2669 | if (needScope && !extraScope) { | 2794 | if (needScope && !extraScope) { |
| 2670 | extraScope = true; | 2795 | extraScope = true; |
| 2671 | temp.push_back(indent() + "do"s + nll(x)); | 2796 | temp.push_back(indent() + "do"s + nl(x)); |
| 2672 | pushScope(); | 2797 | pushScope(); |
| 2673 | } | 2798 | } |
| 2674 | transformAssignment(destruct.inlineAssignment, temp); | 2799 | transformAssignment(destruct.inlineAssignment, temp); |
| @@ -2733,13 +2858,13 @@ private: | |||
| 2733 | } | 2858 | } |
| 2734 | if (extraScope) { | 2859 | if (extraScope) { |
| 2735 | popScope(); | 2860 | popScope(); |
| 2736 | _buf << indent() << "end"sv << nlr(x); | 2861 | _buf << indent() << "end"sv << nl(x); |
| 2737 | temp.push_back(clearBuf()); | 2862 | temp.push_back(clearBuf()); |
| 2738 | } | 2863 | } |
| 2739 | } | 2864 | } |
| 2740 | if (extraScope) { | 2865 | if (extraScope) { |
| 2741 | popScope(); | 2866 | popScope(); |
| 2742 | temp.push_back(indent() + "end"s + nlr(x)); | 2867 | temp.push_back(indent() + "end"s + nl(x)); |
| 2743 | } | 2868 | } |
| 2744 | out.push_back(join(temp)); | 2869 | out.push_back(join(temp)); |
| 2745 | if (assignment->expList->followStmt) { | 2870 | if (assignment->expList->followStmt) { |
| @@ -2757,6 +2882,7 @@ private: | |||
| 2757 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; | 2882 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; |
| 2758 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; | 2883 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; |
| 2759 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; | 2884 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; |
| 2885 | case id<SpreadListExp_t>(): throw CompileError("can only be used for ranged table append assignments"sv, value); break; | ||
| 2760 | default: YUEE("AST node mismatch", value); break; | 2886 | default: YUEE("AST node mismatch", value); break; |
| 2761 | } | 2887 | } |
| 2762 | } | 2888 | } |
| @@ -2771,7 +2897,7 @@ private: | |||
| 2771 | if (auto tbA = item->get_by_path<TableLit_t>()) { | 2897 | if (auto tbA = item->get_by_path<TableLit_t>()) { |
| 2772 | tableItems = &tbA->values.objects(); | 2898 | tableItems = &tbA->values.objects(); |
| 2773 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { | 2899 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { |
| 2774 | if (tbB->items.size() == 2 && ast_is<CompInner_t>(tbB->items.back())) { | 2900 | if (isListComp(tbB)) { |
| 2775 | throw CompileError("invalid destructure value"sv, tbB); | 2901 | throw CompileError("invalid destructure value"sv, tbB); |
| 2776 | } | 2902 | } |
| 2777 | tableItems = &tbB->items.objects(); | 2903 | tableItems = &tbB->items.objects(); |
| @@ -2802,7 +2928,7 @@ private: | |||
| 2802 | } | 2928 | } |
| 2803 | case id<Comprehension_t>(): { | 2929 | case id<Comprehension_t>(): { |
| 2804 | auto table = static_cast<Comprehension_t*>(node); | 2930 | auto table = static_cast<Comprehension_t*>(node); |
| 2805 | if (table->items.size() == 2 && ast_is<CompInner_t>(table->items.back())) { | 2931 | if (isListComp(table)) { |
| 2806 | throw CompileError("invalid destructure value"sv, table); | 2932 | throw CompileError("invalid destructure value"sv, table); |
| 2807 | } | 2933 | } |
| 2808 | tableItems = &table->items.objects(); | 2934 | tableItems = &table->items.objects(); |
| @@ -2813,17 +2939,19 @@ private: | |||
| 2813 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2939 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
| 2814 | std::list<DestructItem> pairs; | 2940 | std::list<DestructItem> pairs; |
| 2815 | int index = 0; | 2941 | int index = 0; |
| 2942 | int count = 0; | ||
| 2943 | bool hasSpread = false; | ||
| 2816 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2944 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
| 2817 | for (auto pair : *tableItems) { | 2945 | for (auto pair : *tableItems) { |
| 2818 | switch (pair->get_id()) { | 2946 | switch (pair->get_id()) { |
| 2819 | case id<Exp_t>(): | 2947 | case id<Exp_t>(): |
| 2820 | case id<NormalDef_t>(): { | 2948 | case id<NormalDef_t>(): { |
| 2949 | ++index; | ||
| 2821 | Exp_t* defVal = nullptr; | 2950 | Exp_t* defVal = nullptr; |
| 2822 | if (auto nd = ast_cast<NormalDef_t>(pair)) { | 2951 | if (auto nd = ast_cast<NormalDef_t>(pair)) { |
| 2823 | pair = nd->item.get(); | 2952 | pair = nd->item.get(); |
| 2824 | defVal = nd->defVal.get(); | 2953 | defVal = nd->defVal.get(); |
| 2825 | } | 2954 | } |
| 2826 | ++index; | ||
| 2827 | bool assignable = false; | 2955 | bool assignable = false; |
| 2828 | try { | 2956 | try { |
| 2829 | assignable = isAssignable(static_cast<Exp_t*>(pair)); | 2957 | assignable = isAssignable(static_cast<Exp_t*>(pair)); |
| @@ -2834,13 +2962,19 @@ private: | |||
| 2834 | if (optional) break; | 2962 | if (optional) break; |
| 2835 | throw CompileError("can't destructure value"sv, pair); | 2963 | throw CompileError("can't destructure value"sv, pair); |
| 2836 | } | 2964 | } |
| 2965 | ast_ptr<true, ast_node> indexItem; | ||
| 2966 | if (hasSpread) { | ||
| 2967 | int rIndex = count - index; | ||
| 2968 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | ||
| 2969 | } else { | ||
| 2970 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | ||
| 2971 | } | ||
| 2837 | if (optional && varDefOnly && !assignable) { | 2972 | if (optional && varDefOnly && !assignable) { |
| 2838 | if (defVal) { | 2973 | if (defVal) { |
| 2839 | throw CompileError("default value is not supported here"sv, defVal); | 2974 | throw CompileError("default value is not supported here"sv, defVal); |
| 2840 | } | 2975 | } |
| 2841 | auto exp = static_cast<Exp_t*>(pair); | 2976 | auto exp = static_cast<Exp_t*>(pair); |
| 2842 | auto chain = exp->new_ptr<ChainValue_t>(); | 2977 | auto chain = exp->new_ptr<ChainValue_t>(); |
| 2843 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
| 2844 | chain->items.push_back(indexItem); | 2978 | chain->items.push_back(indexItem); |
| 2845 | pairs.push_back({exp, Empty, chain, nullptr}); | 2979 | pairs.push_back({exp, Empty, chain, nullptr}); |
| 2846 | break; | 2980 | break; |
| @@ -2855,7 +2989,6 @@ private: | |||
| 2855 | throw CompileError("default value is not supported here"sv, defVal); | 2989 | throw CompileError("default value is not supported here"sv, defVal); |
| 2856 | } | 2990 | } |
| 2857 | } | 2991 | } |
| 2858 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | ||
| 2859 | for (auto& p : subPairs) { | 2992 | for (auto& p : subPairs) { |
| 2860 | if (sep) p.structure->items.push_front(sep); | 2993 | if (sep) p.structure->items.push_front(sep); |
| 2861 | p.structure->items.push_front(indexItem); | 2994 | p.structure->items.push_front(indexItem); |
| @@ -2866,7 +2999,6 @@ private: | |||
| 2866 | auto varName = singleVariableFrom(exp, AccessType::None); | 2999 | auto varName = singleVariableFrom(exp, AccessType::None); |
| 2867 | if (varName == "_"sv) break; | 3000 | if (varName == "_"sv) break; |
| 2868 | auto chain = exp->new_ptr<ChainValue_t>(); | 3001 | auto chain = exp->new_ptr<ChainValue_t>(); |
| 2869 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
| 2870 | chain->items.push_back(indexItem); | 3002 | chain->items.push_back(indexItem); |
| 2871 | pairs.push_back({exp, | 3003 | pairs.push_back({exp, |
| 2872 | varName, | 3004 | varName, |
| @@ -2991,7 +3123,13 @@ private: | |||
| 2991 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 3123 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
| 2992 | ++index; | 3124 | ++index; |
| 2993 | auto subPairs = destructFromExp(tb, varDefOnly, optional); | 3125 | auto subPairs = destructFromExp(tb, varDefOnly, optional); |
| 2994 | auto indexItem = toAst<Exp_t>(std::to_string(index), tb); | 3126 | ast_ptr<true, ast_node> indexItem; |
| 3127 | if (hasSpread) { | ||
| 3128 | int rIndex = count - index; | ||
| 3129 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | ||
| 3130 | } else { | ||
| 3131 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | ||
| 3132 | } | ||
| 2995 | for (auto& p : subPairs) { | 3133 | for (auto& p : subPairs) { |
| 2996 | if (sep) p.structure->items.push_front(sep); | 3134 | if (sep) p.structure->items.push_front(sep); |
| 2997 | p.structure->items.push_front(indexItem); | 3135 | p.structure->items.push_front(indexItem); |
| @@ -3048,6 +3186,42 @@ private: | |||
| 3048 | subMetaDestruct->values.push_back(newPairDef); | 3186 | subMetaDestruct->values.push_back(newPairDef); |
| 3049 | break; | 3187 | break; |
| 3050 | } | 3188 | } |
| 3189 | case id<SpreadListExp_t>(): | ||
| 3190 | case id<SpreadExp_t>(): { | ||
| 3191 | ++index; | ||
| 3192 | if (hasSpread) { | ||
| 3193 | throw CompileError("duplicated spread expression"sv, pair); | ||
| 3194 | } | ||
| 3195 | hasSpread = true; | ||
| 3196 | for (auto item : *tableItems) { | ||
| 3197 | if (ast_is< | ||
| 3198 | SpreadListExp_t, SpreadExp_t, | ||
| 3199 | TableBlockIndent_t, | ||
| 3200 | Exp_t, NormalDef_t>(item)) { | ||
| 3201 | count++; | ||
| 3202 | } | ||
| 3203 | } | ||
| 3204 | Exp_t* exp = nullptr; | ||
| 3205 | if (auto se = ast_cast<SpreadExp_t>(pair)) { | ||
| 3206 | exp = se->exp.get(); | ||
| 3207 | } else { | ||
| 3208 | exp = ast_to<SpreadListExp_t>(pair)->exp.get(); | ||
| 3209 | } | ||
| 3210 | auto varName = singleVariableFrom(exp, AccessType::None); | ||
| 3211 | if (varName == "_"sv) break; | ||
| 3212 | int start = index; | ||
| 3213 | int stop = index - count - 1; | ||
| 3214 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
| 3215 | auto slice = toAst<Slice_t>( | ||
| 3216 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | ||
| 3217 | chain->items.push_back(slice); | ||
| 3218 | auto nil = toAst<Exp_t>("nil"sv, slice); | ||
| 3219 | pairs.push_back({exp, | ||
| 3220 | varName, | ||
| 3221 | chain, | ||
| 3222 | nil.get()}); | ||
| 3223 | break; | ||
| 3224 | } | ||
| 3051 | default: YUEE("AST node mismatch", pair); break; | 3225 | default: YUEE("AST node mismatch", pair); break; |
| 3052 | } | 3226 | } |
| 3053 | } | 3227 | } |
| @@ -3125,7 +3299,7 @@ private: | |||
| 3125 | if (auto tab = sVal->value.as<TableLit_t>()) { | 3299 | if (auto tab = sVal->value.as<TableLit_t>()) { |
| 3126 | destructNode = tab; | 3300 | destructNode = tab; |
| 3127 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { | 3301 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { |
| 3128 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 3302 | if (!isListComp(comp)) { |
| 3129 | destructNode = comp; | 3303 | destructNode = comp; |
| 3130 | } | 3304 | } |
| 3131 | } | 3305 | } |
| @@ -3512,7 +3686,7 @@ private: | |||
| 3512 | _buf << defs; | 3686 | _buf << defs; |
| 3513 | else | 3687 | else |
| 3514 | _buf << indent() << left; | 3688 | _buf << indent() << left; |
| 3515 | _buf << " = "sv << left << ' ' << op << ' ' << right << nll(assignment); | 3689 | _buf << " = "sv << left << ' ' << op << ' ' << right << nl(assignment); |
| 3516 | out.push_back(clearBuf()); | 3690 | out.push_back(clearBuf()); |
| 3517 | break; | 3691 | break; |
| 3518 | } | 3692 | } |
| @@ -3559,9 +3733,9 @@ private: | |||
| 3559 | transformExpList(expList, temp); | 3733 | transformExpList(expList, temp); |
| 3560 | std::string left = std::move(temp.back()); | 3734 | std::string left = std::move(temp.back()); |
| 3561 | temp.pop_back(); | 3735 | temp.pop_back(); |
| 3562 | out.push_back(indent() + left + " = "s + join(temp, ", "sv) + nll(assignment)); | 3736 | out.push_back(indent() + left + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3563 | } else { | 3737 | } else { |
| 3564 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nll(assignment)); | 3738 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3565 | } | 3739 | } |
| 3566 | } else { | 3740 | } else { |
| 3567 | std::string preDefine = toLocalDecl(defs); | 3741 | std::string preDefine = toLocalDecl(defs); |
| @@ -3577,7 +3751,7 @@ private: | |||
| 3577 | for (auto value : assign->values.objects()) { | 3751 | for (auto value : assign->values.objects()) { |
| 3578 | transformAssignItem(value, temp); | 3752 | transformAssignItem(value, temp); |
| 3579 | } | 3753 | } |
| 3580 | out.push_back((preDefine.empty() ? Empty : preDefine + nll(assignment)) + indent() + left + " = "s + join(temp, ", "sv) + nll(assignment)); | 3754 | out.push_back((preDefine.empty() ? Empty : preDefine + nl(assignment)) + indent() + left + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3581 | } | 3755 | } |
| 3582 | break; | 3756 | break; |
| 3583 | } | 3757 | } |
| @@ -3678,7 +3852,7 @@ private: | |||
| 3678 | if (usage != ExpUsage::Closure) { | 3852 | if (usage != ExpUsage::Closure) { |
| 3679 | if (!currentScope().lastStatement) { | 3853 | if (!currentScope().lastStatement) { |
| 3680 | extraScope = true; | 3854 | extraScope = true; |
| 3681 | temp.push_back(indent() + "do"s + nll(asmt)); | 3855 | temp.push_back(indent() + "do"s + nl(asmt)); |
| 3682 | pushScope(); | 3856 | pushScope(); |
| 3683 | } | 3857 | } |
| 3684 | } | 3858 | } |
| @@ -3711,7 +3885,7 @@ private: | |||
| 3711 | if (usage != ExpUsage::Closure) { | 3885 | if (usage != ExpUsage::Closure) { |
| 3712 | if (!currentScope().lastStatement) { | 3886 | if (!currentScope().lastStatement) { |
| 3713 | extraScope = true; | 3887 | extraScope = true; |
| 3714 | temp.push_back(indent() + "do"s + nll(asmt)); | 3888 | temp.push_back(indent() + "do"s + nl(asmt)); |
| 3715 | pushScope(); | 3889 | pushScope(); |
| 3716 | } | 3890 | } |
| 3717 | } | 3891 | } |
| @@ -3740,12 +3914,12 @@ private: | |||
| 3740 | if (pair != ifCondPairs.front()) { | 3914 | if (pair != ifCondPairs.front()) { |
| 3741 | _buf << "else"sv; | 3915 | _buf << "else"sv; |
| 3742 | } | 3916 | } |
| 3743 | _buf << "if "sv << condStr << " then"sv << nll(condition); | 3917 | _buf << "if "sv << condStr << " then"sv << nl(condition); |
| 3744 | temp.push_back(clearBuf()); | 3918 | temp.push_back(clearBuf()); |
| 3745 | } | 3919 | } |
| 3746 | if (pair.second) { | 3920 | if (pair.second) { |
| 3747 | if (!pair.first) { | 3921 | if (!pair.first) { |
| 3748 | temp.push_back(indent() + "else"s + nll(pair.second)); | 3922 | temp.push_back(indent() + "else"s + nl(pair.second)); |
| 3749 | } | 3923 | } |
| 3750 | pushScope(); | 3924 | pushScope(); |
| 3751 | if (pair == ifCondPairs.front() && extraAssignment) { | 3925 | if (pair == ifCondPairs.front() && extraAssignment) { |
| @@ -3755,17 +3929,17 @@ private: | |||
| 3755 | popScope(); | 3929 | popScope(); |
| 3756 | } | 3930 | } |
| 3757 | if (!pair.first) { | 3931 | if (!pair.first) { |
| 3758 | temp.push_back(indent() + "end"s + nll(nodes.front())); | 3932 | temp.push_back(indent() + "end"s + nl(nodes.front())); |
| 3759 | break; | 3933 | break; |
| 3760 | } | 3934 | } |
| 3761 | } | 3935 | } |
| 3762 | if (extraScope) { | 3936 | if (extraScope) { |
| 3763 | popScope(); | 3937 | popScope(); |
| 3764 | temp.push_back(indent() + "end"s + nlr(nodes.front())); | 3938 | temp.push_back(indent() + "end"s + nl(nodes.front())); |
| 3765 | } | 3939 | } |
| 3766 | if (usage == ExpUsage::Closure) { | 3940 | if (usage == ExpUsage::Closure) { |
| 3767 | popScope(); | 3941 | popScope(); |
| 3768 | *funcStart = anonFuncStart() + nll(nodes.front()); | 3942 | *funcStart = anonFuncStart() + nl(nodes.front()); |
| 3769 | temp.push_back(indent() + anonFuncEnd()); | 3943 | temp.push_back(indent() + anonFuncEnd()); |
| 3770 | popAnonVarArg(); | 3944 | popAnonVarArg(); |
| 3771 | popFunctionScope(); | 3945 | popFunctionScope(); |
| @@ -3860,7 +4034,7 @@ private: | |||
| 3860 | } else { | 4034 | } else { |
| 3861 | transformExp(arg, out, ExpUsage::Closure); | 4035 | transformExp(arg, out, ExpUsage::Closure); |
| 3862 | out.back().insert(0, indent()); | 4036 | out.back().insert(0, indent()); |
| 3863 | out.back().append(nlr(x)); | 4037 | out.back().append(nl(x)); |
| 3864 | } | 4038 | } |
| 3865 | return; | 4039 | return; |
| 3866 | } | 4040 | } |
| @@ -3984,7 +4158,7 @@ private: | |||
| 3984 | auto stmt = exp->new_ptr<Statement_t>(); | 4158 | auto stmt = exp->new_ptr<Statement_t>(); |
| 3985 | stmt->content.set(preDefine); | 4159 | stmt->content.set(preDefine); |
| 3986 | preDefine.set(nullptr); | 4160 | preDefine.set(nullptr); |
| 3987 | block->statements.push_back(stmt); | 4161 | block->statementOrComments.push_back(stmt); |
| 3988 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | 4162 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); |
| 3989 | simpleValue->value.set(ifNode); | 4163 | simpleValue->value.set(ifNode); |
| 3990 | auto explist = exp->new_ptr<ExpList_t>(); | 4164 | auto explist = exp->new_ptr<ExpList_t>(); |
| @@ -3993,7 +4167,7 @@ private: | |||
| 3993 | expListAssign->expList.set(explist); | 4167 | expListAssign->expList.set(explist); |
| 3994 | stmt = exp->new_ptr<Statement_t>(); | 4168 | stmt = exp->new_ptr<Statement_t>(); |
| 3995 | stmt->content.set(expListAssign); | 4169 | stmt->content.set(expListAssign); |
| 3996 | block->statements.push_back(stmt); | 4170 | block->statementOrComments.push_back(stmt); |
| 3997 | nodes->push_back(block); | 4171 | nodes->push_back(block); |
| 3998 | nodes = &ifNode->nodes; | 4172 | nodes = &ifNode->nodes; |
| 3999 | } else { | 4173 | } else { |
| @@ -4001,7 +4175,7 @@ private: | |||
| 4001 | auto stmt = exp->new_ptr<Statement_t>(); | 4175 | auto stmt = exp->new_ptr<Statement_t>(); |
| 4002 | stmt->content.set(preDefine); | 4176 | stmt->content.set(preDefine); |
| 4003 | preDefine.set(nullptr); | 4177 | preDefine.set(nullptr); |
| 4004 | block->statements.push_back(stmt); | 4178 | block->statementOrComments.push_back(stmt); |
| 4005 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | 4179 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); |
| 4006 | simpleValue->value.set(ifNode); | 4180 | simpleValue->value.set(ifNode); |
| 4007 | auto explist = exp->new_ptr<ExpList_t>(); | 4181 | auto explist = exp->new_ptr<ExpList_t>(); |
| @@ -4010,7 +4184,7 @@ private: | |||
| 4010 | expListAssign->expList.set(explist); | 4184 | expListAssign->expList.set(explist); |
| 4011 | stmt = exp->new_ptr<Statement_t>(); | 4185 | stmt = exp->new_ptr<Statement_t>(); |
| 4012 | stmt->content.set(expListAssign); | 4186 | stmt->content.set(expListAssign); |
| 4013 | block->statements.push_back(stmt); | 4187 | block->statementOrComments.push_back(stmt); |
| 4014 | auto body = exp->new_ptr<Body_t>(); | 4188 | auto body = exp->new_ptr<Body_t>(); |
| 4015 | body->content.set(block); | 4189 | body->content.set(block); |
| 4016 | auto doNode = exp->new_ptr<Do_t>(); | 4190 | auto doNode = exp->new_ptr<Do_t>(); |
| @@ -4172,7 +4346,7 @@ private: | |||
| 4172 | auto stmt = x->new_ptr<Statement_t>(); | 4346 | auto stmt = x->new_ptr<Statement_t>(); |
| 4173 | stmt->content.set(expListAssign); | 4347 | stmt->content.set(expListAssign); |
| 4174 | auto blk = x->new_ptr<Block_t>(); | 4348 | auto blk = x->new_ptr<Block_t>(); |
| 4175 | blk->statements.push_back(stmt); | 4349 | blk->statementOrComments.push_back(stmt); |
| 4176 | newBlock.set(blk); | 4350 | newBlock.set(blk); |
| 4177 | } | 4351 | } |
| 4178 | if (!globals.empty()) { | 4352 | if (!globals.empty()) { |
| @@ -4264,15 +4438,25 @@ private: | |||
| 4264 | 4438 | ||
| 4265 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { | 4439 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { |
| 4266 | if (checkUpValueFuncAvailable(exp)) { | 4440 | if (checkUpValueFuncAvailable(exp)) { |
| 4441 | auto block = exp->new_ptr<Block_t>(); | ||
| 4442 | if (auto sVal = simpleSingleValueFrom(exp)) { | ||
| 4443 | if (auto doNode = sVal->value.as<Do_t>()) { | ||
| 4444 | if (auto blk = doNode->body->content.as<Block_t>()) { | ||
| 4445 | block->statementOrComments.dup(blk->statementOrComments); | ||
| 4446 | } else { | ||
| 4447 | block->statementOrComments.push_back(doNode->body->content.to<Statement_t>()); | ||
| 4448 | } | ||
| 4449 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | ||
| 4450 | } | ||
| 4451 | } | ||
| 4267 | auto returnNode = exp->new_ptr<Return_t>(); | 4452 | auto returnNode = exp->new_ptr<Return_t>(); |
| 4268 | returnNode->explicitReturn = false; | 4453 | returnNode->explicitReturn = false; |
| 4269 | auto returnList = exp->new_ptr<ExpListLow_t>(); | 4454 | auto returnList = exp->new_ptr<ExpListLow_t>(); |
| 4270 | returnList->exprs.push_back(exp); | 4455 | returnList->exprs.push_back(exp); |
| 4271 | returnNode->valueList.set(returnList); | 4456 | returnNode->valueList.set(returnList); |
| 4272 | auto block = exp->new_ptr<Block_t>(); | ||
| 4273 | auto stmt = exp->new_ptr<Statement_t>(); | 4457 | auto stmt = exp->new_ptr<Statement_t>(); |
| 4274 | stmt->content.set(returnNode); | 4458 | stmt->content.set(returnNode); |
| 4275 | block->statements.push_back(stmt); | 4459 | block->statementOrComments.push_back(stmt); |
| 4276 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | 4460 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); |
| 4277 | } | 4461 | } |
| 4278 | return std::nullopt; | 4462 | return std::nullopt; |
| @@ -4329,7 +4513,7 @@ private: | |||
| 4329 | bool extraScope = !currentScope().lastStatement; | 4513 | bool extraScope = !currentScope().lastStatement; |
| 4330 | if (forAssignment) { | 4514 | if (forAssignment) { |
| 4331 | if (extraScope) { | 4515 | if (extraScope) { |
| 4332 | temp.push_back(indent() + "do"s + nll(x)); | 4516 | temp.push_back(indent() + "do"s + nl(x)); |
| 4333 | pushScope(); | 4517 | pushScope(); |
| 4334 | } | 4518 | } |
| 4335 | } | 4519 | } |
| @@ -4352,9 +4536,9 @@ private: | |||
| 4352 | case ExpUsage::Return: | 4536 | case ExpUsage::Return: |
| 4353 | case ExpUsage::Closure: { | 4537 | case ExpUsage::Closure: { |
| 4354 | prepareValue(); | 4538 | prepareValue(); |
| 4355 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 4539 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 4356 | _buf << indent(1) << "return "s << objVar << nll(x); | 4540 | _buf << indent(1) << "return "s << objVar << nl(x); |
| 4357 | _buf << indent() << "else"s << nll(x); | 4541 | _buf << indent() << "else"s << nl(x); |
| 4358 | temp.push_back(clearBuf()); | 4542 | temp.push_back(clearBuf()); |
| 4359 | auto ret = x->new_ptr<Return_t>(); | 4543 | auto ret = x->new_ptr<Return_t>(); |
| 4360 | ret->explicitReturn = false; | 4544 | ret->explicitReturn = false; |
| @@ -4364,10 +4548,10 @@ private: | |||
| 4364 | incIndentOffset(); | 4548 | incIndentOffset(); |
| 4365 | transformReturn(ret, temp); | 4549 | transformReturn(ret, temp); |
| 4366 | decIndentOffset(); | 4550 | decIndentOffset(); |
| 4367 | temp.push_back(indent() + "end"s + nll(x)); | 4551 | temp.push_back(indent() + "end"s + nl(x)); |
| 4368 | if (usage == ExpUsage::Closure) { | 4552 | if (usage == ExpUsage::Closure) { |
| 4369 | popScope(); | 4553 | popScope(); |
| 4370 | *funcStart = anonFuncStart() + nll(x); | 4554 | *funcStart = anonFuncStart() + nl(x); |
| 4371 | temp.push_back(indent() + anonFuncEnd()); | 4555 | temp.push_back(indent() + anonFuncEnd()); |
| 4372 | popAnonVarArg(); | 4556 | popAnonVarArg(); |
| 4373 | popFunctionScope(); | 4557 | popFunctionScope(); |
| @@ -4384,14 +4568,14 @@ private: | |||
| 4384 | assign->values.push_back(exp); | 4568 | assign->values.push_back(exp); |
| 4385 | temp.push_back(getPreDefineLine(assignment)); | 4569 | temp.push_back(getPreDefineLine(assignment)); |
| 4386 | extraScope = prepareValue(true); | 4570 | extraScope = prepareValue(true); |
| 4387 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 4571 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 4388 | temp.push_back(clearBuf()); | 4572 | temp.push_back(clearBuf()); |
| 4389 | pushScope(); | 4573 | pushScope(); |
| 4390 | assign->values.clear(); | 4574 | assign->values.clear(); |
| 4391 | assign->values.push_back(toAst<Exp_t>(objVar, x)); | 4575 | assign->values.push_back(toAst<Exp_t>(objVar, x)); |
| 4392 | transformAssignment(assignment, temp); | 4576 | transformAssignment(assignment, temp); |
| 4393 | popScope(); | 4577 | popScope(); |
| 4394 | temp.push_back(indent() + "else"s + nll(x)); | 4578 | temp.push_back(indent() + "else"s + nl(x)); |
| 4395 | assign->values.clear(); | 4579 | assign->values.clear(); |
| 4396 | assign->values.push_back(exp->nilCoalesed); | 4580 | assign->values.push_back(exp->nilCoalesed); |
| 4397 | } else { | 4581 | } else { |
| @@ -4399,17 +4583,17 @@ private: | |||
| 4399 | assign->values.push_back(exp->nilCoalesed); | 4583 | assign->values.push_back(exp->nilCoalesed); |
| 4400 | temp.push_back(getPreDefineLine(assignment)); | 4584 | temp.push_back(getPreDefineLine(assignment)); |
| 4401 | transformExp(left, temp, ExpUsage::Closure); | 4585 | transformExp(left, temp, ExpUsage::Closure); |
| 4402 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nll(x); | 4586 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nl(x); |
| 4403 | temp.pop_back(); | 4587 | temp.pop_back(); |
| 4404 | temp.push_back(clearBuf()); | 4588 | temp.push_back(clearBuf()); |
| 4405 | } | 4589 | } |
| 4406 | pushScope(); | 4590 | pushScope(); |
| 4407 | transformAssignment(assignment, temp); | 4591 | transformAssignment(assignment, temp); |
| 4408 | popScope(); | 4592 | popScope(); |
| 4409 | temp.push_back(indent() + "end"s + nlr(x)); | 4593 | temp.push_back(indent() + "end"s + nl(x)); |
| 4410 | if (extraScope) { | 4594 | if (extraScope) { |
| 4411 | popScope(); | 4595 | popScope(); |
| 4412 | temp.push_back(indent() + "end"s + nlr(x)); | 4596 | temp.push_back(indent() + "end"s + nl(x)); |
| 4413 | } | 4597 | } |
| 4414 | break; | 4598 | break; |
| 4415 | } | 4599 | } |
| @@ -4439,7 +4623,7 @@ private: | |||
| 4439 | if (accessType == AccessType::Read && _funcLevel > 1) { | 4623 | if (accessType == AccessType::Read && _funcLevel > 1) { |
| 4440 | accessType = AccessType::Capture; | 4624 | accessType = AccessType::Capture; |
| 4441 | } | 4625 | } |
| 4442 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType}; | 4626 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType, isSolidDefined(out.back())}; |
| 4443 | } | 4627 | } |
| 4444 | } | 4628 | } |
| 4445 | break; | 4629 | break; |
| @@ -4471,6 +4655,7 @@ private: | |||
| 4471 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 4655 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
| 4472 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; | 4656 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; |
| 4473 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; | 4657 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
| 4658 | case id<Repeat_t>(): transformRepeatClosure(static_cast<Repeat_t*>(value), out); break; | ||
| 4474 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; | 4659 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; |
| 4475 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 4660 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
| 4476 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; | 4661 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
| @@ -4507,11 +4692,11 @@ private: | |||
| 4507 | switch (content->get_id()) { | 4692 | switch (content->get_id()) { |
| 4508 | case id<Block_t>(): { | 4693 | case id<Block_t>(): { |
| 4509 | auto block = static_cast<Block_t*>(content); | 4694 | auto block = static_cast<Block_t*>(content); |
| 4510 | newBlock->statements.dup(block->statements); | 4695 | newBlock->statementOrComments.dup(block->statementOrComments); |
| 4511 | break; | 4696 | break; |
| 4512 | } | 4697 | } |
| 4513 | case id<Statement_t>(): { | 4698 | case id<Statement_t>(): { |
| 4514 | newBlock->statements.push_back(content); | 4699 | newBlock->statementOrComments.push_back(content); |
| 4515 | break; | 4700 | break; |
| 4516 | } | 4701 | } |
| 4517 | default: YUEE("AST node mismatch", content); break; | 4702 | default: YUEE("AST node mismatch", content); break; |
| @@ -4523,7 +4708,7 @@ private: | |||
| 4523 | returnNode->valueList.set(funLit->defaultReturn); | 4708 | returnNode->valueList.set(funLit->defaultReturn); |
| 4524 | auto stmt = newBlock->new_ptr<Statement_t>(); | 4709 | auto stmt = newBlock->new_ptr<Statement_t>(); |
| 4525 | stmt->content.set(returnNode); | 4710 | stmt->content.set(returnNode); |
| 4526 | newBlock->statements.push_back(stmt); | 4711 | newBlock->statementOrComments.push_back(stmt); |
| 4527 | } | 4712 | } |
| 4528 | transformBlock(newBlock, temp, ExpUsage::Common); | 4713 | transformBlock(newBlock, temp, ExpUsage::Common); |
| 4529 | } else { | 4714 | } else { |
| @@ -4545,7 +4730,7 @@ private: | |||
| 4545 | } | 4730 | } |
| 4546 | _buf << args << ')'; | 4731 | _buf << args << ')'; |
| 4547 | if (!initArgs.empty() || !bodyCodes.empty()) { | 4732 | if (!initArgs.empty() || !bodyCodes.empty()) { |
| 4548 | _buf << nlr(argsDef) << initArgs << bodyCodes; | 4733 | _buf << nl(argsDef) << initArgs << bodyCodes; |
| 4549 | popScope(); | 4734 | popScope(); |
| 4550 | _buf << indent() << "end"sv; | 4735 | _buf << indent() << "end"sv; |
| 4551 | } else { | 4736 | } else { |
| @@ -4556,7 +4741,7 @@ private: | |||
| 4556 | auto& bodyCodes = temp.back(); | 4741 | auto& bodyCodes = temp.back(); |
| 4557 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; | 4742 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; |
| 4558 | if (!bodyCodes.empty()) { | 4743 | if (!bodyCodes.empty()) { |
| 4559 | _buf << nll(funLit) << bodyCodes; | 4744 | _buf << nl(funLit) << bodyCodes; |
| 4560 | popScope(); | 4745 | popScope(); |
| 4561 | _buf << indent() << "end"sv; | 4746 | _buf << indent() << "end"sv; |
| 4562 | } else { | 4747 | } else { |
| @@ -4573,7 +4758,7 @@ private: | |||
| 4573 | auto x = body; | 4758 | auto x = body; |
| 4574 | if (auto stmt = body->content.as<Statement_t>()) { | 4759 | if (auto stmt = body->content.as<Statement_t>()) { |
| 4575 | auto block = x->new_ptr<Block_t>(); | 4760 | auto block = x->new_ptr<Block_t>(); |
| 4576 | block->statements.push_back(stmt); | 4761 | block->statementOrComments.push_back(stmt); |
| 4577 | transformBlock(block, out, usage, assignList); | 4762 | transformBlock(block, out, usage, assignList); |
| 4578 | } else { | 4763 | } else { |
| 4579 | transformBlock(body->content.to<Block_t>(), out, usage, assignList); | 4764 | transformBlock(body->content.to<Block_t>(), out, usage, assignList); |
| @@ -4585,13 +4770,15 @@ private: | |||
| 4585 | out.push_back(Empty); | 4770 | out.push_back(Empty); |
| 4586 | return; | 4771 | return; |
| 4587 | } | 4772 | } |
| 4588 | const auto& nodes = block->statements.objects(); | 4773 | const auto& nodes = block->statementOrComments.objects(); |
| 4774 | auto lastStmt = lastStatementFrom(nodes); | ||
| 4589 | LocalMode mode = LocalMode::None; | 4775 | LocalMode mode = LocalMode::None; |
| 4590 | Local_t *any = nullptr, *capital = nullptr; | 4776 | Local_t *any = nullptr, *capital = nullptr; |
| 4591 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { | 4777 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { |
| 4592 | auto node = *it; | 4778 | auto node = *it; |
| 4593 | auto stmt = static_cast<Statement_t*>(node); | 4779 | auto stmt = ast_cast<Statement_t>(node); |
| 4594 | if (!stmt->appendix && stmt->content.is<Return_t>() && stmt != nodes.back()) { | 4780 | if (!stmt) continue; |
| 4781 | if (!stmt->appendix && stmt->content.is<Return_t>() && stmt != lastStmt) { | ||
| 4595 | throw CompileError("'return' statement must be the last line in the block"sv, stmt->content); | 4782 | throw CompileError("'return' statement must be the last line in the block"sv, stmt->content); |
| 4596 | } else if (auto pipeBody = stmt->content.as<PipeBody_t>()) { | 4783 | } else if (auto pipeBody = stmt->content.as<PipeBody_t>()) { |
| 4597 | auto x = stmt; | 4784 | auto x = stmt; |
| @@ -4600,6 +4787,16 @@ private: | |||
| 4600 | BREAK_IF(it == nodes.begin()); | 4787 | BREAK_IF(it == nodes.begin()); |
| 4601 | auto last = it; | 4788 | auto last = it; |
| 4602 | --last; | 4789 | --last; |
| 4790 | bool found = true; | ||
| 4791 | while (!ast_is<Statement_t>(*last)) { | ||
| 4792 | if (last == nodes.begin()) { | ||
| 4793 | found = false; | ||
| 4794 | break; | ||
| 4795 | } else { | ||
| 4796 | --last; | ||
| 4797 | } | ||
| 4798 | } | ||
| 4799 | BREAK_IF(!found); | ||
| 4603 | auto lst = static_cast<Statement_t*>(*last); | 4800 | auto lst = static_cast<Statement_t*>(*last); |
| 4604 | if (lst->appendix) { | 4801 | if (lst->appendix) { |
| 4605 | throw CompileError("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()); | 4802 | throw CompileError("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()); |
| @@ -4617,9 +4814,17 @@ private: | |||
| 4617 | stmt->content.set(nullptr); | 4814 | stmt->content.set(nullptr); |
| 4618 | auto next = it; | 4815 | auto next = it; |
| 4619 | ++next; | 4816 | ++next; |
| 4817 | Statement_t* nextStmt = nullptr; | ||
| 4818 | while (next != nodes.end()) { | ||
| 4819 | nextStmt = ast_cast<Statement_t>(*next); | ||
| 4820 | if (nextStmt) { | ||
| 4821 | break; | ||
| 4822 | } | ||
| 4823 | ++next; | ||
| 4824 | } | ||
| 4620 | BLOCK_START | 4825 | BLOCK_START |
| 4621 | BREAK_IF(next == nodes.end()); | 4826 | BREAK_IF(!nextStmt); |
| 4622 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>()); | 4827 | BREAK_IF(!nextStmt->content.as<PipeBody_t>()); |
| 4623 | throw CompileError("indent mismatch in pipe chain"sv, *next); | 4828 | throw CompileError("indent mismatch in pipe chain"sv, *next); |
| 4624 | BLOCK_END | 4829 | BLOCK_END |
| 4625 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { | 4830 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { |
| @@ -4627,7 +4832,7 @@ private: | |||
| 4627 | auto newBlock = x->new_ptr<Block_t>(); | 4832 | auto newBlock = x->new_ptr<Block_t>(); |
| 4628 | if (it != nodes.begin()) { | 4833 | if (it != nodes.begin()) { |
| 4629 | for (auto i = nodes.begin(); i != it; ++i) { | 4834 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4630 | newBlock->statements.push_back(*i); | 4835 | newBlock->statementOrComments.push_back(*i); |
| 4631 | } | 4836 | } |
| 4632 | } | 4837 | } |
| 4633 | x = backcall; | 4838 | x = backcall; |
| @@ -4638,7 +4843,7 @@ private: | |||
| 4638 | ++next; | 4843 | ++next; |
| 4639 | if (next != nodes.end()) { | 4844 | if (next != nodes.end()) { |
| 4640 | for (auto i = next; i != nodes.end(); ++i) { | 4845 | for (auto i = next; i != nodes.end(); ++i) { |
| 4641 | block->statements.push_back(*i); | 4846 | block->statementOrComments.push_back(*i); |
| 4642 | } | 4847 | } |
| 4643 | } | 4848 | } |
| 4644 | auto body = x->new_ptr<Body_t>(); | 4849 | auto body = x->new_ptr<Body_t>(); |
| @@ -4690,7 +4895,7 @@ private: | |||
| 4690 | expListAssign->expList.set(expList); | 4895 | expListAssign->expList.set(expList); |
| 4691 | newStmt->content.set(expListAssign); | 4896 | newStmt->content.set(expListAssign); |
| 4692 | newStmt->appendix.set(stmt->appendix); | 4897 | newStmt->appendix.set(stmt->appendix); |
| 4693 | newBlock->statements.push_back(newStmt); | 4898 | newBlock->statementOrComments.push_back(newStmt); |
| 4694 | } | 4899 | } |
| 4695 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4900 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4696 | return; | 4901 | return; |
| @@ -4717,7 +4922,7 @@ private: | |||
| 4717 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); | 4922 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); |
| 4718 | break; | 4923 | break; |
| 4719 | } | 4924 | } |
| 4720 | case id<CompInner_t>(): { | 4925 | case id<CompFor_t>(): { |
| 4721 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); | 4926 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); |
| 4722 | break; | 4927 | break; |
| 4723 | } | 4928 | } |
| @@ -4746,7 +4951,7 @@ private: | |||
| 4746 | auto newBlock = x->new_ptr<Block_t>(); | 4951 | auto newBlock = x->new_ptr<Block_t>(); |
| 4747 | if (it != nodes.begin()) { | 4952 | if (it != nodes.begin()) { |
| 4748 | for (auto i = nodes.begin(); i != it; ++i) { | 4953 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4749 | newBlock->statements.push_back(*i); | 4954 | newBlock->statementOrComments.push_back(*i); |
| 4750 | } | 4955 | } |
| 4751 | } | 4956 | } |
| 4752 | x = expListAssign; | 4957 | x = expListAssign; |
| @@ -4756,7 +4961,7 @@ private: | |||
| 4756 | ++next; | 4961 | ++next; |
| 4757 | if (next != nodes.end()) { | 4962 | if (next != nodes.end()) { |
| 4758 | for (auto i = next; i != nodes.end(); ++i) { | 4963 | for (auto i = next; i != nodes.end(); ++i) { |
| 4759 | followingBlock->statements.push_back(*i); | 4964 | followingBlock->statementOrComments.push_back(*i); |
| 4760 | } | 4965 | } |
| 4761 | } | 4966 | } |
| 4762 | } | 4967 | } |
| @@ -4784,17 +4989,13 @@ private: | |||
| 4784 | newAssignment->action.set(newAssign); | 4989 | newAssignment->action.set(newAssign); |
| 4785 | auto newStatement = x->new_ptr<Statement_t>(); | 4990 | auto newStatement = x->new_ptr<Statement_t>(); |
| 4786 | newStatement->content.set(newAssignment); | 4991 | newStatement->content.set(newAssignment); |
| 4787 | followingBlock->statements.push_front(newStatement); | 4992 | followingBlock->statementOrComments.push_front(newStatement); |
| 4788 | } | 4993 | } |
| 4789 | argNames.push_back("..."s); | 4994 | argNames.push_back("..."s); |
| 4790 | auto newBody = x->new_ptr<Body_t>(); | 4995 | auto newBody = x->new_ptr<Body_t>(); |
| 4791 | newBody->content.set(followingBlock); | 4996 | newBody->content.set(followingBlock); |
| 4792 | { | 4997 | { |
| 4793 | auto doNode = x->new_ptr<Do_t>(); | 4998 | if (auto result = upValueFuncFromBlock(followingBlock.get(), &argNames, false, true)) { |
| 4794 | doNode->body.set(newBody); | ||
| 4795 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 4796 | simpleValue->value.set(doNode); | ||
| 4797 | if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) { | ||
| 4798 | auto [funcName, args] = std::move(*result); | 4999 | auto [funcName, args] = std::move(*result); |
| 4799 | str_list finalArgs; | 5000 | str_list finalArgs; |
| 4800 | for (const auto& arg : args) { | 5001 | for (const auto& arg : args) { |
| @@ -4802,9 +5003,14 @@ private: | |||
| 4802 | finalArgs.push_back(arg); | 5003 | finalArgs.push_back(arg); |
| 4803 | } | 5004 | } |
| 4804 | } | 5005 | } |
| 4805 | newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x)); | 5006 | auto lastNewStmt = toAst<Statement_t>(funcName + ' ' + (finalArgs.empty() ? "nil"s : join(finalArgs, ","sv)), x); |
| 4806 | auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList); | 5007 | newBlock->statementOrComments.push_back(lastNewStmt); |
| 4807 | ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back())->args.dup(newInvoke->args); | 5008 | auto sVal = singleValueFrom(lastNewStmt->content.to<ExpListAssign_t>()->expList); |
| 5009 | auto invokArgs = ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back()); | ||
| 5010 | if (finalArgs.empty()) { | ||
| 5011 | invokArgs->args.clear(); | ||
| 5012 | } | ||
| 5013 | invokArgs->args.dup(newInvoke->args); | ||
| 4808 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5014 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4809 | return; | 5015 | return; |
| 4810 | } | 5016 | } |
| @@ -4829,7 +5035,7 @@ private: | |||
| 4829 | newItemListAssign->expList.set(newItemList); | 5035 | newItemListAssign->expList.set(newItemList); |
| 4830 | auto newItemStatement = x->new_ptr<Statement_t>(); | 5036 | auto newItemStatement = x->new_ptr<Statement_t>(); |
| 4831 | newItemStatement->content.set(newItemListAssign); | 5037 | newItemStatement->content.set(newItemListAssign); |
| 4832 | newBlock->statements.push_back(newItemStatement); | 5038 | newBlock->statementOrComments.push_back(newItemStatement); |
| 4833 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5039 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4834 | return; | 5040 | return; |
| 4835 | BLOCK_END | 5041 | BLOCK_END |
| @@ -4838,11 +5044,11 @@ private: | |||
| 4838 | auto newBlock = x->new_ptr<Block_t>(); | 5044 | auto newBlock = x->new_ptr<Block_t>(); |
| 4839 | if (it != nodes.begin()) { | 5045 | if (it != nodes.begin()) { |
| 4840 | for (auto i = nodes.begin(); i != it; ++i) { | 5046 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4841 | newBlock->statements.push_back(*i); | 5047 | newBlock->statementOrComments.push_back(*i); |
| 4842 | } | 5048 | } |
| 4843 | } | 5049 | } |
| 4844 | localAttrib->attrib.set(localAttrib->new_ptr<ConstAttrib_t>()); | 5050 | localAttrib->attrib.set(localAttrib->new_ptr<ConstAttrib_t>()); |
| 4845 | newBlock->statements.push_back(*it); | 5051 | newBlock->statementOrComments.push_back(*it); |
| 4846 | x = localAttrib; | 5052 | x = localAttrib; |
| 4847 | auto followingBlock = x->new_ptr<Block_t>(); | 5053 | auto followingBlock = x->new_ptr<Block_t>(); |
| 4848 | { | 5054 | { |
| @@ -4850,7 +5056,7 @@ private: | |||
| 4850 | ++next; | 5056 | ++next; |
| 4851 | if (next != nodes.end()) { | 5057 | if (next != nodes.end()) { |
| 4852 | for (auto i = next; i != nodes.end(); ++i) { | 5058 | for (auto i = next; i != nodes.end(); ++i) { |
| 4853 | followingBlock->statements.push_back(*i); | 5059 | followingBlock->statementOrComments.push_back(*i); |
| 4854 | } | 5060 | } |
| 4855 | } | 5061 | } |
| 4856 | } | 5062 | } |
| @@ -4872,13 +5078,13 @@ private: | |||
| 4872 | auto value = singleValueFrom(pCallExp); | 5078 | auto value = singleValueFrom(pCallExp); |
| 4873 | value->item.to<SimpleValue_t>()->value.to<Try_t>()->func.set(followingBlock); | 5079 | value->item.to<SimpleValue_t>()->value.to<Try_t>()->func.set(followingBlock); |
| 4874 | for (const auto& stmt : getCloses) { | 5080 | for (const auto& stmt : getCloses) { |
| 4875 | newBlock->statements.push_back(toAst<Statement_t>(stmt, x)); | 5081 | newBlock->statementOrComments.push_back(toAst<Statement_t>(stmt, x)); |
| 4876 | } | 5082 | } |
| 4877 | newBlock->statements.push_back(pCallStmt); | 5083 | newBlock->statementOrComments.push_back(pCallStmt); |
| 4878 | for (const auto& stmt : doCloses) { | 5084 | for (const auto& stmt : doCloses) { |
| 4879 | newBlock->statements.push_back(toAst<Statement_t>(stmt, x)); | 5085 | newBlock->statementOrComments.push_back(toAst<Statement_t>(stmt, x)); |
| 4880 | } | 5086 | } |
| 4881 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); | 5087 | newBlock->statementOrComments.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); |
| 4882 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5088 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4883 | return; | 5089 | return; |
| 4884 | } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); | 5090 | } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); |
| @@ -4887,7 +5093,7 @@ private: | |||
| 4887 | auto newBlock = x->new_ptr<Block_t>(); | 5093 | auto newBlock = x->new_ptr<Block_t>(); |
| 4888 | if (it != nodes.begin()) { | 5094 | if (it != nodes.begin()) { |
| 4889 | for (auto i = nodes.begin(); i != it; ++i) { | 5095 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4890 | newBlock->statements.push_back(*i); | 5096 | newBlock->statementOrComments.push_back(*i); |
| 4891 | } | 5097 | } |
| 4892 | } | 5098 | } |
| 4893 | auto doBackcall = static_cast<SubBackcall_t*>(expListAssign->action.get()); | 5099 | auto doBackcall = static_cast<SubBackcall_t*>(expListAssign->action.get()); |
| @@ -4904,12 +5110,11 @@ private: | |||
| 4904 | backcall->value.set(doBackcall->value); | 5110 | backcall->value.set(doBackcall->value); |
| 4905 | auto newStmt = backcall->new_ptr<Statement_t>(); | 5111 | auto newStmt = backcall->new_ptr<Statement_t>(); |
| 4906 | newStmt->content.set(backcall); | 5112 | newStmt->content.set(backcall); |
| 4907 | newStmt->comments.dup(stmt->comments); | ||
| 4908 | newStmt->appendix.set(stmt->appendix); | 5113 | newStmt->appendix.set(stmt->appendix); |
| 4909 | newBlock->statements.push_back(newStmt); | 5114 | newBlock->statementOrComments.push_back(newStmt); |
| 4910 | auto ait = it; | 5115 | auto ait = it; |
| 4911 | for (auto i = ++ait; i != nodes.end(); ++i) { | 5116 | for (auto i = ++ait; i != nodes.end(); ++i) { |
| 4912 | newBlock->statements.push_back(*i); | 5117 | newBlock->statementOrComments.push_back(*i); |
| 4913 | } | 5118 | } |
| 4914 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5119 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4915 | return; | 5120 | return; |
| @@ -5021,7 +5226,7 @@ private: | |||
| 5021 | } | 5226 | } |
| 5022 | } | 5227 | } |
| 5023 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { | 5228 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 5024 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : (_info.exportMetatable ? "=<>:{}"s : "={}"s)), block)); | 5229 | block->statementOrComments.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : (_info.exportMetatable ? "=<>:{}"s : "={}"s)), block)); |
| 5025 | } | 5230 | } |
| 5026 | switch (usage) { | 5231 | switch (usage) { |
| 5027 | case ExpUsage::Closure: | 5232 | case ExpUsage::Closure: |
| @@ -5058,7 +5263,7 @@ private: | |||
| 5058 | break; | 5263 | break; |
| 5059 | } | 5264 | } |
| 5060 | } | 5265 | } |
| 5061 | bool lastAssignable = (expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content)); | 5266 | bool lastAssignable = (expListFrom(last) || ast_is<For_t, While_t>(last->content)); |
| 5062 | if (lastAssignable) { | 5267 | if (lastAssignable) { |
| 5063 | auto x = last; | 5268 | auto x = last; |
| 5064 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 5269 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -5083,37 +5288,54 @@ private: | |||
| 5083 | } | 5288 | } |
| 5084 | if (!nodes.empty()) { | 5289 | if (!nodes.empty()) { |
| 5085 | str_list temp; | 5290 | str_list temp; |
| 5291 | auto lastStmt = lastStatementFrom(nodes); | ||
| 5086 | for (auto node : nodes) { | 5292 | for (auto node : nodes) { |
| 5087 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; | 5293 | if (auto comment = ast_cast<YueComment_t>(node)) { |
| 5088 | transformStatement(static_cast<Statement_t*>(node), temp); | 5294 | transformComment(comment, temp); |
| 5089 | if (isRoot && !_rootDefs.empty()) { | 5295 | continue; |
| 5090 | auto last = std::move(temp.back()); | 5296 | } |
| 5091 | temp.pop_back(); | 5297 | if (!ast_is<Statement_t>(node)) { |
| 5092 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); | 5298 | continue; |
| 5093 | _rootDefs.clear(); | 5299 | } |
| 5094 | temp.push_back(std::move(last)); | 5300 | auto transformNode = [&]() { |
| 5095 | } | 5301 | currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None; |
| 5096 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | 5302 | transformStatement(static_cast<Statement_t*>(node), temp); |
| 5097 | auto rit = ++temp.rbegin(); | 5303 | if (isRoot && !_rootDefs.empty()) { |
| 5098 | if (rit != temp.rend() && !rit->empty()) { | 5304 | auto last = std::move(temp.back()); |
| 5099 | auto index = std::string::npos; | 5305 | temp.pop_back(); |
| 5100 | if (_config.reserveLineNumber) { | 5306 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); |
| 5101 | index = rit->rfind(" -- "sv); | 5307 | _rootDefs.clear(); |
| 5102 | } else { | 5308 | temp.push_back(std::move(last)); |
| 5103 | index = rit->find_last_not_of('\n'); | 5309 | } |
| 5104 | if (index != std::string::npos) index++; | 5310 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { |
| 5105 | } | 5311 | auto rit = ++temp.rbegin(); |
| 5106 | if (index != std::string::npos) { | 5312 | if (rit != temp.rend() && !rit->empty()) { |
| 5107 | auto ending = rit->substr(0, index); | 5313 | auto index = std::string::npos; |
| 5108 | auto ind = ending.find_last_of(" \t\n"sv); | 5314 | if (_config.reserveLineNumber) { |
| 5109 | if (ind != std::string::npos) { | 5315 | index = rit->rfind(" -- "sv); |
| 5110 | ending = ending.substr(ind + 1); | 5316 | } else { |
| 5317 | index = rit->find_last_not_of('\n'); | ||
| 5318 | if (index != std::string::npos) index++; | ||
| 5111 | } | 5319 | } |
| 5112 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | 5320 | if (index != std::string::npos) { |
| 5113 | rit->insert(index, ";"sv); | 5321 | auto ending = rit->substr(0, index); |
| 5322 | auto ind = ending.find_last_of(" \t\n"sv); | ||
| 5323 | if (ind != std::string::npos) { | ||
| 5324 | ending = ending.substr(ind + 1); | ||
| 5325 | } | ||
| 5326 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
| 5327 | rit->insert(index, ";"sv); | ||
| 5328 | } | ||
| 5114 | } | 5329 | } |
| 5115 | } | 5330 | } |
| 5116 | } | 5331 | } |
| 5332 | }; | ||
| 5333 | if (_config.lax) { | ||
| 5334 | try { | ||
| 5335 | transformNode(); | ||
| 5336 | } catch (const CompileError&) { } | ||
| 5337 | } else { | ||
| 5338 | transformNode(); | ||
| 5117 | } | 5339 | } |
| 5118 | } | 5340 | } |
| 5119 | out.push_back(join(temp)); | 5341 | out.push_back(join(temp)); |
| @@ -5121,7 +5343,7 @@ private: | |||
| 5121 | out.push_back(Empty); | 5343 | out.push_back(Empty); |
| 5122 | } | 5344 | } |
| 5123 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { | 5345 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 5124 | out.back().append(indent() + "return "s + _info.moduleName + nlr(block)); | 5346 | out.back().append(indent() + "return "s + _info.moduleName + nl(block)); |
| 5125 | } | 5347 | } |
| 5126 | } | 5348 | } |
| 5127 | 5349 | ||
| @@ -5322,18 +5544,29 @@ private: | |||
| 5322 | auto macroLit = macro->decl.to<MacroLit_t>(); | 5544 | auto macroLit = macro->decl.to<MacroLit_t>(); |
| 5323 | auto argsDef = macroLit->argsDef.get(); | 5545 | auto argsDef = macroLit->argsDef.get(); |
| 5324 | str_list newArgs; | 5546 | str_list newArgs; |
| 5547 | str_list argChecks; | ||
| 5548 | bool hasCheck = false; | ||
| 5325 | if (argsDef) { | 5549 | if (argsDef) { |
| 5326 | for (auto def_ : argsDef->definitions.objects()) { | 5550 | for (auto def_ : argsDef->definitions.objects()) { |
| 5327 | auto def = static_cast<FnArgDef_t*>(def_); | 5551 | auto def = static_cast<FnArgDef_t*>(def_); |
| 5328 | if (def->name.is<SelfItem_t>()) { | 5552 | if (def->name.is<SelfItem_t>()) { |
| 5329 | throw CompileError("self name is not supported for macro function argument"sv, def->name); | 5553 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
| 5330 | } else { | 5554 | } else { |
| 5555 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5556 | if (def->label) { | ||
| 5557 | hasCheck = true; | ||
| 5558 | const auto& astName = argChecks.emplace_back(_parser.toString(def->label)); | ||
| 5559 | if (!_parser.hasAST(astName)) { | ||
| 5560 | throw CompileError("invalid AST name"sv, def->label); | ||
| 5561 | } | ||
| 5562 | } else { | ||
| 5563 | argChecks.emplace_back(); | ||
| 5564 | } | ||
| 5331 | std::string defVal; | 5565 | std::string defVal; |
| 5332 | if (def->defaultValue) { | 5566 | if (def->defaultValue) { |
| 5333 | defVal = _parser.toString(def->defaultValue); | 5567 | defVal = _parser.toString(def->defaultValue); |
| 5334 | Utils::trim(defVal); | 5568 | Utils::trim(defVal); |
| 5335 | defVal.insert(0, "=[==========["sv); | 5569 | defVal = '=' + Utils::toLuaDoubleString(defVal); |
| 5336 | defVal.append("]==========]"sv); | ||
| 5337 | } | 5570 | } |
| 5338 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | 5571 | newArgs.emplace_back(_parser.toString(def->name) + defVal); |
| 5339 | } | 5572 | } |
| @@ -5341,6 +5574,14 @@ private: | |||
| 5341 | if (argsDef->varArg) { | 5574 | if (argsDef->varArg) { |
| 5342 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | 5575 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); |
| 5343 | } | 5576 | } |
| 5577 | if (argsDef->label) { | ||
| 5578 | hasCheck = true; | ||
| 5579 | const auto& astName = _parser.toString(argsDef->label); | ||
| 5580 | if (!_parser.hasAST(astName)) { | ||
| 5581 | throw CompileError("invalid AST name"sv, argsDef->label); | ||
| 5582 | } | ||
| 5583 | argChecks.emplace_back("..."s + astName); | ||
| 5584 | } | ||
| 5344 | } | 5585 | } |
| 5345 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); | 5586 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); |
| 5346 | auto chunkName = "=(macro "s + macroName + ')'; | 5587 | auto chunkName = "=(macro "s + macroName + ')'; |
| @@ -5371,6 +5612,24 @@ private: | |||
| 5371 | throw CompileError("failed to generate macro function\n"s + err, macroLit); | 5612 | throw CompileError("failed to generate macro function\n"s + err, macroLit); |
| 5372 | } // cur true macro | 5613 | } // cur true macro |
| 5373 | lua_remove(L, -2); // cur macro | 5614 | lua_remove(L, -2); // cur macro |
| 5615 | if (hasCheck) { | ||
| 5616 | lua_createtable(L, 0, 0); // cur macro checks | ||
| 5617 | int i = 1; | ||
| 5618 | for (const auto& check : argChecks) { | ||
| 5619 | if (check.empty()) { | ||
| 5620 | lua_pushboolean(L, 0); | ||
| 5621 | lua_rawseti(L, -2, i); | ||
| 5622 | } else { | ||
| 5623 | lua_pushlstring(L, check.c_str(), check.size()); | ||
| 5624 | lua_rawseti(L, -2, i); | ||
| 5625 | } | ||
| 5626 | i++; | ||
| 5627 | } | ||
| 5628 | lua_createtable(L, 2, 0); // cur macro checks macrotab | ||
| 5629 | lua_insert(L, -3); // cur macrotab macro checks | ||
| 5630 | lua_rawseti(L, -3, 1); // macrotab[1] = checks, cur macrotab macro | ||
| 5631 | lua_rawseti(L, -2, 2); // macrotab[2] = macro, cur macrotab | ||
| 5632 | } // cur macro | ||
| 5374 | if (exporting && _config.exporting && !_config.module.empty()) { | 5633 | if (exporting && _config.exporting && !_config.module.empty()) { |
| 5375 | pushModuleTable(_config.module); // cur macro module | 5634 | pushModuleTable(_config.module); // cur macro module |
| 5376 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 5635 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
| @@ -5445,11 +5704,11 @@ private: | |||
| 5445 | case id<While_t>(): | 5704 | case id<While_t>(): |
| 5446 | transformWhileInPlace(static_cast<While_t*>(value), out); | 5705 | transformWhileInPlace(static_cast<While_t*>(value), out); |
| 5447 | return; | 5706 | return; |
| 5448 | case id<For_t>(): | 5707 | case id<Repeat_t>(): |
| 5449 | transformForInPlace(static_cast<For_t*>(value), out); | 5708 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out); |
| 5450 | return; | 5709 | return; |
| 5451 | case id<ForEach_t>(): | 5710 | case id<For_t>(): |
| 5452 | transformForEachInPlace(static_cast<ForEach_t*>(value), out); | 5711 | transformForInPlace(static_cast<For_t*>(value), out, nullptr); |
| 5453 | return; | 5712 | return; |
| 5454 | case id<If_t>(): | 5713 | case id<If_t>(): |
| 5455 | transformIf(static_cast<If_t*>(value), out, ExpUsage::Return); | 5714 | transformIf(static_cast<If_t*>(value), out, ExpUsage::Return); |
| @@ -5469,12 +5728,12 @@ private: | |||
| 5469 | } | 5728 | } |
| 5470 | } | 5729 | } |
| 5471 | transformValue(singleValue, out); | 5730 | transformValue(singleValue, out); |
| 5472 | out.back() = indent() + "return "s + out.back() + nlr(returnNode); | 5731 | out.back() = indent() + "return "s + out.back() + nl(returnNode); |
| 5473 | return; | 5732 | return; |
| 5474 | } else { | 5733 | } else { |
| 5475 | str_list temp; | 5734 | str_list temp; |
| 5476 | transformExpListLow(valueList, temp); | 5735 | transformExpListLow(valueList, temp); |
| 5477 | out.push_back(indent() + "return "s + temp.back() + nlr(returnNode)); | 5736 | out.push_back(indent() + "return "s + temp.back() + nl(returnNode)); |
| 5478 | } | 5737 | } |
| 5479 | } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { | 5738 | } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { |
| 5480 | const auto& values = tableBlock->values.objects(); | 5739 | const auto& values = tableBlock->values.objects(); |
| @@ -5482,10 +5741,10 @@ private: | |||
| 5482 | transformSpreadTable(values, out, ExpUsage::Return, nullptr, false); | 5741 | transformSpreadTable(values, out, ExpUsage::Return, nullptr, false); |
| 5483 | } else { | 5742 | } else { |
| 5484 | transformTable(values, out); | 5743 | transformTable(values, out); |
| 5485 | out.back() = indent() + "return "s + out.back() + nlr(returnNode); | 5744 | out.back() = indent() + "return "s + out.back() + nl(returnNode); |
| 5486 | } | 5745 | } |
| 5487 | } else { | 5746 | } else { |
| 5488 | out.push_back(indent() + "return"s + nll(returnNode)); | 5747 | out.push_back(indent() + "return"s + nl(returnNode)); |
| 5489 | } | 5748 | } |
| 5490 | } | 5749 | } |
| 5491 | 5750 | ||
| @@ -5516,6 +5775,7 @@ private: | |||
| 5516 | bool checkExistence = false; | 5775 | bool checkExistence = false; |
| 5517 | std::string name; | 5776 | std::string name; |
| 5518 | std::string assignSelf; | 5777 | std::string assignSelf; |
| 5778 | ast_ptr<false, ExpListAssign_t> assignment; | ||
| 5519 | }; | 5779 | }; |
| 5520 | std::list<ArgItem> argItems; | 5780 | std::list<ArgItem> argItems; |
| 5521 | str_list temp; | 5781 | str_list temp; |
| @@ -5525,7 +5785,11 @@ private: | |||
| 5525 | auto def = static_cast<FnArgDef_t*>(_def); | 5785 | auto def = static_cast<FnArgDef_t*>(_def); |
| 5526 | auto& arg = argItems.emplace_back(); | 5786 | auto& arg = argItems.emplace_back(); |
| 5527 | switch (def->name->get_id()) { | 5787 | switch (def->name->get_id()) { |
| 5528 | case id<Variable_t>(): arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); break; | 5788 | case id<Variable_t>(): { |
| 5789 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5790 | arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); | ||
| 5791 | break; | ||
| 5792 | } | ||
| 5529 | case id<SelfItem_t>(): { | 5793 | case id<SelfItem_t>(): { |
| 5530 | assignSelf = true; | 5794 | assignSelf = true; |
| 5531 | if (def->op) { | 5795 | if (def->op) { |
| @@ -5566,6 +5830,22 @@ private: | |||
| 5566 | } | 5830 | } |
| 5567 | break; | 5831 | break; |
| 5568 | } | 5832 | } |
| 5833 | case id<TableLit_t>(): { | ||
| 5834 | arg.name = getUnusedName("_arg_"sv); | ||
| 5835 | auto simpleValue = def->new_ptr<SimpleValue_t>(); | ||
| 5836 | simpleValue->value.set(def->name); | ||
| 5837 | auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def); | ||
| 5838 | arg.assignment = asmt; | ||
| 5839 | break; | ||
| 5840 | } | ||
| 5841 | case id<SimpleTable_t>(): { | ||
| 5842 | arg.name = getUnusedName("_arg_"sv); | ||
| 5843 | auto value = def->new_ptr<Value_t>(); | ||
| 5844 | value->item.set(def->name); | ||
| 5845 | auto asmt = assignmentFrom(newExp(value, def), toAst<Exp_t>(arg.name, def), def); | ||
| 5846 | arg.assignment = asmt; | ||
| 5847 | break; | ||
| 5848 | } | ||
| 5569 | default: YUEE("AST node mismatch", def->name.get()); break; | 5849 | default: YUEE("AST node mismatch", def->name.get()); break; |
| 5570 | } | 5850 | } |
| 5571 | forceAddToScope(arg.name); | 5851 | forceAddToScope(arg.name); |
| @@ -5579,23 +5859,46 @@ private: | |||
| 5579 | assignment->action.set(assign); | 5859 | assignment->action.set(assign); |
| 5580 | transformAssignment(assignment, temp); | 5860 | transformAssignment(assignment, temp); |
| 5581 | popScope(); | 5861 | popScope(); |
| 5582 | _buf << indent() << "if "sv << arg.name << " == nil then"sv << nll(def); | 5862 | _buf << indent() << "if "sv << arg.name << " == nil then"sv << nl(def); |
| 5583 | _buf << temp.back(); | 5863 | _buf << temp.back(); |
| 5584 | _buf << indent() << "end"sv << nll(def); | 5864 | _buf << indent() << "end"sv << nl(def); |
| 5585 | temp.back() = clearBuf(); | 5865 | temp.back() = clearBuf(); |
| 5586 | } | 5866 | } |
| 5587 | if (varNames.empty()) | 5867 | if (arg.assignment) { |
| 5868 | auto names = getArgDestructureList(arg.assignment); | ||
| 5869 | for (const auto& name : names) { | ||
| 5870 | forceAddToScope(name); | ||
| 5871 | } | ||
| 5872 | temp.emplace_back(indent() + "local "s + join(names, ", "sv) + nl(def)); | ||
| 5873 | transformAssignment(arg.assignment, temp); | ||
| 5874 | } | ||
| 5875 | if (varNames.empty()) { | ||
| 5588 | varNames = arg.name; | 5876 | varNames = arg.name; |
| 5589 | else | 5877 | } else { |
| 5590 | varNames.append(", "s + arg.name); | 5878 | varNames.append(", "s + arg.name); |
| 5879 | } | ||
| 5591 | } | 5880 | } |
| 5592 | if (argDefList->varArg) { | 5881 | if (argDefList->varArg) { |
| 5882 | std::string varStr; | ||
| 5883 | if (auto varName = argDefList->varArg->name.get()) { | ||
| 5884 | varStr = variableToString(varName); | ||
| 5885 | int target = getLuaTarget(varName); | ||
| 5886 | forceAddToScope(varStr); | ||
| 5887 | if (target < 505) { | ||
| 5888 | temp.push_back(indent() + "local "s + varStr + " = {"s + nl(varName)); | ||
| 5889 | temp.push_back(indent(1) + "n = "s + globalVar("select", varName, AccessType::Read) + "(\"#\", ...),"s + nl(varName)); | ||
| 5890 | temp.push_back(indent(1) + "..."s + nl(varName)); | ||
| 5891 | temp.push_back(indent() + '}' + nl(varName)); | ||
| 5892 | varStr.clear(); | ||
| 5893 | } | ||
| 5894 | } | ||
| 5593 | auto& arg = argItems.emplace_back(); | 5895 | auto& arg = argItems.emplace_back(); |
| 5594 | arg.name = "..."sv; | 5896 | arg.name = "..."sv; |
| 5595 | if (varNames.empty()) | 5897 | if (varNames.empty()) { |
| 5596 | varNames = arg.name; | 5898 | varNames = arg.name + varStr; |
| 5597 | else | 5899 | } else { |
| 5598 | varNames.append(", "s + arg.name); | 5900 | varNames.append(", "s + arg.name + varStr); |
| 5901 | } | ||
| 5599 | _varArgs.top().hasVar = true; | 5902 | _varArgs.top().hasVar = true; |
| 5600 | } | 5903 | } |
| 5601 | if (assignSelf) { | 5904 | if (assignSelf) { |
| @@ -5664,6 +5967,45 @@ private: | |||
| 5664 | } | 5967 | } |
| 5665 | } | 5968 | } |
| 5666 | 5969 | ||
| 5970 | bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
| 5971 | auto x = chainList.front(); | ||
| 5972 | if (ast_is<Slice_t>(chainList.back())) { | ||
| 5973 | auto comp = x->new_ptr<Comprehension_t>(); | ||
| 5974 | { | ||
| 5975 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
| 5976 | for (auto item : chainList) { | ||
| 5977 | chainValue->items.push_back(item); | ||
| 5978 | } | ||
| 5979 | auto itemVar = getUnusedName("_item_"sv); | ||
| 5980 | auto expCode = YueFormat{}.toString(chainValue); | ||
| 5981 | auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']'; | ||
| 5982 | comp.set(toAst<Comprehension_t>(compCode, x)); | ||
| 5983 | } | ||
| 5984 | switch (usage) { | ||
| 5985 | case ExpUsage::Assignment: { | ||
| 5986 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 5987 | simpleValue->value.set(comp); | ||
| 5988 | auto exp = newExp(simpleValue, x); | ||
| 5989 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 5990 | assignment->expList.set(assignList); | ||
| 5991 | auto assign = x->new_ptr<Assign_t>(); | ||
| 5992 | assign->values.push_back(exp); | ||
| 5993 | assignment->action.set(assign); | ||
| 5994 | transformAssignment(assignment, out); | ||
| 5995 | break; | ||
| 5996 | } | ||
| 5997 | case ExpUsage::Return: | ||
| 5998 | transformComprehension(comp, out, ExpUsage::Return); | ||
| 5999 | break; | ||
| 6000 | default: | ||
| 6001 | transformComprehension(comp, out, ExpUsage::Closure); | ||
| 6002 | break; | ||
| 6003 | } | ||
| 6004 | return true; | ||
| 6005 | } | ||
| 6006 | return false; | ||
| 6007 | } | ||
| 6008 | |||
| 5667 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | 6009 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
| 5668 | auto x = chainList.front(); | 6010 | auto x = chainList.front(); |
| 5669 | if (ast_is<ExistentialOp_t>(chainList.back())) { | 6011 | if (ast_is<ExistentialOp_t>(chainList.back())) { |
| @@ -5698,7 +6040,7 @@ private: | |||
| 5698 | case ExpUsage::Return: | 6040 | case ExpUsage::Return: |
| 5699 | transformParens(parens, out); | 6041 | transformParens(parens, out); |
| 5700 | out.back().insert(0, indent() + "return "s); | 6042 | out.back().insert(0, indent() + "return "s); |
| 5701 | out.back().append(nlr(x)); | 6043 | out.back().append(nl(x)); |
| 5702 | break; | 6044 | break; |
| 5703 | default: | 6045 | default: |
| 5704 | transformParens(parens, out); | 6046 | transformParens(parens, out); |
| @@ -5769,7 +6111,7 @@ private: | |||
| 5769 | } | 6111 | } |
| 5770 | } | 6112 | } |
| 5771 | if (isScoped) { | 6113 | if (isScoped) { |
| 5772 | temp.push_back(indent() + "do"s + nll(x)); | 6114 | temp.push_back(indent() + "do"s + nl(x)); |
| 5773 | pushScope(); | 6115 | pushScope(); |
| 5774 | } | 6116 | } |
| 5775 | objVar = getUnusedName("_obj_"sv); | 6117 | objVar = getUnusedName("_obj_"sv); |
| @@ -5829,9 +6171,9 @@ private: | |||
| 5829 | _buf << typeVar << "=type "sv << objVar; | 6171 | _buf << typeVar << "=type "sv << objVar; |
| 5830 | auto typeAssign = toAst<ExpListAssign_t>(clearBuf(), partOne); | 6172 | auto typeAssign = toAst<ExpListAssign_t>(clearBuf(), partOne); |
| 5831 | transformAssignment(typeAssign, temp); | 6173 | transformAssignment(typeAssign, temp); |
| 5832 | _buf << indent() << "if \"table\" == " << typeVar << " or \"userdata\" == "sv << typeVar << " then"sv << nll(x); | 6174 | _buf << indent() << "if \"table\" == " << typeVar << " or \"userdata\" == "sv << typeVar << " then"sv << nl(x); |
| 5833 | } else { | 6175 | } else { |
| 5834 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 6176 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 5835 | } | 6177 | } |
| 5836 | temp.push_back(clearBuf()); | 6178 | temp.push_back(clearBuf()); |
| 5837 | pushScope(); | 6179 | pushScope(); |
| @@ -5867,15 +6209,15 @@ private: | |||
| 5867 | } | 6209 | } |
| 5868 | } | 6210 | } |
| 5869 | popScope(); | 6211 | popScope(); |
| 5870 | temp.push_back(indent() + "end"s + nlr(x)); | 6212 | temp.push_back(indent() + "end"s + nl(x)); |
| 5871 | switch (usage) { | 6213 | switch (usage) { |
| 5872 | case ExpUsage::Return: | 6214 | case ExpUsage::Return: |
| 5873 | temp.push_back(indent() + "return nil"s + nlr(x)); | 6215 | temp.push_back(indent() + "return nil"s + nl(x)); |
| 5874 | break; | 6216 | break; |
| 5875 | case ExpUsage::Closure: | 6217 | case ExpUsage::Closure: |
| 5876 | temp.push_back(indent() + "return nil"s + nlr(x)); | 6218 | temp.push_back(indent() + "return nil"s + nl(x)); |
| 5877 | popScope(); | 6219 | popScope(); |
| 5878 | *funcStart = anonFuncStart() + nll(x); | 6220 | *funcStart = anonFuncStart() + nl(x); |
| 5879 | temp.push_back(indent() + anonFuncEnd()); | 6221 | temp.push_back(indent() + anonFuncEnd()); |
| 5880 | popAnonVarArg(); | 6222 | popAnonVarArg(); |
| 5881 | popFunctionScope(); | 6223 | popFunctionScope(); |
| @@ -5885,7 +6227,7 @@ private: | |||
| 5885 | } | 6227 | } |
| 5886 | if (isScoped) { | 6228 | if (isScoped) { |
| 5887 | popScope(); | 6229 | popScope(); |
| 5888 | temp.push_back(indent() + "end"s + nlr(x)); | 6230 | temp.push_back(indent() + "end"s + nl(x)); |
| 5889 | } | 6231 | } |
| 5890 | out.push_back(join(temp)); | 6232 | out.push_back(join(temp)); |
| 5891 | return true; | 6233 | return true; |
| @@ -5902,7 +6244,7 @@ private: | |||
| 5902 | switch (usage) { | 6244 | switch (usage) { |
| 5903 | case ExpUsage::Assignment: | 6245 | case ExpUsage::Assignment: |
| 5904 | if (isScoped) { | 6246 | if (isScoped) { |
| 5905 | temp.push_back(indent() + "do"s + nll(x)); | 6247 | temp.push_back(indent() + "do"s + nl(x)); |
| 5906 | pushScope(); | 6248 | pushScope(); |
| 5907 | } | 6249 | } |
| 5908 | break; | 6250 | break; |
| @@ -5980,12 +6322,12 @@ private: | |||
| 5980 | case ExpUsage::Assignment: | 6322 | case ExpUsage::Assignment: |
| 5981 | if (isScoped) { | 6323 | if (isScoped) { |
| 5982 | popScope(); | 6324 | popScope(); |
| 5983 | temp.push_back(indent() + "end"s + nlr(x)); | 6325 | temp.push_back(indent() + "end"s + nl(x)); |
| 5984 | } | 6326 | } |
| 5985 | break; | 6327 | break; |
| 5986 | case ExpUsage::Closure: | 6328 | case ExpUsage::Closure: |
| 5987 | popScope(); | 6329 | popScope(); |
| 5988 | *funcStart = anonFuncStart() + nll(x); | 6330 | *funcStart = anonFuncStart() + nl(x); |
| 5989 | temp.push_back(indent() + anonFuncEnd()); | 6331 | temp.push_back(indent() + anonFuncEnd()); |
| 5990 | popAnonVarArg(); | 6332 | popAnonVarArg(); |
| 5991 | popFunctionScope(); | 6333 | popFunctionScope(); |
| @@ -6061,7 +6403,7 @@ private: | |||
| 6061 | pushScope(); | 6403 | pushScope(); |
| 6062 | } else if (usage != ExpUsage::Return) { | 6404 | } else if (usage != ExpUsage::Return) { |
| 6063 | if (isScoped) { | 6405 | if (isScoped) { |
| 6064 | temp.push_back(indent() + "do"s + nll(x)); | 6406 | temp.push_back(indent() + "do"s + nl(x)); |
| 6065 | pushScope(); | 6407 | pushScope(); |
| 6066 | } | 6408 | } |
| 6067 | } | 6409 | } |
| @@ -6098,7 +6440,7 @@ private: | |||
| 6098 | returnNode->valueList.set(values); | 6440 | returnNode->valueList.set(values); |
| 6099 | transformReturn(returnNode, temp); | 6441 | transformReturn(returnNode, temp); |
| 6100 | popScope(); | 6442 | popScope(); |
| 6101 | *funcStart = anonFuncStart() + nll(x); | 6443 | *funcStart = anonFuncStart() + nl(x); |
| 6102 | temp.push_back(indent() + anonFuncEnd()); | 6444 | temp.push_back(indent() + anonFuncEnd()); |
| 6103 | popAnonVarArg(); | 6445 | popAnonVarArg(); |
| 6104 | popFunctionScope(); | 6446 | popFunctionScope(); |
| @@ -6122,7 +6464,7 @@ private: | |||
| 6122 | transformAssignment(assignment, temp); | 6464 | transformAssignment(assignment, temp); |
| 6123 | if (isScoped) { | 6465 | if (isScoped) { |
| 6124 | popScope(); | 6466 | popScope(); |
| 6125 | temp.push_back(indent() + "end"s + nlr(x)); | 6467 | temp.push_back(indent() + "end"s + nl(x)); |
| 6126 | } | 6468 | } |
| 6127 | break; | 6469 | break; |
| 6128 | } | 6470 | } |
| @@ -6130,7 +6472,7 @@ private: | |||
| 6130 | transformExp(newChainExp, temp, usage); | 6472 | transformExp(newChainExp, temp, usage); |
| 6131 | if (isScoped) { | 6473 | if (isScoped) { |
| 6132 | popScope(); | 6474 | popScope(); |
| 6133 | temp.push_back(indent() + "end"s + nlr(x)); | 6475 | temp.push_back(indent() + "end"s + nl(x)); |
| 6134 | } | 6476 | } |
| 6135 | break; | 6477 | break; |
| 6136 | } | 6478 | } |
| @@ -6181,7 +6523,7 @@ private: | |||
| 6181 | case id<ColonChainItem_t>(): | 6523 | case id<ColonChainItem_t>(): |
| 6182 | case id<Exp_t>(): | 6524 | case id<Exp_t>(): |
| 6183 | if (_withVars.empty()) { | 6525 | if (_withVars.empty()) { |
| 6184 | throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); | 6526 | throw CompileError("short dot/colon/indexing syntax must be called within a with block"sv, x); |
| 6185 | } else { | 6527 | } else { |
| 6186 | temp.push_back(_withVars.top()); | 6528 | temp.push_back(_withVars.top()); |
| 6187 | } | 6529 | } |
| @@ -6235,7 +6577,7 @@ private: | |||
| 6235 | assignment->action.set(assign); | 6577 | assignment->action.set(assign); |
| 6236 | auto stmt = x->new_ptr<Statement_t>(); | 6578 | auto stmt = x->new_ptr<Statement_t>(); |
| 6237 | stmt->content.set(assignment); | 6579 | stmt->content.set(assignment); |
| 6238 | block->statements.push_back(stmt); | 6580 | block->statementOrComments.push_back(stmt); |
| 6239 | } | 6581 | } |
| 6240 | } | 6582 | } |
| 6241 | ast_ptr<false, Exp_t> nexp; | 6583 | ast_ptr<false, Exp_t> nexp; |
| @@ -6281,7 +6623,7 @@ private: | |||
| 6281 | expListAssign->expList.set(expList); | 6623 | expListAssign->expList.set(expList); |
| 6282 | auto stmt = x->new_ptr<Statement_t>(); | 6624 | auto stmt = x->new_ptr<Statement_t>(); |
| 6283 | stmt->content.set(expListAssign); | 6625 | stmt->content.set(expListAssign); |
| 6284 | block->statements.push_back(stmt); | 6626 | block->statementOrComments.push_back(stmt); |
| 6285 | } | 6627 | } |
| 6286 | switch (usage) { | 6628 | switch (usage) { |
| 6287 | case ExpUsage::Common: | 6629 | case ExpUsage::Common: |
| @@ -6295,7 +6637,7 @@ private: | |||
| 6295 | default: | 6637 | default: |
| 6296 | break; | 6638 | break; |
| 6297 | } | 6639 | } |
| 6298 | if (block->statements.size() == 1) { | 6640 | if (block->statementOrComments.size() == 1) { |
| 6299 | transformExp(nexp, out, usage, assignList); | 6641 | transformExp(nexp, out, usage, assignList); |
| 6300 | } else { | 6642 | } else { |
| 6301 | auto body = x->new_ptr<Body_t>(); | 6643 | auto body = x->new_ptr<Body_t>(); |
| @@ -6327,6 +6669,120 @@ private: | |||
| 6327 | } | 6669 | } |
| 6328 | return; | 6670 | return; |
| 6329 | } | 6671 | } |
| 6672 | break; | ||
| 6673 | } | ||
| 6674 | case id<ReversedIndex_t>(): { | ||
| 6675 | auto rIndex = static_cast<ReversedIndex_t*>(*it); | ||
| 6676 | auto current = it; | ||
| 6677 | auto prevChain = x->new_ptr<ChainValue_t>(); | ||
| 6678 | for (auto i = chainList.begin(); i != current; ++i) { | ||
| 6679 | prevChain->items.push_back(*i); | ||
| 6680 | } | ||
| 6681 | auto var = singleVariableFrom(prevChain, AccessType::None); | ||
| 6682 | if (!var.empty() && isLocal(var)) { | ||
| 6683 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | ||
| 6684 | if (rIndex->modifier) { | ||
| 6685 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6686 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6687 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6688 | indexNode->opValues.push_back(opValue); | ||
| 6689 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6690 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6691 | } | ||
| 6692 | prevChain->items.push_back(indexNode); | ||
| 6693 | auto next = current; | ||
| 6694 | ++next; | ||
| 6695 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6696 | prevChain->items.push_back(*i); | ||
| 6697 | } | ||
| 6698 | if (usage == ExpUsage::Assignment) { | ||
| 6699 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6700 | assignment->expList.set(assignList); | ||
| 6701 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6702 | assign->values.push_back(newExp(prevChain, x)); | ||
| 6703 | assignment->action.set(assign); | ||
| 6704 | transformAssignment(assignment, out); | ||
| 6705 | return; | ||
| 6706 | } | ||
| 6707 | transformChainValue(prevChain, out, usage, assignList); | ||
| 6708 | return; | ||
| 6709 | } else { | ||
| 6710 | auto itemVar = getUnusedName("_item_"sv); | ||
| 6711 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | ||
| 6712 | auto stmt1 = x->new_ptr<Statement_t>(); | ||
| 6713 | stmt1->content.set(asmt); | ||
| 6714 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
| 6715 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | ||
| 6716 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | ||
| 6717 | if (rIndex->modifier) { | ||
| 6718 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6719 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6720 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6721 | indexNode->opValues.push_back(opValue); | ||
| 6722 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6723 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6724 | } | ||
| 6725 | newChain->items.push_back(indexNode); | ||
| 6726 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 6727 | expList->exprs.push_back(newExp(newChain, x)); | ||
| 6728 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
| 6729 | expListAssign->expList.set(expList); | ||
| 6730 | auto stmt2 = x->new_ptr<Statement_t>(); | ||
| 6731 | stmt2->content.set(expListAssign); | ||
| 6732 | auto block = x->new_ptr<Block_t>(); | ||
| 6733 | block->statementOrComments.push_back(stmt1); | ||
| 6734 | block->statementOrComments.push_back(stmt2); | ||
| 6735 | auto body = x->new_ptr<Body_t>(); | ||
| 6736 | body->content.set(block); | ||
| 6737 | auto doNode = x->new_ptr<Do_t>(); | ||
| 6738 | doNode->body.set(body); | ||
| 6739 | if (usage == ExpUsage::Assignment) { | ||
| 6740 | auto next = current; | ||
| 6741 | ++next; | ||
| 6742 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6743 | newChain->items.push_back(*i); | ||
| 6744 | } | ||
| 6745 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6746 | assignment->expList.set(assignList); | ||
| 6747 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6748 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 6749 | sVal->value.set(doNode); | ||
| 6750 | assign->values.push_back(newExp(sVal, x)); | ||
| 6751 | assignment->action.set(assign); | ||
| 6752 | transformAssignment(assignment, out); | ||
| 6753 | return; | ||
| 6754 | } | ||
| 6755 | if (usage == ExpUsage::Closure) { | ||
| 6756 | auto next = current; | ||
| 6757 | ++next; | ||
| 6758 | if (next != chainList.end()) { | ||
| 6759 | doNode->new_ptr<ChainValue_t>(); | ||
| 6760 | auto dVal = doNode->new_ptr<SimpleValue_t>(); | ||
| 6761 | dVal->value.set(doNode); | ||
| 6762 | auto dExp = newExp(dVal, dVal); | ||
| 6763 | auto dParen = dExp->new_ptr<Parens_t>(); | ||
| 6764 | dParen->extra = true; | ||
| 6765 | dParen->expr.set(dExp); | ||
| 6766 | auto dCallable = dExp->new_ptr<Callable_t>(); | ||
| 6767 | dCallable->item.set(dParen); | ||
| 6768 | auto dChain = doNode->new_ptr<ChainValue_t>(); | ||
| 6769 | dChain->items.push_back(dCallable); | ||
| 6770 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6771 | dChain->items.push_back(*i); | ||
| 6772 | } | ||
| 6773 | transformExp(newExp(dChain, dExp), out, usage); | ||
| 6774 | return; | ||
| 6775 | } | ||
| 6776 | } | ||
| 6777 | auto next = current; | ||
| 6778 | ++next; | ||
| 6779 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6780 | newChain->items.push_back(*i); | ||
| 6781 | } | ||
| 6782 | transformDo(doNode, out, usage); | ||
| 6783 | return; | ||
| 6784 | } | ||
| 6785 | break; | ||
| 6330 | } | 6786 | } |
| 6331 | } | 6787 | } |
| 6332 | } | 6788 | } |
| @@ -6376,10 +6832,10 @@ private: | |||
| 6376 | } | 6832 | } |
| 6377 | switch (usage) { | 6833 | switch (usage) { |
| 6378 | case ExpUsage::Common: | 6834 | case ExpUsage::Common: |
| 6379 | out.push_back(indent() + join(temp) + nll(x)); | 6835 | out.push_back(indent() + join(temp) + nl(x)); |
| 6380 | break; | 6836 | break; |
| 6381 | case ExpUsage::Return: | 6837 | case ExpUsage::Return: |
| 6382 | out.push_back(indent() + "return "s + join(temp) + nll(x)); | 6838 | out.push_back(indent() + "return "s + join(temp) + nl(x)); |
| 6383 | break; | 6839 | break; |
| 6384 | case ExpUsage::Assignment: YUEE("invalid expression usage", x); break; | 6840 | case ExpUsage::Assignment: YUEE("invalid expression usage", x); break; |
| 6385 | default: | 6841 | default: |
| @@ -6511,7 +6967,7 @@ private: | |||
| 6511 | } | 6967 | } |
| 6512 | } | 6968 | } |
| 6513 | } | 6969 | } |
| 6514 | int len = lua_objlen(L, -1); | 6970 | int len = static_cast<int>(lua_objlen(L, -1)); |
| 6515 | lua_pushnil(L); // cur nil | 6971 | lua_pushnil(L); // cur nil |
| 6516 | for (int i = len; i >= 1; i--) { | 6972 | for (int i = len; i >= 1; i--) { |
| 6517 | lua_pop(L, 1); // cur | 6973 | lua_pop(L, 1); // cur |
| @@ -6523,7 +6979,25 @@ private: | |||
| 6523 | break; | 6979 | break; |
| 6524 | } | 6980 | } |
| 6525 | } | 6981 | } |
| 6526 | if (!lua_isfunction(L, -1)) { | 6982 | str_list checks; |
| 6983 | if (lua_istable(L, -1)) { | ||
| 6984 | lua_rawgeti(L, -1, 1); // cur macrotab checks | ||
| 6985 | int len = static_cast<int>(lua_objlen(L, -1)); | ||
| 6986 | for (int i = 1; i <= len; i++) { | ||
| 6987 | lua_rawgeti(L, -1, i); | ||
| 6988 | if (lua_toboolean(L, -1) == 0) { | ||
| 6989 | checks.emplace_back(); | ||
| 6990 | } else { | ||
| 6991 | size_t str_len = 0; | ||
| 6992 | auto str = lua_tolstring(L, -1, &str_len); | ||
| 6993 | checks.emplace_back(std::string{str, str_len}); | ||
| 6994 | } | ||
| 6995 | lua_pop(L, 1); | ||
| 6996 | } | ||
| 6997 | lua_pop(L, 1); | ||
| 6998 | lua_rawgeti(L, -1, 2); // cur macrotab macroFunc | ||
| 6999 | lua_remove(L, -2); // cur macroFunc | ||
| 7000 | } else if (!lua_isfunction(L, -1)) { | ||
| 6527 | auto code = expandBuiltinMacro(macroName, x); | 7001 | auto code = expandBuiltinMacro(macroName, x); |
| 6528 | if (!code.empty()) return code; | 7002 | if (!code.empty()) return code; |
| 6529 | if (macroName == "is_ast"sv) { | 7003 | if (macroName == "is_ast"sv) { |
| @@ -6568,11 +7042,34 @@ private: | |||
| 6568 | } // cur macroFunc | 7042 | } // cur macroFunc |
| 6569 | pushYue("pcall"sv); // cur macroFunc pcall | 7043 | pushYue("pcall"sv); // cur macroFunc pcall |
| 6570 | lua_insert(L, -2); // cur pcall macroFunc | 7044 | lua_insert(L, -2); // cur pcall macroFunc |
| 6571 | if (!lua_checkstack(L, argStrs.size())) { | 7045 | if (!lua_checkstack(L, static_cast<int>(argStrs.size()))) { |
| 6572 | throw CompileError("too much macro params"s, x); | 7046 | throw CompileError("too much macro params"s, x); |
| 6573 | } | 7047 | } |
| 7048 | auto checkIt = checks.begin(); | ||
| 7049 | node_container::const_iterator argIt; | ||
| 7050 | if (args) { | ||
| 7051 | argIt = args->begin(); | ||
| 7052 | } | ||
| 6574 | for (const auto& arg : argStrs) { | 7053 | for (const auto& arg : argStrs) { |
| 7054 | if (checkIt != checks.end()) { | ||
| 7055 | if (checkIt->empty()) { | ||
| 7056 | ++checkIt; | ||
| 7057 | } else { | ||
| 7058 | if ((*checkIt)[0] == '.') { | ||
| 7059 | auto astName = checkIt->substr(3); | ||
| 7060 | if (!_parser.match(astName, arg)) { | ||
| 7061 | throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); | ||
| 7062 | } | ||
| 7063 | } else { | ||
| 7064 | if (!_parser.match(*checkIt, arg)) { | ||
| 7065 | throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); | ||
| 7066 | } | ||
| 7067 | ++checkIt; | ||
| 7068 | } | ||
| 7069 | } | ||
| 7070 | } | ||
| 6575 | lua_pushlstring(L, arg.c_str(), arg.size()); | 7071 | lua_pushlstring(L, arg.c_str(), arg.size()); |
| 7072 | ++argIt; | ||
| 6576 | } // cur pcall macroFunc args... | 7073 | } // cur pcall macroFunc args... |
| 6577 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; | 7074 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; |
| 6578 | if (!success) { // cur err | 7075 | if (!success) { // cur err |
| @@ -6664,8 +7161,8 @@ private: | |||
| 6664 | throw CompileError("lua macro is not expanding to valid block\n"s + err, x); | 7161 | throw CompileError("lua macro is not expanding to valid block\n"s + err, x); |
| 6665 | } | 7162 | } |
| 6666 | if (!codes.empty()) { | 7163 | if (!codes.empty()) { |
| 6667 | codes.insert(0, indent() + "do"s + nll(chainValue)); | 7164 | codes.insert(0, indent() + "do"s + nl(chainValue)); |
| 6668 | codes.append(_newLine + indent() + "end"s + nlr(chainValue)); | 7165 | codes.append(_newLine + indent() + "end"s + nl(chainValue)); |
| 6669 | } | 7166 | } |
| 6670 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; | 7167 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
| 6671 | } else { | 7168 | } else { |
| @@ -6702,14 +7199,14 @@ private: | |||
| 6702 | } else { | 7199 | } else { |
| 6703 | if (!codes.empty()) { | 7200 | if (!codes.empty()) { |
| 6704 | if (isBlock) { | 7201 | if (isBlock) { |
| 6705 | info = _parser.parse<BlockEnd_t>(codes); | 7202 | info = _parser.parse<BlockEnd_t>(codes, false); |
| 6706 | if (info.error) { | 7203 | if (info.error) { |
| 6707 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); | 7204 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); |
| 6708 | } | 7205 | } |
| 6709 | } else { | 7206 | } else { |
| 6710 | info = _parser.parse<Exp_t>(codes); | 7207 | info = _parser.parse<Exp_t>(codes, false); |
| 6711 | if (!info.node && allowBlockMacroReturn) { | 7208 | if (!info.node && allowBlockMacroReturn) { |
| 6712 | info = _parser.parse<BlockEnd_t>(codes); | 7209 | info = _parser.parse<BlockEnd_t>(codes, false); |
| 6713 | if (info.error) { | 7210 | if (info.error) { |
| 6714 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); | 7211 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); |
| 6715 | } | 7212 | } |
| @@ -6754,7 +7251,7 @@ private: | |||
| 6754 | auto stmt = x->new_ptr<Statement_t>(); | 7251 | auto stmt = x->new_ptr<Statement_t>(); |
| 6755 | stmt->content.set(exps); | 7252 | stmt->content.set(exps); |
| 6756 | auto block = x->new_ptr<Block_t>(); | 7253 | auto block = x->new_ptr<Block_t>(); |
| 6757 | block->statements.push_back(stmt); | 7254 | block->statementOrComments.push_back(stmt); |
| 6758 | info.node.set(block); | 7255 | info.node.set(block); |
| 6759 | } else { | 7256 | } else { |
| 6760 | info.node.set(exp); | 7257 | info.node.set(exp); |
| @@ -6791,7 +7288,7 @@ private: | |||
| 6791 | return; | 7288 | return; |
| 6792 | } | 7289 | } |
| 6793 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { | 7290 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { |
| 6794 | if (node.to<Block_t>()->statements.empty()) { | 7291 | if (node.to<Block_t>()->statementOrComments.empty()) { |
| 6795 | out.push_back(Empty); | 7292 | out.push_back(Empty); |
| 6796 | } else { | 7293 | } else { |
| 6797 | auto doBody = node->new_ptr<Body_t>(); | 7294 | auto doBody = node->new_ptr<Body_t>(); |
| @@ -6845,6 +7342,9 @@ private: | |||
| 6845 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 7342 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
| 6846 | return; | 7343 | return; |
| 6847 | } | 7344 | } |
| 7345 | if (transformChainEndWithSlice(chainList, out, usage, assignList)) { | ||
| 7346 | return; | ||
| 7347 | } | ||
| 6848 | transformChainList(chainList, out, usage, assignList); | 7348 | transformChainList(chainList, out, usage, assignList); |
| 6849 | } | 7349 | } |
| 6850 | 7350 | ||
| @@ -6941,7 +7441,7 @@ private: | |||
| 6941 | } | 7441 | } |
| 6942 | } | 7442 | } |
| 6943 | } else if (auto comp = sval->value.as<Comprehension_t>()) { | 7443 | } else if (auto comp = sval->value.as<Comprehension_t>()) { |
| 6944 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 7444 | if (!isListComp(comp)) { |
| 6945 | discrete = inExp->new_ptr<ExpList_t>(); | 7445 | discrete = inExp->new_ptr<ExpList_t>(); |
| 6946 | for (ast_node* val : comp->items.objects()) { | 7446 | for (ast_node* val : comp->items.objects()) { |
| 6947 | if (auto def = ast_cast<NormalDef_t>(val)) { | 7447 | if (auto def = ast_cast<NormalDef_t>(val)) { |
| @@ -6970,7 +7470,7 @@ private: | |||
| 6970 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); | 7470 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); |
| 6971 | auto stmt = x->new_ptr<Statement_t>(); | 7471 | auto stmt = x->new_ptr<Statement_t>(); |
| 6972 | stmt->content.set(assignment); | 7472 | stmt->content.set(assignment); |
| 6973 | block->statements.push_back(stmt); | 7473 | block->statementOrComments.push_back(stmt); |
| 6974 | } | 7474 | } |
| 6975 | if (varName.empty()) { | 7475 | if (varName.empty()) { |
| 6976 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | 7476 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); |
| @@ -6982,7 +7482,7 @@ private: | |||
| 6982 | auto assignment = assignmentFrom(assignExp, exp, x); | 7482 | auto assignment = assignmentFrom(assignExp, exp, x); |
| 6983 | auto stmt = x->new_ptr<Statement_t>(); | 7483 | auto stmt = x->new_ptr<Statement_t>(); |
| 6984 | stmt->content.set(assignment); | 7484 | stmt->content.set(assignment); |
| 6985 | block->statements.push_back(stmt); | 7485 | block->statementOrComments.push_back(stmt); |
| 6986 | } | 7486 | } |
| 6987 | auto findVar = getUnusedName("_find_"); | 7487 | auto findVar = getUnusedName("_find_"); |
| 6988 | auto itemVar = getUnusedName("_item_"); | 7488 | auto itemVar = getUnusedName("_item_"); |
| @@ -6998,7 +7498,7 @@ private: | |||
| 6998 | } | 7498 | } |
| 6999 | auto blockStr = clearBuf(); | 7499 | auto blockStr = clearBuf(); |
| 7000 | auto checkBlock = toAst<Block_t>(blockStr, inExp); | 7500 | auto checkBlock = toAst<Block_t>(blockStr, inExp); |
| 7001 | block->statements.dup(checkBlock->statements); | 7501 | block->statementOrComments.dup(checkBlock->statementOrComments); |
| 7002 | auto body = x->new_ptr<Body_t>(); | 7502 | auto body = x->new_ptr<Body_t>(); |
| 7003 | body->content.set(block); | 7503 | body->content.set(block); |
| 7004 | auto doNode = x->new_ptr<Do_t>(); | 7504 | auto doNode = x->new_ptr<Do_t>(); |
| @@ -7018,16 +7518,16 @@ private: | |||
| 7018 | } else { | 7518 | } else { |
| 7019 | auto arrayCheck = [&](bool exist) { | 7519 | auto arrayCheck = [&](bool exist) { |
| 7020 | auto indexVar = getUnusedName("_index_"); | 7520 | auto indexVar = getUnusedName("_index_"); |
| 7021 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); | 7521 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nl(x); |
| 7022 | incIndentOffset(); | 7522 | incIndentOffset(); |
| 7023 | _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); | 7523 | _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nl(x); |
| 7024 | incIndentOffset(); | 7524 | incIndentOffset(); |
| 7025 | _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x); | 7525 | _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nl(x); |
| 7026 | decIndentOffset(); | 7526 | decIndentOffset(); |
| 7027 | _buf << indent() << "end"sv << nll(x); | 7527 | _buf << indent() << "end"sv << nl(x); |
| 7028 | decIndentOffset(); | 7528 | decIndentOffset(); |
| 7029 | _buf << indent() << "end"sv << nll(x); | 7529 | _buf << indent() << "end"sv << nl(x); |
| 7030 | _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x); | 7530 | _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nl(x); |
| 7031 | temp.push_back(clearBuf()); | 7531 | temp.push_back(clearBuf()); |
| 7032 | }; | 7532 | }; |
| 7033 | bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); | 7533 | bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); |
| @@ -7043,7 +7543,7 @@ private: | |||
| 7043 | pushAnonVarArg(); | 7543 | pushAnonVarArg(); |
| 7044 | pushScope(); | 7544 | pushScope(); |
| 7045 | arrayCheck(true); | 7545 | arrayCheck(true); |
| 7046 | temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); | 7546 | temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nl(x)); |
| 7047 | popScope(); | 7547 | popScope(); |
| 7048 | temp.push_back(indent() + anonFuncEnd() + ')'); | 7548 | temp.push_back(indent() + anonFuncEnd() + ')'); |
| 7049 | if (unary_exp->inExp->not_) { | 7549 | if (unary_exp->inExp->not_) { |
| @@ -7080,7 +7580,7 @@ private: | |||
| 7080 | arrayCheck(!unary_exp->inExp->not_); | 7580 | arrayCheck(!unary_exp->inExp->not_); |
| 7081 | } else { | 7581 | } else { |
| 7082 | arrayCheck(!unary_exp->inExp->not_); | 7582 | arrayCheck(!unary_exp->inExp->not_); |
| 7083 | temp.push_front(anonFuncStart() + nll(x)); | 7583 | temp.push_front(anonFuncStart() + nl(x)); |
| 7084 | popScope(); | 7584 | popScope(); |
| 7085 | temp.push_back(indent() + anonFuncEnd()); | 7585 | temp.push_back(indent() + anonFuncEnd()); |
| 7086 | popAnonVarArg(); | 7586 | popAnonVarArg(); |
| @@ -7120,7 +7620,7 @@ private: | |||
| 7120 | pushScope(); | 7620 | pushScope(); |
| 7121 | } else if (usage == ExpUsage::Assignment) { | 7621 | } else if (usage == ExpUsage::Assignment) { |
| 7122 | if (isScoped) { | 7622 | if (isScoped) { |
| 7123 | temp.push_back(indent() + "do"s + nll(x)); | 7623 | temp.push_back(indent() + "do"s + nl(x)); |
| 7124 | pushScope(); | 7624 | pushScope(); |
| 7125 | } | 7625 | } |
| 7126 | } | 7626 | } |
| @@ -7160,10 +7660,10 @@ private: | |||
| 7160 | if (unary_exp->inExp->not_) { | 7660 | if (unary_exp->inExp->not_) { |
| 7161 | _buf << ")"sv; | 7661 | _buf << ")"sv; |
| 7162 | } | 7662 | } |
| 7163 | _buf << nll(x); | 7663 | _buf << nl(x); |
| 7164 | temp.push_back(clearBuf()); | 7664 | temp.push_back(clearBuf()); |
| 7165 | if (usage == ExpUsage::Closure) { | 7665 | if (usage == ExpUsage::Closure) { |
| 7166 | temp.push_front(anonFuncStart() + nll(x)); | 7666 | temp.push_front(anonFuncStart() + nl(x)); |
| 7167 | popScope(); | 7667 | popScope(); |
| 7168 | temp.push_back(indent() + anonFuncEnd()); | 7668 | temp.push_back(indent() + anonFuncEnd()); |
| 7169 | out.push_back(join(temp)); | 7669 | out.push_back(join(temp)); |
| @@ -7172,7 +7672,7 @@ private: | |||
| 7172 | } else if (usage == ExpUsage::Assignment) { | 7672 | } else if (usage == ExpUsage::Assignment) { |
| 7173 | if (isScoped) { | 7673 | if (isScoped) { |
| 7174 | popScope(); | 7674 | popScope(); |
| 7175 | temp.push_back(indent() + "end"s + nll(x)); | 7675 | temp.push_back(indent() + "end"s + nl(x)); |
| 7176 | } | 7676 | } |
| 7177 | out.push_back(join(temp)); | 7677 | out.push_back(join(temp)); |
| 7178 | } else { | 7678 | } else { |
| @@ -7206,7 +7706,7 @@ private: | |||
| 7206 | } | 7706 | } |
| 7207 | _buf << ')'; | 7707 | _buf << ')'; |
| 7208 | if (usage == ExpUsage::Assignment || usage == ExpUsage::Return) { | 7708 | if (usage == ExpUsage::Assignment || usage == ExpUsage::Return) { |
| 7209 | _buf << nll(discrete); | 7709 | _buf << nl(discrete); |
| 7210 | } | 7710 | } |
| 7211 | out.push_back(clearBuf()); | 7711 | out.push_back(clearBuf()); |
| 7212 | } | 7712 | } |
| @@ -7326,7 +7826,7 @@ private: | |||
| 7326 | forceAddToScope(tableVar); | 7826 | forceAddToScope(tableVar); |
| 7327 | auto it = values.begin(); | 7827 | auto it = values.begin(); |
| 7328 | if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 7828 | if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { |
| 7329 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 7829 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nl(x)); |
| 7330 | } else { | 7830 | } else { |
| 7331 | auto initialTab = x->new_ptr<TableLit_t>(); | 7831 | auto initialTab = x->new_ptr<TableLit_t>(); |
| 7332 | while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 7832 | while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { |
| @@ -7334,7 +7834,7 @@ private: | |||
| 7334 | ++it; | 7834 | ++it; |
| 7335 | } | 7835 | } |
| 7336 | transformTable(initialTab->values.objects(), temp); | 7836 | transformTable(initialTab->values.objects(), temp); |
| 7337 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); | 7837 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nl(*it); |
| 7338 | } | 7838 | } |
| 7339 | for (; it != values.end(); ++it) { | 7839 | for (; it != values.end(); ++it) { |
| 7340 | auto item = *it; | 7840 | auto item = *it; |
| @@ -7354,14 +7854,14 @@ private: | |||
| 7354 | transformAssignment(assignment, temp); | 7854 | transformAssignment(assignment, temp); |
| 7355 | } | 7855 | } |
| 7356 | forceAddToScope(indexVar); | 7856 | forceAddToScope(indexVar); |
| 7357 | temp.push_back(indent() + "local "s + indexVar + " = 1"s + nll(item)); | 7857 | temp.push_back(indent() + "local "s + indexVar + " = 1"s + nl(item)); |
| 7358 | _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar | 7858 | _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar |
| 7359 | << "\n\tif "sv << indexVar << "=="sv << keyVar | 7859 | << "\n\tif "sv << indexVar << "=="sv << keyVar |
| 7360 | << "\n\t\t"sv << tableVar << "[]="sv << valueVar | 7860 | << "\n\t\t"sv << tableVar << "[]="sv << valueVar |
| 7361 | << "\n\t\t"sv << indexVar << "+=1"sv | 7861 | << "\n\t\t"sv << indexVar << "+=1"sv |
| 7362 | << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; | 7862 | << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; |
| 7363 | auto forEach = toAst<ForEach_t>(clearBuf(), item); | 7863 | auto forNode = toAst<For_t>(clearBuf(), item); |
| 7364 | transformForEach(forEach, temp); | 7864 | transformFor(forNode, temp); |
| 7365 | break; | 7865 | break; |
| 7366 | } | 7866 | } |
| 7367 | case id<SpreadListExp_t>(): { | 7867 | case id<SpreadListExp_t>(): { |
| @@ -7378,12 +7878,12 @@ private: | |||
| 7378 | transformAssignment(assignment, temp); | 7878 | transformAssignment(assignment, temp); |
| 7379 | } | 7879 | } |
| 7380 | forceAddToScope(indexVar); | 7880 | forceAddToScope(indexVar); |
| 7381 | temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nll(item)); | 7881 | temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nl(item)); |
| 7382 | _buf << "for "sv << valueVar << " in *"sv << objVar | 7882 | _buf << "for "sv << valueVar << " in *"sv << objVar |
| 7383 | << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar | 7883 | << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar |
| 7384 | << "\n\t"sv << indexVar << "+=1"sv; | 7884 | << "\n\t"sv << indexVar << "+=1"sv; |
| 7385 | auto forEach = toAst<ForEach_t>(clearBuf(), item); | 7885 | auto forNode = toAst<For_t>(clearBuf(), item); |
| 7386 | transformForEach(forEach, temp); | 7886 | transformFor(forNode, temp); |
| 7387 | break; | 7887 | break; |
| 7388 | } | 7888 | } |
| 7389 | case id<VariablePair_t>(): | 7889 | case id<VariablePair_t>(): |
| @@ -7561,9 +8061,9 @@ private: | |||
| 7561 | break; | 8061 | break; |
| 7562 | case ExpUsage::Closure: { | 8062 | case ExpUsage::Closure: { |
| 7563 | out.push_back(join(temp)); | 8063 | out.push_back(join(temp)); |
| 7564 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 8064 | out.back().append(indent() + "return "s + tableVar + nl(x)); |
| 7565 | popScope(); | 8065 | popScope(); |
| 7566 | out.back().insert(0, anonFuncStart() + nll(x)); | 8066 | out.back().insert(0, anonFuncStart() + nl(x)); |
| 7567 | out.back().append(indent() + anonFuncEnd()); | 8067 | out.back().append(indent() + anonFuncEnd()); |
| 7568 | popAnonVarArg(); | 8068 | popAnonVarArg(); |
| 7569 | popFunctionScope(); | 8069 | popFunctionScope(); |
| @@ -7579,13 +8079,13 @@ private: | |||
| 7579 | if (extraScope) popScope(); | 8079 | if (extraScope) popScope(); |
| 7580 | out.push_back(join(temp)); | 8080 | out.push_back(join(temp)); |
| 7581 | if (extraScope) { | 8081 | if (extraScope) { |
| 7582 | out.back() = indent() + "do"s + nll(x) + out.back() + indent() + "end"s + nlr(x); | 8082 | out.back() = indent() + "do"s + nl(x) + out.back() + indent() + "end"s + nl(x); |
| 7583 | } | 8083 | } |
| 7584 | break; | 8084 | break; |
| 7585 | } | 8085 | } |
| 7586 | case ExpUsage::Return: | 8086 | case ExpUsage::Return: |
| 7587 | out.push_back(join(temp)); | 8087 | out.push_back(join(temp)); |
| 7588 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 8088 | out.back().append(indent() + "return "s + tableVar + nl(x)); |
| 7589 | break; | 8089 | break; |
| 7590 | default: | 8090 | default: |
| 7591 | break; | 8091 | break; |
| @@ -7706,11 +8206,11 @@ private: | |||
| 7706 | default: YUEE("AST node mismatch", item); break; | 8206 | default: YUEE("AST node mismatch", item); break; |
| 7707 | } | 8207 | } |
| 7708 | if (!isMetamethod) { | 8208 | if (!isMetamethod) { |
| 7709 | temp.back() = indent() + (value == values.back() ? temp.back() : temp.back() + ',') + nll(value); | 8209 | temp.back() = indent() + (value == values.back() ? temp.back() : temp.back() + ',') + nl(value); |
| 7710 | } | 8210 | } |
| 7711 | } | 8211 | } |
| 7712 | if (metatable->pairs.empty() && !metatableItem) { | 8212 | if (metatable->pairs.empty() && !metatableItem) { |
| 7713 | out.push_back('{' + nll(x) + join(temp)); | 8213 | out.push_back('{' + nl(x) + join(temp)); |
| 7714 | decIndentOffset(); | 8214 | decIndentOffset(); |
| 7715 | out.back() += (indent() + '}'); | 8215 | out.back() += (indent() + '}'); |
| 7716 | } else { | 8216 | } else { |
| @@ -7720,7 +8220,7 @@ private: | |||
| 7720 | decIndentOffset(); | 8220 | decIndentOffset(); |
| 7721 | tabStr += "{ }"sv; | 8221 | tabStr += "{ }"sv; |
| 7722 | } else { | 8222 | } else { |
| 7723 | tabStr += ('{' + nll(x) + join(temp)); | 8223 | tabStr += ('{' + nl(x) + join(temp)); |
| 7724 | decIndentOffset(); | 8224 | decIndentOffset(); |
| 7725 | tabStr += (indent() + '}'); | 8225 | tabStr += (indent() + '}'); |
| 7726 | } | 8226 | } |
| @@ -7764,18 +8264,18 @@ private: | |||
| 7764 | void transformCompCommon(Comprehension_t* comp, str_list& out) { | 8264 | void transformCompCommon(Comprehension_t* comp, str_list& out) { |
| 7765 | str_list temp; | 8265 | str_list temp; |
| 7766 | auto x = comp; | 8266 | auto x = comp; |
| 7767 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | 8267 | auto compFor = static_cast<CompFor_t*>(comp->items.back()); |
| 7768 | for (auto item : compInner->items.objects()) { | 8268 | for (auto item : compFor->items.objects()) { |
| 7769 | switch (item->get_id()) { | 8269 | switch (item->get_id()) { |
| 7770 | case id<CompForEach_t>(): | 8270 | case id<CompForEach_t>(): |
| 7771 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 8271 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 7772 | break; | 8272 | break; |
| 7773 | case id<CompFor_t>(): | 8273 | case id<CompForNum_t>(): |
| 7774 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 8274 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 7775 | break; | 8275 | break; |
| 7776 | case id<Exp_t>(): | 8276 | case id<Exp_t>(): |
| 7777 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 8277 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 7778 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 8278 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 7779 | pushScope(); | 8279 | pushScope(); |
| 7780 | break; | 8280 | break; |
| 7781 | default: YUEE("AST node mismatch", item); break; | 8281 | default: YUEE("AST node mismatch", item); break; |
| @@ -7795,16 +8295,16 @@ private: | |||
| 7795 | auto value = std::move(temp.back()); | 8295 | auto value = std::move(temp.back()); |
| 7796 | temp.pop_back(); | 8296 | temp.pop_back(); |
| 7797 | _buf << join(temp) << value; | 8297 | _buf << join(temp) << value; |
| 7798 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 8298 | for (size_t i = 0; i < compFor->items.objects().size(); ++i) { |
| 7799 | popScope(); | 8299 | popScope(); |
| 7800 | _buf << indent() << "end"sv << nll(comp); | 8300 | _buf << indent() << "end"sv << nl(comp); |
| 7801 | } | 8301 | } |
| 7802 | out.push_back(clearBuf()); | 8302 | out.push_back(clearBuf()); |
| 7803 | } | 8303 | } |
| 7804 | 8304 | ||
| 7805 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8305 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 7806 | auto x = comp; | 8306 | auto x = comp; |
| 7807 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 8307 | if (!isListComp(comp)) { |
| 7808 | switch (usage) { | 8308 | switch (usage) { |
| 7809 | case ExpUsage::Assignment: { | 8309 | case ExpUsage::Assignment: { |
| 7810 | auto tableLit = x->new_ptr<TableLit_t>(); | 8310 | auto tableLit = x->new_ptr<TableLit_t>(); |
| @@ -7843,9 +8343,16 @@ private: | |||
| 7843 | } | 8343 | } |
| 7844 | return; | 8344 | return; |
| 7845 | } | 8345 | } |
| 7846 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | 8346 | ast_node* value = nullptr; |
| 7847 | if (!def || def->defVal) { | 8347 | bool isSpread = ast_is<SpreadListExp_t>(comp->items.front()); |
| 7848 | throw CompileError("invalid comprehension expression", comp->items.front()); | 8348 | if (isSpread) { |
| 8349 | value = comp->items.front(); | ||
| 8350 | } else { | ||
| 8351 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | ||
| 8352 | if (!def || def->defVal) { | ||
| 8353 | throw CompileError("invalid comprehension expression", comp->items.front()); | ||
| 8354 | } | ||
| 8355 | value = def->item.get(); | ||
| 7849 | } | 8356 | } |
| 7850 | bool extraScope = false; | 8357 | bool extraScope = false; |
| 7851 | switch (usage) { | 8358 | switch (usage) { |
| @@ -7869,31 +8376,33 @@ private: | |||
| 7869 | default: | 8376 | default: |
| 7870 | break; | 8377 | break; |
| 7871 | } | 8378 | } |
| 7872 | auto value = def->item.get(); | 8379 | auto compFor = static_cast<CompFor_t*>(comp->items.back()); |
| 7873 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | ||
| 7874 | str_list temp; | 8380 | str_list temp; |
| 7875 | std::string accumVar = getUnusedName("_accum_"sv); | 8381 | std::string accumVar = getUnusedName("_accum_"sv); |
| 7876 | std::string lenVar = getUnusedName("_len_"sv); | ||
| 7877 | addToScope(accumVar); | 8382 | addToScope(accumVar); |
| 7878 | addToScope(lenVar); | 8383 | std::string lenVar; |
| 7879 | for (auto item : compInner->items.objects()) { | 8384 | if (!isSpread) { |
| 8385 | lenVar = getUnusedName("_len_"sv); | ||
| 8386 | addToScope(lenVar); | ||
| 8387 | } | ||
| 8388 | for (auto item : compFor->items.objects()) { | ||
| 7880 | switch (item->get_id()) { | 8389 | switch (item->get_id()) { |
| 7881 | case id<CompForEach_t>(): | 8390 | case id<CompForEach_t>(): |
| 7882 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 8391 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 7883 | break; | 8392 | break; |
| 7884 | case id<CompFor_t>(): | 8393 | case id<CompForNum_t>(): |
| 7885 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 8394 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 7886 | break; | 8395 | break; |
| 7887 | case id<Exp_t>(): | 8396 | case id<Exp_t>(): |
| 7888 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 8397 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 7889 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 8398 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 7890 | pushScope(); | 8399 | pushScope(); |
| 7891 | break; | 8400 | break; |
| 7892 | default: YUEE("AST node mismatch", item); break; | 8401 | default: YUEE("AST node mismatch", item); break; |
| 7893 | } | 8402 | } |
| 7894 | } | 8403 | } |
| 7895 | { | 8404 | { |
| 7896 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 8405 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + (isSpread ? "]"s : lenVar + ']'), x); |
| 7897 | auto assign = x->new_ptr<Assign_t>(); | 8406 | auto assign = x->new_ptr<Assign_t>(); |
| 7898 | assign->values.push_back(value); | 8407 | assign->values.push_back(value); |
| 7899 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8408 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -7903,25 +8412,30 @@ private: | |||
| 7903 | } | 8412 | } |
| 7904 | auto assignStr = std::move(temp.back()); | 8413 | auto assignStr = std::move(temp.back()); |
| 7905 | temp.pop_back(); | 8414 | temp.pop_back(); |
| 7906 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 8415 | for (size_t i = 0; i < compFor->items.objects().size(); ++i) { |
| 7907 | popScope(); | 8416 | popScope(); |
| 7908 | } | 8417 | } |
| 7909 | _buf << indent() << "local "sv << accumVar << " = { }"sv << nll(comp); | 8418 | _buf << indent() << "local "sv << accumVar << " = { }"sv << nl(comp); |
| 7910 | _buf << indent() << "local "sv << lenVar << " = 1"sv << nll(comp); | 8419 | if (isSpread) { |
| 7911 | _buf << join(temp); | 8420 | _buf << join(temp); |
| 7912 | _buf << assignStr; | 8421 | _buf << assignStr; |
| 7913 | _buf << indent(int(temp.size())) << lenVar << " = "sv << lenVar << " + 1"sv << nll(comp); | 8422 | } else { |
| 8423 | _buf << indent() << "local "sv << lenVar << " = 1"sv << nl(comp); | ||
| 8424 | _buf << join(temp); | ||
| 8425 | _buf << assignStr; | ||
| 8426 | _buf << indent(int(temp.size())) << lenVar << " = "sv << lenVar << " + 1"sv << nl(comp); | ||
| 8427 | } | ||
| 7914 | for (int ind = int(temp.size()) - 1; ind > -1; --ind) { | 8428 | for (int ind = int(temp.size()) - 1; ind > -1; --ind) { |
| 7915 | _buf << indent(ind) << "end"sv << nll(comp); | 8429 | _buf << indent(ind) << "end"sv << nl(comp); |
| 7916 | } | 8430 | } |
| 7917 | switch (usage) { | 8431 | switch (usage) { |
| 7918 | case ExpUsage::Common: | 8432 | case ExpUsage::Common: |
| 7919 | break; | 8433 | break; |
| 7920 | case ExpUsage::Closure: { | 8434 | case ExpUsage::Closure: { |
| 7921 | out.push_back(clearBuf()); | 8435 | out.push_back(clearBuf()); |
| 7922 | out.back().append(indent() + "return "s + accumVar + nlr(comp)); | 8436 | out.back().append(indent() + "return "s + accumVar + nl(comp)); |
| 7923 | popScope(); | 8437 | popScope(); |
| 7924 | out.back().insert(0, anonFuncStart() + nll(comp)); | 8438 | out.back().insert(0, anonFuncStart() + nl(comp)); |
| 7925 | out.back().append(indent() + anonFuncEnd()); | 8439 | out.back().append(indent() + anonFuncEnd()); |
| 7926 | popAnonVarArg(); | 8440 | popAnonVarArg(); |
| 7927 | popFunctionScope(); | 8441 | popFunctionScope(); |
| @@ -7938,13 +8452,13 @@ private: | |||
| 7938 | out.back().append(temp.back()); | 8452 | out.back().append(temp.back()); |
| 7939 | if (extraScope) { | 8453 | if (extraScope) { |
| 7940 | popScope(); | 8454 | popScope(); |
| 7941 | out.back() = indent() + "do"s + nll(comp) + out.back() + indent() + "end"s + nlr(comp); | 8455 | out.back() = indent() + "do"s + nl(comp) + out.back() + indent() + "end"s + nl(comp); |
| 7942 | } | 8456 | } |
| 7943 | break; | 8457 | break; |
| 7944 | } | 8458 | } |
| 7945 | case ExpUsage::Return: | 8459 | case ExpUsage::Return: |
| 7946 | out.push_back(clearBuf()); | 8460 | out.push_back(clearBuf()); |
| 7947 | out.back().append(indent() + "return "s + accumVar + nlr(comp)); | 8461 | out.back().append(indent() + "return "s + accumVar + nl(comp)); |
| 7948 | break; | 8462 | break; |
| 7949 | default: | 8463 | default: |
| 7950 | break; | 8464 | break; |
| @@ -7952,6 +8466,11 @@ private: | |||
| 7952 | } | 8466 | } |
| 7953 | 8467 | ||
| 7954 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { | 8468 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { |
| 8469 | enum class NumState { | ||
| 8470 | Unknown, | ||
| 8471 | Positive, | ||
| 8472 | Negtive | ||
| 8473 | }; | ||
| 7955 | auto x = nameList; | 8474 | auto x = nameList; |
| 7956 | str_list temp; | 8475 | str_list temp; |
| 7957 | str_list vars; | 8476 | str_list vars; |
| @@ -7970,13 +8489,8 @@ private: | |||
| 7970 | varConstAfter = vars.back(); | 8489 | varConstAfter = vars.back(); |
| 7971 | } | 8490 | } |
| 7972 | break; | 8491 | break; |
| 7973 | case id<TableLit_t>(): { | 8492 | case id<SimpleTable_t>(): |
| 7974 | auto desVar = getUnusedName("_des_"sv); | 8493 | case id<TableLit_t>(): |
| 7975 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); | ||
| 7976 | vars.push_back(desVar); | ||
| 7977 | varAfter.push_back(desVar); | ||
| 7978 | break; | ||
| 7979 | } | ||
| 7980 | case id<Comprehension_t>(): { | 8494 | case id<Comprehension_t>(): { |
| 7981 | auto desVar = getUnusedName("_des_"sv); | 8495 | auto desVar = getUnusedName("_des_"sv); |
| 7982 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); | 8496 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); |
| @@ -8018,15 +8532,35 @@ private: | |||
| 8018 | for (auto item : chainList) { | 8532 | for (auto item : chainList) { |
| 8019 | chain->items.push_back(item); | 8533 | chain->items.push_back(item); |
| 8020 | } | 8534 | } |
| 8021 | std::string startValue("1"sv); | 8535 | std::string startValue; |
| 8536 | NumState startStatus = NumState::Unknown; | ||
| 8022 | if (auto exp = slice->startValue.as<Exp_t>()) { | 8537 | if (auto exp = slice->startValue.as<Exp_t>()) { |
| 8023 | transformExp(exp, temp, ExpUsage::Closure); | 8538 | transformExp(exp, temp, ExpUsage::Closure); |
| 8539 | if (temp.back().at(0) == '-') { | ||
| 8540 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
| 8541 | startStatus = NumState::Negtive; | ||
| 8542 | } | ||
| 8543 | } else { | ||
| 8544 | if (_parser.match<Num_t>(temp.back())) { | ||
| 8545 | startStatus = NumState::Positive; | ||
| 8546 | } | ||
| 8547 | } | ||
| 8024 | startValue = std::move(temp.back()); | 8548 | startValue = std::move(temp.back()); |
| 8025 | temp.pop_back(); | 8549 | temp.pop_back(); |
| 8026 | } | 8550 | } |
| 8027 | std::string stopValue; | 8551 | std::string stopValue; |
| 8552 | NumState stopStatus = NumState::Unknown; | ||
| 8028 | if (auto exp = slice->stopValue.as<Exp_t>()) { | 8553 | if (auto exp = slice->stopValue.as<Exp_t>()) { |
| 8029 | transformExp(exp, temp, ExpUsage::Closure); | 8554 | transformExp(exp, temp, ExpUsage::Closure); |
| 8555 | if (temp.back().at(0) == '-') { | ||
| 8556 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
| 8557 | stopStatus = NumState::Negtive; | ||
| 8558 | } | ||
| 8559 | } else { | ||
| 8560 | if (_parser.match<Num_t>(temp.back())) { | ||
| 8561 | stopStatus = NumState::Positive; | ||
| 8562 | } | ||
| 8563 | } | ||
| 8030 | stopValue = std::move(temp.back()); | 8564 | stopValue = std::move(temp.back()); |
| 8031 | temp.pop_back(); | 8565 | temp.pop_back(); |
| 8032 | } | 8566 | } |
| @@ -8040,38 +8574,94 @@ private: | |||
| 8040 | std::string prefix; | 8574 | std::string prefix; |
| 8041 | if (!inClosure && needScope) { | 8575 | if (!inClosure && needScope) { |
| 8042 | extraScope = true; | 8576 | extraScope = true; |
| 8043 | prefix = indent() + "do"s + nll(x); | 8577 | prefix = indent() + "do"s + nl(x); |
| 8044 | pushScope(); | 8578 | pushScope(); |
| 8045 | } | 8579 | } |
| 8046 | listVar = getUnusedName("_list_"sv); | 8580 | listVar = getUnusedName("_list_"sv); |
| 8047 | varBefore.push_back(listVar); | 8581 | varBefore.push_back(listVar); |
| 8048 | transformChainValue(chain, temp, ExpUsage::Closure); | 8582 | transformChainValue(chain, temp, ExpUsage::Closure); |
| 8049 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8583 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nl(nameList); |
| 8584 | } | ||
| 8585 | if (startValue.empty()) { | ||
| 8586 | startValue = "1"s; | ||
| 8587 | startStatus = NumState::Positive; | ||
| 8588 | } | ||
| 8589 | std::string minVar; | ||
| 8590 | if (startStatus != NumState::Positive) { | ||
| 8591 | std::string prefix; | ||
| 8592 | if (!extraScope && !inClosure && needScope) { | ||
| 8593 | extraScope = true; | ||
| 8594 | prefix = indent() + "do"s + nl(x); | ||
| 8595 | pushScope(); | ||
| 8596 | } | ||
| 8597 | minVar = getUnusedName("_min_"sv); | ||
| 8598 | varBefore.push_back(minVar); | ||
| 8599 | if (startStatus == NumState::Negtive) { | ||
| 8600 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << "#"sv << listVar << " + "sv << startValue << " + 1"sv << nl(nameList); | ||
| 8601 | } else { | ||
| 8602 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << startValue << nl(nameList); | ||
| 8603 | } | ||
| 8604 | } | ||
| 8605 | bool defaultStop = false; | ||
| 8606 | if (stopValue.empty()) { | ||
| 8607 | stopValue = "#"s + listVar; | ||
| 8608 | defaultStop = true; | ||
| 8050 | } | 8609 | } |
| 8051 | std::string maxVar; | 8610 | std::string maxVar; |
| 8052 | if (!stopValue.empty()) { | 8611 | if (stopStatus != NumState::Positive) { |
| 8053 | std::string prefix; | 8612 | std::string prefix; |
| 8054 | if (!extraScope && !inClosure && needScope) { | 8613 | if (!extraScope && !inClosure && needScope) { |
| 8055 | extraScope = true; | 8614 | extraScope = true; |
| 8056 | prefix = indent() + "do"s + nll(x); | 8615 | prefix = indent() + "do"s + nl(x); |
| 8057 | pushScope(); | 8616 | pushScope(); |
| 8058 | } | 8617 | } |
| 8059 | maxVar = getUnusedName("_max_"sv); | 8618 | maxVar = getUnusedName("_max_"sv); |
| 8060 | varBefore.push_back(maxVar); | 8619 | varBefore.push_back(maxVar); |
| 8061 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | 8620 | if (stopStatus == NumState::Negtive) { |
| 8621 | _buf << indent() << "local "sv << maxVar << " = "sv << "#"sv << listVar << " + "sv << stopValue << " + 1"sv << nl(nameList); | ||
| 8622 | } else { | ||
| 8623 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nl(nameList); | ||
| 8624 | } | ||
| 8625 | } | ||
| 8626 | if (startStatus == NumState::Unknown) { | ||
| 8627 | _buf << indent() << minVar << " = "sv << minVar << " < 0 and #"sv << listVar << " + "sv << minVar << " + 1 or "sv << minVar << nl(nameList); | ||
| 8628 | } | ||
| 8629 | if (!defaultStop && stopStatus == NumState::Unknown) { | ||
| 8630 | _buf << indent() << maxVar << " = "sv << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar << nl(nameList); | ||
| 8062 | } | 8631 | } |
| 8063 | _buf << indent() << "for "sv << indexVar << " = "sv; | 8632 | _buf << indent() << "for "sv << indexVar << " = "sv; |
| 8064 | _buf << startValue << ", "sv; | 8633 | if (startValue.empty()) { |
| 8634 | _buf << "1"sv; | ||
| 8635 | } else { | ||
| 8636 | switch (startStatus) { | ||
| 8637 | case NumState::Unknown: | ||
| 8638 | case NumState::Negtive: | ||
| 8639 | _buf << minVar; | ||
| 8640 | break; | ||
| 8641 | case NumState::Positive: | ||
| 8642 | _buf << startValue; | ||
| 8643 | break; | ||
| 8644 | } | ||
| 8645 | } | ||
| 8646 | _buf << ", "sv; | ||
| 8065 | if (stopValue.empty()) { | 8647 | if (stopValue.empty()) { |
| 8066 | _buf << "#"sv << listVar; | 8648 | _buf << "#"sv << listVar; |
| 8067 | } else { | 8649 | } else { |
| 8068 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; | 8650 | switch (stopStatus) { |
| 8651 | case NumState::Unknown: | ||
| 8652 | case NumState::Negtive: | ||
| 8653 | _buf << maxVar; | ||
| 8654 | break; | ||
| 8655 | case NumState::Positive: | ||
| 8656 | _buf << stopValue; | ||
| 8657 | break; | ||
| 8658 | } | ||
| 8069 | } | 8659 | } |
| 8070 | if (!stepValue.empty()) { | 8660 | if (!stepValue.empty()) { |
| 8071 | _buf << ", "sv << stepValue; | 8661 | _buf << ", "sv << stepValue; |
| 8072 | } | 8662 | } |
| 8073 | _buf << " do"sv << nlr(loopTarget); | 8663 | _buf << " do"sv << nl(loopTarget); |
| 8074 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); | 8664 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nl(nameList); |
| 8075 | out.push_back(clearBuf()); | 8665 | out.push_back(clearBuf()); |
| 8076 | BLOCK_END | 8666 | BLOCK_END |
| 8077 | bool newListVal = false; | 8667 | bool newListVal = false; |
| @@ -8082,21 +8672,21 @@ private: | |||
| 8082 | } | 8672 | } |
| 8083 | if (!endWithSlice) { | 8673 | if (!endWithSlice) { |
| 8084 | transformExp(star_exp->value, temp, ExpUsage::Closure); | 8674 | transformExp(star_exp->value, temp, ExpUsage::Closure); |
| 8085 | if (newListVal) _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8675 | if (newListVal) _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nl(nameList); |
| 8086 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << listVar << " do"sv << nlr(loopTarget); | 8676 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << listVar << " do"sv << nl(loopTarget); |
| 8087 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); | 8677 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nl(nameList); |
| 8088 | out.push_back(clearBuf()); | 8678 | out.push_back(clearBuf()); |
| 8089 | } | 8679 | } |
| 8090 | break; | 8680 | break; |
| 8091 | } | 8681 | } |
| 8092 | case id<Exp_t>(): | 8682 | case id<Exp_t>(): |
| 8093 | transformExp(static_cast<Exp_t*>(loopTarget), temp, ExpUsage::Closure); | 8683 | transformExp(static_cast<Exp_t*>(loopTarget), temp, ExpUsage::Closure); |
| 8094 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); | 8684 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nl(loopTarget); |
| 8095 | out.push_back(clearBuf()); | 8685 | out.push_back(clearBuf()); |
| 8096 | break; | 8686 | break; |
| 8097 | case id<ExpList_t>(): | 8687 | case id<ExpList_t>(): |
| 8098 | transformExpList(static_cast<ExpList_t*>(loopTarget), temp); | 8688 | transformExpList(static_cast<ExpList_t*>(loopTarget), temp); |
| 8099 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); | 8689 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nl(loopTarget); |
| 8100 | out.push_back(clearBuf()); | 8690 | out.push_back(clearBuf()); |
| 8101 | break; | 8691 | break; |
| 8102 | default: YUEE("AST node mismatch", loopTarget); break; | 8692 | default: YUEE("AST node mismatch", loopTarget); break; |
| @@ -8109,11 +8699,18 @@ private: | |||
| 8109 | if (!destructPairs.empty()) { | 8699 | if (!destructPairs.empty()) { |
| 8110 | temp.clear(); | 8700 | temp.clear(); |
| 8111 | for (auto& pair : destructPairs) { | 8701 | for (auto& pair : destructPairs) { |
| 8112 | auto sValue = x->new_ptr<SimpleValue_t>(); | ||
| 8113 | sValue->value.set(pair.first); | ||
| 8114 | auto exp = newExp(sValue, x); | ||
| 8115 | auto expList = x->new_ptr<ExpList_t>(); | 8702 | auto expList = x->new_ptr<ExpList_t>(); |
| 8116 | expList->exprs.push_back(exp); | 8703 | if (ast_is<SimpleTable_t>(pair.first)) { |
| 8704 | auto value = x->new_ptr<Value_t>(); | ||
| 8705 | value->item.set(pair.first); | ||
| 8706 | auto exp = newExp(value, x); | ||
| 8707 | expList->exprs.push_back(exp); | ||
| 8708 | } else { | ||
| 8709 | auto sValue = x->new_ptr<SimpleValue_t>(); | ||
| 8710 | sValue->value.set(pair.first); | ||
| 8711 | auto exp = newExp(sValue, x); | ||
| 8712 | expList->exprs.push_back(exp); | ||
| 8713 | } | ||
| 8117 | auto assign = x->new_ptr<Assign_t>(); | 8714 | auto assign = x->new_ptr<Assign_t>(); |
| 8118 | assign->values.push_back(pair.second); | 8715 | assign->values.push_back(pair.second); |
| 8119 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8716 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -8173,7 +8770,7 @@ private: | |||
| 8173 | out.push_back('(' + join(temp, ", "sv) + ')'); | 8770 | out.push_back('(' + join(temp, ", "sv) + ')'); |
| 8174 | } | 8771 | } |
| 8175 | 8772 | ||
| 8176 | void transformForHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { | 8773 | void transformForNumHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { |
| 8177 | str_list temp; | 8774 | str_list temp; |
| 8178 | std::string varName = variableToString(var); | 8775 | std::string varName = variableToString(var); |
| 8179 | transformExp(startVal, temp, ExpUsage::Closure); | 8776 | transformExp(startVal, temp, ExpUsage::Closure); |
| @@ -8187,15 +8784,15 @@ private: | |||
| 8187 | const auto& start = *it; | 8784 | const auto& start = *it; |
| 8188 | const auto& stop = *(++it); | 8785 | const auto& stop = *(++it); |
| 8189 | const auto& step = *(++it); | 8786 | const auto& step = *(++it); |
| 8190 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); | 8787 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nl(var); |
| 8191 | pushScope(); | 8788 | pushScope(); |
| 8192 | forceAddToScope(varName); | 8789 | forceAddToScope(varName); |
| 8193 | markVarLocalConst(varName); | 8790 | markVarLocalConst(varName); |
| 8194 | out.push_back(clearBuf()); | 8791 | out.push_back(clearBuf()); |
| 8195 | } | 8792 | } |
| 8196 | 8793 | ||
| 8197 | void transformForHead(For_t* forNode, str_list& out) { | 8794 | void transformForNumHead(ForNum_t* forNum, str_list& out) { |
| 8198 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); | 8795 | transformForNumHead(forNum->varName, forNum->startValue, forNum->stopValue, forNum->stepValue, out); |
| 8199 | } | 8796 | } |
| 8200 | 8797 | ||
| 8201 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8798 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| @@ -8205,7 +8802,7 @@ private: | |||
| 8205 | break; | 8802 | break; |
| 8206 | case id<Statement_t>(): { | 8803 | case id<Statement_t>(): { |
| 8207 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); | 8804 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); |
| 8208 | newBlock->statements.push_back(bodyOrStmt); | 8805 | newBlock->statementOrComments.push_back(bodyOrStmt); |
| 8209 | transformBlock(newBlock, out, usage, assignList); | 8806 | transformBlock(newBlock, out, usage, assignList); |
| 8210 | break; | 8807 | break; |
| 8211 | } | 8808 | } |
| @@ -8302,9 +8899,9 @@ private: | |||
| 8302 | } | 8899 | } |
| 8303 | 8900 | ||
| 8304 | void addDoToLastLineReturn(ast_node* body) { | 8901 | void addDoToLastLineReturn(ast_node* body) { |
| 8305 | if (auto block = ast_cast<Block_t>(body); block && !block->statements.empty()) { | 8902 | if (auto block = ast_cast<Block_t>(body); block && !block->statementOrComments.empty()) { |
| 8306 | auto last = static_cast<Statement_t*>(block->statements.back()); | 8903 | auto last = lastStatementFrom(block); |
| 8307 | if (last->content.is<Return_t>()) { | 8904 | if (last && last->content.is<Return_t>()) { |
| 8308 | auto doNode = last->new_ptr<Do_t>(); | 8905 | auto doNode = last->new_ptr<Do_t>(); |
| 8309 | auto newBody = last->new_ptr<Body_t>(); | 8906 | auto newBody = last->new_ptr<Body_t>(); |
| 8310 | auto newStmt = last->new_ptr<Statement_t>(); | 8907 | auto newStmt = last->new_ptr<Statement_t>(); |
| @@ -8331,8 +8928,8 @@ private: | |||
| 8331 | if (withContinue) { | 8928 | if (withContinue) { |
| 8332 | if (target < 502) { | 8929 | if (target < 502) { |
| 8333 | if (auto block = ast_cast<Block_t>(body)) { | 8930 | if (auto block = ast_cast<Block_t>(body)) { |
| 8334 | if (!block->statements.empty()) { | 8931 | if (!block->statementOrComments.empty()) { |
| 8335 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8932 | auto stmt = lastStatementFrom(block); |
| 8336 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8933 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
| 8337 | extraDo = breakLoop->type.is<Break_t>(); | 8934 | extraDo = breakLoop->type.is<Break_t>(); |
| 8338 | } | 8935 | } |
| @@ -8341,11 +8938,11 @@ private: | |||
| 8341 | auto continueVar = getUnusedName("_continue_"sv); | 8938 | auto continueVar = getUnusedName("_continue_"sv); |
| 8342 | addToScope(continueVar); | 8939 | addToScope(continueVar); |
| 8343 | _continueVars.push({continueVar, nullptr}); | 8940 | _continueVars.push({continueVar, nullptr}); |
| 8344 | _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); | 8941 | _buf << indent() << "local "sv << continueVar << " = false"sv << nl(body); |
| 8345 | _buf << indent() << "repeat"sv << nll(body); | 8942 | _buf << indent() << "repeat"sv << nl(body); |
| 8346 | pushScope(); | 8943 | pushScope(); |
| 8347 | if (extraDo) { | 8944 | if (extraDo) { |
| 8348 | _buf << indent() << "do"sv << nll(body); | 8945 | _buf << indent() << "do"sv << nl(body); |
| 8349 | pushScope(); | 8946 | pushScope(); |
| 8350 | } | 8947 | } |
| 8351 | temp.push_back(clearBuf()); | 8948 | temp.push_back(clearBuf()); |
| @@ -8365,14 +8962,14 @@ private: | |||
| 8365 | if (target < 502) { | 8962 | if (target < 502) { |
| 8366 | if (extraDo) { | 8963 | if (extraDo) { |
| 8367 | popScope(); | 8964 | popScope(); |
| 8368 | _buf << indent() << "end"sv << nll(body); | 8965 | _buf << indent() << "end"sv << nl(body); |
| 8369 | } | 8966 | } |
| 8370 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 8967 | _buf << indent() << _continueVars.top().var << " = true"sv << nl(body); |
| 8371 | popScope(); | 8968 | popScope(); |
| 8372 | _buf << indent() << "until true"sv << nlr(body); | 8969 | _buf << indent() << "until true"sv << nl(body); |
| 8373 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body); | 8970 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nl(body); |
| 8374 | _buf << indent(1) << "break"sv << nlr(body); | 8971 | _buf << indent(1) << "break"sv << nl(body); |
| 8375 | _buf << indent() << "end"sv << nlr(body); | 8972 | _buf << indent() << "end"sv << nl(body); |
| 8376 | temp.push_back(clearBuf()); | 8973 | temp.push_back(clearBuf()); |
| 8377 | _continueVars.pop(); | 8974 | _continueVars.pop(); |
| 8378 | } else { | 8975 | } else { |
| @@ -8386,7 +8983,7 @@ private: | |||
| 8386 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { | 8983 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { |
| 8387 | str_list temp; | 8984 | str_list temp; |
| 8388 | bool extraDo = false; | 8985 | bool extraDo = false; |
| 8389 | auto body = repeatNode->body->content.get(); | 8986 | auto body = repeatNode->body.get(); |
| 8390 | auto breakLoopType = getBreakLoopType(body, Empty); | 8987 | auto breakLoopType = getBreakLoopType(body, Empty); |
| 8391 | bool withContinue = hasContinue(breakLoopType); | 8988 | bool withContinue = hasContinue(breakLoopType); |
| 8392 | std::string conditionVar; | 8989 | std::string conditionVar; |
| @@ -8396,8 +8993,8 @@ private: | |||
| 8396 | if (withContinue) { | 8993 | if (withContinue) { |
| 8397 | if (target < 502) { | 8994 | if (target < 502) { |
| 8398 | if (auto block = ast_cast<Block_t>(body)) { | 8995 | if (auto block = ast_cast<Block_t>(body)) { |
| 8399 | if (!block->statements.empty()) { | 8996 | if (!block->statementOrComments.empty()) { |
| 8400 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8997 | auto stmt = lastStatementFrom(block); |
| 8401 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8998 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
| 8402 | extraDo = breakLoop->type.is<Break_t>(); | 8999 | extraDo = breakLoop->type.is<Break_t>(); |
| 8403 | } | 9000 | } |
| @@ -8414,12 +9011,12 @@ private: | |||
| 8414 | assign->values.push_back(repeatNode->condition); | 9011 | assign->values.push_back(repeatNode->condition); |
| 8415 | _continueVars.push({continueVar, assignment.get()}); | 9012 | _continueVars.push({continueVar, assignment.get()}); |
| 8416 | } | 9013 | } |
| 8417 | _buf << indent() << "local "sv << conditionVar << " = false"sv << nll(body); | 9014 | _buf << indent() << "local "sv << conditionVar << " = false"sv << nl(body); |
| 8418 | _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); | 9015 | _buf << indent() << "local "sv << continueVar << " = false"sv << nl(body); |
| 8419 | _buf << indent() << "repeat"sv << nll(body); | 9016 | _buf << indent() << "repeat"sv << nl(body); |
| 8420 | pushScope(); | 9017 | pushScope(); |
| 8421 | if (extraDo) { | 9018 | if (extraDo) { |
| 8422 | _buf << indent() << "do"sv << nll(body); | 9019 | _buf << indent() << "do"sv << nl(body); |
| 8423 | pushScope(); | 9020 | pushScope(); |
| 8424 | } | 9021 | } |
| 8425 | temp.push_back(clearBuf()); | 9022 | temp.push_back(clearBuf()); |
| @@ -8440,14 +9037,14 @@ private: | |||
| 8440 | transformAssignment(_continueVars.top().condAssign, temp); | 9037 | transformAssignment(_continueVars.top().condAssign, temp); |
| 8441 | if (extraDo) { | 9038 | if (extraDo) { |
| 8442 | popScope(); | 9039 | popScope(); |
| 8443 | _buf << indent() << "end"sv << nll(body); | 9040 | _buf << indent() << "end"sv << nl(body); |
| 8444 | } | 9041 | } |
| 8445 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 9042 | _buf << indent() << _continueVars.top().var << " = true"sv << nl(body); |
| 8446 | popScope(); | 9043 | popScope(); |
| 8447 | _buf << indent() << "until true"sv << nlr(body); | 9044 | _buf << indent() << "until true"sv << nl(body); |
| 8448 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body); | 9045 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nl(body); |
| 8449 | _buf << indent(1) << "break"sv << nlr(body); | 9046 | _buf << indent(1) << "break"sv << nl(body); |
| 8450 | _buf << indent() << "end"sv << nlr(body); | 9047 | _buf << indent() << "end"sv << nl(body); |
| 8451 | temp.push_back(clearBuf()); | 9048 | temp.push_back(clearBuf()); |
| 8452 | _continueVars.pop(); | 9049 | _continueVars.pop(); |
| 8453 | } else { | 9050 | } else { |
| @@ -8459,46 +9056,48 @@ private: | |||
| 8459 | return conditionVar; | 9056 | return conditionVar; |
| 8460 | } | 9057 | } |
| 8461 | 9058 | ||
| 8462 | void transformFor(For_t* forNode, str_list& out) { | 9059 | void transformForNum(ForNum_t* forNum, str_list& out) { |
| 8463 | str_list temp; | 9060 | str_list temp; |
| 8464 | transformForHead(forNode, temp); | 9061 | transformForNumHead(forNum, temp); |
| 8465 | auto breakLoopType = getBreakLoopType(forNode->body, Empty); | 9062 | auto breakLoopType = getBreakLoopType(forNum->body, Empty); |
| 8466 | transformLoopBody(forNode->body, temp, breakLoopType, ExpUsage::Common); | 9063 | transformLoopBody(forNum->body, temp, breakLoopType, ExpUsage::Common); |
| 8467 | popScope(); | 9064 | popScope(); |
| 8468 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); | 9065 | out.push_back(join(temp) + indent() + "end"s + nl(forNum)); |
| 8469 | } | 9066 | } |
| 8470 | 9067 | ||
| 8471 | std::string transformForInner(For_t* forNode, str_list& out) { | 9068 | std::string transformForNumInner(ForNum_t* forNum, str_list& out) { |
| 8472 | auto x = forNode; | 9069 | auto x = forNum; |
| 8473 | std::string accum = getUnusedName("_accum_"sv); | 9070 | std::string accum = getUnusedName("_accum_"sv); |
| 8474 | addToScope(accum); | 9071 | addToScope(accum); |
| 8475 | std::string len = getUnusedName("_len_"sv); | 9072 | std::string len = getUnusedName("_len_"sv); |
| 8476 | addToScope(len); | 9073 | addToScope(len); |
| 8477 | auto breakLoopType = getBreakLoopType(forNode->body, accum); | 9074 | auto breakLoopType = getBreakLoopType(forNum->body, accum); |
| 8478 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forNode); | 9075 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forNum); |
| 8479 | out.emplace_back(clearBuf()); | 9076 | out.emplace_back(clearBuf()); |
| 8480 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); | 9077 | _buf << indent() << "local "sv << len << " = 1"sv << nl(forNum); |
| 8481 | auto& lenAssign = out.emplace_back(clearBuf()); | 9078 | auto& lenAssign = out.emplace_back(clearBuf()); |
| 8482 | transformForHead(forNode, out); | 9079 | transformForNumHead(forNum, out); |
| 8483 | if (hasBreakWithValue(breakLoopType)) { | 9080 | if (hasBreakWithValue(breakLoopType)) { |
| 8484 | lenAssign.clear(); | 9081 | lenAssign.clear(); |
| 8485 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Common); | 9082 | transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Common); |
| 8486 | } else { | 9083 | } else { |
| 8487 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 9084 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); |
| 8488 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNode->body); | 9085 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNum->body); |
| 8489 | expList->followStmt = followStmt.get(); | 9086 | expList->followStmt = followStmt.get(); |
| 8490 | transformLoopBody(forNode->body, out, breakLoopType, ExpUsage::Assignment, expList); | 9087 | transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Assignment, expList); |
| 8491 | if (!expList->followStmtProcessed) { | 9088 | if (!expList->followStmtProcessed) { |
| 8492 | lenAssign.clear(); | 9089 | lenAssign.clear(); |
| 8493 | } | 9090 | } |
| 8494 | } | 9091 | } |
| 8495 | popScope(); | 9092 | popScope(); |
| 8496 | out.push_back(indent() + "end"s + nlr(forNode)); | 9093 | out.push_back(indent() + "end"s + nl(forNum)); |
| 8497 | return accum; | 9094 | return accum; |
| 8498 | } | 9095 | } |
| 8499 | 9096 | ||
| 8500 | void transformForClosure(For_t* forNode, str_list& out) { | 9097 | void transformForNumClosure(ForNum_t* forNum, str_list& out) { |
| 8501 | auto simpleValue = forNode->new_ptr<SimpleValue_t>(); | 9098 | auto forNode = forNum->new_ptr<For_t>(); |
| 9099 | forNode->forLoop.set(forNum); | ||
| 9100 | auto simpleValue = forNum->new_ptr<SimpleValue_t>(); | ||
| 8502 | simpleValue->value.set(forNode); | 9101 | simpleValue->value.set(forNode); |
| 8503 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { | 9102 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { |
| 8504 | return; | 9103 | return; |
| @@ -8508,26 +9107,26 @@ private: | |||
| 8508 | pushAnonVarArg(); | 9107 | pushAnonVarArg(); |
| 8509 | std::string& funcStart = temp.emplace_back(); | 9108 | std::string& funcStart = temp.emplace_back(); |
| 8510 | pushScope(); | 9109 | pushScope(); |
| 8511 | auto accum = transformForInner(forNode, temp); | 9110 | auto accum = transformForNumInner(forNum, temp); |
| 8512 | temp.push_back(indent() + "return "s + accum + nlr(forNode)); | 9111 | temp.push_back(indent() + "return "s + accum + nl(forNum)); |
| 8513 | popScope(); | 9112 | popScope(); |
| 8514 | funcStart = anonFuncStart() + nll(forNode); | 9113 | funcStart = anonFuncStart() + nl(forNum); |
| 8515 | temp.push_back(indent() + anonFuncEnd()); | 9114 | temp.push_back(indent() + anonFuncEnd()); |
| 8516 | popAnonVarArg(); | 9115 | popAnonVarArg(); |
| 8517 | popFunctionScope(); | 9116 | popFunctionScope(); |
| 8518 | out.push_back(join(temp)); | 9117 | out.push_back(join(temp)); |
| 8519 | } | 9118 | } |
| 8520 | 9119 | ||
| 8521 | void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { | 9120 | void transformForNumInPlace(ForNum_t* forNum, str_list& out, ExpList_t* assignExpList) { |
| 8522 | auto x = forNode; | 9121 | auto x = forNum; |
| 8523 | str_list temp; | 9122 | str_list temp; |
| 8524 | bool isScoped = !currentScope().lastStatement; | 9123 | bool isScoped = !currentScope().lastStatement; |
| 8525 | if (assignExpList) { | 9124 | if (assignExpList) { |
| 8526 | if (isScoped) { | 9125 | if (isScoped) { |
| 8527 | _buf << indent() << "do"sv << nll(forNode); | 9126 | _buf << indent() << "do"sv << nl(forNum); |
| 8528 | pushScope(); | 9127 | pushScope(); |
| 8529 | } | 9128 | } |
| 8530 | auto accum = transformForInner(forNode, temp); | 9129 | auto accum = transformForNumInner(forNum, temp); |
| 8531 | auto assign = x->new_ptr<Assign_t>(); | 9130 | auto assign = x->new_ptr<Assign_t>(); |
| 8532 | assign->values.push_back(toAst<Exp_t>(accum, x)); | 9131 | assign->values.push_back(toAst<Exp_t>(accum, x)); |
| 8533 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9132 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -8536,10 +9135,10 @@ private: | |||
| 8536 | transformAssignment(assignment, temp); | 9135 | transformAssignment(assignment, temp); |
| 8537 | if (isScoped) { | 9136 | if (isScoped) { |
| 8538 | popScope(); | 9137 | popScope(); |
| 8539 | temp.push_back(indent() + "end"s + nlr(forNode)); | 9138 | temp.push_back(indent() + "end"s + nl(forNum)); |
| 8540 | } | 9139 | } |
| 8541 | } else { | 9140 | } else { |
| 8542 | auto accum = transformForInner(forNode, temp); | 9141 | auto accum = transformForNumInner(forNum, temp); |
| 8543 | auto returnNode = x->new_ptr<Return_t>(); | 9142 | auto returnNode = x->new_ptr<Return_t>(); |
| 8544 | returnNode->explicitReturn = false; | 9143 | returnNode->explicitReturn = false; |
| 8545 | auto expListLow = toAst<ExpListLow_t>(accum, x); | 9144 | auto expListLow = toAst<ExpListLow_t>(accum, x); |
| @@ -8573,10 +9172,10 @@ private: | |||
| 8573 | auto breakLoopType = getBreakLoopType(forEach->body, Empty); | 9172 | auto breakLoopType = getBreakLoopType(forEach->body, Empty); |
| 8574 | transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common); | 9173 | transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common); |
| 8575 | popScope(); | 9174 | popScope(); |
| 8576 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); | 9175 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nl(forEach)); |
| 8577 | if (extraScoped) { | 9176 | if (extraScoped) { |
| 8578 | popScope(); | 9177 | popScope(); |
| 8579 | out.back().append(indent() + "end"s + nlr(forEach)); | 9178 | out.back().append(indent() + "end"s + nl(forEach)); |
| 8580 | } | 9179 | } |
| 8581 | } | 9180 | } |
| 8582 | 9181 | ||
| @@ -8587,9 +9186,9 @@ private: | |||
| 8587 | std::string len = getUnusedName("_len_"sv); | 9186 | std::string len = getUnusedName("_len_"sv); |
| 8588 | addToScope(len); | 9187 | addToScope(len); |
| 8589 | auto breakLoopType = getBreakLoopType(forEach->body, accum); | 9188 | auto breakLoopType = getBreakLoopType(forEach->body, accum); |
| 8590 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(forEach); | 9189 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forEach); |
| 8591 | out.emplace_back(clearBuf()); | 9190 | out.emplace_back(clearBuf()); |
| 8592 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 9191 | _buf << indent() << "local "sv << len << " = 1"sv << nl(forEach); |
| 8593 | auto& lenAssign = out.emplace_back(clearBuf()); | 9192 | auto& lenAssign = out.emplace_back(clearBuf()); |
| 8594 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); | 9193 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); |
| 8595 | if (hasBreakWithValue(breakLoopType)) { | 9194 | if (hasBreakWithValue(breakLoopType)) { |
| @@ -8605,14 +9204,16 @@ private: | |||
| 8605 | } | 9204 | } |
| 8606 | } | 9205 | } |
| 8607 | popScope(); | 9206 | popScope(); |
| 8608 | out.push_back(indent() + "end"s + nlr(forEach)); | 9207 | out.push_back(indent() + "end"s + nl(forEach)); |
| 8609 | return accum; | 9208 | return accum; |
| 8610 | } | 9209 | } |
| 8611 | 9210 | ||
| 8612 | void transformForEachClosure(ForEach_t* forEach, str_list& out) { | 9211 | void transformForEachClosure(ForEach_t* forEach, str_list& out) { |
| 9212 | auto forNode = forEach->new_ptr<For_t>(); | ||
| 9213 | forNode->forLoop.set(forEach); | ||
| 8613 | auto simpleValue = forEach->new_ptr<SimpleValue_t>(); | 9214 | auto simpleValue = forEach->new_ptr<SimpleValue_t>(); |
| 8614 | simpleValue->value.set(forEach); | 9215 | simpleValue->value.set(forNode); |
| 8615 | if (transformAsUpValueFunc(newExp(simpleValue, forEach), out)) { | 9216 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { |
| 8616 | return; | 9217 | return; |
| 8617 | } | 9218 | } |
| 8618 | str_list temp; | 9219 | str_list temp; |
| @@ -8621,22 +9222,22 @@ private: | |||
| 8621 | std::string& funcStart = temp.emplace_back(); | 9222 | std::string& funcStart = temp.emplace_back(); |
| 8622 | pushScope(); | 9223 | pushScope(); |
| 8623 | auto accum = transformForEachInner(forEach, temp); | 9224 | auto accum = transformForEachInner(forEach, temp); |
| 8624 | temp.push_back(indent() + "return "s + accum + nlr(forEach)); | 9225 | temp.push_back(indent() + "return "s + accum + nl(forEach)); |
| 8625 | popScope(); | 9226 | popScope(); |
| 8626 | funcStart = anonFuncStart() + nll(forEach); | 9227 | funcStart = anonFuncStart() + nl(forEach); |
| 8627 | temp.push_back(indent() + anonFuncEnd()); | 9228 | temp.push_back(indent() + anonFuncEnd()); |
| 8628 | popAnonVarArg(); | 9229 | popAnonVarArg(); |
| 8629 | popFunctionScope(); | 9230 | popFunctionScope(); |
| 8630 | out.push_back(join(temp)); | 9231 | out.push_back(join(temp)); |
| 8631 | } | 9232 | } |
| 8632 | 9233 | ||
| 8633 | void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { | 9234 | void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList) { |
| 8634 | auto x = forEach; | 9235 | auto x = forEach; |
| 8635 | str_list temp; | 9236 | str_list temp; |
| 8636 | bool isScoped = !currentScope().lastStatement; | 9237 | bool isScoped = !currentScope().lastStatement; |
| 8637 | if (assignExpList) { | 9238 | if (assignExpList) { |
| 8638 | if (isScoped) { | 9239 | if (isScoped) { |
| 8639 | _buf << indent() << "do"sv << nll(forEach); | 9240 | _buf << indent() << "do"sv << nl(forEach); |
| 8640 | pushScope(); | 9241 | pushScope(); |
| 8641 | } | 9242 | } |
| 8642 | auto accum = transformForEachInner(forEach, temp); | 9243 | auto accum = transformForEachInner(forEach, temp); |
| @@ -8648,7 +9249,7 @@ private: | |||
| 8648 | transformAssignment(assignment, temp); | 9249 | transformAssignment(assignment, temp); |
| 8649 | if (isScoped) { | 9250 | if (isScoped) { |
| 8650 | popScope(); | 9251 | popScope(); |
| 8651 | temp.push_back(indent() + "end"s + nlr(forEach)); | 9252 | temp.push_back(indent() + "end"s + nl(forEach)); |
| 8652 | } | 9253 | } |
| 8653 | } else { | 9254 | } else { |
| 8654 | auto accum = transformForEachInner(forEach, temp); | 9255 | auto accum = transformForEachInner(forEach, temp); |
| @@ -8661,6 +9262,48 @@ private: | |||
| 8661 | out.push_back(join(temp)); | 9262 | out.push_back(join(temp)); |
| 8662 | } | 9263 | } |
| 8663 | 9264 | ||
| 9265 | void transformFor(For_t* forNode, str_list& out) { | ||
| 9266 | switch (forNode->forLoop->get_id()) { | ||
| 9267 | case id<ForNum_t>(): | ||
| 9268 | transformForNum(static_cast<ForNum_t*>(forNode->forLoop.get()), out); | ||
| 9269 | break; | ||
| 9270 | case id<ForEach_t>(): | ||
| 9271 | transformForEach(static_cast<ForEach_t*>(forNode->forLoop.get()), out); | ||
| 9272 | break; | ||
| 9273 | default: | ||
| 9274 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9275 | break; | ||
| 9276 | } | ||
| 9277 | } | ||
| 9278 | |||
| 9279 | void transformForClosure(For_t* forNode, str_list& out) { | ||
| 9280 | switch (forNode->forLoop->get_id()) { | ||
| 9281 | case id<ForNum_t>(): | ||
| 9282 | transformForNumClosure(static_cast<ForNum_t*>(forNode->forLoop.get()), out); | ||
| 9283 | break; | ||
| 9284 | case id<ForEach_t>(): | ||
| 9285 | transformForEachClosure(static_cast<ForEach_t*>(forNode->forLoop.get()), out); | ||
| 9286 | break; | ||
| 9287 | default: | ||
| 9288 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9289 | break; | ||
| 9290 | } | ||
| 9291 | } | ||
| 9292 | |||
| 9293 | void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList) { | ||
| 9294 | switch (forNode->forLoop->get_id()) { | ||
| 9295 | case id<ForNum_t>(): | ||
| 9296 | transformForNumInPlace(static_cast<ForNum_t*>(forNode->forLoop.get()), out, assignExpList); | ||
| 9297 | break; | ||
| 9298 | case id<ForEach_t>(): | ||
| 9299 | transformForEachInPlace(static_cast<ForEach_t*>(forNode->forLoop.get()), out, assignExpList); | ||
| 9300 | break; | ||
| 9301 | default: | ||
| 9302 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9303 | break; | ||
| 9304 | } | ||
| 9305 | } | ||
| 9306 | |||
| 8664 | void transform_variable_pair(VariablePair_t* pair, str_list& out) { | 9307 | void transform_variable_pair(VariablePair_t* pair, str_list& out) { |
| 8665 | auto name = _parser.toString(pair->name); | 9308 | auto name = _parser.toString(pair->name); |
| 8666 | if (pair->name->name.is<UnicodeName_t>()) { | 9309 | if (pair->name->name.is<UnicodeName_t>()) { |
| @@ -8672,8 +9315,8 @@ private: | |||
| 8672 | } | 9315 | } |
| 8673 | if (_config.lintGlobalVariable && !isLocal(name)) { | 9316 | if (_config.lintGlobalVariable && !isLocal(name)) { |
| 8674 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); | 9317 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); |
| 8675 | if (_globals.find(key) != _globals.end()) { | 9318 | if (_globals.find(key) == _globals.end()) { |
| 8676 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read}; | 9319 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read, isSolidDefined(name)}; |
| 8677 | } | 9320 | } |
| 8678 | } | 9321 | } |
| 8679 | } | 9322 | } |
| @@ -8787,12 +9430,64 @@ private: | |||
| 8787 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); | 9430 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); |
| 8788 | } | 9431 | } |
| 8789 | 9432 | ||
| 9433 | void transformYAMLMultiline(YAMLMultiline_t* multiline, str_list& out) { | ||
| 9434 | std::optional<std::string> indent; | ||
| 9435 | str_list temp; | ||
| 9436 | for (auto line_ : multiline->lines.objects()) { | ||
| 9437 | auto line = static_cast<YAMLLine_t*>(line_); | ||
| 9438 | auto indentStr = _parser.toString(line->indent); | ||
| 9439 | if (!indent) { | ||
| 9440 | indent = indentStr; | ||
| 9441 | } | ||
| 9442 | if (std::string_view{indentStr.c_str(), indent.value().size()} != indent.value()) { | ||
| 9443 | throw CompileError("inconsistent indent"sv, line); | ||
| 9444 | } | ||
| 9445 | indentStr = indentStr.substr(indent.value().size()); | ||
| 9446 | str_list segs; | ||
| 9447 | bool firstSeg = true; | ||
| 9448 | for (auto seg_ : line->segments.objects()) { | ||
| 9449 | auto content = static_cast<YAMLLineContent_t*>(seg_)->content.get(); | ||
| 9450 | switch (content->get_id()) { | ||
| 9451 | case id<YAMLLineInner_t>(): { | ||
| 9452 | auto seqStr = _parser.toString(content); | ||
| 9453 | Utils::replace(seqStr, "\\#"sv, "#"sv); | ||
| 9454 | if (firstSeg) { | ||
| 9455 | firstSeg = false; | ||
| 9456 | seqStr.insert(0, indentStr); | ||
| 9457 | } | ||
| 9458 | segs.push_back(Utils::toLuaDoubleString(seqStr)); | ||
| 9459 | break; | ||
| 9460 | } | ||
| 9461 | case id<Exp_t>(): { | ||
| 9462 | if (firstSeg) { | ||
| 9463 | firstSeg = false; | ||
| 9464 | if (!indentStr.empty()) { | ||
| 9465 | segs.push_back(Utils::toLuaDoubleString(indentStr)); | ||
| 9466 | } | ||
| 9467 | } | ||
| 9468 | transformExp(static_cast<Exp_t*>(content), segs, ExpUsage::Closure); | ||
| 9469 | segs.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + segs.back() + ')'; | ||
| 9470 | break; | ||
| 9471 | } | ||
| 9472 | default: YUEE("AST node mismatch", content); break; | ||
| 9473 | } | ||
| 9474 | } | ||
| 9475 | temp.push_back(join(segs, " .. "sv)); | ||
| 9476 | } | ||
| 9477 | auto str = join(temp, " .. '\\n' .. "sv); | ||
| 9478 | Utils::replace(str, "\" .. '\\n' .. \""sv, "\\n"sv); | ||
| 9479 | Utils::replace(str, "\" .. '\\n'"sv, "\\n\""sv); | ||
| 9480 | Utils::replace(str, "'\\n' .. \""sv, "\"\\n"sv); | ||
| 9481 | out.push_back(str); | ||
| 9482 | } | ||
| 9483 | |||
| 8790 | void transformString(String_t* string, str_list& out) { | 9484 | void transformString(String_t* string, str_list& out) { |
| 8791 | auto str = string->str.get(); | 9485 | auto str = string->str.get(); |
| 8792 | switch (str->get_id()) { | 9486 | switch (str->get_id()) { |
| 8793 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; | 9487 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; |
| 8794 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; | 9488 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; |
| 8795 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; | 9489 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; |
| 9490 | case id<YAMLMultiline_t>(): transformYAMLMultiline(static_cast<YAMLMultiline_t*>(str), out); break; | ||
| 8796 | default: YUEE("AST node mismatch", str); break; | 9491 | default: YUEE("AST node mismatch", str); break; |
| 8797 | } | 9492 | } |
| 8798 | } | 9493 | } |
| @@ -8823,7 +9518,7 @@ private: | |||
| 8823 | pushScope(); | 9518 | pushScope(); |
| 8824 | transformClassDecl(classDecl, temp, ExpUsage::Return); | 9519 | transformClassDecl(classDecl, temp, ExpUsage::Return); |
| 8825 | popScope(); | 9520 | popScope(); |
| 8826 | funcStart = anonFuncStart() + nll(classDecl); | 9521 | funcStart = anonFuncStart() + nl(classDecl); |
| 8827 | temp.push_back(indent() + anonFuncEnd()); | 9522 | temp.push_back(indent() + anonFuncEnd()); |
| 8828 | popAnonVarArg(); | 9523 | popAnonVarArg(); |
| 8829 | popFunctionScope(); | 9524 | popFunctionScope(); |
| @@ -8847,7 +9542,7 @@ private: | |||
| 8847 | bool newDefined = false; | 9542 | bool newDefined = false; |
| 8848 | std::tie(className, newDefined, classTextName) = defineClassVariable(assignable); | 9543 | std::tie(className, newDefined, classTextName) = defineClassVariable(assignable); |
| 8849 | if (newDefined) { | 9544 | if (newDefined) { |
| 8850 | temp.push_back(indent() + "local "s + className + nll(classDecl)); | 9545 | temp.push_back(indent() + "local "s + className + nl(classDecl)); |
| 8851 | } | 9546 | } |
| 8852 | if (classTextName.empty()) { | 9547 | if (classTextName.empty()) { |
| 8853 | if (auto chain = ast_cast<AssignableChain_t>(assignable->item)) { | 9548 | if (auto chain = ast_cast<AssignableChain_t>(assignable->item)) { |
| @@ -8884,12 +9579,12 @@ private: | |||
| 8884 | } | 9579 | } |
| 8885 | } | 9580 | } |
| 8886 | if (isScoped) { | 9581 | if (isScoped) { |
| 8887 | temp.push_back(indent() + "do"s + nll(classDecl)); | 9582 | temp.push_back(indent() + "do"s + nl(classDecl)); |
| 8888 | pushScope(); | 9583 | pushScope(); |
| 8889 | } | 9584 | } |
| 8890 | auto classVar = getUnusedName("_class_"sv); | 9585 | auto classVar = getUnusedName("_class_"sv); |
| 8891 | addToScope(classVar); | 9586 | addToScope(classVar); |
| 8892 | temp.push_back(indent() + "local "s + classVar + nll(classDecl)); | 9587 | temp.push_back(indent() + "local "s + classVar + nl(classDecl)); |
| 8893 | auto block = classDecl->new_ptr<Block_t>(); | 9588 | auto block = classDecl->new_ptr<Block_t>(); |
| 8894 | str_list classConstVars; | 9589 | str_list classConstVars; |
| 8895 | if (body) { | 9590 | if (body) { |
| @@ -8898,7 +9593,7 @@ private: | |||
| 8898 | if (auto statement = ast_cast<Statement_t>(item)) { | 9593 | if (auto statement = ast_cast<Statement_t>(item)) { |
| 8899 | ClassDecl_t* clsDecl = nullptr; | 9594 | ClassDecl_t* clsDecl = nullptr; |
| 8900 | if (auto assignment = assignmentFrom(statement)) { | 9595 | if (auto assignment = assignmentFrom(statement)) { |
| 8901 | block->statements.push_back(statement); | 9596 | block->statementOrComments.push_back(statement); |
| 8902 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 9597 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 8903 | for (const auto& name : names) { | 9598 | for (const auto& name : names) { |
| 8904 | varDefs.push_back(name.first); | 9599 | varDefs.push_back(name.first); |
| @@ -8928,12 +9623,12 @@ private: | |||
| 8928 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); | 9623 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); |
| 8929 | BLOCK_END | 9624 | BLOCK_END |
| 8930 | } else if (auto expList = expListFrom(statement)) { | 9625 | } else if (auto expList = expListFrom(statement)) { |
| 8931 | block->statements.push_back(statement); | 9626 | block->statementOrComments.push_back(statement); |
| 8932 | if (auto value = singleValueFrom(expList)) { | 9627 | if (auto value = singleValueFrom(expList)) { |
| 8933 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); | 9628 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); |
| 8934 | } | 9629 | } |
| 8935 | } else if (auto local = statement->content.as<Local_t>()) { | 9630 | } else if (auto local = statement->content.as<Local_t>()) { |
| 8936 | block->statements.push_back(statement); | 9631 | block->statementOrComments.push_back(statement); |
| 8937 | if (auto values = local->item.as<LocalValues_t>()) { | 9632 | if (auto values = local->item.as<LocalValues_t>()) { |
| 8938 | for (auto name : values->nameList->names.objects()) { | 9633 | for (auto name : values->nameList->names.objects()) { |
| 8939 | auto varName = variableToString(static_cast<Variable_t*>(name)); | 9634 | auto varName = variableToString(static_cast<Variable_t*>(name)); |
| @@ -8996,7 +9691,6 @@ private: | |||
| 8996 | } | 9691 | } |
| 8997 | } | 9692 | } |
| 8998 | auto stmt = statement->new_ptr<Statement_t>(); | 9693 | auto stmt = statement->new_ptr<Statement_t>(); |
| 8999 | stmt->comments.dup(statement->comments); | ||
| 9000 | auto newAttrib = localAttrib->new_ptr<LocalAttrib_t>(); | 9694 | auto newAttrib = localAttrib->new_ptr<LocalAttrib_t>(); |
| 9001 | newAttrib->attrib.set(localAttrib->attrib); | 9695 | newAttrib->attrib.set(localAttrib->attrib); |
| 9002 | newAttrib->leftList.dup(localAttrib->leftList); | 9696 | newAttrib->leftList.dup(localAttrib->leftList); |
| @@ -9004,7 +9698,7 @@ private: | |||
| 9004 | newAttrib->forceLocal = false; | 9698 | newAttrib->forceLocal = false; |
| 9005 | stmt->content.set(newAttrib); | 9699 | stmt->content.set(newAttrib); |
| 9006 | stmt->appendix.set(statement->appendix); | 9700 | stmt->appendix.set(statement->appendix); |
| 9007 | block->statements.push_back(stmt); | 9701 | block->statementOrComments.push_back(stmt); |
| 9008 | } else if (statement->content.is<Global_t>()) { | 9702 | } else if (statement->content.is<Global_t>()) { |
| 9009 | throw CompileError("global statement is not allowed here"sv, statement->content); | 9703 | throw CompileError("global statement is not allowed here"sv, statement->content); |
| 9010 | } | 9704 | } |
| @@ -9018,7 +9712,7 @@ private: | |||
| 9018 | } | 9712 | } |
| 9019 | } | 9713 | } |
| 9020 | if (!varDefs.empty()) { | 9714 | if (!varDefs.empty()) { |
| 9021 | temp.push_back(indent() + "local "s + join(varDefs, ", "sv) + nll(body)); | 9715 | temp.push_back(indent() + "local "s + join(varDefs, ", "sv) + nl(body)); |
| 9022 | } | 9716 | } |
| 9023 | } | 9717 | } |
| 9024 | std::string parent, parentVar; | 9718 | std::string parent, parentVar; |
| @@ -9028,7 +9722,7 @@ private: | |||
| 9028 | transformExp(extend, temp, ExpUsage::Closure); | 9722 | transformExp(extend, temp, ExpUsage::Closure); |
| 9029 | parent = std::move(temp.back()); | 9723 | parent = std::move(temp.back()); |
| 9030 | temp.pop_back(); | 9724 | temp.pop_back(); |
| 9031 | temp.push_back(indent() + "local "s + parentVar + " = "s + parent + nll(classDecl)); | 9725 | temp.push_back(indent() + "local "s + parentVar + " = "s + parent + nl(classDecl)); |
| 9032 | } | 9726 | } |
| 9033 | auto baseVar = getUnusedName("_base_"sv); | 9727 | auto baseVar = getUnusedName("_base_"sv); |
| 9034 | addToScope(baseVar); | 9728 | addToScope(baseVar); |
| @@ -9047,7 +9741,7 @@ private: | |||
| 9047 | for (; it != members.end(); ++it) { | 9741 | for (; it != members.end(); ++it) { |
| 9048 | auto& member = *it; | 9742 | auto& member = *it; |
| 9049 | if (member.type == MemType::Property) { | 9743 | if (member.type == MemType::Property) { |
| 9050 | statements.push_back(indent() + member.item + nll(content)); | 9744 | statements.push_back(indent() + member.item + nl(content)); |
| 9051 | } else { | 9745 | } else { |
| 9052 | member.item = indent(1) + member.item; | 9746 | member.item = indent(1) + member.item; |
| 9053 | } | 9747 | } |
| @@ -9059,32 +9753,34 @@ private: | |||
| 9059 | } | 9753 | } |
| 9060 | } | 9754 | } |
| 9061 | for (const auto& classVar : classConstVars) { | 9755 | for (const auto& classVar : classConstVars) { |
| 9062 | auto& scope = _scopes.back(); | 9756 | forceAddToScope(classVar); |
| 9063 | scope.vars->insert_or_assign(classVar, VarType::Local); | ||
| 9064 | } | 9757 | } |
| 9065 | for (auto stmt_ : block->statements.objects()) { | 9758 | forceAddToScope("self"s); |
| 9066 | transformStatement(static_cast<Statement_t*>(stmt_), statements); | 9759 | for (auto stmt_ : block->statementOrComments.objects()) { |
| 9760 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { | ||
| 9761 | transformStatement(stmt, statements); | ||
| 9762 | } | ||
| 9067 | } | 9763 | } |
| 9068 | for (auto& member : members) { | 9764 | for (auto& member : members) { |
| 9069 | switch (member.type) { | 9765 | switch (member.type) { |
| 9070 | case MemType::Common: | 9766 | case MemType::Common: |
| 9071 | commons.push_back((commons.empty() ? Empty : ',' + nll(member.node)) + member.item); | 9767 | commons.push_back((commons.empty() ? Empty : ',' + nl(member.node)) + member.item); |
| 9072 | break; | 9768 | break; |
| 9073 | case MemType::Builtin: | 9769 | case MemType::Builtin: |
| 9074 | builtins.push_back((builtins.empty() ? Empty : ',' + nll(member.node)) + member.item); | 9770 | builtins.push_back((builtins.empty() ? Empty : ',' + nl(member.node)) + member.item); |
| 9075 | break; | 9771 | break; |
| 9076 | default: break; | 9772 | default: break; |
| 9077 | } | 9773 | } |
| 9078 | } | 9774 | } |
| 9079 | if (!commons.empty()) { | 9775 | if (!commons.empty()) { |
| 9080 | temp.back() += '{' + nll(body); | 9776 | temp.back() += '{' + nl(body); |
| 9081 | temp.push_back(join(commons) + nll(body)); | 9777 | temp.push_back(join(commons) + nl(body)); |
| 9082 | temp.push_back(indent() + '}' + nll(body)); | 9778 | temp.push_back(indent() + '}' + nl(body)); |
| 9083 | } else { | 9779 | } else { |
| 9084 | temp.back() += "{ }"s + nll(body); | 9780 | temp.back() += "{ }"s + nl(body); |
| 9085 | } | 9781 | } |
| 9086 | } else { | 9782 | } else { |
| 9087 | temp.back() += "{ }"s + nll(classDecl); | 9783 | temp.back() += "{ }"s + nl(classDecl); |
| 9088 | } | 9784 | } |
| 9089 | if (classDecl->mixes) { | 9785 | if (classDecl->mixes) { |
| 9090 | auto item = getUnusedName("_item_"sv); | 9786 | auto item = getUnusedName("_item_"sv); |
| @@ -9117,72 +9813,72 @@ private: | |||
| 9117 | transformAssignment(assignment, tmp); | 9813 | transformAssignment(assignment, tmp); |
| 9118 | } | 9814 | } |
| 9119 | if (extend) { | 9815 | if (extend) { |
| 9120 | _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl); | 9816 | _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nl(classDecl); |
| 9121 | } | 9817 | } |
| 9122 | _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl, AccessType::Read) << "({"sv << nll(classDecl); | 9818 | _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl, AccessType::Read) << "({"sv << nl(classDecl); |
| 9123 | if (!builtins.empty()) { | 9819 | if (!builtins.empty()) { |
| 9124 | _buf << join(builtins) << ',' << nll(classDecl); | 9820 | _buf << join(builtins) << ',' << nl(classDecl); |
| 9125 | } else { | 9821 | } else { |
| 9126 | if (extend) { | 9822 | if (extend) { |
| 9127 | _buf << indent(1) << "__init = function(self, ...)"sv << nll(classDecl); | 9823 | _buf << indent(1) << "__init = function(self, ...)"sv << nl(classDecl); |
| 9128 | _buf << indent(2) << "return "sv << classVar << ".__parent.__init(self, ...)"sv << nll(classDecl); | 9824 | _buf << indent(2) << "return "sv << classVar << ".__parent.__init(self, ...)"sv << nl(classDecl); |
| 9129 | _buf << indent(1) << "end,"sv << nll(classDecl); | 9825 | _buf << indent(1) << "end,"sv << nl(classDecl); |
| 9130 | } else { | 9826 | } else { |
| 9131 | _buf << indent(1) << "__init = function() end,"sv << nll(classDecl); | 9827 | _buf << indent(1) << "__init = function() end,"sv << nl(classDecl); |
| 9132 | } | 9828 | } |
| 9133 | } | 9829 | } |
| 9134 | _buf << indent(1) << "__base = "sv << baseVar; | 9830 | _buf << indent(1) << "__base = "sv << baseVar; |
| 9135 | if (!classTextName.empty()) { | 9831 | if (!classTextName.empty()) { |
| 9136 | _buf << ","sv << nll(classDecl); | 9832 | _buf << ","sv << nl(classDecl); |
| 9137 | _buf << indent(1) << "__name = "sv << classTextName; | 9833 | _buf << indent(1) << "__name = "sv << classTextName; |
| 9138 | } | 9834 | } |
| 9139 | if (extend) { | 9835 | if (extend) { |
| 9140 | _buf << ","sv << nll(classDecl); | 9836 | _buf << ","sv << nl(classDecl); |
| 9141 | _buf << indent(1) << "__parent = "sv << parentVar; | 9837 | _buf << indent(1) << "__parent = "sv << parentVar; |
| 9142 | } | 9838 | } |
| 9143 | _buf << nll(classDecl); | 9839 | _buf << nl(classDecl); |
| 9144 | _buf << indent() << "}, {"sv << nll(classDecl); | 9840 | _buf << indent() << "}, {"sv << nl(classDecl); |
| 9145 | if (extend) { | 9841 | if (extend) { |
| 9146 | _buf << indent(1) << "__index = function(cls, name)"sv << nll(classDecl); | 9842 | _buf << indent(1) << "__index = function(cls, name)"sv << nl(classDecl); |
| 9147 | _buf << indent(2) << "local val = rawget("sv << baseVar << ", name)"sv << nll(classDecl); | 9843 | _buf << indent(2) << "local val = rawget("sv << baseVar << ", name)"sv << nl(classDecl); |
| 9148 | _buf << indent(2) << "if val == nil then"sv << nll(classDecl); | 9844 | _buf << indent(2) << "if val == nil then"sv << nl(classDecl); |
| 9149 | _buf << indent(3) << "local parent = rawget(cls, \"__parent\")"sv << nll(classDecl); | 9845 | _buf << indent(3) << "local parent = rawget(cls, \"__parent\")"sv << nl(classDecl); |
| 9150 | _buf << indent(3) << "if parent then"sv << nll(classDecl); | 9846 | _buf << indent(3) << "if parent then"sv << nl(classDecl); |
| 9151 | _buf << indent(4) << "return parent[name]"sv << nll(classDecl); | 9847 | _buf << indent(4) << "return parent[name]"sv << nl(classDecl); |
| 9152 | _buf << indent(3) << "end"sv << nll(classDecl); | 9848 | _buf << indent(3) << "end"sv << nl(classDecl); |
| 9153 | _buf << indent(2) << "else"sv << nll(classDecl); | 9849 | _buf << indent(2) << "else"sv << nl(classDecl); |
| 9154 | _buf << indent(3) << "return val"sv << nll(classDecl); | 9850 | _buf << indent(3) << "return val"sv << nl(classDecl); |
| 9155 | _buf << indent(2) << "end"sv << nll(classDecl); | 9851 | _buf << indent(2) << "end"sv << nl(classDecl); |
| 9156 | _buf << indent(1) << "end,"sv << nll(classDecl); | 9852 | _buf << indent(1) << "end,"sv << nl(classDecl); |
| 9157 | } else { | 9853 | } else { |
| 9158 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); | 9854 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nl(classDecl); |
| 9159 | } | 9855 | } |
| 9160 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); | 9856 | _buf << indent(1) << "__call = function(cls, ...)"sv << nl(classDecl); |
| 9161 | pushScope(); | 9857 | pushScope(); |
| 9162 | auto selfVar = getUnusedName("_self_"sv); | 9858 | auto selfVar = getUnusedName("_self_"sv); |
| 9163 | addToScope(selfVar); | 9859 | addToScope(selfVar); |
| 9164 | _buf << indent(1) << "local "sv << selfVar << " = setmetatable({ }, "sv << baseVar << ")"sv << nll(classDecl); | 9860 | _buf << indent(1) << "local "sv << selfVar << " = setmetatable({ }, "sv << baseVar << ")"sv << nl(classDecl); |
| 9165 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | 9861 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nl(classDecl); |
| 9166 | _buf << indent(1) << "return "sv << selfVar << nll(classDecl); | 9862 | _buf << indent(1) << "return "sv << selfVar << nl(classDecl); |
| 9167 | popScope(); | 9863 | popScope(); |
| 9168 | _buf << indent(1) << "end"sv << nll(classDecl); | 9864 | _buf << indent(1) << "end"sv << nl(classDecl); |
| 9169 | _buf << indent() << "})"sv << nll(classDecl); | 9865 | _buf << indent() << "})"sv << nl(classDecl); |
| 9170 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); | 9866 | _buf << indent() << baseVar << ".__class = "sv << classVar << nl(classDecl); |
| 9171 | if (!statements.empty()) { | 9867 | if (!statements.empty()) { |
| 9172 | _buf << indent() << "local self = "sv << classVar << ';' << nll(classDecl); | 9868 | _buf << indent() << "local self = "sv << classVar << ';' << nl(classDecl); |
| 9173 | } | 9869 | } |
| 9174 | _buf << join(statements); | 9870 | _buf << join(statements); |
| 9175 | if (extend) { | 9871 | if (extend) { |
| 9176 | _buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nll(classDecl); | 9872 | _buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nl(classDecl); |
| 9177 | _buf << indent(1) << parentVar << ".__inherited("sv << parentVar << ", "sv << classVar << ")"sv << nll(classDecl); | 9873 | _buf << indent(1) << parentVar << ".__inherited("sv << parentVar << ", "sv << classVar << ")"sv << nl(classDecl); |
| 9178 | _buf << indent() << "end"sv << nll(classDecl); | 9874 | _buf << indent() << "end"sv << nl(classDecl); |
| 9179 | } | 9875 | } |
| 9180 | if (!assignItem.empty()) { | 9876 | if (!assignItem.empty()) { |
| 9181 | _buf << indent() << assignItem << " = "sv << classVar << nll(classDecl); | 9877 | _buf << indent() << assignItem << " = "sv << classVar << nl(classDecl); |
| 9182 | } | 9878 | } |
| 9183 | switch (usage) { | 9879 | switch (usage) { |
| 9184 | case ExpUsage::Return: { | 9880 | case ExpUsage::Return: { |
| 9185 | _buf << indent() << "return "sv << classVar << nlr(classDecl); | 9881 | _buf << indent() << "return "sv << classVar << nl(classDecl); |
| 9186 | break; | 9882 | break; |
| 9187 | } | 9883 | } |
| 9188 | case ExpUsage::Assignment: { | 9884 | case ExpUsage::Assignment: { |
| @@ -9194,7 +9890,7 @@ private: | |||
| 9194 | temp.push_back(clearBuf()); | 9890 | temp.push_back(clearBuf()); |
| 9195 | if (isScoped) { | 9891 | if (isScoped) { |
| 9196 | popScope(); | 9892 | popScope(); |
| 9197 | temp.push_back(indent() + "end"s + nlr(classDecl)); | 9893 | temp.push_back(indent() + "end"s + nl(classDecl)); |
| 9198 | } | 9894 | } |
| 9199 | out.push_back(join(temp)); | 9895 | out.push_back(join(temp)); |
| 9200 | } | 9896 | } |
| @@ -9357,7 +10053,7 @@ private: | |||
| 9357 | pushScope(); | 10053 | pushScope(); |
| 9358 | transformWith(with, temp, nullptr, true); | 10054 | transformWith(with, temp, nullptr, true); |
| 9359 | popScope(); | 10055 | popScope(); |
| 9360 | funcStart = anonFuncStart() + nll(with); | 10056 | funcStart = anonFuncStart() + nl(with); |
| 9361 | temp.push_back(indent() + anonFuncEnd()); | 10057 | temp.push_back(indent() + anonFuncEnd()); |
| 9362 | popAnonVarArg(); | 10058 | popAnonVarArg(); |
| 9363 | popFunctionScope(); | 10059 | popFunctionScope(); |
| @@ -9370,11 +10066,11 @@ private: | |||
| 9370 | std::string withVar; | 10066 | std::string withVar; |
| 9371 | bool needScope = !currentScope().lastStatement && !returnValue; | 10067 | bool needScope = !currentScope().lastStatement && !returnValue; |
| 9372 | bool extraScope = false; | 10068 | bool extraScope = false; |
| 9373 | if (with->assigns) { | 10069 | if (with->assign) { |
| 9374 | auto vars = getAssignVars(with); | 10070 | auto vars = getAssignVars(with); |
| 9375 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { | 10071 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { |
| 9376 | if (with->assigns->values.objects().size() == 1) { | 10072 | if (with->assign->values.objects().size() == 1) { |
| 9377 | auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); | 10073 | auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read); |
| 9378 | if (!var.empty() && isLocal(var)) { | 10074 | if (!var.empty() && isLocal(var)) { |
| 9379 | withVar = var; | 10075 | withVar = var; |
| 9380 | } | 10076 | } |
| @@ -9384,11 +10080,11 @@ private: | |||
| 9384 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10080 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9385 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 10081 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); |
| 9386 | auto assign = x->new_ptr<Assign_t>(); | 10082 | auto assign = x->new_ptr<Assign_t>(); |
| 9387 | assign->values.push_back(with->assigns->values.objects().front()); | 10083 | assign->values.push_back(with->assign->values.objects().front()); |
| 9388 | assignment->action.set(assign); | 10084 | assignment->action.set(assign); |
| 9389 | if (needScope) { | 10085 | if (needScope) { |
| 9390 | extraScope = true; | 10086 | extraScope = true; |
| 9391 | temp.push_back(indent() + "do"s + nll(with)); | 10087 | temp.push_back(indent() + "do"s + nl(with)); |
| 9392 | pushScope(); | 10088 | pushScope(); |
| 9393 | } | 10089 | } |
| 9394 | transformAssignment(assignment, temp); | 10090 | transformAssignment(assignment, temp); |
| @@ -9398,7 +10094,7 @@ private: | |||
| 9398 | auto assign = x->new_ptr<Assign_t>(); | 10094 | auto assign = x->new_ptr<Assign_t>(); |
| 9399 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 10095 | assign->values.push_back(toAst<Exp_t>(withVar, x)); |
| 9400 | bool skipFirst = true; | 10096 | bool skipFirst = true; |
| 9401 | for (auto value : with->assigns->values.objects()) { | 10097 | for (auto value : with->assign->values.objects()) { |
| 9402 | if (skipFirst) { | 10098 | if (skipFirst) { |
| 9403 | skipFirst = false; | 10099 | skipFirst = false; |
| 9404 | continue; | 10100 | continue; |
| @@ -9411,10 +10107,10 @@ private: | |||
| 9411 | withVar = vars.front(); | 10107 | withVar = vars.front(); |
| 9412 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10108 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9413 | assignment->expList.set(with->valueList); | 10109 | assignment->expList.set(with->valueList); |
| 9414 | assignment->action.set(with->assigns); | 10110 | assignment->action.set(with->assign); |
| 9415 | if (needScope) { | 10111 | if (needScope) { |
| 9416 | extraScope = true; | 10112 | extraScope = true; |
| 9417 | temp.push_back(indent() + "do"s + nll(with)); | 10113 | temp.push_back(indent() + "do"s + nl(with)); |
| 9418 | pushScope(); | 10114 | pushScope(); |
| 9419 | } | 10115 | } |
| 9420 | transformAssignment(assignment, temp); | 10116 | transformAssignment(assignment, temp); |
| @@ -9430,7 +10126,7 @@ private: | |||
| 9430 | assignment->action.set(assign); | 10126 | assignment->action.set(assign); |
| 9431 | if (needScope) { | 10127 | if (needScope) { |
| 9432 | extraScope = true; | 10128 | extraScope = true; |
| 9433 | temp.push_back(indent() + "do"s + nll(with)); | 10129 | temp.push_back(indent() + "do"s + nl(with)); |
| 9434 | pushScope(); | 10130 | pushScope(); |
| 9435 | } | 10131 | } |
| 9436 | transformAssignment(assignment, temp); | 10132 | transformAssignment(assignment, temp); |
| @@ -9484,7 +10180,7 @@ private: | |||
| 9484 | }); | 10180 | }); |
| 9485 | popScope(); | 10181 | popScope(); |
| 9486 | if (extraScope) { | 10182 | if (extraScope) { |
| 9487 | temp.push_back(indent() + "do"s + nll(with)); | 10183 | temp.push_back(indent() + "do"s + nl(with)); |
| 9488 | pushScope(); | 10184 | pushScope(); |
| 9489 | } | 10185 | } |
| 9490 | } | 10186 | } |
| @@ -9513,49 +10209,40 @@ private: | |||
| 9513 | expListAssign->expList.set(expList); | 10209 | expListAssign->expList.set(expList); |
| 9514 | auto stmt = x->new_ptr<Statement_t>(); | 10210 | auto stmt = x->new_ptr<Statement_t>(); |
| 9515 | stmt->content.set(expListAssign); | 10211 | stmt->content.set(expListAssign); |
| 9516 | auto whileNode = toAst<While_t>("while true do break"s, x); | 10212 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); |
| 9517 | auto block = x->new_ptr<Block_t>(); | 10213 | auto block = x->new_ptr<Block_t>(); |
| 9518 | block->statements.push_back(stmt); | 10214 | block->statementOrComments.push_back(stmt); |
| 9519 | block->statements.push_back(whileNode->body); | 10215 | repeatNode->body.set(block); |
| 9520 | auto body = x->new_ptr<Body_t>(); | ||
| 9521 | body->content.set(block); | ||
| 9522 | whileNode->body.set(block); | ||
| 9523 | auto sVal = x->new_ptr<SimpleValue_t>(); | 10216 | auto sVal = x->new_ptr<SimpleValue_t>(); |
| 9524 | sVal->value.set(whileNode); | 10217 | sVal->value.set(repeatNode); |
| 9525 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | 10218 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); |
| 9526 | transformAssignment(asmt, temp); | 10219 | transformAssignment(asmt, temp); |
| 9527 | } | 10220 | } |
| 9528 | } else { | 10221 | } else { |
| 9529 | bool transformed = false; | 10222 | bool transformed = false; |
| 9530 | if (!breakWithVar.empty()) { | 10223 | if (!breakWithVar.empty()) { |
| 9531 | auto whileNode = toAst<While_t>("while true do break"s, x); | 10224 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); |
| 9532 | auto block = x->new_ptr<Block_t>(); | 10225 | auto block = x->new_ptr<Block_t>(); |
| 9533 | if (auto blk = with->body.as<Block_t>()) { | 10226 | if (auto blk = with->body.as<Block_t>()) { |
| 9534 | block->statements.dup(blk->statements); | 10227 | block->statementOrComments.dup(blk->statementOrComments); |
| 9535 | } else { | 10228 | } else { |
| 9536 | auto stmt = with->body.to<Statement_t>(); | 10229 | auto stmt = with->body.to<Statement_t>(); |
| 9537 | block->statements.push_back(stmt); | 10230 | block->statementOrComments.push_back(stmt); |
| 9538 | } | ||
| 9539 | auto breakLoop = whileNode->body.to<Statement_t>()->content.as<BreakLoop_t>(); | ||
| 9540 | if (!(breakLoop && breakLoop->type.is<Break_t>())) { | ||
| 9541 | block->statements.push_back(whileNode->body); | ||
| 9542 | } | 10231 | } |
| 9543 | auto body = x->new_ptr<Body_t>(); | 10232 | repeatNode->body.set(block); |
| 9544 | body->content.set(block); | ||
| 9545 | whileNode->body.set(block); | ||
| 9546 | auto sVal = x->new_ptr<SimpleValue_t>(); | 10233 | auto sVal = x->new_ptr<SimpleValue_t>(); |
| 9547 | sVal->value.set(whileNode); | 10234 | sVal->value.set(repeatNode); |
| 9548 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | 10235 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); |
| 9549 | transformAssignment(asmt, temp); | 10236 | transformAssignment(asmt, temp); |
| 9550 | transformed = true; | 10237 | transformed = true; |
| 9551 | } else if (!extraScope && assignList) { | 10238 | } else if (!extraScope && assignList) { |
| 9552 | if (auto block = with->body.as<Block_t>()) { | 10239 | if (auto block = with->body.as<Block_t>()) { |
| 9553 | if (!block->statements.empty()) { | 10240 | if (!block->statementOrComments.empty()) { |
| 9554 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); | 10241 | Statement_t* stmt = lastStatementFrom(block); |
| 9555 | if (stmt->content.is<Return_t>()) { | 10242 | if (stmt && stmt->content.is<Return_t>()) { |
| 9556 | auto newBlock = with->body->new_ptr<Block_t>(); | 10243 | auto newBlock = with->body->new_ptr<Block_t>(); |
| 9557 | newBlock->statements.dup(block->statements); | 10244 | newBlock->statementOrComments.dup(block->statementOrComments); |
| 9558 | newBlock->statements.pop_back(); | 10245 | newBlock->statementOrComments.pop_back(); |
| 9559 | transform_plain_body(newBlock, temp, ExpUsage::Common); | 10246 | transform_plain_body(newBlock, temp, ExpUsage::Common); |
| 9560 | auto newBody = stmt->new_ptr<Body_t>(); | 10247 | auto newBody = stmt->new_ptr<Body_t>(); |
| 9561 | newBody->content.set(stmt); | 10248 | newBody->content.set(stmt); |
| @@ -9593,12 +10280,12 @@ private: | |||
| 9593 | if (returnValue) { | 10280 | if (returnValue) { |
| 9594 | auto last = lastStatementFrom(with->body); | 10281 | auto last = lastStatementFrom(with->body); |
| 9595 | if (last && !last->content.is<Return_t>()) { | 10282 | if (last && !last->content.is<Return_t>()) { |
| 9596 | temp.push_back(indent() + "return "s + withVar + nll(with)); | 10283 | temp.push_back(indent() + "return "s + withVar + nl(with)); |
| 9597 | } | 10284 | } |
| 9598 | } | 10285 | } |
| 9599 | if (extraScope) { | 10286 | if (extraScope) { |
| 9600 | popScope(); | 10287 | popScope(); |
| 9601 | temp.push_back(indent() + "end"s + nll(with)); | 10288 | temp.push_back(indent() + "end"s + nl(with)); |
| 9602 | } | 10289 | } |
| 9603 | out.push_back(join(temp)); | 10290 | out.push_back(join(temp)); |
| 9604 | } | 10291 | } |
| @@ -9808,7 +10495,7 @@ private: | |||
| 9808 | } | 10495 | } |
| 9809 | } | 10496 | } |
| 9810 | if (_info.exportDefault) { | 10497 | if (_info.exportDefault) { |
| 9811 | out.back().append(indent() + _info.moduleName + " = "s + names.back().first + nlr(exportNode)); | 10498 | out.back().append(indent() + _info.moduleName + " = "s + names.back().first + nl(exportNode)); |
| 9812 | } else { | 10499 | } else { |
| 9813 | str_list lefts, rights; | 10500 | str_list lefts, rights; |
| 9814 | for (const auto& name : names) { | 10501 | for (const auto& name : names) { |
| @@ -9821,7 +10508,7 @@ private: | |||
| 9821 | lefts.push_back(_info.moduleName + "[\""s + realName + "\"]"s); | 10508 | lefts.push_back(_info.moduleName + "[\""s + realName + "\"]"s); |
| 9822 | rights.push_back(name.first); | 10509 | rights.push_back(name.first); |
| 9823 | } | 10510 | } |
| 9824 | out.back().append(indent() + join(lefts, ", "sv) + " = "s + join(rights, ", "sv) + nlr(exportNode)); | 10511 | out.back().append(indent() + join(lefts, ", "sv) + " = "s + join(rights, ", "sv) + nl(exportNode)); |
| 9825 | } | 10512 | } |
| 9826 | } | 10513 | } |
| 9827 | } else { | 10514 | } else { |
| @@ -9905,12 +10592,12 @@ private: | |||
| 9905 | case id<CompForEach_t>(): | 10592 | case id<CompForEach_t>(): |
| 9906 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 10593 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 9907 | break; | 10594 | break; |
| 9908 | case id<CompFor_t>(): | 10595 | case id<CompForNum_t>(): |
| 9909 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 10596 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 9910 | break; | 10597 | break; |
| 9911 | case id<Exp_t>(): | 10598 | case id<Exp_t>(): |
| 9912 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 10599 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 9913 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 10600 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 9914 | pushScope(); | 10601 | pushScope(); |
| 9915 | break; | 10602 | break; |
| 9916 | default: YUEE("AST node mismatch", item); break; | 10603 | default: YUEE("AST node mismatch", item); break; |
| @@ -9923,27 +10610,27 @@ private: | |||
| 9923 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 10610 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { |
| 9924 | popScope(); | 10611 | popScope(); |
| 9925 | } | 10612 | } |
| 9926 | _buf << indent() << "local "sv << tbl << " = { }"sv << nll(comp); | 10613 | _buf << indent() << "local "sv << tbl << " = { }"sv << nl(comp); |
| 9927 | _buf << join(temp); | 10614 | _buf << join(temp); |
| 9928 | pushScope(); | 10615 | pushScope(); |
| 9929 | if (!comp->value) { | 10616 | if (!comp->value) { |
| 9930 | auto keyVar = getUnusedName("_key_"sv); | 10617 | auto keyVar = getUnusedName("_key_"sv); |
| 9931 | auto valVar = getUnusedName("_val_"sv); | 10618 | auto valVar = getUnusedName("_val_"sv); |
| 9932 | _buf << indent(int(temp.size()) - 1) << "local "sv << keyVar << ", "sv << valVar << " = "sv << kv.front() << nll(comp); | 10619 | _buf << indent(int(temp.size()) - 1) << "local "sv << keyVar << ", "sv << valVar << " = "sv << kv.front() << nl(comp); |
| 9933 | kv.front() = keyVar; | 10620 | kv.front() = keyVar; |
| 9934 | kv.push_back(valVar); | 10621 | kv.push_back(valVar); |
| 9935 | } | 10622 | } |
| 9936 | _buf << indent(int(temp.size()) - 1) << tbl << "["sv << kv.front() << "] = "sv << kv.back() << nll(comp); | 10623 | _buf << indent(int(temp.size()) - 1) << tbl << "["sv << kv.front() << "] = "sv << kv.back() << nl(comp); |
| 9937 | for (int ind = int(temp.size()) - 2; ind > -1; --ind) { | 10624 | for (int ind = int(temp.size()) - 2; ind > -1; --ind) { |
| 9938 | _buf << indent(ind) << "end"sv << nll(comp); | 10625 | _buf << indent(ind) << "end"sv << nl(comp); |
| 9939 | } | 10626 | } |
| 9940 | popScope(); | 10627 | popScope(); |
| 9941 | _buf << indent() << "end"sv << nll(comp); | 10628 | _buf << indent() << "end"sv << nl(comp); |
| 9942 | switch (usage) { | 10629 | switch (usage) { |
| 9943 | case ExpUsage::Closure: | 10630 | case ExpUsage::Closure: |
| 9944 | out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp)); | 10631 | out.push_back(clearBuf() + indent() + "return "s + tbl + nl(comp)); |
| 9945 | popScope(); | 10632 | popScope(); |
| 9946 | out.back().insert(0, anonFuncStart() + nll(comp)); | 10633 | out.back().insert(0, anonFuncStart() + nl(comp)); |
| 9947 | out.back().append(indent() + anonFuncEnd()); | 10634 | out.back().append(indent() + anonFuncEnd()); |
| 9948 | popAnonVarArg(); | 10635 | popAnonVarArg(); |
| 9949 | popFunctionScope(); | 10636 | popFunctionScope(); |
| @@ -9959,21 +10646,21 @@ private: | |||
| 9959 | out.back().append(temp.back()); | 10646 | out.back().append(temp.back()); |
| 9960 | if (extraScope) { | 10647 | if (extraScope) { |
| 9961 | popScope(); | 10648 | popScope(); |
| 9962 | out.back().insert(0, indent() + "do"s + nll(comp)); | 10649 | out.back().insert(0, indent() + "do"s + nl(comp)); |
| 9963 | out.back().append(indent() + "end"s + nlr(comp)); | 10650 | out.back().append(indent() + "end"s + nl(comp)); |
| 9964 | } | 10651 | } |
| 9965 | break; | 10652 | break; |
| 9966 | } | 10653 | } |
| 9967 | case ExpUsage::Return: | 10654 | case ExpUsage::Return: |
| 9968 | out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp)); | 10655 | out.push_back(clearBuf() + indent() + "return "s + tbl + nl(comp)); |
| 9969 | break; | 10656 | break; |
| 9970 | default: | 10657 | default: |
| 9971 | break; | 10658 | break; |
| 9972 | } | 10659 | } |
| 9973 | } | 10660 | } |
| 9974 | 10661 | ||
| 9975 | void transformCompFor(CompFor_t* comp, str_list& out) { | 10662 | void transformCompForNum(CompForNum_t* comp, str_list& out) { |
| 9976 | transformForHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); | 10663 | transformForNumHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); |
| 9977 | } | 10664 | } |
| 9978 | 10665 | ||
| 9979 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { | 10666 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { |
| @@ -10003,25 +10690,64 @@ private: | |||
| 10003 | funcStart = &temp.emplace_back(); | 10690 | funcStart = &temp.emplace_back(); |
| 10004 | pushScope(); | 10691 | pushScope(); |
| 10005 | } else { | 10692 | } else { |
| 10006 | temp.push_back(indent() + "do"s + nll(doNode)); | 10693 | temp.push_back(indent() + "do"s + nl(doNode)); |
| 10007 | pushScope(); | 10694 | pushScope(); |
| 10008 | } | 10695 | } |
| 10009 | transformBody(doNode->body, temp, usage, assignList); | 10696 | transformBody(doNode->body, temp, usage, assignList); |
| 10010 | if (usage == ExpUsage::Closure) { | 10697 | if (usage == ExpUsage::Closure) { |
| 10011 | popScope(); | 10698 | popScope(); |
| 10012 | *funcStart = anonFuncStart() + nll(doNode); | 10699 | *funcStart = anonFuncStart() + nl(doNode); |
| 10013 | temp.push_back(indent() + anonFuncEnd()); | 10700 | temp.push_back(indent() + anonFuncEnd()); |
| 10014 | popAnonVarArg(); | 10701 | popAnonVarArg(); |
| 10015 | popFunctionScope(); | 10702 | popFunctionScope(); |
| 10016 | } else { | 10703 | } else { |
| 10017 | popScope(); | 10704 | popScope(); |
| 10018 | temp.push_back(indent() + "end"s + nlr(doNode)); | 10705 | temp.push_back(indent() + "end"s + nl(doNode)); |
| 10019 | } | 10706 | } |
| 10020 | out.push_back(join(temp)); | 10707 | out.push_back(join(temp)); |
| 10021 | } | 10708 | } |
| 10022 | 10709 | ||
| 10023 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { | 10710 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 10024 | auto x = tryNode; | 10711 | auto x = tryNode; |
| 10712 | if (tryNode->eop && usage == ExpUsage::Assignment) { | ||
| 10713 | str_list rets; | ||
| 10714 | pushScope(); | ||
| 10715 | auto okVar = getUnusedName("_ok_"sv); | ||
| 10716 | for (size_t i = 0; i < assignList->exprs.size(); i++) { | ||
| 10717 | auto retVar = getUnusedName("_ret_"sv); | ||
| 10718 | rets.emplace_back(retVar); | ||
| 10719 | addToScope(retVar); | ||
| 10720 | } | ||
| 10721 | popScope(); | ||
| 10722 | auto varList = join(rets, ","sv); | ||
| 10723 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); | ||
| 10724 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); | ||
| 10725 | auto sVal = simpleSingleValueFrom(exp); | ||
| 10726 | auto newTry = sVal->value.to<Try_t>(); | ||
| 10727 | newTry->func.set(tryNode->func); | ||
| 10728 | newTry->catchBlock.set(tryNode->catchBlock); | ||
| 10729 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 10730 | assignment->expList.set(assignList); | ||
| 10731 | auto assign = x->new_ptr<Assign_t>(); | ||
| 10732 | assign->values.push_back(ifNode); | ||
| 10733 | assignment->action.set(assign); | ||
| 10734 | transformAssignment(assignment, out); | ||
| 10735 | return; | ||
| 10736 | } | ||
| 10737 | if (tryNode->eop && usage != ExpUsage::Common) { | ||
| 10738 | auto okVar = getUnusedName("_ok_"sv); | ||
| 10739 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; | ||
| 10740 | auto doNode = toAst<Do_t>(code, x); | ||
| 10741 | auto block = doNode->body->content.to<Block_t>(); | ||
| 10742 | auto asmt = static_cast<Statement_t*>(block->statementOrComments.front())->content.to<ExpListAssign_t>(); | ||
| 10743 | auto assign = asmt->action.to<Assign_t>(); | ||
| 10744 | auto sVal = simpleSingleValueFrom(assign->values.back()); | ||
| 10745 | auto newTry = sVal->value.to<Try_t>(); | ||
| 10746 | newTry->func.set(tryNode->func); | ||
| 10747 | newTry->catchBlock.set(tryNode->catchBlock); | ||
| 10748 | transformDo(doNode, out, usage); | ||
| 10749 | return; | ||
| 10750 | } | ||
| 10025 | ast_ptr<true, Exp_t> errHandler; | 10751 | ast_ptr<true, Exp_t> errHandler; |
| 10026 | if (tryNode->catchBlock) { | 10752 | if (tryNode->catchBlock) { |
| 10027 | auto catchBlock = tryNode->catchBlock.get(); | 10753 | auto catchBlock = tryNode->catchBlock.get(); |
| @@ -10037,8 +10763,8 @@ private: | |||
| 10037 | tryFunc.set(tryNode->func); | 10763 | tryFunc.set(tryNode->func); |
| 10038 | if (auto tryBlock = tryFunc.as<Block_t>()) { | 10764 | if (auto tryBlock = tryFunc.as<Block_t>()) { |
| 10039 | BLOCK_START | 10765 | BLOCK_START |
| 10040 | BREAK_IF(tryBlock->statements.size() != 1); | 10766 | BREAK_IF(countStatementFrom(tryBlock) != 1); |
| 10041 | auto stmt = static_cast<Statement_t*>(tryBlock->statements.front()); | 10767 | auto stmt = firstStatementFrom(tryBlock); |
| 10042 | auto expListAssign = stmt->content.as<ExpListAssign_t>(); | 10768 | auto expListAssign = stmt->content.as<ExpListAssign_t>(); |
| 10043 | BREAK_IF(!expListAssign); | 10769 | BREAK_IF(!expListAssign); |
| 10044 | BREAK_IF(expListAssign->action); | 10770 | BREAK_IF(expListAssign->action); |
| @@ -10102,7 +10828,7 @@ private: | |||
| 10102 | auto stmt = x->new_ptr<Statement_t>(); | 10828 | auto stmt = x->new_ptr<Statement_t>(); |
| 10103 | stmt->content.set(expListAssign); | 10829 | stmt->content.set(expListAssign); |
| 10104 | auto block = x->new_ptr<Block_t>(); | 10830 | auto block = x->new_ptr<Block_t>(); |
| 10105 | block->statements.push_back(stmt); | 10831 | block->statementOrComments.push_back(stmt); |
| 10106 | tryFunc.set(block); | 10832 | tryFunc.set(block); |
| 10107 | } | 10833 | } |
| 10108 | } | 10834 | } |
| @@ -10130,7 +10856,7 @@ private: | |||
| 10130 | } | 10856 | } |
| 10131 | if (usage == ExpUsage::Common) { | 10857 | if (usage == ExpUsage::Common) { |
| 10132 | out.back().insert(0, indent()); | 10858 | out.back().insert(0, indent()); |
| 10133 | out.back().append(nlr(x)); | 10859 | out.back().append(nl(x)); |
| 10134 | } | 10860 | } |
| 10135 | return; | 10861 | return; |
| 10136 | } | 10862 | } |
| @@ -10155,7 +10881,7 @@ private: | |||
| 10155 | } | 10881 | } |
| 10156 | if (usage == ExpUsage::Common) { | 10882 | if (usage == ExpUsage::Common) { |
| 10157 | out.back().insert(0, indent()); | 10883 | out.back().insert(0, indent()); |
| 10158 | out.back().append(nlr(x)); | 10884 | out.back().append(nl(x)); |
| 10159 | } | 10885 | } |
| 10160 | return; | 10886 | return; |
| 10161 | } else if (auto value = singleValueFrom(tryFunc)) { | 10887 | } else if (auto value = singleValueFrom(tryFunc)) { |
| @@ -10216,7 +10942,7 @@ private: | |||
| 10216 | } | 10942 | } |
| 10217 | if (usage == ExpUsage::Common) { | 10943 | if (usage == ExpUsage::Common) { |
| 10218 | out.back().insert(0, indent()); | 10944 | out.back().insert(0, indent()); |
| 10219 | out.back().append(nlr(x)); | 10945 | out.back().append(nl(x)); |
| 10220 | } | 10946 | } |
| 10221 | return; | 10947 | return; |
| 10222 | BLOCK_END | 10948 | BLOCK_END |
| @@ -10235,13 +10961,13 @@ private: | |||
| 10235 | } | 10961 | } |
| 10236 | if (usage == ExpUsage::Common) { | 10962 | if (usage == ExpUsage::Common) { |
| 10237 | out.back().insert(0, indent()); | 10963 | out.back().insert(0, indent()); |
| 10238 | out.back().append(nlr(x)); | 10964 | out.back().append(nl(x)); |
| 10239 | } | 10965 | } |
| 10240 | } | 10966 | } |
| 10241 | 10967 | ||
| 10242 | void transformImportFrom(ImportFrom_t* importNode, str_list& out) { | 10968 | void transformImportFrom(ImportFrom_t* importNode, str_list& out) { |
| 10243 | str_list temp; | 10969 | str_list temp; |
| 10244 | auto x = importNode; | 10970 | auto x = importNode->item.get(); |
| 10245 | auto objVar = singleVariableFrom(importNode->item, AccessType::Read); | 10971 | auto objVar = singleVariableFrom(importNode->item, AccessType::Read); |
| 10246 | ast_ptr<false, ExpListAssign_t> objAssign; | 10972 | ast_ptr<false, ExpListAssign_t> objAssign; |
| 10247 | if (objVar.empty()) { | 10973 | if (objVar.empty()) { |
| @@ -10311,11 +11037,11 @@ private: | |||
| 10311 | if (objAssign) { | 11037 | if (objAssign) { |
| 10312 | auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); | 11038 | auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); |
| 10313 | if (!preDef.empty()) { | 11039 | if (!preDef.empty()) { |
| 10314 | temp.push_back(preDef + nll(importNode)); | 11040 | temp.push_back(preDef + nl(importNode)); |
| 10315 | } | 11041 | } |
| 10316 | if (!currentScope().lastStatement) { | 11042 | if (!currentScope().lastStatement) { |
| 10317 | extraScope = true; | 11043 | extraScope = true; |
| 10318 | temp.push_back(indent() + "do"s + nll(importNode)); | 11044 | temp.push_back(indent() + "do"s + nl(importNode)); |
| 10319 | pushScope(); | 11045 | pushScope(); |
| 10320 | } | 11046 | } |
| 10321 | transformAssignment(objAssign, temp); | 11047 | transformAssignment(objAssign, temp); |
| @@ -10327,7 +11053,7 @@ private: | |||
| 10327 | if (objAssign) { | 11053 | if (objAssign) { |
| 10328 | if (extraScope) { | 11054 | if (extraScope) { |
| 10329 | popScope(); | 11055 | popScope(); |
| 10330 | temp.push_back(indent() + "end"s + nlr(importNode)); | 11056 | temp.push_back(indent() + "end"s + nl(importNode)); |
| 10331 | } | 11057 | } |
| 10332 | } | 11058 | } |
| 10333 | out.push_back(join(temp)); | 11059 | out.push_back(join(temp)); |
| @@ -10567,6 +11293,30 @@ private: | |||
| 10567 | } | 11293 | } |
| 10568 | } | 11294 | } |
| 10569 | 11295 | ||
| 11296 | void transformImportGlobal(ImportGlobal_t* importNode, str_list& out) { | ||
| 11297 | auto uname = static_cast<UnicodeName_t*>(importNode->segs.front()); | ||
| 11298 | auto var = _parser.toString(uname); | ||
| 11299 | auto isNormal = _parser.match<Name_t>(var) && _parser.match<Variable_t>(var); | ||
| 11300 | auto varName = unicodeVariableFrom(uname); | ||
| 11301 | str_list temp; | ||
| 11302 | auto it = ++importNode->segs.objects().begin(); | ||
| 11303 | for (; it != importNode->segs.objects().end(); ++it) { | ||
| 11304 | temp.emplace_back(_parser.toString(*it)); | ||
| 11305 | } | ||
| 11306 | temp.emplace_front(var); | ||
| 11307 | if (isLocal(varName) || !isNormal) { | ||
| 11308 | temp.emplace_front("_G"s); | ||
| 11309 | } | ||
| 11310 | std::string stmt; | ||
| 11311 | if (importNode->target) { | ||
| 11312 | stmt = "const "s + _parser.toString(importNode->target) + '=' + join(temp, "."sv); | ||
| 11313 | } else { | ||
| 11314 | stmt = "const "s + temp.back() + '=' + join(temp, "."sv); | ||
| 11315 | } | ||
| 11316 | auto localAttrib = toAst<LocalAttrib_t>(stmt, importNode); | ||
| 11317 | transformLocalAttrib(localAttrib, out); | ||
| 11318 | } | ||
| 11319 | |||
| 10570 | void transformImport(Import_t* import, str_list& out) { | 11320 | void transformImport(Import_t* import, str_list& out) { |
| 10571 | auto content = import->content.get(); | 11321 | auto content = import->content.get(); |
| 10572 | switch (content->get_id()) { | 11322 | switch (content->get_id()) { |
| @@ -10579,6 +11329,9 @@ private: | |||
| 10579 | case id<FromImport_t>(): | 11329 | case id<FromImport_t>(): |
| 10580 | transformFromImport(static_cast<FromImport_t*>(content), out); | 11330 | transformFromImport(static_cast<FromImport_t*>(content), out); |
| 10581 | break; | 11331 | break; |
| 11332 | case id<ImportGlobal_t>(): | ||
| 11333 | transformImportGlobal(static_cast<ImportGlobal_t*>(content), out); | ||
| 11334 | break; | ||
| 10582 | default: YUEE("AST node mismatch", content); break; | 11335 | default: YUEE("AST node mismatch", content); break; |
| 10583 | } | 11336 | } |
| 10584 | } | 11337 | } |
| @@ -10590,7 +11343,7 @@ private: | |||
| 10590 | if (expList) { | 11343 | if (expList) { |
| 10591 | if (!currentScope().lastStatement) { | 11344 | if (!currentScope().lastStatement) { |
| 10592 | extraScope = true; | 11345 | extraScope = true; |
| 10593 | temp.push_back(indent() + "do"s + nll(whileNode)); | 11346 | temp.push_back(indent() + "do"s + nl(whileNode)); |
| 10594 | pushScope(); | 11347 | pushScope(); |
| 10595 | } | 11348 | } |
| 10596 | } | 11349 | } |
| @@ -10599,13 +11352,13 @@ private: | |||
| 10599 | auto lenVar = getUnusedName("_len_"sv); | 11352 | auto lenVar = getUnusedName("_len_"sv); |
| 10600 | addToScope(lenVar); | 11353 | addToScope(lenVar); |
| 10601 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); | 11354 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
| 10602 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); | 11355 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(whileNode); |
| 10603 | temp.emplace_back(clearBuf()); | 11356 | temp.emplace_back(clearBuf()); |
| 10604 | _buf << indent() << "local "s << lenVar << " = 1"s << nll(whileNode); | 11357 | _buf << indent() << "local "s << lenVar << " = 1"s << nl(whileNode); |
| 10605 | auto& lenAssign = temp.emplace_back(clearBuf()); | 11358 | auto& lenAssign = temp.emplace_back(clearBuf()); |
| 10606 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11359 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 10607 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11360 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10608 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11361 | temp.push_back(indent() + "while "s + condStr + " do"s + nl(whileNode)); |
| 10609 | pushScope(); | 11362 | pushScope(); |
| 10610 | if (hasBreakWithValue(breakLoopType)) { | 11363 | if (hasBreakWithValue(breakLoopType)) { |
| 10611 | lenAssign.clear(); | 11364 | lenAssign.clear(); |
| @@ -10620,7 +11373,7 @@ private: | |||
| 10620 | } | 11373 | } |
| 10621 | } | 11374 | } |
| 10622 | popScope(); | 11375 | popScope(); |
| 10623 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11376 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10624 | if (expList) { | 11377 | if (expList) { |
| 10625 | auto assign = x->new_ptr<Assign_t>(); | 11378 | auto assign = x->new_ptr<Assign_t>(); |
| 10626 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | 11379 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); |
| @@ -10630,10 +11383,10 @@ private: | |||
| 10630 | transformAssignment(assignment, temp); | 11383 | transformAssignment(assignment, temp); |
| 10631 | if (extraScope) popScope(); | 11384 | if (extraScope) popScope(); |
| 10632 | } else { | 11385 | } else { |
| 10633 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11386 | temp.push_back(indent() + "return "s + accumVar + nl(whileNode)); |
| 10634 | } | 11387 | } |
| 10635 | if (expList && extraScope) { | 11388 | if (expList && extraScope) { |
| 10636 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11389 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10637 | } | 11390 | } |
| 10638 | out.push_back(join(temp)); | 11391 | out.push_back(join(temp)); |
| 10639 | } | 11392 | } |
| @@ -10655,12 +11408,12 @@ private: | |||
| 10655 | auto lenVar = getUnusedName("_len_"sv); | 11408 | auto lenVar = getUnusedName("_len_"sv); |
| 10656 | addToScope(lenVar); | 11409 | addToScope(lenVar); |
| 10657 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); | 11410 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
| 10658 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nll(whileNode); | 11411 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(whileNode); |
| 10659 | temp.emplace_back(clearBuf()); | 11412 | temp.emplace_back(clearBuf()); |
| 10660 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11413 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nl(whileNode)); |
| 10661 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11414 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 10662 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11415 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10663 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11416 | temp.push_back(indent() + "while "s + condStr + " do"s + nl(whileNode)); |
| 10664 | pushScope(); | 11417 | pushScope(); |
| 10665 | if (hasBreakWithValue(breakLoopType)) { | 11418 | if (hasBreakWithValue(breakLoopType)) { |
| 10666 | lenAssign.clear(); | 11419 | lenAssign.clear(); |
| @@ -10675,10 +11428,10 @@ private: | |||
| 10675 | } | 11428 | } |
| 10676 | } | 11429 | } |
| 10677 | popScope(); | 11430 | popScope(); |
| 10678 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11431 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10679 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11432 | temp.push_back(indent() + "return "s + accumVar + nl(whileNode)); |
| 10680 | popScope(); | 11433 | popScope(); |
| 10681 | funcStart = anonFuncStart() + nll(whileNode); | 11434 | funcStart = anonFuncStart() + nl(whileNode); |
| 10682 | temp.push_back(indent() + anonFuncEnd()); | 11435 | temp.push_back(indent() + anonFuncEnd()); |
| 10683 | popAnonVarArg(); | 11436 | popAnonVarArg(); |
| 10684 | popFunctionScope(); | 11437 | popFunctionScope(); |
| @@ -10708,9 +11461,7 @@ private: | |||
| 10708 | expListAssign->expList.set(expList); | 11461 | expListAssign->expList.set(expList); |
| 10709 | auto stmt = x->new_ptr<Statement_t>(); | 11462 | auto stmt = x->new_ptr<Statement_t>(); |
| 10710 | stmt->content.set(expListAssign); | 11463 | stmt->content.set(expListAssign); |
| 10711 | auto body = x->new_ptr<Body_t>(); | 11464 | repeat->body.set(stmt); |
| 10712 | body->content.set(stmt); | ||
| 10713 | repeat->body.set(body); | ||
| 10714 | transformRepeat(repeat, out); | 11465 | transformRepeat(repeat, out); |
| 10715 | return; | 11466 | return; |
| 10716 | } | 11467 | } |
| @@ -10721,12 +11472,112 @@ private: | |||
| 10721 | auto breakLoopType = getBreakLoopType(whileNode->body, Empty); | 11472 | auto breakLoopType = getBreakLoopType(whileNode->body, Empty); |
| 10722 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | 11473 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
| 10723 | popScope(); | 11474 | popScope(); |
| 10724 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); | 11475 | _buf << indent() << "while "sv << condStr << " do"sv << nl(whileNode); |
| 10725 | _buf << temp.back(); | 11476 | _buf << temp.back(); |
| 10726 | _buf << indent() << "end"sv << nlr(whileNode); | 11477 | _buf << indent() << "end"sv << nl(whileNode); |
| 10727 | out.push_back(clearBuf()); | 11478 | out.push_back(clearBuf()); |
| 10728 | } | 11479 | } |
| 10729 | 11480 | ||
| 11481 | void transformRepeatInPlace(Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr) { | ||
| 11482 | auto x = repeatNode; | ||
| 11483 | str_list temp; | ||
| 11484 | bool extraScope = false; | ||
| 11485 | if (expList) { | ||
| 11486 | if (!currentScope().lastStatement) { | ||
| 11487 | extraScope = true; | ||
| 11488 | temp.push_back(indent() + "do"s + nl(repeatNode)); | ||
| 11489 | pushScope(); | ||
| 11490 | } | ||
| 11491 | } | ||
| 11492 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 11493 | addToScope(accumVar); | ||
| 11494 | auto lenVar = getUnusedName("_len_"sv); | ||
| 11495 | addToScope(lenVar); | ||
| 11496 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 11497 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(repeatNode); | ||
| 11498 | temp.emplace_back(clearBuf()); | ||
| 11499 | _buf << indent() << "local "s << lenVar << " = 1"s << nl(repeatNode); | ||
| 11500 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
| 11501 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 11502 | temp.push_back(indent() + "repeat"s + nl(repeatNode)); | ||
| 11503 | pushScope(); | ||
| 11504 | if (hasBreakWithValue(breakLoopType)) { | ||
| 11505 | lenAssign.clear(); | ||
| 11506 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 11507 | } else { | ||
| 11508 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11509 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 11510 | assignLeft->followStmt = followStmt.get(); | ||
| 11511 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11512 | if (!assignLeft->followStmtProcessed) { | ||
| 11513 | lenAssign.clear(); | ||
| 11514 | } | ||
| 11515 | } | ||
| 11516 | popScope(); | ||
| 11517 | temp.push_back(indent() + "until "s + condStr + nl(repeatNode)); | ||
| 11518 | if (expList) { | ||
| 11519 | auto assign = x->new_ptr<Assign_t>(); | ||
| 11520 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | ||
| 11521 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 11522 | assignment->expList.set(expList); | ||
| 11523 | assignment->action.set(assign); | ||
| 11524 | transformAssignment(assignment, temp); | ||
| 11525 | if (extraScope) popScope(); | ||
| 11526 | } else { | ||
| 11527 | temp.push_back(indent() + "return "s + accumVar + nl(repeatNode)); | ||
| 11528 | } | ||
| 11529 | if (expList && extraScope) { | ||
| 11530 | temp.push_back(indent() + "end"s + nl(repeatNode)); | ||
| 11531 | } | ||
| 11532 | out.push_back(join(temp)); | ||
| 11533 | } | ||
| 11534 | |||
| 11535 | void transformRepeatClosure(Repeat_t* repeatNode, str_list& out) { | ||
| 11536 | auto x = repeatNode; | ||
| 11537 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 11538 | simpleValue->value.set(repeatNode); | ||
| 11539 | if (transformAsUpValueFunc(newExp(simpleValue, x), out)) { | ||
| 11540 | return; | ||
| 11541 | } | ||
| 11542 | str_list temp; | ||
| 11543 | pushAnonFunctionScope(); | ||
| 11544 | pushAnonVarArg(); | ||
| 11545 | std::string& funcStart = temp.emplace_back(); | ||
| 11546 | pushScope(); | ||
| 11547 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 11548 | addToScope(accumVar); | ||
| 11549 | auto lenVar = getUnusedName("_len_"sv); | ||
| 11550 | addToScope(lenVar); | ||
| 11551 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 11552 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(repeatNode); | ||
| 11553 | temp.emplace_back(clearBuf()); | ||
| 11554 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nl(repeatNode)); | ||
| 11555 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 11556 | temp.push_back(indent() + "repeat"s + nl(repeatNode)); | ||
| 11557 | pushScope(); | ||
| 11558 | if (hasBreakWithValue(breakLoopType)) { | ||
| 11559 | lenAssign.clear(); | ||
| 11560 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 11561 | } else { | ||
| 11562 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11563 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 11564 | assignLeft->followStmt = followStmt.get(); | ||
| 11565 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11566 | if (!assignLeft->followStmtProcessed) { | ||
| 11567 | lenAssign.clear(); | ||
| 11568 | } | ||
| 11569 | } | ||
| 11570 | popScope(); | ||
| 11571 | temp.push_back(indent() + "until "s + condStr + nl(repeatNode)); | ||
| 11572 | temp.push_back(indent() + "return "s + accumVar + nl(repeatNode)); | ||
| 11573 | popScope(); | ||
| 11574 | funcStart = anonFuncStart() + nl(repeatNode); | ||
| 11575 | temp.push_back(indent() + anonFuncEnd()); | ||
| 11576 | popAnonVarArg(); | ||
| 11577 | popFunctionScope(); | ||
| 11578 | out.push_back(join(temp)); | ||
| 11579 | } | ||
| 11580 | |||
| 10730 | void transformRepeat(Repeat_t* repeat, str_list& out) { | 11581 | void transformRepeat(Repeat_t* repeat, str_list& out) { |
| 10731 | str_list temp; | 11582 | str_list temp; |
| 10732 | pushScope(); | 11583 | pushScope(); |
| @@ -10737,9 +11588,9 @@ private: | |||
| 10737 | temp.push_back(condVar); | 11588 | temp.push_back(condVar); |
| 10738 | } | 11589 | } |
| 10739 | popScope(); | 11590 | popScope(); |
| 10740 | _buf << indent() << "repeat"sv << nll(repeat); | 11591 | _buf << indent() << "repeat"sv << nl(repeat); |
| 10741 | _buf << temp.front(); | 11592 | _buf << temp.front(); |
| 10742 | _buf << indent() << "until "sv << temp.back() << nlr(repeat); | 11593 | _buf << indent() << "until "sv << temp.back() << nl(repeat); |
| 10743 | out.push_back(clearBuf()); | 11594 | out.push_back(clearBuf()); |
| 10744 | } | 11595 | } |
| 10745 | 11596 | ||
| @@ -10760,12 +11611,28 @@ private: | |||
| 10760 | pushScope(); | 11611 | pushScope(); |
| 10761 | } | 11612 | } |
| 10762 | bool extraScope = false; | 11613 | bool extraScope = false; |
| 11614 | if (switchNode->assignment) { | ||
| 11615 | if (needScope) { | ||
| 11616 | extraScope = true; | ||
| 11617 | temp.push_back(indent() + "do"s + nl(x)); | ||
| 11618 | pushScope(); | ||
| 11619 | } | ||
| 11620 | auto asmt = x->new_ptr<ExpListAssign_t>(); | ||
| 11621 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 11622 | expList->exprs.push_back(switchNode->target); | ||
| 11623 | if (switchNode->assignment->expList) { | ||
| 11624 | expList->exprs.dup(switchNode->assignment->expList->exprs); | ||
| 11625 | } | ||
| 11626 | asmt->expList.set(expList); | ||
| 11627 | asmt->action.set(switchNode->assignment->assign); | ||
| 11628 | transformAssignment(asmt, temp); | ||
| 11629 | } | ||
| 10763 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); | 11630 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); |
| 10764 | if (objVar.empty() || !isLocal(objVar)) { | 11631 | if (objVar.empty() || !isLocal(objVar)) { |
| 10765 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 11632 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
| 10766 | if (needScope) { | 11633 | if (needScope && !extraScope) { |
| 10767 | extraScope = true; | 11634 | extraScope = true; |
| 10768 | temp.push_back(indent() + "do"s + nll(x)); | 11635 | temp.push_back(indent() + "do"s + nl(x)); |
| 10769 | pushScope(); | 11636 | pushScope(); |
| 10770 | } | 11637 | } |
| 10771 | } | 11638 | } |
| @@ -10795,13 +11662,13 @@ private: | |||
| 10795 | } | 11662 | } |
| 10796 | if (tableMatching) { | 11663 | if (tableMatching) { |
| 10797 | if (!firstBranch) { | 11664 | if (!firstBranch) { |
| 10798 | temp.push_back(indent() + "else"s + nll(branch)); | 11665 | temp.push_back(indent() + "else"s + nl(branch)); |
| 10799 | pushScope(); | 11666 | pushScope(); |
| 10800 | addScope++; | 11667 | addScope++; |
| 10801 | } | 11668 | } |
| 10802 | if (tabCheckVar.empty()) { | 11669 | if (tabCheckVar.empty()) { |
| 10803 | if (!extraScope && needScope) { | 11670 | if (!extraScope && needScope) { |
| 10804 | temp.push_back(indent() + "do"s + nll(branch)); | 11671 | temp.push_back(indent() + "do"s + nl(branch)); |
| 10805 | pushScope(); | 11672 | pushScope(); |
| 10806 | extraScope = true; | 11673 | extraScope = true; |
| 10807 | } | 11674 | } |
| @@ -10809,17 +11676,17 @@ private: | |||
| 10809 | forceAddToScope(typeVar); | 11676 | forceAddToScope(typeVar); |
| 10810 | tabCheckVar = getUnusedName("_tab_"sv); | 11677 | tabCheckVar = getUnusedName("_tab_"sv); |
| 10811 | forceAddToScope(tabCheckVar); | 11678 | forceAddToScope(tabCheckVar); |
| 10812 | temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch, AccessType::Read) + '(' + objVar + ')' + nll(branch)); | 11679 | temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch, AccessType::Read) + '(' + objVar + ')' + nl(branch)); |
| 10813 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nll(branch)); | 11680 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nl(branch)); |
| 10814 | } | 11681 | } |
| 10815 | std::string matchVar; | 11682 | std::string matchVar; |
| 10816 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; | 11683 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; |
| 10817 | if (!lastBranch) { | 11684 | if (!lastBranch) { |
| 10818 | matchVar = getUnusedName("_match_"sv); | 11685 | matchVar = getUnusedName("_match_"sv); |
| 10819 | forceAddToScope(matchVar); | 11686 | forceAddToScope(matchVar); |
| 10820 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nll(branch)); | 11687 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nl(branch)); |
| 10821 | } | 11688 | } |
| 10822 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | 11689 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nl(branch)); |
| 10823 | pushScope(); | 11690 | pushScope(); |
| 10824 | auto chainValue = toAst<ChainValue_t>(objVar, branch); | 11691 | auto chainValue = toAst<ChainValue_t>(objVar, branch); |
| 10825 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), newExp(chainValue, branch), branch); | 11692 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), newExp(chainValue, branch), branch); |
| @@ -10862,21 +11729,21 @@ private: | |||
| 10862 | } | 11729 | } |
| 10863 | } | 11730 | } |
| 10864 | if (!conds.empty()) { | 11731 | if (!conds.empty()) { |
| 10865 | temp.push_back(indent() + "if "s + join(conds, " and "sv) + " then"s + nll(branch)); | 11732 | temp.push_back(indent() + "if "s + join(conds, " and "sv) + " then"s + nl(branch)); |
| 10866 | pushScope(); | 11733 | pushScope(); |
| 10867 | } | 11734 | } |
| 10868 | if (!lastBranch) { | 11735 | if (!lastBranch) { |
| 10869 | temp.push_back(indent() + matchVar + " = true"s + nll(branch)); | 11736 | temp.push_back(indent() + matchVar + " = true"s + nl(branch)); |
| 10870 | } | 11737 | } |
| 10871 | transform_plain_body(branch->body, temp, usage, assignList); | 11738 | transform_plain_body(branch->body, temp, usage, assignList); |
| 10872 | if (!conds.empty()) { | 11739 | if (!conds.empty()) { |
| 10873 | popScope(); | 11740 | popScope(); |
| 10874 | temp.push_back(indent() + "end"s + nll(branch)); | 11741 | temp.push_back(indent() + "end"s + nl(branch)); |
| 10875 | } | 11742 | } |
| 10876 | if (!lastBranch) { | 11743 | if (!lastBranch) { |
| 10877 | popScope(); | 11744 | popScope(); |
| 10878 | temp.push_back(indent() + "end"s + nll(branch)); | 11745 | temp.push_back(indent() + "end"s + nl(branch)); |
| 10879 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nll(branch)); | 11746 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nl(branch)); |
| 10880 | pushScope(); | 11747 | pushScope(); |
| 10881 | addScope++; | 11748 | addScope++; |
| 10882 | } else { | 11749 | } else { |
| @@ -10896,7 +11763,7 @@ private: | |||
| 10896 | } | 11763 | } |
| 10897 | temp.back().append(' ' + tmp.back() + " == "s + (exp == exprs.back() ? objVar : objVar + " or"s)); | 11764 | temp.back().append(' ' + tmp.back() + " == "s + (exp == exprs.back() ? objVar : objVar + " or"s)); |
| 10898 | } | 11765 | } |
| 10899 | temp.back().append(" then"s + nll(branch)); | 11766 | temp.back().append(" then"s + nl(branch)); |
| 10900 | pushScope(); | 11767 | pushScope(); |
| 10901 | transform_plain_body(branch->body, temp, usage, assignList); | 11768 | transform_plain_body(branch->body, temp, usage, assignList); |
| 10902 | popScope(); | 11769 | popScope(); |
| @@ -10904,7 +11771,7 @@ private: | |||
| 10904 | } | 11771 | } |
| 10905 | if (switchNode->lastBranch) { | 11772 | if (switchNode->lastBranch) { |
| 10906 | if (!firstBranch) { | 11773 | if (!firstBranch) { |
| 10907 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); | 11774 | temp.push_back(indent() + "else"s + nl(switchNode->lastBranch)); |
| 10908 | pushScope(); | 11775 | pushScope(); |
| 10909 | } else { | 11776 | } else { |
| 10910 | addScope--; | 11777 | addScope--; |
| @@ -10914,20 +11781,20 @@ private: | |||
| 10914 | } | 11781 | } |
| 10915 | while (addScope > 0) { | 11782 | while (addScope > 0) { |
| 10916 | addScope--; | 11783 | addScope--; |
| 10917 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11784 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10918 | popScope(); | 11785 | popScope(); |
| 10919 | } | 11786 | } |
| 10920 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11787 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10921 | if (usage == ExpUsage::Closure) { | 11788 | if (usage == ExpUsage::Closure) { |
| 10922 | popFunctionScope(); | 11789 | popFunctionScope(); |
| 10923 | popScope(); | 11790 | popScope(); |
| 10924 | *funcStart = anonFuncStart() + nll(switchNode); | 11791 | *funcStart = anonFuncStart() + nl(switchNode); |
| 10925 | temp.push_back(indent() + anonFuncEnd()); | 11792 | temp.push_back(indent() + anonFuncEnd()); |
| 10926 | popAnonVarArg(); | 11793 | popAnonVarArg(); |
| 10927 | } | 11794 | } |
| 10928 | if (extraScope) { | 11795 | if (extraScope) { |
| 10929 | popScope(); | 11796 | popScope(); |
| 10930 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11797 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10931 | } | 11798 | } |
| 10932 | out.push_back(join(temp)); | 11799 | out.push_back(join(temp)); |
| 10933 | } | 11800 | } |
| @@ -10946,7 +11813,7 @@ private: | |||
| 10946 | } | 11813 | } |
| 10947 | auto preDefine = toLocalDecl(defs); | 11814 | auto preDefine = toLocalDecl(defs); |
| 10948 | if (!preDefine.empty()) { | 11815 | if (!preDefine.empty()) { |
| 10949 | out.push_back(preDefine + nll(local)); | 11816 | out.push_back(preDefine + nl(local)); |
| 10950 | } | 11817 | } |
| 10951 | } | 11818 | } |
| 10952 | } | 11819 | } |
| @@ -11151,7 +12018,7 @@ private: | |||
| 11151 | } | 12018 | } |
| 11152 | str_list temp; | 12019 | str_list temp; |
| 11153 | if (localAttrib->forceLocal) { | 12020 | if (localAttrib->forceLocal) { |
| 11154 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 12021 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nl(x)); |
| 11155 | } | 12022 | } |
| 11156 | transformAssignment(assignment, temp); | 12023 | transformAssignment(assignment, temp); |
| 11157 | for (const auto& name : vars) { | 12024 | for (const auto& name : vars) { |
| @@ -11197,13 +12064,13 @@ private: | |||
| 11197 | auto rit = items.begin(); | 12064 | auto rit = items.begin(); |
| 11198 | str_list tmp; | 12065 | str_list tmp; |
| 11199 | while (lit != vars.end()) { | 12066 | while (lit != vars.end()) { |
| 11200 | tmp.push_back(indent() + "local "s + *lit + (target >= 504 ? " <close> = "s : " = "s) + *rit + nll(x)); | 12067 | tmp.push_back(indent() + "local "s + *lit + (target >= 504 ? " <close> = "s : " = "s) + *rit + nl(x)); |
| 11201 | lit++; | 12068 | lit++; |
| 11202 | rit++; | 12069 | rit++; |
| 11203 | } | 12070 | } |
| 11204 | temp.push_back(join(tmp)); | 12071 | temp.push_back(join(tmp)); |
| 11205 | } else { | 12072 | } else { |
| 11206 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 12073 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(items, ", "sv) + nl(x)); |
| 11207 | str_list leftVars; | 12074 | str_list leftVars; |
| 11208 | pushScope(); | 12075 | pushScope(); |
| 11209 | for (size_t i = 0; i < vars.size(); i++) { | 12076 | for (size_t i = 0; i < vars.size(); i++) { |
| @@ -11224,7 +12091,7 @@ private: | |||
| 11224 | for (auto item : assignA->values.objects()) { | 12091 | for (auto item : assignA->values.objects()) { |
| 11225 | transformAssignItem(item, items); | 12092 | transformAssignItem(item, items); |
| 11226 | } | 12093 | } |
| 11227 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 12094 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nl(x)); |
| 11228 | } | 12095 | } |
| 11229 | for (const auto& var : vars) { | 12096 | for (const auto& var : vars) { |
| 11230 | markVarLocalConst(var); | 12097 | markVarLocalConst(var); |
| @@ -11249,7 +12116,7 @@ private: | |||
| 11249 | vars.push_back(item.targetVar); | 12116 | vars.push_back(item.targetVar); |
| 11250 | } | 12117 | } |
| 11251 | } | 12118 | } |
| 11252 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 12119 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nl(x)); |
| 11253 | transformAssignment(assignment, temp); | 12120 | transformAssignment(assignment, temp); |
| 11254 | for (const auto& name : vars) { | 12121 | for (const auto& name : vars) { |
| 11255 | markVarLocalConst(name); | 12122 | markVarLocalConst(name); |
| @@ -11270,7 +12137,7 @@ private: | |||
| 11270 | auto assignment = assignmentFrom(exp, breakLoop->value, breakLoop); | 12137 | auto assignment = assignmentFrom(exp, breakLoop->value, breakLoop); |
| 11271 | transformAssignment(assignment, out); | 12138 | transformAssignment(assignment, out); |
| 11272 | } | 12139 | } |
| 11273 | out.push_back(indent() + keyword + nll(breakLoop)); | 12140 | out.push_back(indent() + keyword + nl(breakLoop)); |
| 11274 | return; | 12141 | return; |
| 11275 | } | 12142 | } |
| 11276 | if (_continueVars.empty()) throw CompileError("continue is not inside a loop"sv, breakLoop); | 12143 | if (_continueVars.empty()) throw CompileError("continue is not inside a loop"sv, breakLoop); |
| @@ -11283,8 +12150,8 @@ private: | |||
| 11283 | if (!temp.empty()) { | 12150 | if (!temp.empty()) { |
| 11284 | _buf << temp.back(); | 12151 | _buf << temp.back(); |
| 11285 | } | 12152 | } |
| 11286 | _buf << indent() << item.var << " = true"sv << nll(breakLoop); | 12153 | _buf << indent() << item.var << " = true"sv << nl(breakLoop); |
| 11287 | _buf << indent() << "break"sv << nll(breakLoop); | 12154 | _buf << indent() << "break"sv << nl(breakLoop); |
| 11288 | out.push_back(clearBuf()); | 12155 | out.push_back(clearBuf()); |
| 11289 | } else { | 12156 | } else { |
| 11290 | transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp); | 12157 | transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp); |
| @@ -11296,7 +12163,7 @@ private: | |||
| 11296 | if (getLuaTarget(label) < 502) { | 12163 | if (getLuaTarget(label) < 502) { |
| 11297 | throw CompileError("label statement is not available when not targeting Lua version 5.2 or higher"sv, label); | 12164 | throw CompileError("label statement is not available when not targeting Lua version 5.2 or higher"sv, label); |
| 11298 | } | 12165 | } |
| 11299 | auto labelStr = unicodeVariableFrom(label->label->name); | 12166 | auto labelStr = unicodeVariableFrom(label->label); |
| 11300 | int currentScope = _gotoScopes.top(); | 12167 | int currentScope = _gotoScopes.top(); |
| 11301 | if (static_cast<int>(_labels.size()) <= currentScope) { | 12168 | if (static_cast<int>(_labels.size()) <= currentScope) { |
| 11302 | _labels.resize(currentScope + 1, std::nullopt); | 12169 | _labels.resize(currentScope + 1, std::nullopt); |
| @@ -11310,16 +12177,16 @@ private: | |||
| 11310 | throw CompileError("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label); | 12177 | throw CompileError("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label); |
| 11311 | } | 12178 | } |
| 11312 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; | 12179 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; |
| 11313 | out.push_back(indent() + "::"s + labelStr + "::"s + nll(label)); | 12180 | out.push_back(indent() + "::"s + labelStr + "::"s + nl(label)); |
| 11314 | } | 12181 | } |
| 11315 | 12182 | ||
| 11316 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 12183 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
| 11317 | if (getLuaTarget(gotoNode) < 502) { | 12184 | if (getLuaTarget(gotoNode) < 502) { |
| 11318 | throw CompileError("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode); | 12185 | throw CompileError("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode); |
| 11319 | } | 12186 | } |
| 11320 | auto labelStr = unicodeVariableFrom(gotoNode->label->name); | 12187 | auto labelStr = unicodeVariableFrom(gotoNode->label); |
| 11321 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); | 12188 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); |
| 11322 | out.push_back(indent() + "goto "s + labelStr + nll(gotoNode)); | 12189 | out.push_back(indent() + "goto "s + labelStr + nl(gotoNode)); |
| 11323 | } | 12190 | } |
| 11324 | 12191 | ||
| 11325 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { | 12192 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { |
| @@ -11383,13 +12250,13 @@ private: | |||
| 11383 | temp.push_back(getPreDefineLine(assignment)); | 12250 | temp.push_back(getPreDefineLine(assignment)); |
| 11384 | } | 12251 | } |
| 11385 | assignments.push_front(assignmentFrom(newValue, value, value)); | 12252 | assignments.push_front(assignmentFrom(newValue, value, value)); |
| 11386 | temp.push_back(indent() + "do"s + nll(x)); | 12253 | temp.push_back(indent() + "do"s + nl(x)); |
| 11387 | pushScope(); | 12254 | pushScope(); |
| 11388 | for (auto item : assignments.objects()) { | 12255 | for (auto item : assignments.objects()) { |
| 11389 | transformAssignment(static_cast<ExpListAssign_t*>(item), temp); | 12256 | transformAssignment(static_cast<ExpListAssign_t*>(item), temp); |
| 11390 | } | 12257 | } |
| 11391 | popScope(); | 12258 | popScope(); |
| 11392 | temp.push_back(indent() + "end"s + nll(x)); | 12259 | temp.push_back(indent() + "end"s + nl(x)); |
| 11393 | out.push_back(join(temp)); | 12260 | out.push_back(join(temp)); |
| 11394 | } | 12261 | } |
| 11395 | }; | 12262 | }; |
diff --git a/src/yuescript/yue_compiler.h b/src/yuescript/yue_compiler.h index d352636..eb5fb16 100644 --- a/src/yuescript/yue_compiler.h +++ b/src/yuescript/yue_compiler.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -31,6 +31,7 @@ struct YueConfig { | |||
| 31 | bool reserveLineNumber = true; | 31 | bool reserveLineNumber = true; |
| 32 | bool useSpaceOverTab = false; | 32 | bool useSpaceOverTab = false; |
| 33 | bool reserveComment = false; | 33 | bool reserveComment = false; |
| 34 | bool lax = false; | ||
| 34 | // internal options | 35 | // internal options |
| 35 | bool exporting = false; | 36 | bool exporting = false; |
| 36 | bool profiling = false; | 37 | bool profiling = false; |
| @@ -51,6 +52,7 @@ struct GlobalVar { | |||
| 51 | int line; | 52 | int line; |
| 52 | int col; | 53 | int col; |
| 53 | AccessType accessType; | 54 | AccessType accessType; |
| 55 | bool defined; | ||
| 54 | }; | 56 | }; |
| 55 | 57 | ||
| 56 | using GlobalVars = std::vector<GlobalVar>; | 58 | using GlobalVars = std::vector<GlobalVar>; |
diff --git a/src/yuescript/yue_parser.cpp b/src/yuescript/yue_parser.cpp index cd1fd48..1dfe978 100644 --- a/src/yuescript/yue_parser.cpp +++ b/src/yuescript/yue_parser.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -41,6 +41,24 @@ public: | |||
| 41 | int col; | 41 | int col; |
| 42 | }; | 42 | }; |
| 43 | 43 | ||
| 44 | #define RaiseError(msg, item) \ | ||
| 45 | do { \ | ||
| 46 | if (reinterpret_cast<State*>(item.user_data)->lax) { \ | ||
| 47 | return false; \ | ||
| 48 | } else { \ | ||
| 49 | throw ParserError(msg, item.begin); \ | ||
| 50 | } \ | ||
| 51 | } while (false) | ||
| 52 | |||
| 53 | #define RaiseErrorI(msg, item) \ | ||
| 54 | do { \ | ||
| 55 | if (reinterpret_cast<State*>(item.user_data)->lax) { \ | ||
| 56 | return -1; \ | ||
| 57 | } else { \ | ||
| 58 | throw ParserError(msg, item.begin); \ | ||
| 59 | } \ | ||
| 60 | } while (false) | ||
| 61 | |||
| 44 | // clang-format off | 62 | // clang-format off |
| 45 | YueParser::YueParser() { | 63 | YueParser::YueParser() { |
| 46 | plain_space = *set(" \t"); | 64 | plain_space = *set(" \t"); |
| @@ -57,18 +75,20 @@ YueParser::YueParser() { | |||
| 57 | space = -(and_(set(" \t-\\")) >> *space_one >> -comment); | 75 | space = -(and_(set(" \t-\\")) >> *space_one >> -comment); |
| 58 | space_break = space >> line_break; | 76 | space_break = space >> line_break; |
| 59 | white = space >> *(line_break >> space); | 77 | white = space >> *(line_break >> space); |
| 78 | plain_white = plain_space >> *(line_break >> plain_space); | ||
| 60 | alpha_num = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; | 79 | alpha_num = range('a', 'z') | range('A', 'Z') | range('0', '9') | '_'; |
| 61 | not_alpha_num = not_(alpha_num); | 80 | not_alpha_num = not_(alpha_num); |
| 62 | Name = (range('a', 'z') | range('A', 'Z') | '_') >> *alpha_num >> not_(larger(255)); | 81 | Name = (range('a', 'z') | range('A', 'Z') | '_') >> *alpha_num >> not_(larger(255)); |
| 63 | UnicodeName = (range('a', 'z') | range('A', 'Z') | '_' | larger(255)) >> *(larger(255) | alpha_num); | 82 | UnicodeName = (range('a', 'z') | range('A', 'Z') | '_' | larger(255)) >> *(larger(255) | alpha_num); |
| 64 | num_expo = set("eE") >> -set("+-") >> num_char; | 83 | must_num_char = num_char | invalid_number_literal_error; |
| 65 | num_expo_hex = set("pP") >> -set("+-") >> num_char; | 84 | num_expo = set("eE") >> -set("+-") >> must_num_char; |
| 85 | num_expo_hex = set("pP") >> -set("+-") >> must_num_char; | ||
| 66 | lj_num = -set("uU") >> set("lL") >> set("lL"); | 86 | lj_num = -set("uU") >> set("lL") >> set("lL"); |
| 67 | num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9'))); | 87 | num_char = range('0', '9') >> *(range('0', '9') | '_' >> and_(range('0', '9'))); |
| 68 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); | 88 | num_char_hex = range('0', '9') | range('a', 'f') | range('A', 'F'); |
| 69 | num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex)); | 89 | num_lit = num_char_hex >> *(num_char_hex | '_' >> and_(num_char_hex)); |
| 70 | num_bin_lit = set("01") >> *(set("01") | '_' >> and_(set("01"))); | 90 | num_bin_lit = set("01") >> *(set("01") | '_' >> and_(set("01"))); |
| 71 | Num = | 91 | Num = ( |
| 72 | '0' >> ( | 92 | '0' >> ( |
| 73 | set("xX") >> ( | 93 | set("xX") >> ( |
| 74 | num_lit >> ( | 94 | num_lit >> ( |
| @@ -78,50 +98,122 @@ YueParser::YueParser() { | |||
| 78 | true_() | 98 | true_() |
| 79 | ) | ( | 99 | ) | ( |
| 80 | '.' >> num_lit >> -num_expo_hex | 100 | '.' >> num_lit >> -num_expo_hex |
| 81 | ) | 101 | ) | invalid_number_literal_error |
| 82 | ) | | 102 | ) | |
| 83 | set("bB") >> num_bin_lit | 103 | set("bB") >> (num_bin_lit | invalid_number_literal_error) |
| 84 | ) | | 104 | ) | |
| 85 | num_char >> ( | 105 | num_char >> ( |
| 86 | '.' >> num_char >> -num_expo | | 106 | '.' >> must_num_char >> -num_expo | |
| 87 | num_expo | | 107 | num_expo | |
| 88 | lj_num | | 108 | lj_num | |
| 89 | true_() | 109 | true_() |
| 90 | ) | | 110 | ) |
| 91 | '.' >> num_char >> -num_expo; | 111 | ) >> -(and_(alpha_num) >> invalid_number_literal_error) | |
| 112 | '.' >> num_char >> -num_expo >> -(and_(alpha_num) >> invalid_number_literal_error); | ||
| 92 | 113 | ||
| 93 | cut = false_(); | 114 | cut = false_(); |
| 94 | Seperator = true_(); | 115 | Seperator = true_(); |
| 95 | 116 | ||
| 96 | empty_block_error = pl::user(true_(), [](const item_t& item) { | 117 | auto expect_error = [](std::string_view msg) { |
| 97 | throw ParserError("must be followed by a statement or an indented block"sv, item.begin); | 118 | return pl::user(true_(), [msg](const item_t& item) { |
| 98 | return false; | 119 | RaiseError(msg, item); |
| 99 | }); | 120 | return false; |
| 100 | 121 | }); | |
| 101 | export_expression_error = pl::user(true_(), [](const item_t& item) { | 122 | }; |
| 102 | throw ParserError("invalid export expression"sv, item.begin); | ||
| 103 | return false; | ||
| 104 | }); | ||
| 105 | 123 | ||
| 106 | invalid_interpolation_error = pl::user(true_(), [](const item_t& item) { | 124 | empty_block_error = expect_error( |
| 107 | throw ParserError("invalid string interpolation"sv, item.begin); | 125 | "expected a valid statement or indented block"sv |
| 108 | return false; | 126 | ); |
| 109 | }); | 127 | export_expression_error = expect_error( |
| 110 | 128 | "invalid export expression"sv | |
| 111 | confusing_unary_not_error = pl::user(true_(), [](const item_t& item) { | 129 | ); |
| 112 | throw ParserError("deprecated use for unary operator 'not' to be here"sv, item.begin); | 130 | invalid_interpolation_error = expect_error( |
| 113 | return false; | 131 | "invalid string interpolation"sv |
| 114 | }); | 132 | ); |
| 115 | 133 | confusing_unary_not_error = expect_error( | |
| 116 | table_key_pair_error = pl::user(true_(), [](const item_t& item) { | 134 | "deprecated use for unary operator 'not' to be here"sv |
| 117 | throw ParserError("can not put hash pair in a list"sv, item.begin); | 135 | ); |
| 118 | return false; | 136 | table_key_pair_error = expect_error( |
| 119 | }); | 137 | "can not put hash pair in a list"sv |
| 120 | 138 | ); | |
| 121 | if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { | 139 | assignment_expression_syntax_error = expect_error( |
| 122 | throw ParserError("use := for if-assignment expression"sv, item.begin); | 140 | "use := for assignment expression"sv |
| 123 | return false; | 141 | ); |
| 124 | }); | 142 | braces_expression_error = expect_error( |
| 143 | "syntax error in brace expression"sv | ||
| 144 | ); | ||
| 145 | brackets_expression_error = expect_error( | ||
| 146 | "unclosed bracket expression"sv | ||
| 147 | ); | ||
| 148 | slice_expression_error = expect_error( | ||
| 149 | "syntax error in slice expression"sv | ||
| 150 | ); | ||
| 151 | unclosed_single_string_error = expect_error( | ||
| 152 | "unclosed single-quoted string"sv | ||
| 153 | ); | ||
| 154 | unclosed_double_string_error = expect_error( | ||
| 155 | "unclosed double-quoted string"sv | ||
| 156 | ); | ||
| 157 | unclosed_lua_string_error = expect_error( | ||
| 158 | "unclosed Lua string"sv | ||
| 159 | ); | ||
| 160 | unexpected_comma_error = expect_error( | ||
| 161 | "got unexpected comma"sv | ||
| 162 | ); | ||
| 163 | parenthesis_error = expect_error( | ||
| 164 | "expected only one expression in parenthesis"sv | ||
| 165 | ); | ||
| 166 | dangling_clause_error = expect_error( | ||
| 167 | "dangling control clause"sv | ||
| 168 | ); | ||
| 169 | keyword_as_label_error = expect_error( | ||
| 170 | "keyword cannot be used as a label name"sv | ||
| 171 | ); | ||
| 172 | vararg_position_error = expect_error( | ||
| 173 | "vararg '...' must be the last parameter in function argument list"sv | ||
| 174 | ); | ||
| 175 | invalid_import_syntax_error = expect_error( | ||
| 176 | "invalid import syntax, expected `import \"X.mod\"`, `import \"X.mod\" as {:name}`, `from mod import name` or `import mod.name`"sv | ||
| 177 | ); | ||
| 178 | invalid_import_as_syntax_error = expect_error( | ||
| 179 | "invalid import syntax, expected `import \"X.mod\" as modname` or `import \"X.mod\" as {:name}`"sv | ||
| 180 | ); | ||
| 181 | expected_expression_error = expect_error( | ||
| 182 | "expected valid expression"sv | ||
| 183 | ); | ||
| 184 | invalid_from_import_error = expect_error( | ||
| 185 | "invalid import syntax, expected `from \"X.mod\" import name` or `from mod import name`"sv | ||
| 186 | ); | ||
| 187 | invalid_export_syntax_error = expect_error( | ||
| 188 | "invalid export syntax, expected `export item`, `export item = x`, `export.item = x` or `export default item`"sv | ||
| 189 | ); | ||
| 190 | invalid_macro_definition_error = expect_error( | ||
| 191 | "invalid macro definition, expected `macro Name = -> body` or `macro Name = $Name(...)`"sv | ||
| 192 | ); | ||
| 193 | invalid_global_declaration_error = expect_error( | ||
| 194 | "invalid global declaration, expected `global name`, `global name = ...`, `global *`, `global ^` or `global class ...`"sv | ||
| 195 | ); | ||
| 196 | invalid_local_declaration_error = expect_error( | ||
| 197 | "invalid local declaration, expected `local name`, `local name = ...`, `local *` or `local ^`"sv | ||
| 198 | ); | ||
| 199 | invalid_with_syntax_error = expect_error( | ||
| 200 | "invalid 'with' statement"sv | ||
| 201 | ); | ||
| 202 | invalid_try_syntax_error = expect_error( | ||
| 203 | "invalid 'try' expression, expected `try expr` or `try block` optionally followed by `catch err` with a handling block"sv | ||
| 204 | ); | ||
| 205 | keyword_as_identifier_syntax_error = expect_error( | ||
| 206 | "can not use keyword as identifier"sv | ||
| 207 | ); | ||
| 208 | invalid_number_literal_error = expect_error( | ||
| 209 | "invalid numeric literal"sv | ||
| 210 | ); | ||
| 211 | invalid_import_literal_error = expect_error( | ||
| 212 | "invalid import path literal, expected a dotted path like X.Y.Z"sv | ||
| 213 | ); | ||
| 214 | expected_indentifier_error = expect_error( | ||
| 215 | "expected valid identifer"sv | ||
| 216 | ); | ||
| 125 | 217 | ||
| 126 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) | 218 | #define ensure(patt, finally) ((patt) >> (finally) | (finally) >> cut) |
| 127 | 219 | ||
| @@ -162,6 +254,13 @@ YueParser::YueParser() { | |||
| 162 | ) \ | 254 | ) \ |
| 163 | ) | 255 | ) |
| 164 | 256 | ||
| 257 | #define disable_until_rule(patt) ( \ | ||
| 258 | disable_until >> ( \ | ||
| 259 | (patt) >> enable_until | \ | ||
| 260 | enable_until >> cut \ | ||
| 261 | ) \ | ||
| 262 | ) | ||
| 263 | |||
| 165 | #define body_with(str) ( \ | 264 | #define body_with(str) ( \ |
| 166 | key(str) >> space >> (in_block | Statement) | \ | 265 | key(str) >> space >> (in_block | Statement) | \ |
| 167 | in_block | \ | 266 | in_block | \ |
| @@ -194,20 +293,6 @@ YueParser::YueParser() { | |||
| 194 | return isValid; | 293 | return isValid; |
| 195 | }); | 294 | }); |
| 196 | 295 | ||
| 197 | LabelName = pl::user(UnicodeName, [](const item_t& item) { | ||
| 198 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 199 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) { | ||
| 200 | if (*it > 255) { | ||
| 201 | st->buffer.clear(); | ||
| 202 | return true; | ||
| 203 | } | ||
| 204 | st->buffer += static_cast<char>(*it); | ||
| 205 | } | ||
| 206 | auto isValid = LuaKeywords.find(st->buffer) == LuaKeywords.end(); | ||
| 207 | st->buffer.clear(); | ||
| 208 | return isValid; | ||
| 209 | }); | ||
| 210 | |||
| 211 | LuaKeyword = pl::user(Name, [](const item_t& item) { | 296 | LuaKeyword = pl::user(Name, [](const item_t& item) { |
| 212 | State* st = reinterpret_cast<State*>(item.user_data); | 297 | State* st = reinterpret_cast<State*>(item.user_data); |
| 213 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) st->buffer += static_cast<char>(*it); | 298 | for (auto it = item.begin->m_it; it != item.end->m_it; ++it) st->buffer += static_cast<char>(*it); |
| @@ -223,29 +308,46 @@ YueParser::YueParser() { | |||
| 223 | 308 | ||
| 224 | SelfItem = SelfClassName | SelfClass | SelfName | Self; | 309 | SelfItem = SelfClassName | SelfClass | SelfName | Self; |
| 225 | KeyName = SelfItem | Name | UnicodeName; | 310 | KeyName = SelfItem | Name | UnicodeName; |
| 311 | VarArgDef = "..." >> -(space >> Variable); | ||
| 226 | VarArg = "..."; | 312 | VarArg = "..."; |
| 227 | 313 | ||
| 228 | check_indent = pl::user(plain_space, [](const item_t& item) { | 314 | auto getIndent = [](const item_t& item) -> int { |
| 315 | if (item.begin->m_it == item.end->m_it) return 0; | ||
| 316 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 317 | bool useTab = false; | ||
| 318 | if (st->useTab) { | ||
| 319 | useTab = st->useTab.value(); | ||
| 320 | } else { | ||
| 321 | useTab = *item.begin->m_it == '\t'; | ||
| 322 | st->useTab = useTab; | ||
| 323 | } | ||
| 229 | int indent = 0; | 324 | int indent = 0; |
| 230 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { | 325 | if (useTab) { |
| 231 | switch (*i) { | 326 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { |
| 232 | case ' ': indent++; break; | 327 | switch (*i) { |
| 233 | case '\t': indent += 4; break; | 328 | case '\t': indent += 4; break; |
| 329 | default: RaiseErrorI("can not mix the use of tabs and spaces as indents"sv, item); break; | ||
| 330 | } | ||
| 331 | } | ||
| 332 | } else { | ||
| 333 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { | ||
| 334 | switch (*i) { | ||
| 335 | case ' ': indent++; break; | ||
| 336 | default: RaiseErrorI("can not mix the use of tabs and spaces as indents"sv, item); break; | ||
| 337 | } | ||
| 234 | } | 338 | } |
| 235 | } | 339 | } |
| 340 | return indent; | ||
| 341 | }; | ||
| 342 | |||
| 343 | check_indent = pl::user(plain_space, [getIndent](const item_t& item) { | ||
| 236 | State* st = reinterpret_cast<State*>(item.user_data); | 344 | State* st = reinterpret_cast<State*>(item.user_data); |
| 237 | return st->indents.top() == indent; | 345 | return st->indents.top() == getIndent(item); |
| 238 | }); | 346 | }); |
| 239 | check_indent_match = and_(check_indent); | 347 | check_indent_match = and_(check_indent); |
| 240 | 348 | ||
| 241 | advance = pl::user(plain_space, [](const item_t& item) { | 349 | advance = pl::user(plain_space, [getIndent](const item_t& item) { |
| 242 | int indent = 0; | 350 | int indent = getIndent(item); |
| 243 | for (input_it i = item.begin->m_it; i != item.end->m_it; ++i) { | ||
| 244 | switch (*i) { | ||
| 245 | case ' ': indent++; break; | ||
| 246 | case '\t': indent += 4; break; | ||
| 247 | } | ||
| 248 | } | ||
| 249 | State* st = reinterpret_cast<State*>(item.user_data); | 351 | State* st = reinterpret_cast<State*>(item.user_data); |
| 250 | int top = st->indents.top(); | 352 | int top = st->indents.top(); |
| 251 | if (top != -1 && indent > top) { | 353 | if (top != -1 && indent > top) { |
| @@ -265,6 +367,12 @@ YueParser::YueParser() { | |||
| 265 | } | 367 | } |
| 266 | } | 368 | } |
| 267 | State* st = reinterpret_cast<State*>(item.user_data); | 369 | State* st = reinterpret_cast<State*>(item.user_data); |
| 370 | if (st->indents.empty()) { | ||
| 371 | RaiseError("unknown indent level"sv, item); | ||
| 372 | } | ||
| 373 | if (st->indents.top() > indent) { | ||
| 374 | RaiseError("unexpected dedent"sv, item); | ||
| 375 | } | ||
| 268 | st->indents.push(indent); | 376 | st->indents.push(indent); |
| 269 | return true; | 377 | return true; |
| 270 | }); | 378 | }); |
| @@ -285,31 +393,41 @@ YueParser::YueParser() { | |||
| 285 | in_block = space_break >> *(*set(" \t") >> line_break) >> advance_match >> ensure(Block, pop_indent); | 393 | in_block = space_break >> *(*set(" \t") >> line_break) >> advance_match >> ensure(Block, pop_indent); |
| 286 | 394 | ||
| 287 | LocalFlag = expr('*') | '^'; | 395 | LocalFlag = expr('*') | '^'; |
| 288 | LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); | 396 | LocalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); |
| 289 | Local = key("local") >> space >> (LocalFlag | LocalValues); | 397 | Local = key("local") >> space >> (LocalFlag | LocalValues | invalid_local_declaration_error); |
| 290 | 398 | ||
| 291 | ConstAttrib = key("const"); | 399 | ConstAttrib = key("const"); |
| 292 | CloseAttrib = key("close"); | 400 | CloseAttrib = key("close"); |
| 293 | local_const_item = Variable | SimpleTable | TableLit | Comprehension; | 401 | local_const_item = Variable | SimpleTable | TableLit | Comprehension; |
| 294 | LocalAttrib = ( | 402 | LocalAttrib = ( |
| 295 | ConstAttrib >> Seperator >> space >> local_const_item >> *(space >> ',' >> space >> local_const_item) | | 403 | ConstAttrib >> Seperator >> space >> local_const_item >> *(space >> ',' >> space >> local_const_item) | |
| 296 | CloseAttrib >> Seperator >> space >> Variable >> *(space >> ',' >> space >> Variable) | 404 | CloseAttrib >> Seperator >> space >> must_variable >> *(space >> ',' >> space >> must_variable) |
| 297 | ) >> space >> Assign; | 405 | ) >> space >> Assign; |
| 298 | 406 | ||
| 299 | ColonImportName = '\\' >> space >> Variable; | 407 | ColonImportName = '\\' >> must_variable; |
| 300 | import_name = ColonImportName | Variable; | 408 | import_name = not_(key("from")) >> (ColonImportName | must_variable); |
| 301 | import_name_list = Seperator >> *space_break >> space >> import_name >> *((+space_break | space >> ',' >> *space_break) >> space >> import_name); | 409 | import_name_list = Seperator >> *space_break >> space >> import_name >> *( |
| 302 | ImportFrom = import_name_list >> *space_break >> space >> key("from") >> space >> (ImportLiteral | not_(String) >> Exp); | 410 | (+space_break | space >> ',' >> *space_break) >> space >> import_name |
| 303 | from_import_name_list_line = import_name >> *(space >> ',' >> space >> import_name); | 411 | ); |
| 412 | ImportFrom = import_name_list >> *space_break >> space >> key("from") >> space >> (ImportLiteral | not_(String) >> must_exp); | ||
| 413 | from_import_name_list_line = import_name >> *(space >> ',' >> space >> not_(line_break) >> import_name); | ||
| 304 | from_import_name_in_block = +space_break >> advance_match >> ensure(space >> from_import_name_list_line >> *(-(space >> ',') >> +space_break >> check_indent_match >> space >> from_import_name_list_line), pop_indent); | 414 | from_import_name_in_block = +space_break >> advance_match >> ensure(space >> from_import_name_list_line >> *(-(space >> ',') >> +space_break >> check_indent_match >> space >> from_import_name_list_line), pop_indent); |
| 305 | FromImport = key("from") >> space >> (ImportLiteral | not_(String) >> Exp) >> *space_break >> space >> key("import") >> space >> Seperator >> (from_import_name_list_line >> -(space >> ',') >> -from_import_name_in_block | from_import_name_in_block); | 415 | FromImport = key("from") >> space >> ( |
| 416 | ImportLiteral | not_(String) >> Exp | invalid_from_import_error | ||
| 417 | ) >> *space_break >> space >> ( | ||
| 418 | key("import") | invalid_from_import_error | ||
| 419 | ) >> space >> Seperator >> ( | ||
| 420 | from_import_name_in_block | | ||
| 421 | from_import_name_list_line >> -(space >> ',') >> -from_import_name_in_block | | ||
| 422 | invalid_from_import_error | ||
| 423 | ); | ||
| 306 | 424 | ||
| 307 | ImportLiteralInner = (range('a', 'z') | range('A', 'Z') | set("_-") | larger(255)) >> *(alpha_num | '-' | larger(255)); | 425 | ImportLiteralInner = (range('a', 'z') | range('A', 'Z') | set("_-") | larger(255)) >> *(alpha_num | '-' | larger(255)); |
| 308 | import_literal_chain = Seperator >> ImportLiteralInner >> *('.' >> ImportLiteralInner); | 426 | import_literal_chain = Seperator >> ImportLiteralInner >> *('.' >> ImportLiteralInner); |
| 309 | ImportLiteral = ( | 427 | ImportLiteral = ( |
| 310 | '\'' >> import_literal_chain >> '\'' | 428 | '\'' >> import_literal_chain >> -(not_('\'') >> invalid_import_literal_error) >> '\'' |
| 311 | ) | ( | 429 | ) | ( |
| 312 | '"' >> import_literal_chain >> '"' | 430 | '"' >> import_literal_chain >> -(not_('"') >> invalid_import_literal_error) >> '"' |
| 313 | ); | 431 | ); |
| 314 | 432 | ||
| 315 | MacroNamePair = MacroName >> ':' >> space >> MacroName; | 433 | MacroNamePair = MacroName >> ':' >> space >> MacroName; |
| @@ -325,7 +443,7 @@ YueParser::YueParser() { | |||
| 325 | Exp; | 443 | Exp; |
| 326 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); | 444 | import_tab_list = import_tab_item >> *(space >> ',' >> space >> import_tab_item); |
| 327 | import_tab_line = ( | 445 | import_tab_line = ( |
| 328 | push_indent_match >> (space >> import_tab_list >> pop_indent | pop_indent) | 446 | push_indent_match >> ensure(space >> import_tab_list, pop_indent) |
| 329 | ) | space; | 447 | ) | space; |
| 330 | import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); | 448 | import_tab_lines = space_break >> import_tab_line >> *(-(space >> ',') >> space_break >> import_tab_line) >> -(space >> ','); |
| 331 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; | 449 | import_tab_key_value = key_value | ':' >> MacroName | MacroNamePair | ImportAllMacro; |
| @@ -335,18 +453,22 @@ YueParser::YueParser() { | |||
| 335 | -(space >> ',') >> | 453 | -(space >> ',') >> |
| 336 | -import_tab_lines >> | 454 | -import_tab_lines >> |
| 337 | white >> | 455 | white >> |
| 338 | '}' | 456 | end_braces_expression |
| 339 | ) | ( | 457 | ) | ( |
| 340 | Seperator >> import_tab_key_value >> *(space >> ',' >> space >> import_tab_key_value) | 458 | Seperator >> import_tab_key_value >> *(space >> ',' >> space >> import_tab_key_value) |
| 341 | ); | 459 | ); |
| 342 | 460 | ||
| 343 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> (ImportTabLit | Variable | ImportAllMacro)); | 461 | ImportAs = ImportLiteral >> -(space >> key("as") >> space >> ( |
| 462 | ImportTabLit | Variable | ImportAllMacro | invalid_import_as_syntax_error | ||
| 463 | )); | ||
| 464 | |||
| 465 | ImportGlobal = Seperator >> UnicodeName >> *('.' >> UnicodeName) >> space >> not_(',' | key("from")) >> -(key("as") >> space >> must_variable); | ||
| 344 | 466 | ||
| 345 | Import = key("import") >> space >> (ImportAs | ImportFrom) | FromImport; | 467 | Import = key("import") >> space >> (ImportGlobal | ImportAs | ImportFrom | invalid_import_syntax_error) | FromImport; |
| 346 | 468 | ||
| 347 | Label = "::" >> LabelName >> "::"; | 469 | Label = "::" >> (and_(LuaKeyword >> "::") >> keyword_as_label_error | UnicodeName >> "::"); |
| 348 | 470 | ||
| 349 | Goto = key("goto") >> space >> LabelName; | 471 | Goto = key("goto") >> space >> (and_(LuaKeyword >> not_alpha_num) >> keyword_as_label_error | UnicodeName); |
| 350 | 472 | ||
| 351 | ShortTabAppending = "[]" >> space >> Assign; | 473 | ShortTabAppending = "[]" >> space >> Assign; |
| 352 | 474 | ||
| @@ -356,9 +478,14 @@ YueParser::YueParser() { | |||
| 356 | 478 | ||
| 357 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); | 479 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); |
| 358 | 480 | ||
| 359 | with_exp = ExpList >> -(space >> Assign); | 481 | must_exp = Exp | expected_expression_error; |
| 360 | 482 | ||
| 361 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 483 | with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error)) | expected_expression_error; |
| 484 | |||
| 485 | With = key("with") >> -ExistentialOp >> space >> ( | ||
| 486 | disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do") | | ||
| 487 | invalid_with_syntax_error | ||
| 488 | ); | ||
| 362 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 489 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); |
| 363 | switch_else = key("else") >> space >> body; | 490 | switch_else = key("else") >> space >> body; |
| 364 | 491 | ||
| @@ -370,9 +497,11 @@ YueParser::YueParser() { | |||
| 370 | 497 | ||
| 371 | SwitchList = Seperator >> ( | 498 | SwitchList = Seperator >> ( |
| 372 | and_(SimpleTable | TableLit) >> Exp | | 499 | and_(SimpleTable | TableLit) >> Exp | |
| 373 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | 500 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | |
| 501 | expected_expression_error | ||
| 374 | ); | 502 | ); |
| 375 | Switch = key("switch") >> space >> Exp >> | 503 | Switch = key("switch") >> space >> |
| 504 | must_exp >> -(space >> Assignment) >> | ||
| 376 | space >> Seperator >> ( | 505 | space >> Seperator >> ( |
| 377 | SwitchCase >> space >> ( | 506 | SwitchCase >> space >> ( |
| 378 | switch_block | | 507 | switch_block | |
| @@ -381,45 +510,53 @@ YueParser::YueParser() { | |||
| 381 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent | 510 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent |
| 382 | ); | 511 | ); |
| 383 | 512 | ||
| 384 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); | 513 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error); |
| 385 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); | 514 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))) | expected_expression_error; |
| 386 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); | 515 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); |
| 387 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; | 516 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; |
| 388 | IfType = (expr("if") | "unless") >> not_alpha_num; | 517 | IfType = (expr("if") | "unless") >> not_alpha_num; |
| 389 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; | 518 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; |
| 390 | 519 | ||
| 391 | WhileType = (expr("while") | "until") >> not_alpha_num; | 520 | WhileType = (expr("while") | pl::user("until", [](const item_t& item) { |
| 392 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | 521 | State* st = reinterpret_cast<State*>(item.user_data); |
| 393 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; | 522 | return st->noUntilStack.empty() || !st->noUntilStack.back(); |
| 523 | })) >> not_alpha_num; | ||
| 524 | While = key(WhileType) >> space >> (disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) | expected_expression_error) >> space >> opt_body_with("do"); | ||
| 525 | Repeat = key("repeat") >> space >> ( | ||
| 526 | in_block >> line_break >> *space_break >> check_indent_match | | ||
| 527 | disable_until_rule(Statement) | ||
| 528 | ) >> space >> key("until") >> space >> must_exp; | ||
| 394 | 529 | ||
| 395 | for_key = pl::user(key("for"), [](const item_t& item) { | 530 | for_key = pl::user(key("for"), [](const item_t& item) { |
| 396 | State* st = reinterpret_cast<State*>(item.user_data); | 531 | State* st = reinterpret_cast<State*>(item.user_data); |
| 397 | return st->noForStack.empty() || !st->noForStack.top(); | 532 | return st->noForStack.empty() || !st->noForStack.back(); |
| 398 | }); | 533 | }); |
| 399 | ForStepValue = ',' >> space >> Exp; | 534 | ForStepValue = ',' >> space >> must_exp; |
| 400 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 535 | for_args = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> space >> -ForStepValue; |
| 401 | 536 | ||
| 402 | For = for_key >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); | 537 | ForNum = disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); |
| 403 | 538 | ||
| 404 | for_in = StarExp | ExpList; | 539 | for_in = StarExp | ExpList | expected_expression_error; |
| 405 | 540 | ||
| 406 | ForEach = for_key >> space >> AssignableNameList >> space >> key("in") >> space >> | 541 | ForEach = AssignableNameList >> space >> key("in") >> space >> |
| 407 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); | 542 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); |
| 408 | 543 | ||
| 544 | For = for_key >> space >> (ForNum | ForEach); | ||
| 545 | |||
| 409 | Do = pl::user(key("do"), [](const item_t& item) { | 546 | Do = pl::user(key("do"), [](const item_t& item) { |
| 410 | State* st = reinterpret_cast<State*>(item.user_data); | 547 | State* st = reinterpret_cast<State*>(item.user_data); |
| 411 | return st->noDoStack.empty() || !st->noDoStack.top(); | 548 | return st->noDoStack.empty() || !st->noDoStack.back(); |
| 412 | }) >> space >> Body; | 549 | }) >> space >> Body; |
| 413 | 550 | ||
| 414 | disable_do = pl::user(true_(), [](const item_t& item) { | 551 | disable_do = pl::user(true_(), [](const item_t& item) { |
| 415 | State* st = reinterpret_cast<State*>(item.user_data); | 552 | State* st = reinterpret_cast<State*>(item.user_data); |
| 416 | st->noDoStack.push(true); | 553 | st->noDoStack.push_back(true); |
| 417 | return true; | 554 | return true; |
| 418 | }); | 555 | }); |
| 419 | 556 | ||
| 420 | enable_do = pl::user(true_(), [](const item_t& item) { | 557 | enable_do = pl::user(true_(), [](const item_t& item) { |
| 421 | State* st = reinterpret_cast<State*>(item.user_data); | 558 | State* st = reinterpret_cast<State*>(item.user_data); |
| 422 | st->noDoStack.pop(); | 559 | st->noDoStack.pop_back(); |
| 423 | return true; | 560 | return true; |
| 424 | }); | 561 | }); |
| 425 | 562 | ||
| @@ -437,46 +574,58 @@ YueParser::YueParser() { | |||
| 437 | 574 | ||
| 438 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 575 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 439 | State* st = reinterpret_cast<State*>(item.user_data); | 576 | State* st = reinterpret_cast<State*>(item.user_data); |
| 440 | st->noDoStack.push(true); | 577 | st->noDoStack.push_back(true); |
| 441 | st->noChainBlockStack.push(true); | 578 | st->noChainBlockStack.push_back(true); |
| 442 | st->noTableBlockStack.push(true); | 579 | st->noTableBlockStack.push_back(true); |
| 443 | return true; | 580 | return true; |
| 444 | }); | 581 | }); |
| 445 | 582 | ||
| 446 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 583 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 447 | State* st = reinterpret_cast<State*>(item.user_data); | 584 | State* st = reinterpret_cast<State*>(item.user_data); |
| 448 | st->noDoStack.pop(); | 585 | st->noDoStack.pop_back(); |
| 449 | st->noChainBlockStack.pop(); | 586 | st->noChainBlockStack.pop_back(); |
| 450 | st->noTableBlockStack.pop(); | 587 | st->noTableBlockStack.pop_back(); |
| 451 | return true; | 588 | return true; |
| 452 | }); | 589 | }); |
| 453 | 590 | ||
| 454 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 591 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 455 | State* st = reinterpret_cast<State*>(item.user_data); | 592 | State* st = reinterpret_cast<State*>(item.user_data); |
| 456 | st->noTableBlockStack.push(true); | 593 | st->noTableBlockStack.push_back(true); |
| 457 | return true; | 594 | return true; |
| 458 | }); | 595 | }); |
| 459 | 596 | ||
| 460 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 597 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 461 | State* st = reinterpret_cast<State*>(item.user_data); | 598 | State* st = reinterpret_cast<State*>(item.user_data); |
| 462 | st->noTableBlockStack.pop(); | 599 | st->noTableBlockStack.pop_back(); |
| 463 | return true; | 600 | return true; |
| 464 | }); | 601 | }); |
| 465 | 602 | ||
| 466 | disable_for = pl::user(true_(), [](const item_t& item) { | 603 | disable_for = pl::user(true_(), [](const item_t& item) { |
| 467 | State* st = reinterpret_cast<State*>(item.user_data); | 604 | State* st = reinterpret_cast<State*>(item.user_data); |
| 468 | st->noForStack.push(true); | 605 | st->noForStack.push_back(true); |
| 469 | return true; | 606 | return true; |
| 470 | }); | 607 | }); |
| 471 | 608 | ||
| 472 | enable_for = pl::user(true_(), [](const item_t& item) { | 609 | enable_for = pl::user(true_(), [](const item_t& item) { |
| 473 | State* st = reinterpret_cast<State*>(item.user_data); | 610 | State* st = reinterpret_cast<State*>(item.user_data); |
| 474 | st->noForStack.pop(); | 611 | st->noForStack.pop_back(); |
| 475 | return true; | 612 | return true; |
| 476 | }); | 613 | }); |
| 477 | 614 | ||
| 478 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 615 | disable_until = pl::user(true_(), [](const item_t& item) { |
| 479 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 616 | State* st = reinterpret_cast<State*>(item.user_data); |
| 617 | st->noUntilStack.push_back(true); | ||
| 618 | return true; | ||
| 619 | }); | ||
| 620 | |||
| 621 | enable_until = pl::user(true_(), [](const item_t& item) { | ||
| 622 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 623 | st->noUntilStack.pop_back(); | ||
| 624 | return true; | ||
| 625 | }); | ||
| 626 | |||
| 627 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> must_variable >> space >> (in_block | invalid_try_syntax_error); | ||
| 628 | Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp | invalid_try_syntax_error) >> -CatchBlock; | ||
| 480 | 629 | ||
| 481 | list_value = | 630 | list_value = |
| 482 | and_( | 631 | and_( |
| @@ -498,28 +647,33 @@ YueParser::YueParser() { | |||
| 498 | 647 | ||
| 499 | list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); | 648 | list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); |
| 500 | 649 | ||
| 650 | end_brackets_expression = ']' | brackets_expression_error; | ||
| 651 | |||
| 501 | Comprehension = '[' >> not_('[') >> | 652 | Comprehension = '[' >> not_('[') >> |
| 502 | Seperator >> space >> ( | 653 | Seperator >> space >> ( |
| 503 | disable_for_rule(list_value) >> space >> ( | 654 | disable_for_rule(list_value) >> space >> ( |
| 504 | CompInner >> space >> ']' | | 655 | CompFor >> space >> end_brackets_expression | |
| 505 | (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> ']' | 656 | (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> end_brackets_expression |
| 506 | ) | | 657 | ) | |
| 507 | list_lit_lines >> white >> ']' | | 658 | list_lit_lines >> white >> end_brackets_expression | |
| 508 | white >> ']' >> not_(space >> '=') | 659 | white >> ']' >> not_(space >> '=') |
| 509 | ); | 660 | ); |
| 510 | 661 | ||
| 511 | CompValue = ',' >> space >> Exp; | 662 | end_braces_expression = '}' | braces_expression_error; |
| 512 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); | ||
| 513 | 663 | ||
| 514 | CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); | 664 | CompValue = ',' >> space >> must_exp; |
| 515 | StarExp = '*' >> space >> Exp; | 665 | TblComprehension = '{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> (CompFor | braces_expression_error) >> space >> end_braces_expression; |
| 516 | CompForEach = key("for") >> space >> AssignableNameList >> space >> key("in") >> space >> (StarExp | Exp); | 666 | |
| 517 | CompFor = key("for") >> space >> Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> -ForStepValue; | 667 | CompFor = key("for") >> space >> Seperator >> (CompForNum | CompForEach) >> *(space >> comp_clause); |
| 518 | comp_clause = CompFor | CompForEach | key("when") >> space >> Exp; | 668 | StarExp = '*' >> space >> must_exp; |
| 669 | CompForEach = AssignableNameList >> space >> key("in") >> space >> (StarExp | must_exp); | ||
| 670 | CompForNum = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> -ForStepValue; | ||
| 671 | comp_clause = key("when") >> space >> must_exp | key("for") >> space >> (CompForNum | CompForEach); | ||
| 519 | 672 | ||
| 520 | Assign = '=' >> space >> Seperator >> ( | 673 | Assign = '=' >> space >> Seperator >> ( |
| 521 | With | If | Switch | TableBlock | | 674 | With | If | Switch | TableBlock | |
| 522 | Exp >> *(space >> set(",;") >> space >> Exp) | 675 | (SpreadListExp | Exp) >> *(space >> set(",;") >> space >> (SpreadListExp | Exp)) | |
| 676 | expected_expression_error | ||
| 523 | ); | 677 | ); |
| 524 | 678 | ||
| 525 | UpdateOp = | 679 | UpdateOp = |
| @@ -527,7 +681,7 @@ YueParser::YueParser() { | |||
| 527 | ">>" | "<<" | "??" | | 681 | ">>" | "<<" | "??" | |
| 528 | set("+-*/%&|^"); | 682 | set("+-*/%&|^"); |
| 529 | 683 | ||
| 530 | Update = UpdateOp >> '=' >> space >> Exp; | 684 | Update = UpdateOp >> '=' >> space >> must_exp; |
| 531 | 685 | ||
| 532 | Assignable = AssignableChain | Variable | SelfItem; | 686 | Assignable = AssignableChain | Variable | SelfItem; |
| 533 | 687 | ||
| @@ -548,35 +702,38 @@ YueParser::YueParser() { | |||
| 548 | UnaryExp = *(UnaryOperator >> space) >> expo_exp >> -(space >> In); | 702 | UnaryExp = *(UnaryOperator >> space) >> expo_exp >> -(space >> In); |
| 549 | 703 | ||
| 550 | pipe_operator = "|>"; | 704 | pipe_operator = "|>"; |
| 551 | pipe_value = pipe_operator >> *space_break >> space >> UnaryExp; | 705 | pipe_value = pipe_operator >> *space_break >> space >> must_unary_exp; |
| 552 | pipe_exp = UnaryExp >> *(space >> pipe_value); | 706 | pipe_exp = UnaryExp >> *(space >> pipe_value); |
| 553 | 707 | ||
| 554 | BinaryOperator = | 708 | BinaryOperator = ( |
| 555 | key("or") | | 709 | key("or") | |
| 556 | key("and") | | 710 | key("and") | |
| 557 | "<=" | ">=" | "~=" | "!=" | "==" | | 711 | "<=" | ">=" | "~=" | "!=" | "==" | |
| 558 | ".." | "<<" | ">>" | "//" | | 712 | ".." | "<<" | ">>" | "//" | |
| 559 | set("+-*/%><|&~"); | 713 | set("+*/%>|&~") | |
| 714 | '-' >> not_('>') | | ||
| 715 | '<' >> not_('-') | ||
| 716 | ) >> not_('='); | ||
| 560 | 717 | ||
| 561 | ExpOpValue = BinaryOperator >> *space_break >> space >> pipe_exp; | 718 | ExpOpValue = BinaryOperator >> *space_break >> space >> (pipe_exp | expected_expression_error); |
| 562 | Exp = Seperator >> pipe_exp >> *(space >> ExpOpValue) >> -(space >> "??" >> space >> Exp); | 719 | Exp = Seperator >> pipe_exp >> *(space >> ExpOpValue) >> -(space >> "??" >> not_('=') >> *space_break >> space >> must_exp); |
| 563 | 720 | ||
| 564 | disable_chain = pl::user(true_(), [](const item_t& item) { | 721 | disable_chain = pl::user(true_(), [](const item_t& item) { |
| 565 | State* st = reinterpret_cast<State*>(item.user_data); | 722 | State* st = reinterpret_cast<State*>(item.user_data); |
| 566 | st->noChainBlockStack.push(true); | 723 | st->noChainBlockStack.push_back(true); |
| 567 | return true; | 724 | return true; |
| 568 | }); | 725 | }); |
| 569 | 726 | ||
| 570 | enable_chain = pl::user(true_(), [](const item_t& item) { | 727 | enable_chain = pl::user(true_(), [](const item_t& item) { |
| 571 | State* st = reinterpret_cast<State*>(item.user_data); | 728 | State* st = reinterpret_cast<State*>(item.user_data); |
| 572 | st->noChainBlockStack.pop(); | 729 | st->noChainBlockStack.pop_back(); |
| 573 | return true; | 730 | return true; |
| 574 | }); | 731 | }); |
| 575 | 732 | ||
| 576 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; | 733 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; |
| 577 | chain_block = pl::user(true_(), [](const item_t& item) { | 734 | chain_block = pl::user(true_(), [](const item_t& item) { |
| 578 | State* st = reinterpret_cast<State*>(item.user_data); | 735 | State* st = reinterpret_cast<State*>(item.user_data); |
| 579 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 736 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); |
| 580 | }) >> +space_break >> advance_match >> ensure( | 737 | }) >> +space_break >> advance_match >> ensure( |
| 581 | chain_line >> *(+space_break >> chain_line), pop_indent); | 738 | chain_line >> *(+space_break >> chain_line), pop_indent); |
| 582 | ChainValue = | 739 | ChainValue = |
| @@ -591,7 +748,7 @@ YueParser::YueParser() { | |||
| 591 | st->expLevel++; | 748 | st->expLevel++; |
| 592 | const int max_exp_level = 100; | 749 | const int max_exp_level = 100; |
| 593 | if (st->expLevel > max_exp_level) { | 750 | if (st->expLevel > max_exp_level) { |
| 594 | throw ParserError("nesting expressions exceeds 100 levels"sv, item.begin); | 751 | RaiseError("nesting expressions exceeds 100 levels"sv, item); |
| 595 | } | 752 | } |
| 596 | return true; | 753 | return true; |
| 597 | }); | 754 | }); |
| @@ -606,14 +763,22 @@ YueParser::YueParser() { | |||
| 606 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); | 763 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); |
| 607 | 764 | ||
| 608 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; | 765 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; |
| 609 | SingleString = '\'' >> *single_string_inner >> '\''; | 766 | SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error); |
| 610 | 767 | ||
| 611 | interp = "#{" >> space >> (Exp >> space >> '}' | invalid_interpolation_error); | 768 | interp = "#{" >> space >> (Exp >> space >> '}' | invalid_interpolation_error); |
| 612 | double_string_plain = '\\' >> set("\"\\#") | not_('"') >> any_char; | 769 | double_string_plain = '\\' >> set("\"\\#") | not_('"') >> any_char; |
| 613 | DoubleStringInner = +(not_("#{") >> double_string_plain); | 770 | DoubleStringInner = +(not_("#{") >> double_string_plain); |
| 614 | DoubleStringContent = DoubleStringInner | interp; | 771 | DoubleStringContent = DoubleStringInner | interp; |
| 615 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; | 772 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> ('"' | unclosed_double_string_error); |
| 616 | String = DoubleString | SingleString | LuaString; | 773 | |
| 774 | YAMLIndent = +set(" \t"); | ||
| 775 | YAMLLineInner = +('\\' >> set("\"\\#") | not_("#{" | stop) >> any_char); | ||
| 776 | YAMLLineContent = YAMLLineInner | interp; | ||
| 777 | YAMLLine = check_indent_match >> YAMLIndent >> +(YAMLLineContent) | | ||
| 778 | advance_match >> YAMLIndent >> ensure(+YAMLLineContent, pop_indent); | ||
| 779 | YAMLMultiline = '|' >> space >> Seperator >> +(*set(" \t") >> line_break) >> advance_match >> ensure(YAMLLine >> *(+(*set(" \t") >> line_break) >> YAMLLine), pop_indent); | ||
| 780 | |||
| 781 | String = DoubleString | SingleString | LuaString | YAMLMultiline; | ||
| 617 | 782 | ||
| 618 | lua_string_open = '[' >> *expr('=') >> '['; | 783 | lua_string_open = '[' >> *expr('=') >> '['; |
| 619 | lua_string_close = ']' >> *expr('=') >> ']'; | 784 | lua_string_close = ']' >> *expr('=') >> ']'; |
| @@ -633,15 +798,15 @@ YueParser::YueParser() { | |||
| 633 | 798 | ||
| 634 | LuaStringContent = *(not_(LuaStringClose) >> any_char); | 799 | LuaStringContent = *(not_(LuaStringClose) >> any_char); |
| 635 | 800 | ||
| 636 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose; | 801 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> (LuaStringClose | unclosed_lua_string_error); |
| 637 | 802 | ||
| 638 | Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')'; | 803 | Parens = '(' >> (*space_break >> space >> Exp >> *space_break >> space >> ')' | parenthesis_error); |
| 639 | Callable = Variable | SelfItem | MacroName | Parens; | 804 | Callable = Variable | SelfItem | MacroName | Parens; |
| 640 | 805 | ||
| 641 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); | 806 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); |
| 642 | 807 | ||
| 643 | fn_args_lit_line = ( | 808 | fn_args_lit_line = ( |
| 644 | push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) | 809 | push_indent_match >> ensure(space >> fn_args_value_list, pop_indent) |
| 645 | ) | ( | 810 | ) | ( |
| 646 | space | 811 | space |
| 647 | ); | 812 | ); |
| @@ -651,14 +816,14 @@ YueParser::YueParser() { | |||
| 651 | fn_args = | 816 | fn_args = |
| 652 | '(' >> -(space >> fn_args_value_list >> -(space >> ',')) >> | 817 | '(' >> -(space >> fn_args_value_list >> -(space >> ',')) >> |
| 653 | -fn_args_lit_lines >> | 818 | -fn_args_lit_lines >> |
| 654 | white >> ')' | space >> '!' >> not_('='); | 819 | white >> -(and_(',') >> unexpected_comma_error) >>')' | space >> '!' >> not_('='); |
| 655 | 820 | ||
| 656 | meta_index = Name | index | String; | 821 | meta_index = Name | index | String; |
| 657 | Metatable = '<' >> space >> '>'; | 822 | Metatable = '<' >> space >> '>'; |
| 658 | Metamethod = '<' >> space >> meta_index >> space >> '>'; | 823 | Metamethod = '<' >> space >> meta_index >> space >> '>'; |
| 659 | 824 | ||
| 660 | ExistentialOp = '?' >> not_('?'); | 825 | ExistentialOp = '?' >> not_('?'); |
| 661 | TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); | 826 | TableAppendingOp = and_('[') >> "[]"; |
| 662 | PlainItem = +any_char; | 827 | PlainItem = +any_char; |
| 663 | 828 | ||
| 664 | chain_call = ( | 829 | chain_call = ( |
| @@ -683,7 +848,8 @@ YueParser::YueParser() { | |||
| 683 | chain_with_colon = +chain_item >> -colon_chain; | 848 | chain_with_colon = +chain_item >> -colon_chain; |
| 684 | chain_items = chain_with_colon | colon_chain; | 849 | chain_items = chain_with_colon | colon_chain; |
| 685 | 850 | ||
| 686 | index = '[' >> not_('[') >> space >> Exp >> space >> ']'; | 851 | index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; |
| 852 | ReversedIndex = '#' >> space >> -('-' >> space >> Exp); | ||
| 687 | chain_item = | 853 | chain_item = |
| 688 | Invoke >> -ExistentialOp | | 854 | Invoke >> -ExistentialOp | |
| 689 | DotChainItem >> -ExistentialOp | | 855 | DotChainItem >> -ExistentialOp | |
| @@ -722,10 +888,8 @@ YueParser::YueParser() { | |||
| 722 | SpreadExp | | 888 | SpreadExp | |
| 723 | NormalDef; | 889 | NormalDef; |
| 724 | 890 | ||
| 725 | table_value_list = table_value >> *(space >> ',' >> space >> table_value); | ||
| 726 | |||
| 727 | table_lit_line = ( | 891 | table_lit_line = ( |
| 728 | push_indent_match >> (space >> table_value_list >> pop_indent | pop_indent) | 892 | push_indent_match >> (space >> not_(line_break | '}') >> (table_value | expected_expression_error) >> *(space >> ',' >> space >> table_value) >> pop_indent | pop_indent) |
| 729 | ) | ( | 893 | ) | ( |
| 730 | space | 894 | space |
| 731 | ); | 895 | ); |
| @@ -734,13 +898,15 @@ YueParser::YueParser() { | |||
| 734 | 898 | ||
| 735 | TableLit = | 899 | TableLit = |
| 736 | '{' >> Seperator >> | 900 | '{' >> Seperator >> |
| 737 | -(space >> table_value_list >> -(space >> ',')) >> | 901 | -(space >> table_value >> *(space >> ',' >> space >> table_value) >> -(space >> ',')) >> |
| 738 | -table_lit_lines >> | 902 | ( |
| 739 | white >> '}'; | 903 | table_lit_lines >> white >> end_braces_expression | |
| 904 | white >> '}' | ||
| 905 | ); | ||
| 740 | 906 | ||
| 741 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); | 907 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); |
| 742 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); | 908 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); |
| 743 | TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( | 909 | TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( |
| 744 | space >> key_value_list >> -(space >> ',') >> | 910 | space >> key_value_list >> -(space >> ',') >> |
| 745 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); | 911 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); |
| 746 | 912 | ||
| @@ -755,13 +921,18 @@ YueParser::YueParser() { | |||
| 755 | ClassDecl = | 921 | ClassDecl = |
| 756 | key("class") >> not_(':') >> disable_arg_table_block_rule( | 922 | key("class") >> not_(':') >> disable_arg_table_block_rule( |
| 757 | -(space >> Assignable) >> | 923 | -(space >> Assignable) >> |
| 758 | -(space >> key("extends") >> prevent_indent >> space >> ensure(Exp, pop_indent)) >> | 924 | -(space >> key("extends") >> prevent_indent >> space >> ensure(must_exp, pop_indent)) >> |
| 759 | -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList, pop_indent)) | 925 | -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList | expected_expression_error, pop_indent)) |
| 760 | ) >> -ClassBlock; | 926 | ) >> -ClassBlock; |
| 761 | 927 | ||
| 762 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); | 928 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow | expected_expression_error)); |
| 763 | GlobalOp = expr('*') | '^'; | 929 | GlobalOp = expr('*') | '^'; |
| 764 | Global = key("global") >> space >> (-(ConstAttrib >> space) >> ClassDecl | GlobalOp | -(ConstAttrib >> space) >> GlobalValues); | 930 | Global = key("global") >> space >> ( |
| 931 | -(ConstAttrib >> space) >> ClassDecl | | ||
| 932 | GlobalOp | | ||
| 933 | -(ConstAttrib >> space) >> GlobalValues | | ||
| 934 | invalid_global_declaration_error | ||
| 935 | ); | ||
| 765 | 936 | ||
| 766 | ExportDefault = key("default"); | 937 | ExportDefault = key("default"); |
| 767 | 938 | ||
| @@ -773,10 +944,10 @@ YueParser::YueParser() { | |||
| 773 | pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { | 944 | pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { |
| 774 | State* st = reinterpret_cast<State*>(item.user_data); | 945 | State* st = reinterpret_cast<State*>(item.user_data); |
| 775 | if (st->exportDefault) { | 946 | if (st->exportDefault) { |
| 776 | throw ParserError("export default has already been declared"sv, item.begin); | 947 | RaiseError("export default has already been declared"sv, item); |
| 777 | } | 948 | } |
| 778 | if (st->exportCount > 1) { | 949 | if (st->exportCount > 1) { |
| 779 | throw ParserError("there are items already being exported"sv, item.begin); | 950 | RaiseError("there are items already being exported"sv, item); |
| 780 | } | 951 | } |
| 781 | st->exportDefault = true; | 952 | st->exportDefault = true; |
| 782 | return true; | 953 | return true; |
| @@ -784,17 +955,17 @@ YueParser::YueParser() { | |||
| 784 | not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { | 955 | not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { |
| 785 | State* st = reinterpret_cast<State*>(item.user_data); | 956 | State* st = reinterpret_cast<State*>(item.user_data); |
| 786 | if (st->exportDefault && st->exportCount > 1) { | 957 | if (st->exportDefault && st->exportCount > 1) { |
| 787 | throw ParserError("can not export any more items when 'export default' is declared"sv, item.begin); | 958 | RaiseError("can not export any more items when 'export default' is declared"sv, item); |
| 788 | } | 959 | } |
| 789 | return true; | 960 | return true; |
| 790 | }) >> ( | 961 | }) >> ( |
| 791 | and_(set(".[")) >> ((pl::user(and_('.' >> Metatable), [](const item_t& item) { | 962 | and_(set(".[")) >> ((pl::user(and_('.' >> Metatable), [](const item_t& item) { |
| 792 | State* st = reinterpret_cast<State*>(item.user_data); | 963 | State* st = reinterpret_cast<State*>(item.user_data); |
| 793 | if (st->exportMetatable) { | 964 | if (st->exportMetatable) { |
| 794 | throw ParserError("module metatable duplicated"sv, item.begin); | 965 | RaiseError("module metatable duplicated"sv, item); |
| 795 | } | 966 | } |
| 796 | if (st->exportMetamethod) { | 967 | if (st->exportMetamethod) { |
| 797 | throw ParserError("metatable should be exported before metamethod"sv, item.begin); | 968 | RaiseError("metatable should be exported before metamethod"sv, item); |
| 798 | } | 969 | } |
| 799 | st->exportMetatable = true; | 970 | st->exportMetatable = true; |
| 800 | return true; | 971 | return true; |
| @@ -809,7 +980,8 @@ YueParser::YueParser() { | |||
| 809 | State* st = reinterpret_cast<State*>(item.user_data); | 980 | State* st = reinterpret_cast<State*>(item.user_data); |
| 810 | st->exportMacro = true; | 981 | st->exportMacro = true; |
| 811 | return true; | 982 | return true; |
| 812 | }) | 983 | }) | |
| 984 | invalid_export_syntax_error | ||
| 813 | ) >> not_(space >> StatementAppendix); | 985 | ) >> not_(space >> StatementAppendix); |
| 814 | 986 | ||
| 815 | VariablePair = ':' >> Variable; | 987 | VariablePair = ':' >> Variable; |
| @@ -819,13 +991,13 @@ YueParser::YueParser() { | |||
| 819 | KeyName | | 991 | KeyName | |
| 820 | '[' >> not_('[') >> space >> Exp >> space >> ']' | | 992 | '[' >> not_('[') >> space >> Exp >> space >> ']' | |
| 821 | String | 993 | String |
| 822 | ) >> ':' >> not_(':') >> space >> | 994 | ) >> ':' >> not_(':' | '=' >> not_('>')) >> space >> |
| 823 | (Exp | TableBlock | +space_break >> space >> Exp); | 995 | (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); |
| 824 | 996 | ||
| 825 | MetaVariablePair = ":<" >> space >> Variable >> space >> '>'; | 997 | MetaVariablePair = ":<" >> space >> must_variable >> space >> '>'; |
| 826 | 998 | ||
| 827 | MetaNormalPair = '<' >> space >> -meta_index >> space >> ">:" >> space >> | 999 | MetaNormalPair = '<' >> space >> -meta_index >> space >> ">:" >> space >> |
| 828 | (Exp | TableBlock | +space_break >> space >> Exp); | 1000 | (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); |
| 829 | 1001 | ||
| 830 | destruct_def = -(space >> '=' >> space >> Exp); | 1002 | destruct_def = -(space >> '=' >> space >> Exp); |
| 831 | VariablePairDef = VariablePair >> destruct_def; | 1003 | VariablePairDef = VariablePair >> destruct_def; |
| @@ -843,29 +1015,39 @@ YueParser::YueParser() { | |||
| 843 | key_value_line = check_indent_match >> space >> ( | 1015 | key_value_line = check_indent_match >> space >> ( |
| 844 | key_value_list >> -(space >> ',') | | 1016 | key_value_list >> -(space >> ',') | |
| 845 | TableBlockIndent | | 1017 | TableBlockIndent | |
| 846 | '*' >> space >> (SpreadExp | Exp | TableBlock) | 1018 | ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock) |
| 847 | ); | 1019 | ); |
| 848 | 1020 | ||
| 849 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); | 1021 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); |
| 850 | 1022 | ||
| 851 | fn_arg_def_lit_line = ( | 1023 | fn_arg_def_lit_line = ( |
| 852 | push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) | 1024 | push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent) |
| 853 | ) | ( | 1025 | ) | ( |
| 854 | space | 1026 | space |
| 855 | ); | 1027 | ); |
| 856 | 1028 | ||
| 857 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); | 1029 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); |
| 858 | 1030 | ||
| 859 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 1031 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; |
| 860 | 1032 | ||
| 861 | FnArgDefList = Seperator >> ( | 1033 | check_vararg_position = and_(white >> (')' | key("using"))) | white >> -(',' >> white) >> vararg_position_error; |
| 862 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | | ||
| 863 | white >> VarArg | ||
| 864 | ); | ||
| 865 | 1034 | ||
| 866 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 1035 | var_arg_def = ( |
| 1036 | VarArgDef | | ||
| 1037 | +space_break >> push_indent_match >> ensure(space >> VarArgDef >> -(space >> '`' >> space >> Name), pop_indent) | ||
| 1038 | ) >> check_vararg_position; | ||
| 867 | 1039 | ||
| 868 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')'; | 1040 | FnArgDefList = Seperator >> |
| 1041 | -fn_arg_def_list >> | ||
| 1042 | -(-(space >> ',') >> +space_break >> fn_arg_def_lit_lines) >> | ||
| 1043 | -(-(space >> ',') >> space >> var_arg_def); | ||
| 1044 | |||
| 1045 | OuterVarShadow = key("using") >> space >> (key("nil") | NameList); | ||
| 1046 | |||
| 1047 | outer_var_shadow_def = OuterVarShadow | | ||
| 1048 | +space_break >> push_indent_match >> ensure(space >> OuterVarShadow, pop_indent); | ||
| 1049 | |||
| 1050 | FnArgsDef = '(' >> space >> -FnArgDefList >> -(space >> outer_var_shadow_def) >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; | ||
| 869 | FnArrow = expr("->") | "=>"; | 1051 | FnArrow = expr("->") | "=>"; |
| 870 | FunLit = pl::user(true_(), [](const item_t& item) { | 1052 | FunLit = pl::user(true_(), [](const item_t& item) { |
| 871 | State* st = reinterpret_cast<State*>(item.user_data); | 1053 | State* st = reinterpret_cast<State*>(item.user_data); |
| @@ -877,23 +1059,30 @@ YueParser::YueParser() { | |||
| 877 | ) >> space >> FnArrow >> -(space >> Body); | 1059 | ) >> space >> FnArrow >> -(space >> Body); |
| 878 | 1060 | ||
| 879 | MacroName = '$' >> UnicodeName; | 1061 | MacroName = '$' >> UnicodeName; |
| 880 | macro_args_def = '(' >> white >> -FnArgDefList >> white >> ')'; | 1062 | macro_args_def = '(' >> space >> -FnArgDefList >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; |
| 881 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; | 1063 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; |
| 882 | MacroFunc = MacroName >> (Invoke | InvokeArgs); | 1064 | MacroFunc = MacroName >> (Invoke | InvokeArgs); |
| 883 | Macro = key("macro") >> space >> UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc); | 1065 | Macro = key("macro") >> space >> ( |
| 1066 | UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc | invalid_macro_definition_error) | | ||
| 1067 | invalid_macro_definition_error | ||
| 1068 | ); | ||
| 884 | MacroInPlace = '$' >> space >> "->" >> space >> Body; | 1069 | MacroInPlace = '$' >> space >> "->" >> space >> Body; |
| 885 | 1070 | ||
| 886 | NameList = Seperator >> Variable >> *(space >> ',' >> space >> Variable); | 1071 | must_variable = Variable | and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error | expected_indentifier_error; |
| 887 | NameOrDestructure = Variable | TableLit | Comprehension; | 1072 | |
| 1073 | NameList = Seperator >> must_variable >> *(space >> ',' >> space >> must_variable); | ||
| 1074 | NameOrDestructure = Variable | TableLit | Comprehension | SimpleTable | expected_expression_error; | ||
| 888 | AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); | 1075 | AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); |
| 889 | 1076 | ||
| 890 | FnArrowBack = '<' >> set("-="); | 1077 | FnArrowBack = '<' >> set("-="); |
| 891 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; | 1078 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; |
| 892 | SubBackcall = FnArrowBack >> space >> ChainValue; | 1079 | SubBackcall = FnArrowBack >> space >> ChainValue; |
| 893 | 1080 | ||
| 1081 | must_unary_exp = UnaryExp | expected_expression_error; | ||
| 1082 | |||
| 894 | PipeBody = Seperator >> | 1083 | PipeBody = Seperator >> |
| 895 | pipe_operator >> space >> UnaryExp >> | 1084 | pipe_operator >> space >> must_unary_exp >> |
| 896 | *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> UnaryExp); | 1085 | *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> must_unary_exp); |
| 897 | 1086 | ||
| 898 | ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); | 1087 | ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); |
| 899 | ExpListLow = Seperator >> Exp >> *(space >> set(",;") >> space >> Exp); | 1088 | ExpListLow = Seperator >> Exp >> *(space >> set(",;") >> space >> Exp); |
| @@ -903,7 +1092,7 @@ YueParser::YueParser() { | |||
| 903 | 1092 | ||
| 904 | arg_table_block = pl::user(true_(), [](const item_t& item) { | 1093 | arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 905 | State* st = reinterpret_cast<State*>(item.user_data); | 1094 | State* st = reinterpret_cast<State*>(item.user_data); |
| 906 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); | 1095 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.back(); |
| 907 | }) >> TableBlock; | 1096 | }) >> TableBlock; |
| 908 | 1097 | ||
| 909 | invoke_args_with_table = | 1098 | invoke_args_with_table = |
| @@ -912,38 +1101,17 @@ YueParser::YueParser() { | |||
| 912 | space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block) | 1101 | space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block) |
| 913 | ) | arg_table_block; | 1102 | ) | arg_table_block; |
| 914 | 1103 | ||
| 915 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { | ||
| 916 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses"sv, item.begin); | ||
| 917 | return false; | ||
| 918 | }); | ||
| 919 | |||
| 920 | InvokeArgs = | 1104 | InvokeArgs = |
| 921 | not_(set("-~") | "[]") >> space >> Seperator >> ( | 1105 | not_(set("-~") | "[]") >> space >> Seperator >> ( |
| 922 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | | 1106 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | |
| 923 | arg_table_block | | 1107 | arg_table_block |
| 924 | leading_spaces_error | ||
| 925 | ); | 1108 | ); |
| 926 | 1109 | ||
| 927 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 1110 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
| 928 | 1111 | ||
| 929 | braces_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 930 | throw ParserError("syntax error in brace expression"sv, item.begin); | ||
| 931 | return false; | ||
| 932 | }); | ||
| 933 | |||
| 934 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 935 | throw ParserError("syntax error in bracket expression"sv, item.begin); | ||
| 936 | return false; | ||
| 937 | }); | ||
| 938 | |||
| 939 | slice_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 940 | throw ParserError("syntax error in slice expression"sv, item.begin); | ||
| 941 | return false; | ||
| 942 | }); | ||
| 943 | |||
| 944 | SimpleValue = | 1112 | SimpleValue = |
| 945 | TableLit | ConstValue | If | Switch | Try | With | | 1113 | TableLit | ConstValue | If | Switch | Try | With | |
| 946 | ClassDecl | ForEach | For | While | Do | | 1114 | ClassDecl | For | While | Repeat | Do | |
| 947 | UnaryValue | TblComprehension | Comprehension | | 1115 | UnaryValue | TblComprehension | Comprehension | |
| 948 | FunLit | Num | VarArg; | 1116 | FunLit | Num | VarArg; |
| 949 | 1117 | ||
| @@ -952,63 +1120,59 @@ YueParser::YueParser() { | |||
| 952 | IfLine = IfType >> space >> IfCond; | 1120 | IfLine = IfType >> space >> IfCond; |
| 953 | WhileLine = WhileType >> space >> Exp; | 1121 | WhileLine = WhileType >> space >> Exp; |
| 954 | 1122 | ||
| 955 | YueLineComment = *(not_(set("\r\n")) >> any_char); | ||
| 956 | yue_line_comment = "--" >> YueLineComment >> and_(stop); | ||
| 957 | MultilineCommentInner = multi_line_content; | ||
| 958 | YueMultilineComment = multi_line_open >> MultilineCommentInner >> multi_line_close; | ||
| 959 | yue_comment = check_indent >> ( | ||
| 960 | ( | ||
| 961 | YueMultilineComment >> | ||
| 962 | *(set(" \t") | YueMultilineComment) >> | ||
| 963 | -yue_line_comment | ||
| 964 | ) | yue_line_comment | ||
| 965 | ) >> and_(line_break); | ||
| 966 | |||
| 967 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; | 1123 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; |
| 968 | 1124 | ||
| 969 | StatementAppendix = (IfLine | WhileLine | CompInner) >> space; | 1125 | StatementAppendix = (IfLine | WhileLine | CompFor) >> space; |
| 970 | Statement = | 1126 | Statement = |
| 971 | Seperator >> | 1127 | ( |
| 972 | -( | 1128 | Import | While | Repeat | For | |
| 973 | yue_comment >> | ||
| 974 | *(line_break >> yue_comment) >> | ||
| 975 | line_break >> | ||
| 976 | check_indent_match | ||
| 977 | ) >> | ||
| 978 | space >> ( | ||
| 979 | Import | While | Repeat | For | ForEach | | ||
| 980 | Return | Local | Global | Export | Macro | | 1129 | Return | Local | Global | Export | Macro | |
| 981 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | 1130 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | |
| 982 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | | 1131 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | |
| 983 | StatementAppendix >> empty_block_error | 1132 | StatementAppendix >> empty_block_error | |
| 984 | ) >> | 1133 | and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error |
| 985 | space >> | 1134 | ) >> space >> |
| 986 | -StatementAppendix; | 1135 | -StatementAppendix; |
| 987 | 1136 | ||
| 988 | StatementSep = white >> (set("('\"") | "[[" | "[="); | 1137 | StatementSep = white >> (set("('\"") | "[[" | "[="); |
| 989 | 1138 | ||
| 990 | Body = in_block | Statement; | 1139 | Body = in_block | Statement; |
| 991 | 1140 | ||
| 992 | empty_line_break = | 1141 | YueLineComment = *(not_(set("\r\n")) >> any_char); |
| 993 | check_indent >> (multi_line_comment >> space | comment) >> and_(stop) | | 1142 | yue_line_comment = "--" >> YueLineComment >> and_(stop); |
| 994 | advance >> ensure(multi_line_comment >> space | comment, pop_indent) >> and_(stop) | | 1143 | YueMultilineComment = multi_line_content; |
| 995 | plain_space >> and_(line_break); | 1144 | yue_multiline_comment = multi_line_open >> YueMultilineComment >> multi_line_close; |
| 1145 | comment_line = | ||
| 1146 | yue_multiline_comment >> *(set(" \t") | yue_multiline_comment) >> plain_space >> -yue_line_comment | | ||
| 1147 | yue_line_comment; | ||
| 1148 | YueComment = | ||
| 1149 | check_indent >> comment_line >> and_(stop) | | ||
| 1150 | advance >> ensure(comment_line, pop_indent) >> and_(stop); | ||
| 1151 | |||
| 1152 | EmptyLine = plain_space >> and_(stop); | ||
| 996 | 1153 | ||
| 997 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { | 1154 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { |
| 998 | throw ParserError("unexpected indent"sv, item.begin); | 1155 | RaiseError("unexpected indent"sv, item); |
| 999 | return false; | 1156 | return false; |
| 1000 | }); | 1157 | }); |
| 1001 | 1158 | ||
| 1002 | line = ( | 1159 | line = *(EmptyLine >> line_break) >> ( |
| 1003 | check_indent_match >> Statement | | 1160 | check_indent_match >> space >> Statement | |
| 1004 | empty_line_break | | 1161 | YueComment | |
| 1005 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) | 1162 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) |
| 1006 | ); | 1163 | ); |
| 1007 | Block = Seperator >> line >> *(+line_break >> line); | 1164 | Block = Seperator >> (pl::user(true_(), [](const item_t& item) { |
| 1165 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 1166 | return st->lax; | ||
| 1167 | }) >> lax_line >> *(line_break >> lax_line) | line >> *(line_break >> line)); | ||
| 1008 | 1168 | ||
| 1009 | shebang = "#!" >> *(not_(stop) >> any_char); | 1169 | shebang = "#!" >> *(not_(stop) >> any_char); |
| 1010 | BlockEnd = Block >> white >> stop; | 1170 | BlockEnd = Block >> plain_white >> stop; |
| 1011 | File = -shebang >> -Block >> white >> stop; | 1171 | File = -shebang >> -Block >> plain_white >> stop; |
| 1172 | |||
| 1173 | lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | | ||
| 1174 | line >> and_(stop) | | ||
| 1175 | check_indent_match >> *(not_(stop) >> any()); | ||
| 1012 | } | 1176 | } |
| 1013 | // clang-format on | 1177 | // clang-format on |
| 1014 | 1178 | ||
| @@ -1019,7 +1183,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
| 1019 | } | 1183 | } |
| 1020 | try { | 1184 | try { |
| 1021 | if (!codes.empty()) { | 1185 | if (!codes.empty()) { |
| 1022 | converted = std::make_unique<input>(_converter.from_bytes(&codes.front(), &codes.back() + 1)); | 1186 | converted = std::make_unique<input>(utf8_decode({&codes.front(), &codes.back() + 1})); |
| 1023 | } else { | 1187 | } else { |
| 1024 | converted = std::make_unique<input>(); | 1188 | converted = std::make_unique<input>(); |
| 1025 | } | 1189 | } |
| @@ -1038,24 +1202,25 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
| 1038 | return true; | 1202 | return true; |
| 1039 | } | 1203 | } |
| 1040 | 1204 | ||
| 1041 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 1205 | ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) { |
| 1042 | ParseInfo res; | 1206 | ParseInfo res; |
| 1043 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | 1207 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { |
| 1044 | codes = codes.substr(3); | 1208 | codes = codes.substr(3); |
| 1045 | } | 1209 | } |
| 1046 | try { | 1210 | try { |
| 1047 | if (!codes.empty()) { | 1211 | if (!codes.empty()) { |
| 1048 | res.codes = std::make_unique<input>(_converter.from_bytes(&codes.front(), &codes.back() + 1)); | 1212 | res.codes = std::make_unique<input>(utf8_decode({&codes.front(), &codes.back() + 1})); |
| 1049 | } else { | 1213 | } else { |
| 1050 | res.codes = std::make_unique<input>(); | 1214 | res.codes = std::make_unique<input>(); |
| 1051 | } | 1215 | } |
| 1052 | } catch (const std::range_error&) { | 1216 | } catch (const std::exception&) { |
| 1053 | res.error = {"invalid text encoding"s, 1, 1}; | 1217 | res.error = {"invalid text encoding"s, 1, 1}; |
| 1054 | return res; | 1218 | return res; |
| 1055 | } | 1219 | } |
| 1056 | error_list errors; | 1220 | error_list errors; |
| 1057 | try { | 1221 | try { |
| 1058 | State state; | 1222 | State state; |
| 1223 | state.lax = lax; | ||
| 1059 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); | 1224 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); |
| 1060 | if (state.exportCount > 0) { | 1225 | if (state.exportCount > 0) { |
| 1061 | int index = 0; | 1226 | int index = 0; |
| @@ -1093,29 +1258,31 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
| 1093 | return res; | 1258 | return res; |
| 1094 | } | 1259 | } |
| 1095 | 1260 | ||
| 1096 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { | 1261 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) { |
| 1097 | auto it = _rules.find(astName); | 1262 | auto it = _rules.find(astName); |
| 1098 | if (it != _rules.end()) { | 1263 | if (it != _rules.end()) { |
| 1099 | return parse(codes, *it->second); | 1264 | return parse(codes, *it->second, lax); |
| 1100 | } | 1265 | } |
| 1101 | return {}; | 1266 | ParseInfo info{}; |
| 1267 | info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1}; | ||
| 1268 | return info; | ||
| 1102 | } | 1269 | } |
| 1103 | 1270 | ||
| 1104 | bool YueParser::match(std::string_view astName, std::string_view codes) { | 1271 | bool YueParser::match(std::string_view astName, std::string_view codes) { |
| 1105 | auto it = _rules.find(astName); | 1272 | auto it = _rules.find(astName); |
| 1106 | if (it != _rules.end()) { | 1273 | if (it != _rules.end()) { |
| 1107 | auto rEnd = rule(*it->second >> eof()); | 1274 | auto rEnd = rule(*it->second >> eof()); |
| 1108 | return parse(codes, rEnd).node; | 1275 | return parse(codes, rEnd, false).node; |
| 1109 | } | 1276 | } |
| 1110 | return false; | 1277 | return false; |
| 1111 | } | 1278 | } |
| 1112 | 1279 | ||
| 1113 | std::string YueParser::toString(ast_node* node) { | 1280 | std::string YueParser::toString(ast_node* node) { |
| 1114 | return _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | 1281 | return utf8_encode({node->m_begin.m_it, node->m_end.m_it}); |
| 1115 | } | 1282 | } |
| 1116 | 1283 | ||
| 1117 | std::string YueParser::toString(input::iterator begin, input::iterator end) { | 1284 | std::string YueParser::toString(input::iterator begin, input::iterator end) { |
| 1118 | return _converter.to_bytes(std::wstring(begin, end)); | 1285 | return utf8_encode({begin, end}); |
| 1119 | } | 1286 | } |
| 1120 | 1287 | ||
| 1121 | bool YueParser::hasAST(std::string_view name) const { | 1288 | bool YueParser::hasAST(std::string_view name) const { |
| @@ -1141,6 +1308,24 @@ void trim(std::string& str) { | |||
| 1141 | str.erase(0, str.find_first_not_of(" \t\r\n")); | 1308 | str.erase(0, str.find_first_not_of(" \t\r\n")); |
| 1142 | str.erase(str.find_last_not_of(" \t\r\n") + 1); | 1309 | str.erase(str.find_last_not_of(" \t\r\n") + 1); |
| 1143 | } | 1310 | } |
| 1311 | |||
| 1312 | std::string toLuaDoubleString(const std::string& input) { | ||
| 1313 | std::string luaStr = "\""; | ||
| 1314 | for (char c : input) { | ||
| 1315 | switch (c) { | ||
| 1316 | case '\"': luaStr += "\\\""; break; | ||
| 1317 | case '\\': luaStr += "\\\\"; break; | ||
| 1318 | case '\n': luaStr += "\\n"; break; | ||
| 1319 | case '\r': luaStr += "\\r"; break; | ||
| 1320 | case '\t': luaStr += "\\t"; break; | ||
| 1321 | default: | ||
| 1322 | luaStr += c; | ||
| 1323 | break; | ||
| 1324 | } | ||
| 1325 | } | ||
| 1326 | luaStr += "\""; | ||
| 1327 | return luaStr; | ||
| 1328 | } | ||
| 1144 | } // namespace Utils | 1329 | } // namespace Utils |
| 1145 | 1330 | ||
| 1146 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1331 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
| @@ -1174,7 +1359,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo | |||
| 1174 | } | 1359 | } |
| 1175 | ++it; | 1360 | ++it; |
| 1176 | } | 1361 | } |
| 1177 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | 1362 | auto line = utf8_encode({begin, end}); |
| 1178 | while (col < static_cast<int>(line.size()) | 1363 | while (col < static_cast<int>(line.size()) |
| 1179 | && (line[col] == ' ' || line[col] == '\t')) { | 1364 | && (line[col] == ' ' || line[col] == '\t')) { |
| 1180 | col++; | 1365 | col++; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 4488685..acb56d0 100644 --- a/src/yuescript/yue_parser.h +++ b/src/yuescript/yue_parser.h | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -74,16 +74,16 @@ extern std::unordered_set<std::string> Keywords; | |||
| 74 | class YueParser { | 74 | class YueParser { |
| 75 | public: | 75 | public: |
| 76 | template <class AST> | 76 | template <class AST> |
| 77 | ParseInfo parse(std::string_view codes) { | 77 | ParseInfo parse(std::string_view codes, bool lax) { |
| 78 | return parse(codes, getRule<AST>()); | 78 | return parse(codes, getRule<AST>(), lax); |
| 79 | } | 79 | } |
| 80 | 80 | ||
| 81 | ParseInfo parse(std::string_view astName, std::string_view codes); | 81 | ParseInfo parse(std::string_view astName, std::string_view codes, bool lax); |
| 82 | 82 | ||
| 83 | template <class AST> | 83 | template <class AST> |
| 84 | bool match(std::string_view codes) { | 84 | bool match(std::string_view codes) { |
| 85 | auto rEnd = rule(getRule<AST>() >> eof()); | 85 | auto rEnd = rule(getRule<AST>() >> eof()); |
| 86 | return parse(codes, rEnd).node; | 86 | return parse(codes, rEnd, false).node; |
| 87 | } | 87 | } |
| 88 | 88 | ||
| 89 | bool match(std::string_view astName, std::string_view codes); | 89 | bool match(std::string_view astName, std::string_view codes); |
| @@ -102,13 +102,14 @@ public: | |||
| 102 | 102 | ||
| 103 | protected: | 103 | protected: |
| 104 | YueParser(); | 104 | YueParser(); |
| 105 | ParseInfo parse(std::string_view codes, rule& r); | 105 | ParseInfo parse(std::string_view codes, rule& r, bool lax); |
| 106 | bool startWith(std::string_view codes, rule& r); | 106 | bool startWith(std::string_view codes, rule& r); |
| 107 | 107 | ||
| 108 | struct State { | 108 | struct State { |
| 109 | State() { | 109 | State() { |
| 110 | indents.push(0); | 110 | indents.push(0); |
| 111 | } | 111 | } |
| 112 | bool lax = false; | ||
| 112 | bool exportDefault = false; | 113 | bool exportDefault = false; |
| 113 | bool exportMacro = false; | 114 | bool exportMacro = false; |
| 114 | bool exportMetatable = false; | 115 | bool exportMetatable = false; |
| @@ -118,11 +119,13 @@ protected: | |||
| 118 | int expLevel = 0; | 119 | int expLevel = 0; |
| 119 | size_t stringOpen = 0; | 120 | size_t stringOpen = 0; |
| 120 | std::string buffer; | 121 | std::string buffer; |
| 122 | std::optional<bool> useTab; | ||
| 121 | std::stack<int> indents; | 123 | std::stack<int> indents; |
| 122 | std::stack<bool> noDoStack; | 124 | std::vector<bool> noDoStack; |
| 123 | std::stack<bool> noChainBlockStack; | 125 | std::vector<bool> noChainBlockStack; |
| 124 | std::stack<bool> noTableBlockStack; | 126 | std::vector<bool> noTableBlockStack; |
| 125 | std::stack<bool> noForStack; | 127 | std::vector<bool> noForStack; |
| 128 | std::vector<bool> noUntilStack; | ||
| 126 | std::unordered_set<std::string> usedNames; | 129 | std::unordered_set<std::string> usedNames; |
| 127 | }; | 130 | }; |
| 128 | 131 | ||
| @@ -132,7 +135,6 @@ protected: | |||
| 132 | } | 135 | } |
| 133 | 136 | ||
| 134 | private: | 137 | private: |
| 135 | Converter _converter; | ||
| 136 | std::unordered_map<std::string_view, rule*> _rules; | 138 | std::unordered_map<std::string_view, rule*> _rules; |
| 137 | 139 | ||
| 138 | template <class T> | 140 | template <class T> |
| @@ -147,7 +149,6 @@ private: | |||
| 147 | } | 149 | } |
| 148 | 150 | ||
| 149 | NONE_AST_RULE(empty_block_error); | 151 | NONE_AST_RULE(empty_block_error); |
| 150 | NONE_AST_RULE(leading_spaces_error); | ||
| 151 | NONE_AST_RULE(indentation_error); | 152 | NONE_AST_RULE(indentation_error); |
| 152 | NONE_AST_RULE(braces_expression_error); | 153 | NONE_AST_RULE(braces_expression_error); |
| 153 | NONE_AST_RULE(brackets_expression_error); | 154 | NONE_AST_RULE(brackets_expression_error); |
| @@ -156,12 +157,42 @@ private: | |||
| 156 | NONE_AST_RULE(invalid_interpolation_error); | 157 | NONE_AST_RULE(invalid_interpolation_error); |
| 157 | NONE_AST_RULE(confusing_unary_not_error); | 158 | NONE_AST_RULE(confusing_unary_not_error); |
| 158 | NONE_AST_RULE(table_key_pair_error); | 159 | NONE_AST_RULE(table_key_pair_error); |
| 159 | NONE_AST_RULE(if_assignment_syntax_error); | 160 | NONE_AST_RULE(assignment_expression_syntax_error); |
| 161 | NONE_AST_RULE(unclosed_single_string_error); | ||
| 162 | NONE_AST_RULE(unclosed_double_string_error); | ||
| 163 | NONE_AST_RULE(unclosed_lua_string_error); | ||
| 164 | NONE_AST_RULE(unexpected_comma_error); | ||
| 165 | NONE_AST_RULE(parenthesis_error); | ||
| 166 | NONE_AST_RULE(dangling_clause_error); | ||
| 167 | NONE_AST_RULE(keyword_as_label_error); | ||
| 168 | NONE_AST_RULE(check_vararg_position); | ||
| 169 | NONE_AST_RULE(vararg_position_error); | ||
| 170 | NONE_AST_RULE(invalid_import_syntax_error); | ||
| 171 | NONE_AST_RULE(invalid_import_as_syntax_error); | ||
| 172 | NONE_AST_RULE(expected_expression_error); | ||
| 173 | NONE_AST_RULE(invalid_from_import_error); | ||
| 174 | NONE_AST_RULE(invalid_export_syntax_error); | ||
| 175 | NONE_AST_RULE(invalid_macro_definition_error); | ||
| 176 | NONE_AST_RULE(invalid_global_declaration_error); | ||
| 177 | NONE_AST_RULE(invalid_local_declaration_error); | ||
| 178 | NONE_AST_RULE(invalid_with_syntax_error); | ||
| 179 | NONE_AST_RULE(invalid_try_syntax_error); | ||
| 180 | NONE_AST_RULE(keyword_as_identifier_syntax_error); | ||
| 181 | NONE_AST_RULE(invalid_number_literal_error); | ||
| 182 | NONE_AST_RULE(invalid_import_literal_error); | ||
| 183 | NONE_AST_RULE(expected_indentifier_error); | ||
| 184 | |||
| 185 | NONE_AST_RULE(must_exp); | ||
| 186 | NONE_AST_RULE(must_unary_exp); | ||
| 187 | NONE_AST_RULE(must_variable); | ||
| 188 | NONE_AST_RULE(end_braces_expression); | ||
| 189 | NONE_AST_RULE(end_brackets_expression); | ||
| 160 | 190 | ||
| 161 | NONE_AST_RULE(inc_exp_level); | 191 | NONE_AST_RULE(inc_exp_level); |
| 162 | NONE_AST_RULE(dec_exp_level); | 192 | NONE_AST_RULE(dec_exp_level); |
| 163 | 193 | ||
| 164 | NONE_AST_RULE(num_char); | 194 | NONE_AST_RULE(num_char); |
| 195 | NONE_AST_RULE(must_num_char); | ||
| 165 | NONE_AST_RULE(num_char_hex); | 196 | NONE_AST_RULE(num_char_hex); |
| 166 | NONE_AST_RULE(num_lit); | 197 | NONE_AST_RULE(num_lit); |
| 167 | NONE_AST_RULE(num_bin_lit); | 198 | NONE_AST_RULE(num_bin_lit); |
| @@ -172,6 +203,7 @@ private: | |||
| 172 | NONE_AST_RULE(line_break); | 203 | NONE_AST_RULE(line_break); |
| 173 | NONE_AST_RULE(any_char); | 204 | NONE_AST_RULE(any_char); |
| 174 | NONE_AST_RULE(white); | 205 | NONE_AST_RULE(white); |
| 206 | NONE_AST_RULE(plain_white); | ||
| 175 | NONE_AST_RULE(stop); | 207 | NONE_AST_RULE(stop); |
| 176 | NONE_AST_RULE(comment); | 208 | NONE_AST_RULE(comment); |
| 177 | NONE_AST_RULE(multi_line_open); | 209 | NONE_AST_RULE(multi_line_open); |
| @@ -217,6 +249,8 @@ private: | |||
| 217 | NONE_AST_RULE(enable_for); | 249 | NONE_AST_RULE(enable_for); |
| 218 | NONE_AST_RULE(enable_fun_lit); | 250 | NONE_AST_RULE(enable_fun_lit); |
| 219 | NONE_AST_RULE(disable_fun_lit); | 251 | NONE_AST_RULE(disable_fun_lit); |
| 252 | NONE_AST_RULE(disable_until); | ||
| 253 | NONE_AST_RULE(enable_until); | ||
| 220 | NONE_AST_RULE(switch_else); | 254 | NONE_AST_RULE(switch_else); |
| 221 | NONE_AST_RULE(switch_block); | 255 | NONE_AST_RULE(switch_block); |
| 222 | NONE_AST_RULE(if_else_if); | 256 | NONE_AST_RULE(if_else_if); |
| @@ -246,6 +280,8 @@ private: | |||
| 246 | NONE_AST_RULE(fn_arg_def_lit_lines); | 280 | NONE_AST_RULE(fn_arg_def_lit_lines); |
| 247 | NONE_AST_RULE(destruct_def); | 281 | NONE_AST_RULE(destruct_def); |
| 248 | NONE_AST_RULE(macro_args_def); | 282 | NONE_AST_RULE(macro_args_def); |
| 283 | NONE_AST_RULE(var_arg_def); | ||
| 284 | NONE_AST_RULE(outer_var_shadow_def); | ||
| 249 | NONE_AST_RULE(chain_call); | 285 | NONE_AST_RULE(chain_call); |
| 250 | NONE_AST_RULE(chain_call_list); | 286 | NONE_AST_RULE(chain_call_list); |
| 251 | NONE_AST_RULE(chain_index_chain); | 287 | NONE_AST_RULE(chain_index_chain); |
| @@ -262,7 +298,6 @@ private: | |||
| 262 | NONE_AST_RULE(table_value); | 298 | NONE_AST_RULE(table_value); |
| 263 | NONE_AST_RULE(table_lit_lines); | 299 | NONE_AST_RULE(table_lit_lines); |
| 264 | NONE_AST_RULE(table_lit_line); | 300 | NONE_AST_RULE(table_lit_line); |
| 265 | NONE_AST_RULE(table_value_list); | ||
| 266 | NONE_AST_RULE(table_block_inner); | 301 | NONE_AST_RULE(table_block_inner); |
| 267 | NONE_AST_RULE(class_line); | 302 | NONE_AST_RULE(class_line); |
| 268 | NONE_AST_RULE(key_value_line); | 303 | NONE_AST_RULE(key_value_line); |
| @@ -279,17 +314,17 @@ private: | |||
| 279 | NONE_AST_RULE(expo_exp); | 314 | NONE_AST_RULE(expo_exp); |
| 280 | NONE_AST_RULE(exp_not_tab); | 315 | NONE_AST_RULE(exp_not_tab); |
| 281 | NONE_AST_RULE(local_const_item); | 316 | NONE_AST_RULE(local_const_item); |
| 282 | NONE_AST_RULE(empty_line_break); | 317 | NONE_AST_RULE(comment_line); |
| 283 | NONE_AST_RULE(yue_comment); | ||
| 284 | NONE_AST_RULE(yue_line_comment); | 318 | NONE_AST_RULE(yue_line_comment); |
| 319 | NONE_AST_RULE(yue_multiline_comment); | ||
| 285 | NONE_AST_RULE(line); | 320 | NONE_AST_RULE(line); |
| 286 | NONE_AST_RULE(shebang); | 321 | NONE_AST_RULE(shebang); |
| 322 | NONE_AST_RULE(lax_line); | ||
| 287 | 323 | ||
| 288 | AST_RULE(Num); | 324 | AST_RULE(Num); |
| 289 | AST_RULE(Name); | 325 | AST_RULE(Name); |
| 290 | AST_RULE(UnicodeName); | 326 | AST_RULE(UnicodeName); |
| 291 | AST_RULE(Variable); | 327 | AST_RULE(Variable); |
| 292 | AST_RULE(LabelName); | ||
| 293 | AST_RULE(LuaKeyword); | 328 | AST_RULE(LuaKeyword); |
| 294 | AST_RULE(Self); | 329 | AST_RULE(Self); |
| 295 | AST_RULE(SelfName); | 330 | AST_RULE(SelfName); |
| @@ -298,6 +333,7 @@ private: | |||
| 298 | AST_RULE(SelfItem); | 333 | AST_RULE(SelfItem); |
| 299 | AST_RULE(KeyName); | 334 | AST_RULE(KeyName); |
| 300 | AST_RULE(VarArg); | 335 | AST_RULE(VarArg); |
| 336 | AST_RULE(VarArgDef); | ||
| 301 | AST_RULE(Seperator); | 337 | AST_RULE(Seperator); |
| 302 | AST_RULE(NameList); | 338 | AST_RULE(NameList); |
| 303 | AST_RULE(LocalFlag); | 339 | AST_RULE(LocalFlag); |
| @@ -315,6 +351,7 @@ private: | |||
| 315 | AST_RULE(ImportAllMacro); | 351 | AST_RULE(ImportAllMacro); |
| 316 | AST_RULE(ImportTabLit); | 352 | AST_RULE(ImportTabLit); |
| 317 | AST_RULE(ImportAs); | 353 | AST_RULE(ImportAs); |
| 354 | AST_RULE(ImportGlobal); | ||
| 318 | AST_RULE(Import); | 355 | AST_RULE(Import); |
| 319 | AST_RULE(Label); | 356 | AST_RULE(Label); |
| 320 | AST_RULE(Goto); | 357 | AST_RULE(Goto); |
| @@ -339,6 +376,7 @@ private: | |||
| 339 | AST_RULE(Repeat); | 376 | AST_RULE(Repeat); |
| 340 | AST_RULE(ForStepValue); | 377 | AST_RULE(ForStepValue); |
| 341 | AST_RULE(For); | 378 | AST_RULE(For); |
| 379 | AST_RULE(ForNum); | ||
| 342 | AST_RULE(ForEach); | 380 | AST_RULE(ForEach); |
| 343 | AST_RULE(Do); | 381 | AST_RULE(Do); |
| 344 | AST_RULE(CatchBlock); | 382 | AST_RULE(CatchBlock); |
| @@ -348,8 +386,8 @@ private: | |||
| 348 | AST_RULE(TblComprehension); | 386 | AST_RULE(TblComprehension); |
| 349 | AST_RULE(StarExp); | 387 | AST_RULE(StarExp); |
| 350 | AST_RULE(CompForEach); | 388 | AST_RULE(CompForEach); |
| 389 | AST_RULE(CompForNum); | ||
| 351 | AST_RULE(CompFor); | 390 | AST_RULE(CompFor); |
| 352 | AST_RULE(CompInner); | ||
| 353 | AST_RULE(Assign); | 391 | AST_RULE(Assign); |
| 354 | AST_RULE(UpdateOp); | 392 | AST_RULE(UpdateOp); |
| 355 | AST_RULE(Update); | 393 | AST_RULE(Update); |
| @@ -360,6 +398,7 @@ private: | |||
| 360 | AST_RULE(ExpOpValue); | 398 | AST_RULE(ExpOpValue); |
| 361 | AST_RULE(Exp); | 399 | AST_RULE(Exp); |
| 362 | AST_RULE(Callable); | 400 | AST_RULE(Callable); |
| 401 | AST_RULE(ReversedIndex); | ||
| 363 | AST_RULE(ChainValue); | 402 | AST_RULE(ChainValue); |
| 364 | AST_RULE(SimpleTable); | 403 | AST_RULE(SimpleTable); |
| 365 | AST_RULE(SimpleValue); | 404 | AST_RULE(SimpleValue); |
| @@ -372,6 +411,11 @@ private: | |||
| 372 | AST_RULE(DoubleStringInner); | 411 | AST_RULE(DoubleStringInner); |
| 373 | AST_RULE(DoubleStringContent); | 412 | AST_RULE(DoubleStringContent); |
| 374 | AST_RULE(DoubleString); | 413 | AST_RULE(DoubleString); |
| 414 | AST_RULE(YAMLIndent); | ||
| 415 | AST_RULE(YAMLLineInner); | ||
| 416 | AST_RULE(YAMLLineContent); | ||
| 417 | AST_RULE(YAMLLine); | ||
| 418 | AST_RULE(YAMLMultiline); | ||
| 375 | AST_RULE(String); | 419 | AST_RULE(String); |
| 376 | AST_RULE(Parens); | 420 | AST_RULE(Parens); |
| 377 | AST_RULE(DotChainItem); | 421 | AST_RULE(DotChainItem); |
| @@ -435,8 +479,9 @@ private: | |||
| 435 | AST_RULE(Statement); | 479 | AST_RULE(Statement); |
| 436 | AST_RULE(StatementSep); | 480 | AST_RULE(StatementSep); |
| 437 | AST_RULE(YueLineComment); | 481 | AST_RULE(YueLineComment); |
| 438 | AST_RULE(MultilineCommentInner); | ||
| 439 | AST_RULE(YueMultilineComment); | 482 | AST_RULE(YueMultilineComment); |
| 483 | AST_RULE(YueComment); | ||
| 484 | AST_RULE(EmptyLine); | ||
| 440 | AST_RULE(ChainAssign); | 485 | AST_RULE(ChainAssign); |
| 441 | AST_RULE(Body); | 486 | AST_RULE(Body); |
| 442 | AST_RULE(Block); | 487 | AST_RULE(Block); |
| @@ -447,6 +492,7 @@ private: | |||
| 447 | namespace Utils { | 492 | namespace Utils { |
| 448 | void replace(std::string& str, std::string_view from, std::string_view to); | 493 | void replace(std::string& str, std::string_view from, std::string_view to); |
| 449 | void trim(std::string& str); | 494 | void trim(std::string& str); |
| 495 | std::string toLuaDoubleString(const std::string& input); | ||
| 450 | } // namespace Utils | 496 | } // namespace Utils |
| 451 | 497 | ||
| 452 | } // namespace yue | 498 | } // namespace yue |
diff --git a/src/yuescript/yuescript.cpp b/src/yuescript/yuescript.cpp index 7e8e8b7..fd2bf62 100644 --- a/src/yuescript/yuescript.cpp +++ b/src/yuescript/yuescript.cpp | |||
| @@ -1,4 +1,4 @@ | |||
| 1 | /* Copyright (c) 2017-2025 Li Jin <dragon-fly@qq.com> | 1 | /* Copyright (c) 2017-2026 Li Jin <dragon-fly@qq.com> |
| 2 | 2 | ||
| 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions: |
| 4 | 4 | ||
| @@ -93,6 +93,12 @@ static void get_config(lua_State* L, yue::YueConfig& config) { | |||
| 93 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; | 93 | config.useSpaceOverTab = lua_toboolean(L, -1) != 0; |
| 94 | } | 94 | } |
| 95 | lua_pop(L, 1); | 95 | lua_pop(L, 1); |
| 96 | lua_pushliteral(L, "lax"); | ||
| 97 | lua_gettable(L, -2); | ||
| 98 | if (lua_isboolean(L, -1) != 0) { | ||
| 99 | config.lax = lua_toboolean(L, -1) != 0; | ||
| 100 | } | ||
| 101 | lua_pop(L, 1); | ||
| 96 | lua_pushliteral(L, "options"); | 102 | lua_pushliteral(L, "options"); |
| 97 | lua_gettable(L, -2); | 103 | lua_gettable(L, -2); |
| 98 | if (lua_istable(L, -1) != 0) { | 104 | if (lua_istable(L, -1) != 0) { |
| @@ -179,8 +185,13 @@ static int yueformat(lua_State* L) { | |||
| 179 | if (!lua_isnoneornil(L, 2)) { | 185 | if (!lua_isnoneornil(L, 2)) { |
| 180 | tabSize = static_cast<int>(luaL_checkinteger(L, 2)); | 186 | tabSize = static_cast<int>(luaL_checkinteger(L, 2)); |
| 181 | } | 187 | } |
| 188 | bool reserveComment = true; | ||
| 189 | if (!lua_isnoneornil(L, 3)) { | ||
| 190 | luaL_checktype(L, 3, LUA_TBOOLEAN); | ||
| 191 | reserveComment = lua_toboolean(L, 3) != 0; | ||
| 192 | } | ||
| 182 | std::string_view codes(input, len); | 193 | std::string_view codes(input, len); |
| 183 | auto info = yue::YueParser::shared().parse<yue::File_t>(codes); | 194 | auto info = yue::YueParser::shared().parse<yue::File_t>(codes, false); |
| 184 | if (info.error) { | 195 | if (info.error) { |
| 185 | const auto& error = info.error.value(); | 196 | const auto& error = info.error.value(); |
| 186 | if (!info.codes) { | 197 | if (!info.codes) { |
| @@ -200,7 +211,11 @@ static int yueformat(lua_State* L) { | |||
| 200 | } else { | 211 | } else { |
| 201 | formatter.spaceOverTab = false; | 212 | formatter.spaceOverTab = false; |
| 202 | } | 213 | } |
| 214 | formatter.reserveComment = reserveComment; | ||
| 203 | auto result = formatter.toString(info.node.get()); | 215 | auto result = formatter.toString(info.node.get()); |
| 216 | if (!formatter.reserveComment) { | ||
| 217 | yue::Utils::replace(result, "\n\n", "\n"); | ||
| 218 | } | ||
| 204 | lua_pushlstring(L, result.c_str(), result.size()); | 219 | lua_pushlstring(L, result.c_str(), result.size()); |
| 205 | return 1; | 220 | return 1; |
| 206 | } | 221 | } |
| @@ -235,6 +250,7 @@ static int yuecheck(lua_State* L) { | |||
| 235 | } | 250 | } |
| 236 | if (result.globals) { | 251 | if (result.globals) { |
| 237 | for (const auto& global : *result.globals) { | 252 | for (const auto& global : *result.globals) { |
| 253 | if (global.defined) continue; | ||
| 238 | lua_createtable(L, 4, 0); | 254 | lua_createtable(L, 4, 0); |
| 239 | lua_pushliteral(L, "global"); | 255 | lua_pushliteral(L, "global"); |
| 240 | lua_rawseti(L, -2, 1); | 256 | lua_rawseti(L, -2, 1); |
| @@ -247,7 +263,7 @@ static int yuecheck(lua_State* L) { | |||
| 247 | lua_rawseti(L, -2, ++i); | 263 | lua_rawseti(L, -2, ++i); |
| 248 | } | 264 | } |
| 249 | } | 265 | } |
| 250 | if (result.error) { | 266 | if (!config.lax && result.error) { |
| 251 | lua_pushboolean(L, 0); | 267 | lua_pushboolean(L, 0); |
| 252 | lua_insert(L, -2); | 268 | lua_insert(L, -2); |
| 253 | return 2; | 269 | return 2; |
| @@ -282,8 +298,18 @@ static int yuetoast(lua_State* L) { | |||
| 282 | ruleName = {name, nameSize}; | 298 | ruleName = {name, nameSize}; |
| 283 | } | 299 | } |
| 284 | } | 300 | } |
| 301 | bool lax = false; | ||
| 302 | if (!lua_isnoneornil(L, 4)) { | ||
| 303 | luaL_checktype(L, 4, LUA_TBOOLEAN); | ||
| 304 | lax = lua_toboolean(L, 4) != 0; | ||
| 305 | } | ||
| 306 | bool reserveComment = false; | ||
| 307 | if (!lua_isnoneornil(L, 5)) { | ||
| 308 | luaL_checktype(L, 5, LUA_TBOOLEAN); | ||
| 309 | reserveComment = lua_toboolean(L, 5) != 0; | ||
| 310 | } | ||
| 285 | auto& yueParser = yue::YueParser::shared(); | 311 | auto& yueParser = yue::YueParser::shared(); |
| 286 | auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}) : yueParser.parse(ruleName, {input, size}); | 312 | auto info = ruleName.empty() ? yueParser.parse<yue::File_t>({input, size}, lax) : yueParser.parse(ruleName, {input, size}, lax); |
| 287 | if (!info.error) { | 313 | if (!info.error) { |
| 288 | lua_createtable(L, 0, 0); | 314 | lua_createtable(L, 0, 0); |
| 289 | int tableIndex = lua_gettop(L); | 315 | int tableIndex = lua_gettop(L); |
| @@ -309,13 +335,11 @@ static int yuetoast(lua_State* L) { | |||
| 309 | }; | 335 | }; |
| 310 | do_call(info.node); | 336 | do_call(info.node); |
| 311 | yue::YueFormat formatter{}; | 337 | yue::YueFormat formatter{}; |
| 338 | formatter.reserveComment = reserveComment; | ||
| 312 | while (!stack.empty()) { | 339 | while (!stack.empty()) { |
| 313 | auto& current = stack.top(); | 340 | auto& current = stack.top(); |
| 314 | int continuation = current.continuation; | 341 | int continuation = current.continuation; |
| 315 | auto node = current.node; | 342 | auto node = current.node; |
| 316 | if (auto comment = yue::ast_cast<yue::YueMultilineComment_t>(node)) { | ||
| 317 | node = comment->inner.get(); | ||
| 318 | } | ||
| 319 | switch (continuation) { | 343 | switch (continuation) { |
| 320 | case 0: { | 344 | case 0: { |
| 321 | if (!current.children) { | 345 | if (!current.children) { |
| @@ -324,6 +348,9 @@ static int yuetoast(lua_State* L) { | |||
| 324 | current.hasSep = true; | 348 | current.hasSep = true; |
| 325 | return false; | 349 | return false; |
| 326 | } | 350 | } |
| 351 | if (!reserveComment && yue::ast_is<yue::YueComment_t, yue::EmptyLine_t>(child)) { | ||
| 352 | return false; | ||
| 353 | } | ||
| 327 | if (!current.children) { | 354 | if (!current.children) { |
| 328 | current.children = std::make_unique<std::vector<yue::ast_node*>>(); | 355 | current.children = std::make_unique<std::vector<yue::ast_node*>>(); |
| 329 | } | 356 | } |
diff --git a/win-build/Lua53/Lua53.vcxproj b/win-build/Lua53/Lua53.vcxproj index 4f17bfc..d0e7fee 100644 --- a/win-build/Lua53/Lua53.vcxproj +++ b/win-build/Lua53/Lua53.vcxproj | |||
| @@ -269,69 +269,69 @@ | |||
| 269 | </Link> | 269 | </Link> |
| 270 | </ItemDefinitionGroup> | 270 | </ItemDefinitionGroup> |
| 271 | <ItemGroup> | 271 | <ItemGroup> |
| 272 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lapi.c" /> | 272 | <ClCompile Include="lapi.c" /> |
| 273 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lauxlib.c" /> | 273 | <ClCompile Include="lauxlib.c" /> |
| 274 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lbaselib.c" /> | 274 | <ClCompile Include="lbaselib.c" /> |
| 275 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lbitlib.c" /> | 275 | <ClCompile Include="lbitlib.c" /> |
| 276 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcode.c" /> | 276 | <ClCompile Include="lcode.c" /> |
| 277 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcorolib.c" /> | 277 | <ClCompile Include="lcorolib.c" /> |
| 278 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lctype.c" /> | 278 | <ClCompile Include="lctype.c" /> |
| 279 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldblib.c" /> | 279 | <ClCompile Include="ldblib.c" /> |
| 280 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldebug.c" /> | 280 | <ClCompile Include="ldebug.c" /> |
| 281 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldo.c" /> | 281 | <ClCompile Include="ldo.c" /> |
| 282 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldump.c" /> | 282 | <ClCompile Include="ldump.c" /> |
| 283 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lfunc.c" /> | 283 | <ClCompile Include="lfunc.c" /> |
| 284 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lgc.c" /> | 284 | <ClCompile Include="lgc.c" /> |
| 285 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\linit.c" /> | 285 | <ClCompile Include="linit.c" /> |
| 286 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\liolib.c" /> | 286 | <ClCompile Include="liolib.c" /> |
| 287 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llex.c" /> | 287 | <ClCompile Include="llex.c" /> |
| 288 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmathlib.c" /> | 288 | <ClCompile Include="lmathlib.c" /> |
| 289 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmem.c" /> | 289 | <ClCompile Include="lmem.c" /> |
| 290 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\loadlib.c" /> | 290 | <ClCompile Include="loadlib.c" /> |
| 291 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lobject.c" /> | 291 | <ClCompile Include="lobject.c" /> |
| 292 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lopcodes.c" /> | 292 | <ClCompile Include="lopcodes.c" /> |
| 293 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\loslib.c" /> | 293 | <ClCompile Include="loslib.c" /> |
| 294 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lparser.c" /> | 294 | <ClCompile Include="lparser.c" /> |
| 295 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstate.c" /> | 295 | <ClCompile Include="lstate.c" /> |
| 296 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstring.c" /> | 296 | <ClCompile Include="lstring.c" /> |
| 297 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstrlib.c" /> | 297 | <ClCompile Include="lstrlib.c" /> |
| 298 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltable.c" /> | 298 | <ClCompile Include="ltable.c" /> |
| 299 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltablib.c" /> | 299 | <ClCompile Include="ltablib.c" /> |
| 300 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltm.c" /> | 300 | <ClCompile Include="ltm.c" /> |
| 301 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lundump.c" /> | 301 | <ClCompile Include="lundump.c" /> |
| 302 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lutf8lib.c" /> | 302 | <ClCompile Include="lutf8lib.c" /> |
| 303 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lvm.c" /> | 303 | <ClCompile Include="lvm.c" /> |
| 304 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lzio.c" /> | 304 | <ClCompile Include="lzio.c" /> |
| 305 | </ItemGroup> | 305 | </ItemGroup> |
| 306 | <ItemGroup> | 306 | <ItemGroup> |
| 307 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lapi.h" /> | 307 | <ClInclude Include="lapi.h" /> |
| 308 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lauxlib.h" /> | 308 | <ClInclude Include="lauxlib.h" /> |
| 309 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcode.h" /> | 309 | <ClInclude Include="lcode.h" /> |
| 310 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lctype.h" /> | 310 | <ClInclude Include="lctype.h" /> |
| 311 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldebug.h" /> | 311 | <ClInclude Include="ldebug.h" /> |
| 312 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldo.h" /> | 312 | <ClInclude Include="ldo.h" /> |
| 313 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lfunc.h" /> | 313 | <ClInclude Include="lfunc.h" /> |
| 314 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lgc.h" /> | 314 | <ClInclude Include="lgc.h" /> |
| 315 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llex.h" /> | 315 | <ClInclude Include="llex.h" /> |
| 316 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llimits.h" /> | 316 | <ClInclude Include="llimits.h" /> |
| 317 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmem.h" /> | 317 | <ClInclude Include="lmem.h" /> |
| 318 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lobject.h" /> | 318 | <ClInclude Include="lobject.h" /> |
| 319 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lopcodes.h" /> | 319 | <ClInclude Include="lopcodes.h" /> |
| 320 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lparser.h" /> | 320 | <ClInclude Include="lparser.h" /> |
| 321 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lprefix.h" /> | 321 | <ClInclude Include="lprefix.h" /> |
| 322 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstate.h" /> | 322 | <ClInclude Include="lstate.h" /> |
| 323 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstring.h" /> | 323 | <ClInclude Include="lstring.h" /> |
| 324 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltable.h" /> | 324 | <ClInclude Include="ltable.h" /> |
| 325 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltm.h" /> | 325 | <ClInclude Include="ltm.h" /> |
| 326 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lua.h" /> | 326 | <ClInclude Include="lua.h" /> |
| 327 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lua.hpp" /> | 327 | <ClInclude Include="lua.hpp" /> |
| 328 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\luaconf.h" /> | 328 | <ClInclude Include="luaconf.h" /> |
| 329 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lualib.h" /> | 329 | <ClInclude Include="lualib.h" /> |
| 330 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lundump.h" /> | 330 | <ClInclude Include="lundump.h" /> |
| 331 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lvm.h" /> | 331 | <ClInclude Include="lvm.h" /> |
| 332 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lzio.h" /> | 332 | <ClInclude Include="lzio.h" /> |
| 333 | </ItemGroup> | 333 | </ItemGroup> |
| 334 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | 334 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| 335 | <ImportGroup Label="ExtensionTargets"> | 335 | <ImportGroup Label="ExtensionTargets"> |
| 336 | </ImportGroup> | 336 | </ImportGroup> |
| 337 | </Project> \ No newline at end of file | 337 | </Project> |
diff --git a/win-build/Lua53/Lua53.vcxproj.filters b/win-build/Lua53/Lua53.vcxproj.filters index df8715c..be208ec 100644 --- a/win-build/Lua53/Lua53.vcxproj.filters +++ b/win-build/Lua53/Lua53.vcxproj.filters | |||
| @@ -7,184 +7,184 @@ | |||
| 7 | </Filter> | 7 | </Filter> |
| 8 | </ItemGroup> | 8 | </ItemGroup> |
| 9 | <ItemGroup> | 9 | <ItemGroup> |
| 10 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lapi.c"> | 10 | <ClCompile Include="lapi.c"> |
| 11 | <Filter>src</Filter> | 11 | <Filter>src</Filter> |
| 12 | </ClCompile> | 12 | </ClCompile> |
| 13 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lauxlib.c"> | 13 | <ClCompile Include="lauxlib.c"> |
| 14 | <Filter>src</Filter> | 14 | <Filter>src</Filter> |
| 15 | </ClCompile> | 15 | </ClCompile> |
| 16 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lbaselib.c"> | 16 | <ClCompile Include="lbaselib.c"> |
| 17 | <Filter>src</Filter> | 17 | <Filter>src</Filter> |
| 18 | </ClCompile> | 18 | </ClCompile> |
| 19 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lbitlib.c"> | 19 | <ClCompile Include="lbitlib.c"> |
| 20 | <Filter>src</Filter> | 20 | <Filter>src</Filter> |
| 21 | </ClCompile> | 21 | </ClCompile> |
| 22 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcode.c"> | 22 | <ClCompile Include="lcode.c"> |
| 23 | <Filter>src</Filter> | 23 | <Filter>src</Filter> |
| 24 | </ClCompile> | 24 | </ClCompile> |
| 25 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcorolib.c"> | 25 | <ClCompile Include="lcorolib.c"> |
| 26 | <Filter>src</Filter> | 26 | <Filter>src</Filter> |
| 27 | </ClCompile> | 27 | </ClCompile> |
| 28 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lctype.c"> | 28 | <ClCompile Include="lctype.c"> |
| 29 | <Filter>src</Filter> | 29 | <Filter>src</Filter> |
| 30 | </ClCompile> | 30 | </ClCompile> |
| 31 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldblib.c"> | 31 | <ClCompile Include="ldblib.c"> |
| 32 | <Filter>src</Filter> | 32 | <Filter>src</Filter> |
| 33 | </ClCompile> | 33 | </ClCompile> |
| 34 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldebug.c"> | 34 | <ClCompile Include="ldebug.c"> |
| 35 | <Filter>src</Filter> | 35 | <Filter>src</Filter> |
| 36 | </ClCompile> | 36 | </ClCompile> |
| 37 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldo.c"> | 37 | <ClCompile Include="ldo.c"> |
| 38 | <Filter>src</Filter> | 38 | <Filter>src</Filter> |
| 39 | </ClCompile> | 39 | </ClCompile> |
| 40 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldump.c"> | 40 | <ClCompile Include="ldump.c"> |
| 41 | <Filter>src</Filter> | 41 | <Filter>src</Filter> |
| 42 | </ClCompile> | 42 | </ClCompile> |
| 43 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lfunc.c"> | 43 | <ClCompile Include="lfunc.c"> |
| 44 | <Filter>src</Filter> | 44 | <Filter>src</Filter> |
| 45 | </ClCompile> | 45 | </ClCompile> |
| 46 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lgc.c"> | 46 | <ClCompile Include="lgc.c"> |
| 47 | <Filter>src</Filter> | 47 | <Filter>src</Filter> |
| 48 | </ClCompile> | 48 | </ClCompile> |
| 49 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\linit.c"> | 49 | <ClCompile Include="linit.c"> |
| 50 | <Filter>src</Filter> | 50 | <Filter>src</Filter> |
| 51 | </ClCompile> | 51 | </ClCompile> |
| 52 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\liolib.c"> | 52 | <ClCompile Include="liolib.c"> |
| 53 | <Filter>src</Filter> | 53 | <Filter>src</Filter> |
| 54 | </ClCompile> | 54 | </ClCompile> |
| 55 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llex.c"> | 55 | <ClCompile Include="llex.c"> |
| 56 | <Filter>src</Filter> | 56 | <Filter>src</Filter> |
| 57 | </ClCompile> | 57 | </ClCompile> |
| 58 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmathlib.c"> | 58 | <ClCompile Include="lmathlib.c"> |
| 59 | <Filter>src</Filter> | 59 | <Filter>src</Filter> |
| 60 | </ClCompile> | 60 | </ClCompile> |
| 61 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmem.c"> | 61 | <ClCompile Include="lmem.c"> |
| 62 | <Filter>src</Filter> | 62 | <Filter>src</Filter> |
| 63 | </ClCompile> | 63 | </ClCompile> |
| 64 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\loadlib.c"> | 64 | <ClCompile Include="loadlib.c"> |
| 65 | <Filter>src</Filter> | 65 | <Filter>src</Filter> |
| 66 | </ClCompile> | 66 | </ClCompile> |
| 67 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lobject.c"> | 67 | <ClCompile Include="lobject.c"> |
| 68 | <Filter>src</Filter> | 68 | <Filter>src</Filter> |
| 69 | </ClCompile> | 69 | </ClCompile> |
| 70 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lopcodes.c"> | 70 | <ClCompile Include="lopcodes.c"> |
| 71 | <Filter>src</Filter> | 71 | <Filter>src</Filter> |
| 72 | </ClCompile> | 72 | </ClCompile> |
| 73 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\loslib.c"> | 73 | <ClCompile Include="loslib.c"> |
| 74 | <Filter>src</Filter> | 74 | <Filter>src</Filter> |
| 75 | </ClCompile> | 75 | </ClCompile> |
| 76 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lparser.c"> | 76 | <ClCompile Include="lparser.c"> |
| 77 | <Filter>src</Filter> | 77 | <Filter>src</Filter> |
| 78 | </ClCompile> | 78 | </ClCompile> |
| 79 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstate.c"> | 79 | <ClCompile Include="lstate.c"> |
| 80 | <Filter>src</Filter> | 80 | <Filter>src</Filter> |
| 81 | </ClCompile> | 81 | </ClCompile> |
| 82 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstring.c"> | 82 | <ClCompile Include="lstring.c"> |
| 83 | <Filter>src</Filter> | 83 | <Filter>src</Filter> |
| 84 | </ClCompile> | 84 | </ClCompile> |
| 85 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstrlib.c"> | 85 | <ClCompile Include="lstrlib.c"> |
| 86 | <Filter>src</Filter> | 86 | <Filter>src</Filter> |
| 87 | </ClCompile> | 87 | </ClCompile> |
| 88 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltable.c"> | 88 | <ClCompile Include="ltable.c"> |
| 89 | <Filter>src</Filter> | 89 | <Filter>src</Filter> |
| 90 | </ClCompile> | 90 | </ClCompile> |
| 91 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltablib.c"> | 91 | <ClCompile Include="ltablib.c"> |
| 92 | <Filter>src</Filter> | 92 | <Filter>src</Filter> |
| 93 | </ClCompile> | 93 | </ClCompile> |
| 94 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltm.c"> | 94 | <ClCompile Include="ltm.c"> |
| 95 | <Filter>src</Filter> | 95 | <Filter>src</Filter> |
| 96 | </ClCompile> | 96 | </ClCompile> |
| 97 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lundump.c"> | 97 | <ClCompile Include="lundump.c"> |
| 98 | <Filter>src</Filter> | 98 | <Filter>src</Filter> |
| 99 | </ClCompile> | 99 | </ClCompile> |
| 100 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lutf8lib.c"> | 100 | <ClCompile Include="lutf8lib.c"> |
| 101 | <Filter>src</Filter> | 101 | <Filter>src</Filter> |
| 102 | </ClCompile> | 102 | </ClCompile> |
| 103 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lvm.c"> | 103 | <ClCompile Include="lvm.c"> |
| 104 | <Filter>src</Filter> | 104 | <Filter>src</Filter> |
| 105 | </ClCompile> | 105 | </ClCompile> |
| 106 | <ClCompile Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lzio.c"> | 106 | <ClCompile Include="lzio.c"> |
| 107 | <Filter>src</Filter> | 107 | <Filter>src</Filter> |
| 108 | </ClCompile> | 108 | </ClCompile> |
| 109 | </ItemGroup> | 109 | </ItemGroup> |
| 110 | <ItemGroup> | 110 | <ItemGroup> |
| 111 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lapi.h"> | 111 | <ClInclude Include="lapi.h"> |
| 112 | <Filter>src</Filter> | 112 | <Filter>src</Filter> |
| 113 | </ClInclude> | 113 | </ClInclude> |
| 114 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lauxlib.h"> | 114 | <ClInclude Include="lauxlib.h"> |
| 115 | <Filter>src</Filter> | 115 | <Filter>src</Filter> |
| 116 | </ClInclude> | 116 | </ClInclude> |
| 117 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lcode.h"> | 117 | <ClInclude Include="lcode.h"> |
| 118 | <Filter>src</Filter> | 118 | <Filter>src</Filter> |
| 119 | </ClInclude> | 119 | </ClInclude> |
| 120 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lctype.h"> | 120 | <ClInclude Include="lctype.h"> |
| 121 | <Filter>src</Filter> | 121 | <Filter>src</Filter> |
| 122 | </ClInclude> | 122 | </ClInclude> |
| 123 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldebug.h"> | 123 | <ClInclude Include="ldebug.h"> |
| 124 | <Filter>src</Filter> | 124 | <Filter>src</Filter> |
| 125 | </ClInclude> | 125 | </ClInclude> |
| 126 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ldo.h"> | 126 | <ClInclude Include="ldo.h"> |
| 127 | <Filter>src</Filter> | 127 | <Filter>src</Filter> |
| 128 | </ClInclude> | 128 | </ClInclude> |
| 129 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lfunc.h"> | 129 | <ClInclude Include="lfunc.h"> |
| 130 | <Filter>src</Filter> | 130 | <Filter>src</Filter> |
| 131 | </ClInclude> | 131 | </ClInclude> |
| 132 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lgc.h"> | 132 | <ClInclude Include="lgc.h"> |
| 133 | <Filter>src</Filter> | 133 | <Filter>src</Filter> |
| 134 | </ClInclude> | 134 | </ClInclude> |
| 135 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llex.h"> | 135 | <ClInclude Include="llex.h"> |
| 136 | <Filter>src</Filter> | 136 | <Filter>src</Filter> |
| 137 | </ClInclude> | 137 | </ClInclude> |
| 138 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\llimits.h"> | 138 | <ClInclude Include="llimits.h"> |
| 139 | <Filter>src</Filter> | 139 | <Filter>src</Filter> |
| 140 | </ClInclude> | 140 | </ClInclude> |
| 141 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lmem.h"> | 141 | <ClInclude Include="lmem.h"> |
| 142 | <Filter>src</Filter> | 142 | <Filter>src</Filter> |
| 143 | </ClInclude> | 143 | </ClInclude> |
| 144 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lobject.h"> | 144 | <ClInclude Include="lobject.h"> |
| 145 | <Filter>src</Filter> | 145 | <Filter>src</Filter> |
| 146 | </ClInclude> | 146 | </ClInclude> |
| 147 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lopcodes.h"> | 147 | <ClInclude Include="lopcodes.h"> |
| 148 | <Filter>src</Filter> | 148 | <Filter>src</Filter> |
| 149 | </ClInclude> | 149 | </ClInclude> |
| 150 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lparser.h"> | 150 | <ClInclude Include="lparser.h"> |
| 151 | <Filter>src</Filter> | 151 | <Filter>src</Filter> |
| 152 | </ClInclude> | 152 | </ClInclude> |
| 153 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lprefix.h"> | 153 | <ClInclude Include="lprefix.h"> |
| 154 | <Filter>src</Filter> | 154 | <Filter>src</Filter> |
| 155 | </ClInclude> | 155 | </ClInclude> |
| 156 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstate.h"> | 156 | <ClInclude Include="lstate.h"> |
| 157 | <Filter>src</Filter> | 157 | <Filter>src</Filter> |
| 158 | </ClInclude> | 158 | </ClInclude> |
| 159 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lstring.h"> | 159 | <ClInclude Include="lstring.h"> |
| 160 | <Filter>src</Filter> | 160 | <Filter>src</Filter> |
| 161 | </ClInclude> | 161 | </ClInclude> |
| 162 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltable.h"> | 162 | <ClInclude Include="ltable.h"> |
| 163 | <Filter>src</Filter> | 163 | <Filter>src</Filter> |
| 164 | </ClInclude> | 164 | </ClInclude> |
| 165 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\ltm.h"> | 165 | <ClInclude Include="ltm.h"> |
| 166 | <Filter>src</Filter> | 166 | <Filter>src</Filter> |
| 167 | </ClInclude> | 167 | </ClInclude> |
| 168 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lua.h"> | 168 | <ClInclude Include="lua.h"> |
| 169 | <Filter>src</Filter> | 169 | <Filter>src</Filter> |
| 170 | </ClInclude> | 170 | </ClInclude> |
| 171 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lua.hpp"> | 171 | <ClInclude Include="lua.hpp"> |
| 172 | <Filter>src</Filter> | 172 | <Filter>src</Filter> |
| 173 | </ClInclude> | 173 | </ClInclude> |
| 174 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\luaconf.h"> | 174 | <ClInclude Include="luaconf.h"> |
| 175 | <Filter>src</Filter> | 175 | <Filter>src</Filter> |
| 176 | </ClInclude> | 176 | </ClInclude> |
| 177 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lualib.h"> | 177 | <ClInclude Include="lualib.h"> |
| 178 | <Filter>src</Filter> | 178 | <Filter>src</Filter> |
| 179 | </ClInclude> | 179 | </ClInclude> |
| 180 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lundump.h"> | 180 | <ClInclude Include="lundump.h"> |
| 181 | <Filter>src</Filter> | 181 | <Filter>src</Filter> |
| 182 | </ClInclude> | 182 | </ClInclude> |
| 183 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lvm.h"> | 183 | <ClInclude Include="lvm.h"> |
| 184 | <Filter>src</Filter> | 184 | <Filter>src</Filter> |
| 185 | </ClInclude> | 185 | </ClInclude> |
| 186 | <ClInclude Include="\\Mac\Home\Workspace\Yuescript\win-build\Lua53\lzio.h"> | 186 | <ClInclude Include="lzio.h"> |
| 187 | <Filter>src</Filter> | 187 | <Filter>src</Filter> |
| 188 | </ClInclude> | 188 | </ClInclude> |
| 189 | </ItemGroup> | 189 | </ItemGroup> |
| 190 | </Project> \ No newline at end of file | 190 | </Project> |
diff --git a/win-build/Yuescript/Yuescript.vcxproj b/win-build/Yuescript/Yuescript.vcxproj index d073e70..9b05567 100644 --- a/win-build/Yuescript/Yuescript.vcxproj +++ b/win-build/Yuescript/Yuescript.vcxproj | |||
| @@ -176,11 +176,11 @@ | |||
| 176 | <ClCompile> | 176 | <ClCompile> |
| 177 | <WarningLevel>Level3</WarningLevel> | 177 | <WarningLevel>Level3</WarningLevel> |
| 178 | <SDLCheck>true</SDLCheck> | 178 | <SDLCheck>true</SDLCheck> |
| 179 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 179 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;_ITERATOR_DEBUG_LEVEL=0;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 180 | <ConformanceMode>true</ConformanceMode> | 180 | <ConformanceMode>true</ConformanceMode> |
| 181 | <LanguageStandard>stdcpp17</LanguageStandard> | 181 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 182 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 182 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 183 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 183 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 184 | </ClCompile> | 184 | </ClCompile> |
| 185 | <Link> | 185 | <Link> |
| 186 | <SubSystem>Console</SubSystem> | 186 | <SubSystem>Console</SubSystem> |
| @@ -191,11 +191,11 @@ | |||
| 191 | <ClCompile> | 191 | <ClCompile> |
| 192 | <WarningLevel>Level3</WarningLevel> | 192 | <WarningLevel>Level3</WarningLevel> |
| 193 | <SDLCheck>true</SDLCheck> | 193 | <SDLCheck>true</SDLCheck> |
| 194 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 194 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 195 | <ConformanceMode>true</ConformanceMode> | 195 | <ConformanceMode>true</ConformanceMode> |
| 196 | <LanguageStandard>stdcpp17</LanguageStandard> | 196 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 197 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 197 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 198 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 198 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 199 | </ClCompile> | 199 | </ClCompile> |
| 200 | <Link> | 200 | <Link> |
| 201 | <SubSystem>Console</SubSystem> | 201 | <SubSystem>Console</SubSystem> |
| @@ -206,30 +206,32 @@ | |||
| 206 | <ClCompile> | 206 | <ClCompile> |
| 207 | <WarningLevel>Level3</WarningLevel> | 207 | <WarningLevel>Level3</WarningLevel> |
| 208 | <SDLCheck>true</SDLCheck> | 208 | <SDLCheck>true</SDLCheck> |
| 209 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;_ITERATOR_DEBUG_LEVEL=0;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 209 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;_ITERATOR_DEBUG_LEVEL=0;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 210 | <ConformanceMode>true</ConformanceMode> | 210 | <ConformanceMode>true</ConformanceMode> |
| 211 | <LanguageStandard>stdcpp17</LanguageStandard> | 211 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 212 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 212 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 213 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 213 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 214 | </ClCompile> | 214 | </ClCompile> |
| 215 | <Link> | 215 | <Link> |
| 216 | <SubSystem>Console</SubSystem> | 216 | <SubSystem>Console</SubSystem> |
| 217 | <GenerateDebugInformation>true</GenerateDebugInformation> | 217 | <GenerateDebugInformation>true</GenerateDebugInformation> |
| 218 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
| 218 | </Link> | 219 | </Link> |
| 219 | </ItemDefinitionGroup> | 220 | </ItemDefinitionGroup> |
| 220 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug53|x64'"> | 221 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug53|x64'"> |
| 221 | <ClCompile> | 222 | <ClCompile> |
| 222 | <WarningLevel>Level3</WarningLevel> | 223 | <WarningLevel>Level3</WarningLevel> |
| 223 | <SDLCheck>true</SDLCheck> | 224 | <SDLCheck>true</SDLCheck> |
| 224 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 225 | <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 225 | <ConformanceMode>true</ConformanceMode> | 226 | <ConformanceMode>true</ConformanceMode> |
| 226 | <LanguageStandard>stdcpp17</LanguageStandard> | 227 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 227 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 228 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 228 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 229 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 229 | </ClCompile> | 230 | </ClCompile> |
| 230 | <Link> | 231 | <Link> |
| 231 | <SubSystem>Console</SubSystem> | 232 | <SubSystem>Console</SubSystem> |
| 232 | <GenerateDebugInformation>true</GenerateDebugInformation> | 233 | <GenerateDebugInformation>true</GenerateDebugInformation> |
| 234 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
| 233 | </Link> | 235 | </Link> |
| 234 | </ItemDefinitionGroup> | 236 | </ItemDefinitionGroup> |
| 235 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> | 237 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'"> |
| @@ -238,11 +240,11 @@ | |||
| 238 | <FunctionLevelLinking>true</FunctionLevelLinking> | 240 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 239 | <IntrinsicFunctions>true</IntrinsicFunctions> | 241 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 240 | <SDLCheck>true</SDLCheck> | 242 | <SDLCheck>true</SDLCheck> |
| 241 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 243 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 242 | <ConformanceMode>true</ConformanceMode> | 244 | <ConformanceMode>true</ConformanceMode> |
| 243 | <LanguageStandard>stdcpp17</LanguageStandard> | 245 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 244 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 246 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 245 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 247 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 246 | </ClCompile> | 248 | </ClCompile> |
| 247 | <Link> | 249 | <Link> |
| 248 | <SubSystem>Console</SubSystem> | 250 | <SubSystem>Console</SubSystem> |
| @@ -257,11 +259,11 @@ | |||
| 257 | <FunctionLevelLinking>true</FunctionLevelLinking> | 259 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 258 | <IntrinsicFunctions>true</IntrinsicFunctions> | 260 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 259 | <SDLCheck>true</SDLCheck> | 261 | <SDLCheck>true</SDLCheck> |
| 260 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 262 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 261 | <ConformanceMode>true</ConformanceMode> | 263 | <ConformanceMode>true</ConformanceMode> |
| 262 | <LanguageStandard>stdcpp17</LanguageStandard> | 264 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 263 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 265 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 264 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 266 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 265 | </ClCompile> | 267 | </ClCompile> |
| 266 | <Link> | 268 | <Link> |
| 267 | <SubSystem>Console</SubSystem> | 269 | <SubSystem>Console</SubSystem> |
| @@ -276,17 +278,18 @@ | |||
| 276 | <FunctionLevelLinking>true</FunctionLevelLinking> | 278 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 277 | <IntrinsicFunctions>true</IntrinsicFunctions> | 279 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 278 | <SDLCheck>true</SDLCheck> | 280 | <SDLCheck>true</SDLCheck> |
| 279 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 281 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 280 | <ConformanceMode>true</ConformanceMode> | 282 | <ConformanceMode>true</ConformanceMode> |
| 281 | <LanguageStandard>stdcpp17</LanguageStandard> | 283 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 282 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 284 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 283 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 285 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 284 | </ClCompile> | 286 | </ClCompile> |
| 285 | <Link> | 287 | <Link> |
| 286 | <SubSystem>Console</SubSystem> | 288 | <SubSystem>Console</SubSystem> |
| 287 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | 289 | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
| 288 | <OptimizeReferences>true</OptimizeReferences> | 290 | <OptimizeReferences>true</OptimizeReferences> |
| 289 | <GenerateDebugInformation>true</GenerateDebugInformation> | 291 | <GenerateDebugInformation>true</GenerateDebugInformation> |
| 292 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
| 290 | </Link> | 293 | </Link> |
| 291 | </ItemDefinitionGroup> | 294 | </ItemDefinitionGroup> |
| 292 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release53|x64'"> | 295 | <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release53|x64'"> |
| @@ -295,20 +298,22 @@ | |||
| 295 | <FunctionLevelLinking>true</FunctionLevelLinking> | 298 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 296 | <IntrinsicFunctions>true</IntrinsicFunctions> | 299 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 297 | <SDLCheck>true</SDLCheck> | 300 | <SDLCheck>true</SDLCheck> |
| 298 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;_SCL_SECURE_NO_WARNINGS;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 301 | <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SCL_SECURE_NO_WARNINGS;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 299 | <ConformanceMode>true</ConformanceMode> | 302 | <ConformanceMode>true</ConformanceMode> |
| 300 | <LanguageStandard>stdcpp17</LanguageStandard> | 303 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 301 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 304 | <AdditionalIncludeDirectories>..\..\src;..\..\src\3rdParty;..\..\src\3rdParty\lua;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 302 | <AdditionalOptions>/Zc:__cplusplus %(AdditionalOptions)</AdditionalOptions> | 305 | <AdditionalOptions>/Zc:__cplusplus /utf-8 %(AdditionalOptions)</AdditionalOptions> |
| 303 | </ClCompile> | 306 | </ClCompile> |
| 304 | <Link> | 307 | <Link> |
| 305 | <SubSystem>Console</SubSystem> | 308 | <SubSystem>Console</SubSystem> |
| 306 | <EnableCOMDATFolding>true</EnableCOMDATFolding> | 309 | <EnableCOMDATFolding>true</EnableCOMDATFolding> |
| 307 | <OptimizeReferences>true</OptimizeReferences> | 310 | <OptimizeReferences>true</OptimizeReferences> |
| 308 | <GenerateDebugInformation>true</GenerateDebugInformation> | 311 | <GenerateDebugInformation>true</GenerateDebugInformation> |
| 312 | <AdditionalOptions>/STACK:2097152 %(AdditionalOptions)</AdditionalOptions> | ||
| 309 | </Link> | 313 | </Link> |
| 310 | </ItemDefinitionGroup> | 314 | </ItemDefinitionGroup> |
| 311 | <ItemGroup> | 315 | <ItemGroup> |
| 316 | <ClCompile Include="..\..\src\3rdParty\colib\ljson.c" /> | ||
| 312 | <ClCompile Include="..\..\src\3rdParty\lua\lapi.c" /> | 317 | <ClCompile Include="..\..\src\3rdParty\lua\lapi.c" /> |
| 313 | <ClCompile Include="..\..\src\3rdParty\lua\lauxlib.c" /> | 318 | <ClCompile Include="..\..\src\3rdParty\lua\lauxlib.c" /> |
| 314 | <ClCompile Include="..\..\src\3rdParty\lua\lbaselib.c" /> | 319 | <ClCompile Include="..\..\src\3rdParty\lua\lbaselib.c" /> |
diff --git a/win-build/Yuescript/Yuescript.vcxproj.filters b/win-build/Yuescript/Yuescript.vcxproj.filters index 122f0b6..73efba3 100644 --- a/win-build/Yuescript/Yuescript.vcxproj.filters +++ b/win-build/Yuescript/Yuescript.vcxproj.filters | |||
| @@ -17,6 +17,9 @@ | |||
| 17 | <Filter Include="src\efsw\win"> | 17 | <Filter Include="src\efsw\win"> |
| 18 | <UniqueIdentifier>{4b765224-203c-4df9-ba95-c975f75c4cf1}</UniqueIdentifier> | 18 | <UniqueIdentifier>{4b765224-203c-4df9-ba95-c975f75c4cf1}</UniqueIdentifier> |
| 19 | </Filter> | 19 | </Filter> |
| 20 | <Filter Include="src\colib"> | ||
| 21 | <UniqueIdentifier>{0f5875b7-722d-4903-8299-eeb462a34086}</UniqueIdentifier> | ||
| 22 | </Filter> | ||
| 20 | </ItemGroup> | 23 | </ItemGroup> |
| 21 | <ItemGroup> | 24 | <ItemGroup> |
| 22 | <ClCompile Include="..\..\src\3rdParty\lua\lapi.c"> | 25 | <ClCompile Include="..\..\src\3rdParty\lua\lapi.c"> |
| @@ -205,6 +208,9 @@ | |||
| 205 | <ClCompile Include="..\..\src\yuescript\yue_ast.cpp"> | 208 | <ClCompile Include="..\..\src\yuescript\yue_ast.cpp"> |
| 206 | <Filter>src\yuescript</Filter> | 209 | <Filter>src\yuescript</Filter> |
| 207 | </ClCompile> | 210 | </ClCompile> |
| 211 | <ClCompile Include="..\..\src\3rdParty\colib\ljson.c"> | ||
| 212 | <Filter>src\colib</Filter> | ||
| 213 | </ClCompile> | ||
| 208 | </ItemGroup> | 214 | </ItemGroup> |
| 209 | <ItemGroup> | 215 | <ItemGroup> |
| 210 | <ClInclude Include="..\..\src\3rdParty\lua\lapi.h"> | 216 | <ClInclude Include="..\..\src\3rdParty\lua\lapi.h"> |
diff --git a/win-build/YuescriptDLL/YuescriptDLL.vcxproj b/win-build/YuescriptDLL/YuescriptDLL.vcxproj index b418163..1544c3c 100644 --- a/win-build/YuescriptDLL/YuescriptDLL.vcxproj +++ b/win-build/YuescriptDLL/YuescriptDLL.vcxproj | |||
| @@ -176,9 +176,9 @@ | |||
| 176 | <ClCompile> | 176 | <ClCompile> |
| 177 | <WarningLevel>Level3</WarningLevel> | 177 | <WarningLevel>Level3</WarningLevel> |
| 178 | <SDLCheck>true</SDLCheck> | 178 | <SDLCheck>true</SDLCheck> |
| 179 | <PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 179 | <PreprocessorDefinitions>_DEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 180 | <ConformanceMode>true</ConformanceMode> | 180 | <ConformanceMode>true</ConformanceMode> |
| 181 | <LanguageStandard>stdcpp17</LanguageStandard> | 181 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 182 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 182 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 183 | </ClCompile> | 183 | </ClCompile> |
| 184 | <Link> | 184 | <Link> |
| @@ -194,9 +194,9 @@ | |||
| 194 | <ClCompile> | 194 | <ClCompile> |
| 195 | <WarningLevel>Level3</WarningLevel> | 195 | <WarningLevel>Level3</WarningLevel> |
| 196 | <SDLCheck>true</SDLCheck> | 196 | <SDLCheck>true</SDLCheck> |
| 197 | <PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 197 | <PreprocessorDefinitions>_DEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 198 | <ConformanceMode>true</ConformanceMode> | 198 | <ConformanceMode>true</ConformanceMode> |
| 199 | <LanguageStandard>stdcpp17</LanguageStandard> | 199 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 200 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 200 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 201 | </ClCompile> | 201 | </ClCompile> |
| 202 | <Link> | 202 | <Link> |
| @@ -214,9 +214,9 @@ | |||
| 214 | <FunctionLevelLinking>true</FunctionLevelLinking> | 214 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 215 | <IntrinsicFunctions>true</IntrinsicFunctions> | 215 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 216 | <SDLCheck>true</SDLCheck> | 216 | <SDLCheck>true</SDLCheck> |
| 217 | <PreprocessorDefinitions>NDEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 217 | <PreprocessorDefinitions>NDEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 218 | <ConformanceMode>true</ConformanceMode> | 218 | <ConformanceMode>true</ConformanceMode> |
| 219 | <LanguageStandard>stdcpp17</LanguageStandard> | 219 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 220 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 220 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 221 | </ClCompile> | 221 | </ClCompile> |
| 222 | <Link> | 222 | <Link> |
| @@ -236,9 +236,9 @@ | |||
| 236 | <FunctionLevelLinking>true</FunctionLevelLinking> | 236 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 237 | <IntrinsicFunctions>true</IntrinsicFunctions> | 237 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 238 | <SDLCheck>true</SDLCheck> | 238 | <SDLCheck>true</SDLCheck> |
| 239 | <PreprocessorDefinitions>NDEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 239 | <PreprocessorDefinitions>NDEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 240 | <ConformanceMode>true</ConformanceMode> | 240 | <ConformanceMode>true</ConformanceMode> |
| 241 | <LanguageStandard>stdcpp17</LanguageStandard> | 241 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 242 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 242 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 243 | </ClCompile> | 243 | </ClCompile> |
| 244 | <Link> | 244 | <Link> |
| @@ -256,9 +256,9 @@ | |||
| 256 | <ClCompile> | 256 | <ClCompile> |
| 257 | <WarningLevel>Level3</WarningLevel> | 257 | <WarningLevel>Level3</WarningLevel> |
| 258 | <SDLCheck>true</SDLCheck> | 258 | <SDLCheck>true</SDLCheck> |
| 259 | <PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 259 | <PreprocessorDefinitions>_DEBUG;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 260 | <ConformanceMode>true</ConformanceMode> | 260 | <ConformanceMode>true</ConformanceMode> |
| 261 | <LanguageStandard>stdcpp17</LanguageStandard> | 261 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 262 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 262 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 263 | </ClCompile> | 263 | </ClCompile> |
| 264 | <Link> | 264 | <Link> |
| @@ -274,9 +274,9 @@ | |||
| 274 | <ClCompile> | 274 | <ClCompile> |
| 275 | <WarningLevel>Level3</WarningLevel> | 275 | <WarningLevel>Level3</WarningLevel> |
| 276 | <SDLCheck>true</SDLCheck> | 276 | <SDLCheck>true</SDLCheck> |
| 277 | <PreprocessorDefinitions>_DEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 277 | <PreprocessorDefinitions>_DEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 278 | <ConformanceMode>true</ConformanceMode> | 278 | <ConformanceMode>true</ConformanceMode> |
| 279 | <LanguageStandard>stdcpp17</LanguageStandard> | 279 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 280 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 280 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 281 | </ClCompile> | 281 | </ClCompile> |
| 282 | <Link> | 282 | <Link> |
| @@ -294,9 +294,9 @@ | |||
| 294 | <FunctionLevelLinking>true</FunctionLevelLinking> | 294 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 295 | <IntrinsicFunctions>true</IntrinsicFunctions> | 295 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 296 | <SDLCheck>true</SDLCheck> | 296 | <SDLCheck>true</SDLCheck> |
| 297 | <PreprocessorDefinitions>NDEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 297 | <PreprocessorDefinitions>NDEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 298 | <ConformanceMode>true</ConformanceMode> | 298 | <ConformanceMode>true</ConformanceMode> |
| 299 | <LanguageStandard>stdcpp17</LanguageStandard> | 299 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 300 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 300 | <AdditionalIncludeDirectories>..\lua51;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 301 | </ClCompile> | 301 | </ClCompile> |
| 302 | <Link> | 302 | <Link> |
| @@ -316,9 +316,9 @@ | |||
| 316 | <FunctionLevelLinking>true</FunctionLevelLinking> | 316 | <FunctionLevelLinking>true</FunctionLevelLinking> |
| 317 | <IntrinsicFunctions>true</IntrinsicFunctions> | 317 | <IntrinsicFunctions>true</IntrinsicFunctions> |
| 318 | <SDLCheck>true</SDLCheck> | 318 | <SDLCheck>true</SDLCheck> |
| 319 | <PreprocessorDefinitions>NDEBUG;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;YUE_BUILD_AS_DLL;%(PreprocessorDefinitions)</PreprocessorDefinitions> | 319 | <PreprocessorDefinitions>NDEBUG;UTF_CPP_CPLUSPLUS=202002L;YUE_BUILD_AS_DLL;YUE_UTF8_IMPL;%(PreprocessorDefinitions)</PreprocessorDefinitions> |
| 320 | <ConformanceMode>true</ConformanceMode> | 320 | <ConformanceMode>true</ConformanceMode> |
| 321 | <LanguageStandard>stdcpp17</LanguageStandard> | 321 | <LanguageStandard>stdcpp20</LanguageStandard> |
| 322 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> | 322 | <AdditionalIncludeDirectories>..\lua53;..\..\src;..\..\src\3rdParty;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories> |
| 323 | </ClCompile> | 323 | </ClCompile> |
| 324 | <Link> | 324 | <Link> |
| @@ -352,4 +352,4 @@ | |||
| 352 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> | 352 | <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
| 353 | <ImportGroup Label="ExtensionTargets"> | 353 | <ImportGroup Label="ExtensionTargets"> |
| 354 | </ImportGroup> | 354 | </ImportGroup> |
| 355 | </Project> \ No newline at end of file | 355 | </Project> |
