diff options
98 files changed, 13505 insertions, 2172 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/.github/workflows/windows.yml b/.github/workflows/windows.yml index 2327710..04d08b0 100644 --- a/.github/workflows/windows.yml +++ b/.github/workflows/windows.yml | |||
| @@ -24,6 +24,7 @@ jobs: | |||
| 24 | bin\windows\Win32\Debug\yue.exe spec\inputs\loops.yue -o spec\generated\5.1\loops.lua --target=5.1 | 24 | bin\windows\Win32\Debug\yue.exe spec\inputs\loops.yue -o spec\generated\5.1\loops.lua --target=5.1 |
| 25 | bin\windows\Win32\Debug\yue.exe spec\inputs\try_catch.yue -o spec\generated\5.1\try_catch.lua --target=5.1 | 25 | bin\windows\Win32\Debug\yue.exe spec\inputs\try_catch.yue -o spec\generated\5.1\try_catch.lua --target=5.1 |
| 26 | bin\windows\Win32\Debug\yue.exe spec\inputs\attrib.yue -o spec\generated\5.1\attrib.lua --target=5.1 | 26 | bin\windows\Win32\Debug\yue.exe spec\inputs\attrib.yue -o spec\generated\5.1\attrib.lua --target=5.1 |
| 27 | bin\windows\Win32\Debug\yue.exe spec\inputs\import_global.yue -o spec\generated\5.1\import_global.lua --target=5.1 | ||
| 27 | bin\windows\Win32\Debug\yue.exe spec\inputs\test\loops_spec.yue -o spec\generated\5.1\test\loops_spec.lua --target=5.1 | 28 | bin\windows\Win32\Debug\yue.exe spec\inputs\test\loops_spec.yue -o spec\generated\5.1\test\loops_spec.lua --target=5.1 |
| 28 | bin\windows\Win32\Debug\yue.exe -e spec/inputs/compile_doc.yue spec/generated | 29 | bin\windows\Win32\Debug\yue.exe -e spec/inputs/compile_doc.yue spec/generated |
| 29 | bin\windows\Win32\Debug\yue.exe -e "io.popen('git diff --no-index spec\\outputs spec\\generated')\read('*a') |> ((r)-> r ~= '' and (print(r) or os.exit 1))" | 30 | bin\windows\Win32\Debug\yue.exe -e "io.popen('git diff --no-index spec\\outputs spec\\generated')\read('*a') |> ((r)-> r ~= '' and (print(r) or os.exit 1))" |
| @@ -33,6 +34,7 @@ jobs: | |||
| 33 | bin\windows\x64\Debug\yue.exe spec\inputs\loops.yue -o spec\generated\5.1\loops.lua --target=5.1 | 34 | bin\windows\x64\Debug\yue.exe spec\inputs\loops.yue -o spec\generated\5.1\loops.lua --target=5.1 |
| 34 | bin\windows\x64\Debug\yue.exe spec\inputs\try_catch.yue -o spec\generated\5.1\try_catch.lua --target=5.1 | 35 | bin\windows\x64\Debug\yue.exe spec\inputs\try_catch.yue -o spec\generated\5.1\try_catch.lua --target=5.1 |
| 35 | bin\windows\x64\Debug\yue.exe spec\inputs\attrib.yue -o spec\generated\5.1\attrib.lua --target=5.1 | 36 | bin\windows\x64\Debug\yue.exe spec\inputs\attrib.yue -o spec\generated\5.1\attrib.lua --target=5.1 |
| 37 | bin\windows\x64\Debug\yue.exe spec\inputs\import_global.yue -o spec\generated\5.1\import_global.lua --target=5.1 | ||
| 36 | bin\windows\x64\Debug\yue.exe spec\inputs\test\loops_spec.yue -o spec\generated\5.1\test\loops_spec.lua --target=5.1 | 38 | bin\windows\x64\Debug\yue.exe spec\inputs\test\loops_spec.yue -o spec\generated\5.1\test\loops_spec.lua --target=5.1 |
| 37 | bin\windows\x64\Debug\yue.exe -e spec/inputs/compile_doc.yue spec/generated | 39 | bin\windows\x64\Debug\yue.exe -e spec/inputs/compile_doc.yue spec/generated |
| 38 | bin\windows\x64\Debug\yue.exe -e "io.popen('git diff --no-index spec\\outputs spec\\generated')\read('*a') |> ((r)-> r ~= '' and (print(r) or os.exit 1))" | 40 | bin\windows\x64\Debug\yue.exe -e "io.popen('git diff --no-index spec\\outputs spec\\generated')\read('*a') |> ((r)-> r ~= '' and (print(r) or os.exit 1))" |
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 c4518bf..b5051d4 100755 --- a/doc/docs/doc/README.md +++ b/doc/docs/doc/README.md | |||
| @@ -16,19 +16,29 @@ 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 | ||
| 33 | map = (arr, action) -> | ||
| 34 | [action item for item in *arr] | ||
| 35 | |||
| 36 | filter = (arr, cond) -> | ||
| 37 | [item for item in *arr when cond item] | ||
| 38 | |||
| 39 | reduce = (arr, init, action): init -> | ||
| 40 | init = action init, item for item in *arr | ||
| 41 | |||
| 32 | -- pipe operator | 42 | -- pipe operator |
| 33 | [1, 2, 3] | 43 | [1, 2, 3] |
| 34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
| @@ -51,19 +61,29 @@ export 🌛 = "月之脚本" | |||
| 51 | <YueDisplay> | 61 | <YueDisplay> |
| 52 | <pre> | 62 | <pre> |
| 53 | -- import syntax | 63 | -- import syntax |
| 54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
| 55 | 65 | ||
| 56 | -- object literals | 66 | -- object literals |
| 57 | inventory = | 67 | inventory = |
| 58 | equipment: | 68 | equipment: |
| 59 | * "sword" | 69 | - "sword" |
| 60 | * "shield" | 70 | - "shield" |
| 61 | items: | 71 | items: |
| 62 | * name: "potion" | 72 | - name: "potion" |
| 63 | count: 10 | 73 | count: 10 |
| 64 | * name: "bread" | 74 | - name: "bread" |
| 65 | count: 3 | 75 | count: 3 |
| 66 | 76 | ||
| 77 | -- list comprehension | ||
| 78 | map = (arr, action) -> | ||
| 79 | [action item for item in *arr] | ||
| 80 | |||
| 81 | filter = (arr, cond) -> | ||
| 82 | [item for item in *arr when cond item] | ||
| 83 | |||
| 84 | reduce = (arr, init, action): init -> | ||
| 85 | init = action init, item for item in *arr | ||
| 86 | |||
| 67 | -- pipe operator | 87 | -- pipe operator |
| 68 | [1, 2, 3] | 88 | [1, 2, 3] |
| 69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
| @@ -132,14 +152,14 @@ export 🌛 = "月之脚本" | |||
| 132 | 152 | ||
| 133 |  Use YueScript module in Lua: | 153 |  Use YueScript module in Lua: |
| 134 | 154 | ||
| 135 | * **Case 1** | 155 | * **Case 1** |
| 136 | Require "your_yuescript_entry.yue" in Lua. | 156 | Require "your_yuescript_entry.yue" in Lua. |
| 137 | ```Lua | 157 | ```Lua |
| 138 | require("yue")("your_yuescript_entry") | 158 | require("yue")("your_yuescript_entry") |
| 139 | ``` | 159 | ``` |
| 140 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. | 160 |  And this code still works when you compile "your_yuescript_entry.yue" to "your_yuescript_entry.lua" in the same path. In the rest YueScript files just use the normal **require** or **import**. The code line numbers in error messages will also be handled correctly. |
| 141 | 161 | ||
| 142 | * **Case 2** | 162 | * **Case 2** |
| 143 | Require YueScript module and rewite message by hand. | 163 | Require YueScript module and rewite message by hand. |
| 144 | ```lua | 164 | ```lua |
| 145 | local yue = require("yue") | 165 | local yue = require("yue") |
| @@ -151,7 +171,7 @@ end, function(err) | |||
| 151 | end) | 171 | end) |
| 152 | ``` | 172 | ``` |
| 153 | 173 | ||
| 154 | * **Case 3** | 174 | * **Case 3** |
| 155 | Use the YueScript compiler function in Lua. | 175 | Use the YueScript compiler function in Lua. |
| 156 | ```lua | 176 | ```lua |
| 157 | local yue = require("yue") | 177 | local yue = require("yue") |
| @@ -203,12 +223,12 @@ Usage: yue [options|files|directories] ... | |||
| 203 | Execute without options to enter REPL, type symbol '$' | 223 | Execute without options to enter REPL, type symbol '$' |
| 204 | in a single line to start/stop multi-line mode | 224 | in a single line to start/stop multi-line mode |
| 205 | ``` | 225 | ``` |
| 206 |   Use cases: | 226 |   Use cases: |
| 207 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** | 227 |   Recursively compile every YueScript file with extension **.yue** under current path: **yue .** |
| 208 |   Compile and save results to a target path: **yue -t /target/path/ .** | 228 |   Compile and save results to a target path: **yue -t /target/path/ .** |
| 209 |   Compile and reserve debug info: **yue -l .** | 229 |   Compile and reserve debug info: **yue -l .** |
| 210 |   Compile and generate minified codes: **yue -m .** | 230 |   Compile and generate minified codes: **yue -m .** |
| 211 |   Execute raw codes: **yue -e 'print 123'** | 231 |   Execute raw codes: **yue -e 'print 123'** |
| 212 |   Execute a YueScript file: **yue -e main.yue** | 232 |   Execute a YueScript file: **yue -e main.yue** |
| 213 | 233 | ||
| 214 | ## Macro | 234 | ## Macro |
| @@ -388,16 +408,16 @@ In YueScript, macro functions allow you to generate code at compile time. By nes | |||
| 388 | 408 | ||
| 389 | ```moonscript | 409 | ```moonscript |
| 390 | macro Enum = (...) -> | 410 | macro Enum = (...) -> |
| 391 | items = {...} | 411 | items = {...} |
| 392 | itemSet = {item, true for item in *items} | 412 | itemSet = {item, true for item in *items} |
| 393 | (item) -> | 413 | (item) -> |
| 394 | 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] |
| 395 | "\"#{item}\"" | 415 | "\"#{item}\"" |
| 396 | 416 | ||
| 397 | macro BodyType = $Enum( | 417 | macro BodyType = $Enum( |
| 398 | Static | 418 | Static |
| 399 | Dynamic | 419 | Dynamic |
| 400 | Kinematic | 420 | Kinematic |
| 401 | ) | 421 | ) |
| 402 | 422 | ||
| 403 | print "Valid enum type:", $BodyType Static | 423 | print "Valid enum type:", $BodyType Static |
| @@ -407,16 +427,16 @@ print "Valid enum type:", $BodyType Static | |||
| 407 | <YueDisplay> | 427 | <YueDisplay> |
| 408 | <pre> | 428 | <pre> |
| 409 | macro Enum = (...) -> | 429 | macro Enum = (...) -> |
| 410 | items = {...} | 430 | items = {...} |
| 411 | itemSet = {item, true for item in *items} | 431 | itemSet = {item, true for item in *items} |
| 412 | (item) -> | 432 | (item) -> |
| 413 | 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] |
| 414 | "\"#{item}\"" | 434 | "\"#{item}\"" |
| 415 | 435 | ||
| 416 | macro BodyType = $Enum( | 436 | macro BodyType = $Enum( |
| 417 | Static | 437 | Static |
| 418 | Dynamic | 438 | Dynamic |
| 419 | Kinematic | 439 | Kinematic |
| 420 | ) | 440 | ) |
| 421 | 441 | ||
| 422 | print "Valid enum type:", $BodyType Static | 442 | print "Valid enum type:", $BodyType Static |
| @@ -424,6 +444,54 @@ print "Valid enum type:", $BodyType Static | |||
| 424 | </pre> | 444 | </pre> |
| 425 | </YueDisplay> | 445 | </YueDisplay> |
| 426 | 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 | |||
| 427 | ## Operator | 495 | ## Operator |
| 428 | 496 | ||
| 429 | 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. |
| @@ -466,47 +534,47 @@ Note the evaluation behavior of chained comparisons: | |||
| 466 | 534 | ||
| 467 | ```moonscript | 535 | ```moonscript |
| 468 | v = (x) -> | 536 | v = (x) -> |
| 469 | print x | 537 | print x |
| 470 | x | 538 | x |
| 471 | 539 | ||
| 472 | print v(1) < v(2) <= v(3) | 540 | print v(1) < v(2) <= v(3) |
| 473 | --[[ | 541 | --[[ |
| 474 | output: | 542 | output: |
| 475 | 2 | 543 | 2 |
| 476 | 1 | 544 | 1 |
| 477 | 3 | 545 | 3 |
| 478 | true | 546 | true |
| 479 | ]] | 547 | ]] |
| 480 | 548 | ||
| 481 | print v(1) > v(2) <= v(3) | 549 | print v(1) > v(2) <= v(3) |
| 482 | --[[ | 550 | --[[ |
| 483 | output: | 551 | output: |
| 484 | 2 | 552 | 2 |
| 485 | 1 | 553 | 1 |
| 486 | false | 554 | false |
| 487 | ]] | 555 | ]] |
| 488 | ``` | 556 | ``` |
| 489 | <YueDisplay> | 557 | <YueDisplay> |
| 490 | <pre> | 558 | <pre> |
| 491 | v = (x) -> | 559 | v = (x) -> |
| 492 | print x | 560 | print x |
| 493 | x | 561 | x |
| 494 | 562 | ||
| 495 | print v(1) < v(2) <= v(3) | 563 | print v(1) < v(2) <= v(3) |
| 496 | --[[ | 564 | --[[ |
| 497 | output: | 565 | output: |
| 498 | 2 | 566 | 2 |
| 499 | 1 | 567 | 1 |
| 500 | 3 | 568 | 3 |
| 501 | true | 569 | true |
| 502 | ]] | 570 | ]] |
| 503 | 571 | ||
| 504 | print v(1) > v(2) <= v(3) | 572 | print v(1) > v(2) <= v(3) |
| 505 | --[[ | 573 | --[[ |
| 506 | output: | 574 | output: |
| 507 | 2 | 575 | 2 |
| 508 | 1 | 576 | 1 |
| 509 | false | 577 | false |
| 510 | ]] | 578 | ]] |
| 511 | </pre> | 579 | </pre> |
| 512 | </YueDisplay> | 580 | </YueDisplay> |
| @@ -527,19 +595,36 @@ tab[] = "Value" | |||
| 527 | </pre> | 595 | </pre> |
| 528 | </YueDisplay> | 596 | </YueDisplay> |
| 529 | 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 | |||
| 530 | ### Table Spreading | 615 | ### Table Spreading |
| 531 | 616 | ||
| 532 | 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. |
| 533 | 618 | ||
| 534 | ```moonscript | 619 | ```moonscript |
| 535 | parts = | 620 | parts = |
| 536 | * "shoulders" | 621 | * "shoulders" |
| 537 | * "knees" | 622 | * "knees" |
| 538 | lyrics = | 623 | lyrics = |
| 539 | * "head" | 624 | * "head" |
| 540 | * ...parts | 625 | * ...parts |
| 541 | * "and" | 626 | * "and" |
| 542 | * "toes" | 627 | * "toes" |
| 543 | 628 | ||
| 544 | copy = {...other} | 629 | copy = {...other} |
| 545 | 630 | ||
| @@ -550,13 +635,13 @@ merge = {...a, ...b} | |||
| 550 | <YueDisplay> | 635 | <YueDisplay> |
| 551 | <pre> | 636 | <pre> |
| 552 | parts = | 637 | parts = |
| 553 | * "shoulders" | 638 | * "shoulders" |
| 554 | * "knees" | 639 | * "knees" |
| 555 | lyrics = | 640 | lyrics = |
| 556 | * "head" | 641 | * "head" |
| 557 | * ...parts | 642 | * ...parts |
| 558 | * "and" | 643 | * "and" |
| 559 | * "toes" | 644 | * "toes" |
| 560 | 645 | ||
| 561 | copy = {...other} | 646 | copy = {...other} |
| 562 | 647 | ||
| @@ -566,11 +651,28 @@ merge = {...a, ...b} | |||
| 566 | </pre> | 651 | </pre> |
| 567 | </YueDisplay> | 652 | </YueDisplay> |
| 568 | 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 | |||
| 569 | ### Metatable | 671 | ### Metatable |
| 570 | 672 | ||
| 571 | The **<>** operator can be used as a shortcut for metatable manipulation. | 673 | The **<>** operator can be used as a shortcut for metatable manipulation. |
| 572 | 674 | ||
| 573 | * **Metatable Creation** | 675 | * **Metatable Creation** |
| 574 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. | 676 | Create normal table with empty bracekets **<>** or metamethod key which is surrounded by **<>**. |
| 575 | 677 | ||
| 576 | ```moonscript | 678 | ```moonscript |
| @@ -606,7 +708,7 @@ close _ = <close>: -> print "out of scope" | |||
| 606 | </pre> | 708 | </pre> |
| 607 | </YueDisplay> | 709 | </YueDisplay> |
| 608 | 710 | ||
| 609 | * **Metatable Accessing** | 711 | * **Metatable Accessing** |
| 610 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. | 712 | Accessing metatable with **<>** or metamethod name surrounded by **<>** or writing some expression in **<>**. |
| 611 | 713 | ||
| 612 | ```moonscript | 714 | ```moonscript |
| @@ -630,7 +732,7 @@ print tb.item | |||
| 630 | </pre> | 732 | </pre> |
| 631 | </YueDisplay> | 733 | </YueDisplay> |
| 632 | 734 | ||
| 633 | * **Metatable Destructure** | 735 | * **Metatable Destructure** |
| 634 | Destruct metatable with metamethod key surrounded by **<>**. | 736 | Destruct metatable with metamethod key surrounded by **<>**. |
| 635 | 737 | ||
| 636 | ```moonscript | 738 | ```moonscript |
| @@ -732,34 +834,45 @@ a ??= false | |||
| 732 | 834 | ||
| 733 | ### Implicit Object | 835 | ### Implicit Object |
| 734 | 836 | ||
| 735 | 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 | |||
| 736 | ```moonscript | 839 | ```moonscript |
| 840 | -- assignment with implicit object | ||
| 737 | list = | 841 | list = |
| 738 | * 1 | 842 | * 1 |
| 739 | * 2 | 843 | * 2 |
| 740 | * 3 | 844 | * 3 |
| 741 | 845 | ||
| 846 | -- function call with implicit object | ||
| 742 | func | 847 | func |
| 743 | * 1 | 848 | * 1 |
| 744 | * 2 | 849 | * 2 |
| 745 | * 3 | 850 | * 3 |
| 746 | 851 | ||
| 852 | -- return with implicit object | ||
| 853 | f = -> | ||
| 854 | return | ||
| 855 | * 1 | ||
| 856 | * 2 | ||
| 857 | * 3 | ||
| 858 | |||
| 859 | -- table with implicit object | ||
| 747 | tb = | 860 | tb = |
| 748 | name: "abc" | 861 | name: "abc" |
| 749 | 862 | ||
| 750 | values: | 863 | values: |
| 751 | * "a" | 864 | - "a" |
| 752 | * "b" | 865 | - "b" |
| 753 | * "c" | 866 | - "c" |
| 754 | 867 | ||
| 755 | objects: | 868 | objects: |
| 756 | * name: "a" | 869 | - name: "a" |
| 757 | value: 1 | 870 | value: 1 |
| 758 | func: => @value + 1 | 871 | func: => @value + 1 |
| 759 | tb: | 872 | tb: |
| 760 | fieldA: 1 | 873 | fieldA: 1 |
| 761 | 874 | ||
| 762 | * name: "b" | 875 | - name: "b" |
| 763 | value: 2 | 876 | value: 2 |
| 764 | func: => @value + 2 | 877 | func: => @value + 2 |
| 765 | tb: { } | 878 | tb: { } |
| @@ -767,32 +880,42 @@ tb = | |||
| 767 | ``` | 880 | ``` |
| 768 | <YueDisplay> | 881 | <YueDisplay> |
| 769 | <pre> | 882 | <pre> |
| 883 | -- assignment with implicit object | ||
| 770 | list = | 884 | list = |
| 771 | * 1 | 885 | * 1 |
| 772 | * 2 | 886 | * 2 |
| 773 | * 3 | 887 | * 3 |
| 774 | 888 | ||
| 889 | -- function call with implicit object | ||
| 775 | func | 890 | func |
| 776 | * 1 | 891 | * 1 |
| 777 | * 2 | 892 | * 2 |
| 778 | * 3 | 893 | * 3 |
| 779 | 894 | ||
| 895 | -- return with implicit object | ||
| 896 | f = -> | ||
| 897 | return | ||
| 898 | * 1 | ||
| 899 | * 2 | ||
| 900 | * 3 | ||
| 901 | |||
| 902 | -- table with implicit object | ||
| 780 | tb = | 903 | tb = |
| 781 | name: "abc" | 904 | name: "abc" |
| 782 | 905 | ||
| 783 | values: | 906 | values: |
| 784 | * "a" | 907 | - "a" |
| 785 | * "b" | 908 | - "b" |
| 786 | * "c" | 909 | - "c" |
| 787 | 910 | ||
| 788 | objects: | 911 | objects: |
| 789 | * name: "a" | 912 | - name: "a" |
| 790 | value: 1 | 913 | value: 1 |
| 791 | func: => @value + 1 | 914 | func: => @value + 1 |
| 792 | tb: | 915 | tb: |
| 793 | fieldA: 1 | 916 | fieldA: 1 |
| 794 | 917 | ||
| 795 | * name: "b" | 918 | - name: "b" |
| 796 | value: 2 | 919 | value: 2 |
| 797 | func: => @value + 2 | 920 | func: => @value + 2 |
| 798 | tb: { } | 921 | tb: { } |
| @@ -856,11 +979,67 @@ do | |||
| 856 | </pre> | 979 | </pre> |
| 857 | </YueDisplay> | 980 | </YueDisplay> |
| 858 | 981 | ||
| 982 | ### Import Global | ||
| 983 | |||
| 984 | You can import specific globals into local variables with `import`. When importing a chain of global variable accessings, the last field will be assigned to the local variable. | ||
| 985 | |||
| 986 | ```moonscript | ||
| 987 | do | ||
| 988 | import tostring | ||
| 989 | import table.concat | ||
| 990 | print concat ["a", tostring 1] | ||
| 991 | ``` | ||
| 992 | <YueDisplay> | ||
| 993 | <pre> | ||
| 994 | do | ||
| 995 | import tostring | ||
| 996 | import table.concat | ||
| 997 | print concat ["a", tostring 1] | ||
| 998 | </pre> | ||
| 999 | </YueDisplay> | ||
| 1000 | |||
| 1001 | #### Automatic Import | ||
| 1002 | |||
| 1003 | You can place `import global` at the top of a block to automatically import all names that have not been explicitly declared or assigned in the current scope as globals. These implicit imports are treated as local consts that reference the corresponding globals at the position of the statement. | ||
| 1004 | |||
| 1005 | Names that are explicitly declared as globals in the same scope will not be imported, so you can still assign to them. | ||
| 1006 | |||
| 1007 | ```moonscript | ||
| 1008 | do | ||
| 1009 | import global | ||
| 1010 | print "hello" | ||
| 1011 | math.random 3 | ||
| 1012 | -- print = nil -- error: imported globals are const | ||
| 1013 | |||
| 1014 | do | ||
| 1015 | -- explicit global variable will not be imported | ||
| 1016 | import global | ||
| 1017 | global FLAG | ||
| 1018 | print FLAG | ||
| 1019 | FLAG = 123 | ||
| 1020 | ``` | ||
| 1021 | <YueDisplay> | ||
| 1022 | <pre> | ||
| 1023 | do | ||
| 1024 | import global | ||
| 1025 | print "hello" | ||
| 1026 | math.random 3 | ||
| 1027 | -- print = nil -- error: imported globals are const | ||
| 1028 | |||
| 1029 | do | ||
| 1030 | -- explicit global variable will not be imported | ||
| 1031 | import global | ||
| 1032 | global FLAG | ||
| 1033 | print FLAG | ||
| 1034 | FLAG = 123 | ||
| 1035 | </pre> | ||
| 1036 | </YueDisplay> | ||
| 1037 | |||
| 859 | ### Export | 1038 | ### Export |
| 860 | 1039 | ||
| 861 | The export statement offers a concise way to define modules. | 1040 | The export statement offers a concise way to define modules. |
| 862 | 1041 | ||
| 863 | * **Named Export** | 1042 | * **Named Export** |
| 864 | Named export will define a local variable as well as adding a field in the exported table. | 1043 | Named export will define a local variable as well as adding a field in the exported table. |
| 865 | 1044 | ||
| 866 | ```moonscript | 1045 | ```moonscript |
| @@ -924,7 +1103,7 @@ export["a-b-c"] = 123 | |||
| 924 | </pre> | 1103 | </pre> |
| 925 | </YueDisplay> | 1104 | </YueDisplay> |
| 926 | 1105 | ||
| 927 | * **Unnamed Export** | 1106 | * **Unnamed Export** |
| 928 | Unnamed export will add the target item into the array part of the exported table. | 1107 | Unnamed export will add the target item into the array part of the exported table. |
| 929 | 1108 | ||
| 930 | ```moonscript | 1109 | ```moonscript |
| @@ -954,7 +1133,7 @@ export with tmp | |||
| 954 | </pre> | 1133 | </pre> |
| 955 | </YueDisplay> | 1134 | </YueDisplay> |
| 956 | 1135 | ||
| 957 | * **Default Export** | 1136 | * **Default Export** |
| 958 | Using the **default** keyword in export statement to replace the exported table with any thing. | 1137 | Using the **default** keyword in export statement to replace the exported table with any thing. |
| 959 | 1138 | ||
| 960 | ```moonscript | 1139 | ```moonscript |
| @@ -1202,7 +1381,7 @@ If the destructuring statement is complicated, feel free to spread it out over a | |||
| 1202 | </pre> | 1381 | </pre> |
| 1203 | </YueDisplay> | 1382 | </YueDisplay> |
| 1204 | 1383 | ||
| 1205 | 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: | 1384 | 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: |
| 1206 | 1385 | ||
| 1207 | ```moonscript | 1386 | ```moonscript |
| 1208 | {:concat, :insert} = table | 1387 | {:concat, :insert} = table |
| @@ -1246,6 +1425,52 @@ You can use `_` as placeholder when doing a list destructuring: | |||
| 1246 | </pre> | 1425 | </pre> |
| 1247 | </YueDisplay> | 1426 | </YueDisplay> |
| 1248 | 1427 | ||
| 1428 | ### Range Destructuring | ||
| 1429 | |||
| 1430 | 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. | ||
| 1431 | |||
| 1432 | ```moonscript | ||
| 1433 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1434 | [first, ...bulk, last] = orders | ||
| 1435 | print first -- prints: first | ||
| 1436 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 1437 | print last -- prints: last | ||
| 1438 | ``` | ||
| 1439 | <YueDisplay> | ||
| 1440 | <pre> | ||
| 1441 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1442 | [first, ...bulk, last] = orders | ||
| 1443 | print first -- prints: first | ||
| 1444 | print bulk -- prints: {"second", "third", "fourth"} | ||
| 1445 | print last -- prints: last | ||
| 1446 | </pre> | ||
| 1447 | </YueDisplay> | ||
| 1448 | |||
| 1449 | 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: | ||
| 1450 | |||
| 1451 | ```moonscript | ||
| 1452 | -- Capture everything after first element | ||
| 1453 | [first, ...rest] = orders | ||
| 1454 | |||
| 1455 | -- Capture everything before last element | ||
| 1456 | [...start, last] = orders | ||
| 1457 | |||
| 1458 | -- Capture things except the middle elements | ||
| 1459 | [first, ..._, last] = orders | ||
| 1460 | ``` | ||
| 1461 | <YueDisplay> | ||
| 1462 | <pre> | ||
| 1463 | -- Capture everything after first element | ||
| 1464 | [first, ...rest] = orders | ||
| 1465 | |||
| 1466 | -- Capture everything before last element | ||
| 1467 | [...start, last] = orders | ||
| 1468 | |||
| 1469 | -- Capture things except the middle elements | ||
| 1470 | [first, ..._, last] = orders | ||
| 1471 | </pre> | ||
| 1472 | </YueDisplay> | ||
| 1473 | |||
| 1249 | ### Destructuring In Other Places | 1474 | ### Destructuring In Other Places |
| 1250 | 1475 | ||
| 1251 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: | 1476 | Destructuring can also show up in places where an assignment implicitly takes place. An example of this is a for loop: |
| @@ -1363,6 +1588,19 @@ print ok, count, first | |||
| 1363 | 1588 | ||
| 1364 | YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs. | 1589 | YueScript is a whitespace significant language. You have to write some code block in the same indent with space **' '** or tab **'\t'** like function body, value list and some control blocks. And expressions containing different whitespaces might mean different things. Tab is treated like 4 space, but it's better not mix the use of spaces and tabs. |
| 1365 | 1590 | ||
| 1591 | ### Statement Separator | ||
| 1592 | |||
| 1593 | A statement normally ends at a line break. You can also use a semicolon `;` to explicitly terminate a statement, which allows writing multiple statements on the same line: | ||
| 1594 | |||
| 1595 | ```moonscript | ||
| 1596 | a = 1; b = 2; print a + b | ||
| 1597 | ``` | ||
| 1598 | <YueDisplay> | ||
| 1599 | <pre> | ||
| 1600 | a = 1; b = 2; print a + b | ||
| 1601 | </pre> | ||
| 1602 | </YueDisplay> | ||
| 1603 | |||
| 1366 | ### Multiline Chaining | 1604 | ### Multiline Chaining |
| 1367 | 1605 | ||
| 1368 | You can write multi-line chaining function calls with a same indent. | 1606 | You can write multi-line chaining function calls with a same indent. |
| @@ -1475,6 +1713,47 @@ catch err | |||
| 1475 | </pre> | 1713 | </pre> |
| 1476 | </YueDisplay> | 1714 | </YueDisplay> |
| 1477 | 1715 | ||
| 1716 | ### Try? | ||
| 1717 | |||
| 1718 | `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. | ||
| 1719 | |||
| 1720 | ```moonscript | ||
| 1721 | a, b, c = try? func! | ||
| 1722 | |||
| 1723 | -- with nil coalescing operator | ||
| 1724 | a = (try? func!) ?? "default" | ||
| 1725 | |||
| 1726 | -- as function argument | ||
| 1727 | f try? func! | ||
| 1728 | |||
| 1729 | -- with catch block | ||
| 1730 | f try? | ||
| 1731 | print 123 | ||
| 1732 | func! | ||
| 1733 | catch e | ||
| 1734 | print e | ||
| 1735 | e | ||
| 1736 | ``` | ||
| 1737 | <YueDisplay> | ||
| 1738 | <pre> | ||
| 1739 | a, b, c = try? func! | ||
| 1740 | |||
| 1741 | -- with nil coalescing operator | ||
| 1742 | a = (try? func!) ?? "default" | ||
| 1743 | |||
| 1744 | -- as function argument | ||
| 1745 | f try? func! | ||
| 1746 | |||
| 1747 | -- with catch block | ||
| 1748 | f try? | ||
| 1749 | print 123 | ||
| 1750 | func! | ||
| 1751 | catch e | ||
| 1752 | print e | ||
| 1753 | e | ||
| 1754 | </pre> | ||
| 1755 | </YueDisplay> | ||
| 1756 | |||
| 1478 | ## Attributes | 1757 | ## Attributes |
| 1479 | 1758 | ||
| 1480 | 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. | 1759 | 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. |
| @@ -1503,6 +1782,19 @@ const {:a, :b, c, d} = tb | |||
| 1503 | </pre> | 1782 | </pre> |
| 1504 | </YueDisplay> | 1783 | </YueDisplay> |
| 1505 | 1784 | ||
| 1785 | You can also declare a global variable to be `const`. | ||
| 1786 | |||
| 1787 | ```moonscript | ||
| 1788 | global const Constant = 123 | ||
| 1789 | -- Constant = 1 | ||
| 1790 | ``` | ||
| 1791 | <YueDisplay> | ||
| 1792 | <pre> | ||
| 1793 | global const Constant = 123 | ||
| 1794 | -- Constant = 1 | ||
| 1795 | </pre> | ||
| 1796 | </YueDisplay> | ||
| 1797 | |||
| 1506 | ## Literals | 1798 | ## Literals |
| 1507 | 1799 | ||
| 1508 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. | 1800 | All of the primitive literals in Lua can be used. This applies to numbers, strings, booleans, and **nil**. |
| @@ -1535,12 +1827,73 @@ You can use underscores in a number literal to increase readability. | |||
| 1535 | ```moonscript | 1827 | ```moonscript |
| 1536 | integer = 1_000_000 | 1828 | integer = 1_000_000 |
| 1537 | hex = 0xEF_BB_BF | 1829 | hex = 0xEF_BB_BF |
| 1830 | binary = 0B10011 | ||
| 1538 | ``` | 1831 | ``` |
| 1539 | <YueDisplay> | 1832 | <YueDisplay> |
| 1540 | 1833 | ||
| 1541 | <pre> | 1834 | <pre> |
| 1542 | integer = 1_000_000 | 1835 | integer = 1_000_000 |
| 1543 | hex = 0xEF_BB_BF | 1836 | hex = 0xEF_BB_BF |
| 1837 | binary = 0B10011 | ||
| 1838 | </pre> | ||
| 1839 | </YueDisplay> | ||
| 1840 | |||
| 1841 | ### YAML Multiline String | ||
| 1842 | |||
| 1843 | The `|` prefix introduces a YAML-style multiline string literal: | ||
| 1844 | |||
| 1845 | ```moonscript | ||
| 1846 | str = | | ||
| 1847 | key: value | ||
| 1848 | list: | ||
| 1849 | - item1 | ||
| 1850 | - #{expr} | ||
| 1851 | ``` | ||
| 1852 | <YueDisplay> | ||
| 1853 | <pre> | ||
| 1854 | str = | | ||
| 1855 | key: value | ||
| 1856 | list: | ||
| 1857 | - item1 | ||
| 1858 | - #{expr} | ||
| 1859 | </pre> | ||
| 1860 | </YueDisplay> | ||
| 1861 | |||
| 1862 | 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)`. | ||
| 1863 | |||
| 1864 | 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. | ||
| 1865 | |||
| 1866 | ```moonscript | ||
| 1867 | fn = -> | ||
| 1868 | str = | | ||
| 1869 | foo: | ||
| 1870 | bar: baz | ||
| 1871 | return str | ||
| 1872 | ``` | ||
| 1873 | <YueDisplay> | ||
| 1874 | <pre> | ||
| 1875 | fn = -> | ||
| 1876 | str = | | ||
| 1877 | foo: | ||
| 1878 | bar: baz | ||
| 1879 | return str | ||
| 1880 | </pre> | ||
| 1881 | </YueDisplay> | ||
| 1882 | |||
| 1883 | Internal indentation is preserved relative to the removed common prefix, allowing clean nested structures. | ||
| 1884 | |||
| 1885 | 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. | ||
| 1886 | |||
| 1887 | ```moonscript | ||
| 1888 | str = | | ||
| 1889 | path: "C:\Program Files\App" | ||
| 1890 | note: 'He said: "#{Hello}!"' | ||
| 1891 | ``` | ||
| 1892 | <YueDisplay> | ||
| 1893 | <pre> | ||
| 1894 | str = | | ||
| 1895 | path: "C:\Program Files\App" | ||
| 1896 | note: 'He said: "#{Hello}!"' | ||
| 1544 | </pre> | 1897 | </pre> |
| 1545 | </YueDisplay> | 1898 | </YueDisplay> |
| 1546 | 1899 | ||
| @@ -1861,6 +2214,138 @@ if func 1, 2, 3, | |||
| 1861 | </pre> | 2214 | </pre> |
| 1862 | </YueDisplay> | 2215 | </YueDisplay> |
| 1863 | 2216 | ||
| 2217 | ### Parameter Destructuring | ||
| 2218 | |||
| 2219 | YueScript now supports destructuring function parameters when the argument is an object. Two forms of destructuring table literals are available: | ||
| 2220 | |||
| 2221 | * **Curly-brace wrapped literals/object parameters**, allowing optional default values when fields are missing (e.g., `{:a, :b}`, `{a: a1 = 123}`). | ||
| 2222 | |||
| 2223 | * **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. | ||
| 2224 | |||
| 2225 | ```moonscript | ||
| 2226 | f1 = (:a, :b, :c) -> | ||
| 2227 | print a, b, c | ||
| 2228 | |||
| 2229 | f1 a: 1, b: "2", c: {} | ||
| 2230 | |||
| 2231 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2232 | print a1, b, c | ||
| 2233 | |||
| 2234 | arg1 = {a: 0} | ||
| 2235 | f2 arg1, arg2 | ||
| 2236 | ``` | ||
| 2237 | <YueDisplay> | ||
| 2238 | <pre> | ||
| 2239 | f1 = (:a, :b, :c) -> | ||
| 2240 | print a, b, c | ||
| 2241 | |||
| 2242 | f1 a: 1, b: "2", c: {} | ||
| 2243 | |||
| 2244 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2245 | print a1, b, c | ||
| 2246 | |||
| 2247 | arg1 = {a: 0} | ||
| 2248 | f2 arg1, arg2 | ||
| 2249 | </pre> | ||
| 2250 | </YueDisplay> | ||
| 2251 | |||
| 2252 | ### Prefixed Return Expression | ||
| 2253 | |||
| 2254 | 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: | ||
| 2255 | |||
| 2256 | ```moon | ||
| 2257 | findFirstEven = (list): nil -> | ||
| 2258 | for item in *list | ||
| 2259 | if type(item) == "table" | ||
| 2260 | for sub in *item | ||
| 2261 | if sub % 2 == 0 | ||
| 2262 | return sub | ||
| 2263 | ``` | ||
| 2264 | <YueDisplay> | ||
| 2265 | <pre> | ||
| 2266 | findFirstEven = (list): nil -> | ||
| 2267 | for item in *list | ||
| 2268 | if type(item) == "table" | ||
| 2269 | for sub in *item | ||
| 2270 | if sub % 2 == 0 | ||
| 2271 | return sub | ||
| 2272 | </pre> | ||
| 2273 | </YueDisplay> | ||
| 2274 | |||
| 2275 | This is equivalent to: | ||
| 2276 | |||
| 2277 | ```moon | ||
| 2278 | findFirstEven = (list) -> | ||
| 2279 | for item in *list | ||
| 2280 | if type(item) == "table" | ||
| 2281 | for sub in *item | ||
| 2282 | if sub % 2 == 0 | ||
| 2283 | return sub | ||
| 2284 | nil | ||
| 2285 | ``` | ||
| 2286 | <YueDisplay> | ||
| 2287 | <pre> | ||
| 2288 | findFirstEven = (list) -> | ||
| 2289 | for item in *list | ||
| 2290 | if type(item) == "table" | ||
| 2291 | for sub in *item | ||
| 2292 | if sub % 2 == 0 | ||
| 2293 | return sub | ||
| 2294 | nil | ||
| 2295 | </pre> | ||
| 2296 | </YueDisplay> | ||
| 2297 | |||
| 2298 | 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. | ||
| 2299 | |||
| 2300 | ### Named Varargs | ||
| 2301 | |||
| 2302 | 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). | ||
| 2303 | |||
| 2304 | ```moonscript | ||
| 2305 | f = (...t) -> | ||
| 2306 | print "argument count:", t.n | ||
| 2307 | print "table length:", #t | ||
| 2308 | for i = 1, t.n | ||
| 2309 | print t[i] | ||
| 2310 | |||
| 2311 | f 1, 2, 3 | ||
| 2312 | f "a", "b", "c", "d" | ||
| 2313 | f! | ||
| 2314 | |||
| 2315 | -- Handling cases with nil values | ||
| 2316 | process = (...args) -> | ||
| 2317 | sum = 0 | ||
| 2318 | for i = 1, args.n | ||
| 2319 | if args[i] != nil and type(args[i]) == "number" | ||
| 2320 | sum += args[i] | ||
| 2321 | sum | ||
| 2322 | |||
| 2323 | process 1, nil, 3, nil, 5 | ||
| 2324 | ``` | ||
| 2325 | <YueDisplay> | ||
| 2326 | <pre> | ||
| 2327 | f = (...t) -> | ||
| 2328 | print "argument count:", t.n | ||
| 2329 | print "table length:", #t | ||
| 2330 | for i = 1, t.n | ||
| 2331 | print t[i] | ||
| 2332 | |||
| 2333 | f 1, 2, 3 | ||
| 2334 | f "a", "b", "c", "d" | ||
| 2335 | f! | ||
| 2336 | |||
| 2337 | -- Handling cases with nil values | ||
| 2338 | process = (...args) -> | ||
| 2339 | sum = 0 | ||
| 2340 | for i = 1, args.n | ||
| 2341 | if args[i] != nil and type(args[i]) == "number" | ||
| 2342 | sum += args[i] | ||
| 2343 | sum | ||
| 2344 | |||
| 2345 | process 1, nil, 3, nil, 5 | ||
| 2346 | </pre> | ||
| 2347 | </YueDisplay> | ||
| 2348 | |||
| 1864 | ## Backcalls | 2349 | ## Backcalls |
| 1865 | 2350 | ||
| 1866 | 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. | 2351 | 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. |
| @@ -1902,22 +2387,22 @@ x * 2 | |||
| 1902 | </pre> | 2387 | </pre> |
| 1903 | </YueDisplay> | 2388 | </YueDisplay> |
| 1904 | 2389 | ||
| 1905 | If you wish to have further code after your backcalls, you can set them aside with a do statement. | 2390 | If you wish to have further code after your backcalls, you can set them aside with a do statement. And the parentheses can be omitted with non-fat arrow functions. |
| 1906 | 2391 | ||
| 1907 | ```moonscript | 2392 | ```moonscript |
| 1908 | result, msg = do | 2393 | result, msg = do |
| 1909 | (data) <- readAsync "filename.txt" | 2394 | data <- readAsync "filename.txt" |
| 1910 | print data | 2395 | print data |
| 1911 | (info) <- processAsync data | 2396 | info <- processAsync data |
| 1912 | check info | 2397 | check info |
| 1913 | print result, msg | 2398 | print result, msg |
| 1914 | ``` | 2399 | ``` |
| 1915 | <YueDisplay> | 2400 | <YueDisplay> |
| 1916 | <pre> | 2401 | <pre> |
| 1917 | result, msg = do | 2402 | result, msg = do |
| 1918 | (data) <- readAsync "filename.txt" | 2403 | data <- readAsync "filename.txt" |
| 1919 | print data | 2404 | print data |
| 1920 | (info) <- processAsync data | 2405 | info <- processAsync data |
| 1921 | check info | 2406 | check info |
| 1922 | print result, msg | 2407 | print result, msg |
| 1923 | </pre> | 2408 | </pre> |
| @@ -2115,6 +2600,27 @@ doubled = [item * 2 for item in *items] | |||
| 2115 | </pre> | 2600 | </pre> |
| 2116 | </YueDisplay> | 2601 | </YueDisplay> |
| 2117 | 2602 | ||
| 2603 | In list comprehensions, you can also use the spread operator `...` to flatten nested lists, achieving a flat map effect: | ||
| 2604 | |||
| 2605 | ```moonscript | ||
| 2606 | data = | ||
| 2607 | a: [1, 2, 3] | ||
| 2608 | b: [4, 5, 6] | ||
| 2609 | |||
| 2610 | flat = [...v for k,v in pairs data] | ||
| 2611 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2612 | ``` | ||
| 2613 | <YueDisplay> | ||
| 2614 | <pre> | ||
| 2615 | data = | ||
| 2616 | a: [1, 2, 3] | ||
| 2617 | b: [4, 5, 6] | ||
| 2618 | |||
| 2619 | flat = [...v for k,v in pairs data] | ||
| 2620 | -- flat is now [1, 2, 3, 4, 5, 6] | ||
| 2621 | </pre> | ||
| 2622 | </YueDisplay> | ||
| 2623 | |||
| 2118 | 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. | 2624 | 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. |
| 2119 | 2625 | ||
| 2120 | Using multiple for clauses is the same as using nested loops: | 2626 | Using multiple for clauses is the same as using nested loops: |
| @@ -2248,6 +2754,45 @@ slice = [item for item in *items[,,2]] | |||
| 2248 | </pre> | 2754 | </pre> |
| 2249 | </YueDisplay> | 2755 | </YueDisplay> |
| 2250 | 2756 | ||
| 2757 | Both the minimum and maximum bounds can be negative, which means that the bounds are counted from the end of the table. | ||
| 2758 | |||
| 2759 | ```moonscript | ||
| 2760 | -- take the last 4 items | ||
| 2761 | slice = [item for item in *items[-4,-1]] | ||
| 2762 | ``` | ||
| 2763 | <YueDisplay> | ||
| 2764 | <pre> | ||
| 2765 | -- take the last 4 items | ||
| 2766 | slice = [item for item in *items[-4,-1]] | ||
| 2767 | </pre> | ||
| 2768 | </YueDisplay> | ||
| 2769 | |||
| 2770 | The step size can also be negative, which means that the items are taken in reverse order. | ||
| 2771 | |||
| 2772 | ```moonscript | ||
| 2773 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2774 | ``` | ||
| 2775 | <YueDisplay> | ||
| 2776 | <pre> | ||
| 2777 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2778 | </pre> | ||
| 2779 | </YueDisplay> | ||
| 2780 | |||
| 2781 | #### Slicing Expression | ||
| 2782 | |||
| 2783 | Slicing can also be used as an expression. This is useful for getting a sub-list of a table. | ||
| 2784 | |||
| 2785 | ```moonscript | ||
| 2786 | -- take the 2nd and 4th items as a new list | ||
| 2787 | sub_list = items[2, 4] | ||
| 2788 | ``` | ||
| 2789 | <YueDisplay> | ||
| 2790 | <pre> | ||
| 2791 | -- take the 2nd and 4th items as a new list | ||
| 2792 | sub_list = items[2, 4] | ||
| 2793 | </pre> | ||
| 2794 | </YueDisplay> | ||
| 2795 | |||
| 2251 | ## For Loop | 2796 | ## For Loop |
| 2252 | 2797 | ||
| 2253 | There are two for loop forms, just like in Lua. A numeric one and a generic one: | 2798 | There are two for loop forms, just like in Lua. A numeric one and a generic one: |
| @@ -2324,6 +2869,23 @@ doubled_evens = for i = 1, 20 | |||
| 2324 | </pre> | 2869 | </pre> |
| 2325 | </YueDisplay> | 2870 | </YueDisplay> |
| 2326 | 2871 | ||
| 2872 | In addition, for loops support break with a return value, allowing the loop itself to be used as an expression that exits early with a meaningful result. | ||
| 2873 | |||
| 2874 | For example, to find the first number greater than 10: | ||
| 2875 | |||
| 2876 | ```moonscript | ||
| 2877 | first_large = for n in *numbers | ||
| 2878 | break n if n > 10 | ||
| 2879 | ``` | ||
| 2880 | <YueDisplay> | ||
| 2881 | <pre> | ||
| 2882 | first_large = for n in *numbers | ||
| 2883 | break n if n > 10 | ||
| 2884 | </pre> | ||
| 2885 | </YueDisplay> | ||
| 2886 | |||
| 2887 | This break-with-value syntax enables concise and expressive search or early-exit patterns directly within loop expressions. | ||
| 2888 | |||
| 2327 | You can also filter values by combining the for loop expression with the continue statement. | 2889 | You can also filter values by combining the for loop expression with the continue statement. |
| 2328 | 2890 | ||
| 2329 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. | 2891 | For loops at the end of a function body are not accumulated into a table for a return value (Instead the function will return nil). Either an explicit return statement can be used, or the loop can be converted into a list comprehension. |
| @@ -2345,7 +2907,7 @@ print func_b! -- prints table object | |||
| 2345 | </pre> | 2907 | </pre> |
| 2346 | </YueDisplay> | 2908 | </YueDisplay> |
| 2347 | 2909 | ||
| 2348 | This is done to avoid the needless creation of tables for functions that don’t need to return the results of the loop. | 2910 | This is done to avoid the needless creation of tables for functions that don't need to return the results of the loop. |
| 2349 | 2911 | ||
| 2350 | ## Repeat Loop | 2912 | ## Repeat Loop |
| 2351 | 2913 | ||
| @@ -2624,28 +3186,26 @@ reader\parse_line! until reader\eof! | |||
| 2624 | 3186 | ||
| 2625 | ## Switch | 3187 | ## Switch |
| 2626 | 3188 | ||
| 2627 | 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. | 3189 | 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. |
| 2628 | 3190 | ||
| 2629 | ```moonscript | 3191 | ```moonscript |
| 2630 | name = "Dan" | 3192 | switch name := "Dan" |
| 2631 | switch name | ||
| 2632 | when "Robert" | 3193 | when "Robert" |
| 2633 | print "You are Robert" | 3194 | print "You are Robert" |
| 2634 | when "Dan", "Daniel" | 3195 | when "Dan", "Daniel" |
| 2635 | print "Your name, it's Dan" | 3196 | print "Your name, it's Dan" |
| 2636 | else | 3197 | else |
| 2637 | print "I don't know about your name" | 3198 | print "I don't know about you with name #{name}" |
| 2638 | ``` | 3199 | ``` |
| 2639 | <YueDisplay> | 3200 | <YueDisplay> |
| 2640 | <pre> | 3201 | <pre> |
| 2641 | name = "Dan" | 3202 | switch name := "Dan" |
| 2642 | switch name | ||
| 2643 | when "Robert" | 3203 | when "Robert" |
| 2644 | print "You are Robert" | 3204 | print "You are Robert" |
| 2645 | when "Dan", "Daniel" | 3205 | when "Dan", "Daniel" |
| 2646 | print "Your name, it's Dan" | 3206 | print "Your name, it's Dan" |
| 2647 | else | 3207 | else |
| 2648 | print "I don't know about your name" | 3208 | print "I don't know about you with name #{name}" |
| 2649 | </pre> | 3209 | </pre> |
| 2650 | </YueDisplay> | 3210 | </YueDisplay> |
| 2651 | 3211 | ||
| @@ -2676,7 +3236,7 @@ next_number = switch b | |||
| 2676 | </pre> | 3236 | </pre> |
| 2677 | </YueDisplay> | 3237 | </YueDisplay> |
| 2678 | 3238 | ||
| 2679 | 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. | 3239 | 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. |
| 2680 | 3240 | ||
| 2681 | ```moonscript | 3241 | ```moonscript |
| 2682 | msg = switch math.random(1, 5) | 3242 | msg = switch math.random(1, 5) |
| @@ -2722,7 +3282,7 @@ else | |||
| 2722 | </pre> | 3282 | </pre> |
| 2723 | </YueDisplay> | 3283 | </YueDisplay> |
| 2724 | 3284 | ||
| 2725 | 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. | 3285 | 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. |
| 2726 | 3286 | ||
| 2727 | ### Table Matching | 3287 | ### Table Matching |
| 2728 | 3288 | ||
| @@ -2782,6 +3342,123 @@ switch item | |||
| 2782 | </pre> | 3342 | </pre> |
| 2783 | </YueDisplay> | 3343 | </YueDisplay> |
| 2784 | 3344 | ||
| 3345 | You can also match against array elements, table fields, and even nested structures with array or table literals. | ||
| 3346 | |||
| 3347 | Match against array elements. | ||
| 3348 | |||
| 3349 | ```moonscript | ||
| 3350 | switch tb | ||
| 3351 | when [1, 2, 3] | ||
| 3352 | print "1, 2, 3" | ||
| 3353 | when [1, b, 3] | ||
| 3354 | print "1, #{b}, 3" | ||
| 3355 | when [1, 2, b = 3] -- b has a default value | ||
| 3356 | print "1, 2, #{b}" | ||
| 3357 | ``` | ||
| 3358 | <YueDisplay> | ||
| 3359 | <pre> | ||
| 3360 | switch tb | ||
| 3361 | when [1, 2, 3] | ||
| 3362 | print "1, 2, 3" | ||
| 3363 | when [1, b, 3] | ||
| 3364 | print "1, #{b}, 3" | ||
| 3365 | when [1, 2, b = 3] -- b has a default value | ||
| 3366 | print "1, 2, #{b}" | ||
| 3367 | </pre> | ||
| 3368 | </YueDisplay> | ||
| 3369 | |||
| 3370 | Match against table fields with destructuring. | ||
| 3371 | |||
| 3372 | ```moonscript | ||
| 3373 | switch tb | ||
| 3374 | when success: true, :result | ||
| 3375 | print "success", result | ||
| 3376 | when success: false | ||
| 3377 | print "failed", result | ||
| 3378 | else | ||
| 3379 | print "invalid" | ||
| 3380 | ``` | ||
| 3381 | <YueDisplay> | ||
| 3382 | <pre> | ||
| 3383 | switch tb | ||
| 3384 | when success: true, :result | ||
| 3385 | print "success", result | ||
| 3386 | when success: false | ||
| 3387 | print "failed", result | ||
| 3388 | else | ||
| 3389 | print "invalid" | ||
| 3390 | </pre> | ||
| 3391 | </YueDisplay> | ||
| 3392 | |||
| 3393 | Match against nested table structures. | ||
| 3394 | |||
| 3395 | ```moonscript | ||
| 3396 | switch tb | ||
| 3397 | when data: {type: "success", :content} | ||
| 3398 | print "success", content | ||
| 3399 | when data: {type: "error", :content} | ||
| 3400 | print "failed", content | ||
| 3401 | else | ||
| 3402 | print "invalid" | ||
| 3403 | ``` | ||
| 3404 | <YueDisplay> | ||
| 3405 | <pre> | ||
| 3406 | switch tb | ||
| 3407 | when data: {type: "success", :content} | ||
| 3408 | print "success", content | ||
| 3409 | when data: {type: "error", :content} | ||
| 3410 | print "failed", content | ||
| 3411 | else | ||
| 3412 | print "invalid" | ||
| 3413 | </pre> | ||
| 3414 | </YueDisplay> | ||
| 3415 | |||
| 3416 | Match against array of tables. | ||
| 3417 | |||
| 3418 | ```moonscript | ||
| 3419 | switch tb | ||
| 3420 | when [ | ||
| 3421 | {a: 1, b: 2} | ||
| 3422 | {a: 3, b: 4} | ||
| 3423 | {a: 5, b: 6} | ||
| 3424 | fourth | ||
| 3425 | ] | ||
| 3426 | print "matched", fourth | ||
| 3427 | ``` | ||
| 3428 | <YueDisplay> | ||
| 3429 | <pre> | ||
| 3430 | switch tb | ||
| 3431 | when [ | ||
| 3432 | {a: 1, b: 2} | ||
| 3433 | {a: 3, b: 4} | ||
| 3434 | {a: 5, b: 6} | ||
| 3435 | fourth | ||
| 3436 | ] | ||
| 3437 | print "matched", fourth | ||
| 3438 | </pre> | ||
| 3439 | </YueDisplay> | ||
| 3440 | |||
| 3441 | Match against a list and capture a range of elements. | ||
| 3442 | |||
| 3443 | ```moonscript | ||
| 3444 | segments = ["admin", "users", "logs", "view"] | ||
| 3445 | switch segments | ||
| 3446 | when [...groups, resource, action] | ||
| 3447 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3448 | print "Resource:", resource -- prints: "logs" | ||
| 3449 | print "Action:", action -- prints: "view" | ||
| 3450 | ``` | ||
| 3451 | <YueDisplay> | ||
| 3452 | <pre> | ||
| 3453 | segments = ["admin", "users", "logs", "view"] | ||
| 3454 | switch segments | ||
| 3455 | when [...groups, resource, action] | ||
| 3456 | print "Group:", groups -- prints: {"admin", "users"} | ||
| 3457 | print "Resource:", resource -- prints: "logs" | ||
| 3458 | print "Action:", action -- prints: "view" | ||
| 3459 | </pre> | ||
| 3460 | </YueDisplay> | ||
| 3461 | |||
| 2785 | ## Object Oriented Programming | 3462 | ## Object Oriented Programming |
| 2786 | 3463 | ||
| 2787 | 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. | 3464 | 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. |
| @@ -2913,7 +3590,7 @@ class BackPack extends Inventory | |||
| 2913 | 3590 | ||
| 2914 | Here we extend our Inventory class, and limit the amount of items it can carry. | 3591 | Here we extend our Inventory class, and limit the amount of items it can carry. |
| 2915 | 3592 | ||
| 2916 | 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. | 3593 | 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. |
| 2917 | 3594 | ||
| 2918 | 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. | 3595 | 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. |
| 2919 | 3596 | ||
| @@ -3000,13 +3677,13 @@ print BackPack.size -- prints 10 | |||
| 3000 | 3677 | ||
| 3001 | 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. | 3678 | 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. |
| 3002 | 3679 | ||
| 3003 | 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. | 3680 | 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. |
| 3004 | 3681 | ||
| 3005 | 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. | 3682 | 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. |
| 3006 | 3683 | ||
| 3007 | 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. | 3684 | 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. |
| 3008 | 3685 | ||
| 3009 | 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. | 3686 | 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. |
| 3010 | 3687 | ||
| 3011 | The class object has a couple special properties: | 3688 | The class object has a couple special properties: |
| 3012 | 3689 | ||
| @@ -3079,7 +3756,7 @@ print Counter.count -- prints 2 | |||
| 3079 | </pre> | 3756 | </pre> |
| 3080 | </YueDisplay> | 3757 | </YueDisplay> |
| 3081 | 3758 | ||
| 3082 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua’s colon syntax. | 3759 | The calling semantics of @@ are similar to @. Calling a @@ name will pass the class in as the first argument using Lua's colon syntax. |
| 3083 | 3760 | ||
| 3084 | ```moonscript | 3761 | ```moonscript |
| 3085 | @@hello 1,2,3,4 | 3762 | @@hello 1,2,3,4 |
| @@ -3094,7 +3771,7 @@ The calling semantics of @@ are similar to @. Calling a @@ name will pass the cl | |||
| 3094 | 3771 | ||
| 3095 | 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. | 3772 | 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. |
| 3096 | 3773 | ||
| 3097 | Here is an alternative way to create a class variable compared to what’s described above: | 3774 | Here is an alternative way to create a class variable compared to what's described above: |
| 3098 | 3775 | ||
| 3099 | ```moonscript | 3776 | ```moonscript |
| 3100 | class Things | 3777 | class Things |
| @@ -3360,19 +4037,19 @@ In this usage, with can be seen as a special form of the K combinator. | |||
| 3360 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. | 4037 | The expression in the with statement can also be an assignment, if you want to give a name to the expression. |
| 3361 | 4038 | ||
| 3362 | ```moonscript | 4039 | ```moonscript |
| 3363 | with str = "Hello" | 4040 | with str := "Hello" |
| 3364 | print "original:", str | 4041 | print "original:", str |
| 3365 | print "upper:", \upper! | 4042 | print "upper:", \upper! |
| 3366 | ``` | 4043 | ``` |
| 3367 | <YueDisplay> | 4044 | <YueDisplay> |
| 3368 | <pre> | 4045 | <pre> |
| 3369 | with str = "Hello" | 4046 | with str := "Hello" |
| 3370 | print "original:", str | 4047 | print "original:", str |
| 3371 | print "upper:", \upper! | 4048 | print "upper:", \upper! |
| 3372 | </pre> | 4049 | </pre> |
| 3373 | </YueDisplay> | 4050 | </YueDisplay> |
| 3374 | 4051 | ||
| 3375 | Accessing special keys with `[]` in a `with` statement. | 4052 | You can access special keys with `[]` in a `with` statement. |
| 3376 | 4053 | ||
| 3377 | ```moonscript | 4054 | ```moonscript |
| 3378 | with tb | 4055 | with tb |
| @@ -3395,6 +4072,18 @@ with tb | |||
| 3395 | </pre> | 4072 | </pre> |
| 3396 | </YueDisplay> | 4073 | </YueDisplay> |
| 3397 | 4074 | ||
| 4075 | `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. | ||
| 4076 | |||
| 4077 | ```moonscript | ||
| 4078 | with? obj | ||
| 4079 | print obj.name | ||
| 4080 | ``` | ||
| 4081 | <YueDisplay> | ||
| 4082 | <pre> | ||
| 4083 | with? obj | ||
| 4084 | print obj.name | ||
| 4085 | </pre> | ||
| 4086 | </YueDisplay> | ||
| 3398 | 4087 | ||
| 3399 | ## Do | 4088 | ## Do |
| 3400 | 4089 | ||
| @@ -3415,7 +4104,7 @@ print var -- nil here | |||
| 3415 | </pre> | 4104 | </pre> |
| 3416 | </YueDisplay> | 4105 | </YueDisplay> |
| 3417 | 4106 | ||
| 3418 | 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. | 4107 | 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. |
| 3419 | 4108 | ||
| 3420 | ```moonscript | 4109 | ```moonscript |
| 3421 | counter = do | 4110 | counter = do |
| @@ -3541,7 +4230,7 @@ print i -- will print 0 | |||
| 3541 | </pre> | 4230 | </pre> |
| 3542 | </YueDisplay> | 4231 | </YueDisplay> |
| 3543 | 4232 | ||
| 3544 | 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. | 4233 | 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. |
| 3545 | 4234 | ||
| 3546 | 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. | 4235 | 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. |
| 3547 | 4236 | ||
| @@ -3657,9 +4346,9 @@ The YueScript compiling function. It compiles the YueScript code to Lua code. | |||
| 3657 | **Signature:** | 4346 | **Signature:** |
| 3658 | ```lua | 4347 | ```lua |
| 3659 | to_lua: function(code: string, config?: Config): | 4348 | to_lua: function(code: string, config?: Config): |
| 3660 | --[[codes]] string | nil, | 4349 | --[[codes]] string | nil, |
| 3661 | --[[error]] string | nil, | 4350 | --[[error]] string | nil, |
| 3662 | --[[globals]] {{string, integer, integer}} | nil | 4351 | --[[globals]] {{string, integer, integer}} | nil |
| 3663 | ``` | 4352 | ``` |
| 3664 | 4353 | ||
| 3665 | **Parameters:** | 4354 | **Parameters:** |
| @@ -3782,8 +4471,8 @@ Loads YueScript code from a string into a function. | |||
| 3782 | **Signature:** | 4471 | **Signature:** |
| 3783 | ```lua | 4472 | ```lua |
| 3784 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | 4473 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): |
| 3785 | --[[loaded function]] nil | function(...: any): (any...), | 4474 | --[[loaded function]] nil | function(...: any): (any...), |
| 3786 | --[[error]] string | nil | 4475 | --[[error]] string | nil |
| 3787 | ``` | 4476 | ``` |
| 3788 | 4477 | ||
| 3789 | **Parameters:** | 4478 | **Parameters:** |
| @@ -3813,8 +4502,8 @@ Loads YueScript code from a string into a function. | |||
| 3813 | **Signature:** | 4502 | **Signature:** |
| 3814 | ```lua | 4503 | ```lua |
| 3815 | loadstring: function(input: string, chunkname: string, config?: Config): | 4504 | loadstring: function(input: string, chunkname: string, config?: Config): |
| 3816 | --[[loaded function]] nil | function(...: any): (any...), | 4505 | --[[loaded function]] nil | function(...: any): (any...), |
| 3817 | --[[error]] string | nil | 4506 | --[[error]] string | nil |
| 3818 | ``` | 4507 | ``` |
| 3819 | 4508 | ||
| 3820 | **Parameters:** | 4509 | **Parameters:** |
| @@ -3843,8 +4532,8 @@ Loads YueScript code from a string into a function. | |||
| 3843 | **Signature:** | 4532 | **Signature:** |
| 3844 | ```lua | 4533 | ```lua |
| 3845 | loadstring: function(input: string, config?: Config): | 4534 | loadstring: function(input: string, config?: Config): |
| 3846 | --[[loaded function]] nil | function(...: any): (any...), | 4535 | --[[loaded function]] nil | function(...: any): (any...), |
| 3847 | --[[error]] string | nil | 4536 | --[[error]] string | nil |
| 3848 | ``` | 4537 | ``` |
| 3849 | 4538 | ||
| 3850 | **Parameters:** | 4539 | **Parameters:** |
| @@ -3872,8 +4561,8 @@ Loads YueScript code from a file into a function. | |||
| 3872 | **Signature:** | 4561 | **Signature:** |
| 3873 | ```lua | 4562 | ```lua |
| 3874 | loadfile: function(filename: string, env: table, config?: Config): | 4563 | loadfile: function(filename: string, env: table, config?: Config): |
| 3875 | nil | function(...: any): (any...), | 4564 | nil | function(...: any): (any...), |
| 3876 | string | nil | 4565 | string | nil |
| 3877 | ``` | 4566 | ``` |
| 3878 | 4567 | ||
| 3879 | **Parameters:** | 4568 | **Parameters:** |
| @@ -3902,8 +4591,8 @@ Loads YueScript code from a file into a function. | |||
| 3902 | **Signature:** | 4591 | **Signature:** |
| 3903 | ```lua | 4592 | ```lua |
| 3904 | loadfile: function(filename: string, config?: Config): | 4593 | loadfile: function(filename: string, config?: Config): |
| 3905 | nil | function(...: any): (any...), | 4594 | nil | function(...: any): (any...), |
| 3906 | string | nil | 4595 | string | nil |
| 3907 | ``` | 4596 | ``` |
| 3908 | 4597 | ||
| 3909 | **Parameters:** | 4598 | **Parameters:** |
| @@ -4158,9 +4847,9 @@ Converts the code to the AST. | |||
| 4158 | 4847 | ||
| 4159 | **Signature:** | 4848 | **Signature:** |
| 4160 | ```lua | 4849 | ```lua |
| 4161 | to_ast: function(code: string, flattenLevel?: number, astName?: string): | 4850 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): |
| 4162 | --[[AST]] AST | nil, | 4851 | --[[AST]] AST | nil, |
| 4163 | --[[error]] nil | string | 4852 | --[[error]] nil | string |
| 4164 | ``` | 4853 | ``` |
| 4165 | 4854 | ||
| 4166 | **Parameters:** | 4855 | **Parameters:** |
| @@ -4170,6 +4859,7 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4170 | | code | string | The code. | | 4859 | | code | string | The code. | |
| 4171 | | flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | | 4860 | | flattenLevel | integer | [Optional] The flatten level. Higher level means more flattening. Default is 0. Maximum is 2. | |
| 4172 | | astName | string | [Optional] The AST name. Default is "File". | | 4861 | | astName | string | [Optional] The AST name. Default is "File". | |
| 4862 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is false. | | ||
| 4173 | 4863 | ||
| 4174 | **Returns:** | 4864 | **Returns:** |
| 4175 | 4865 | ||
| @@ -4178,6 +4868,33 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4178 | | AST \| nil | The AST, or nil if the conversion failed. | | 4868 | | AST \| nil | The AST, or nil if the conversion failed. | |
| 4179 | | string \| nil | The error message, or nil if the conversion succeeded. | | 4869 | | string \| nil | The error message, or nil if the conversion succeeded. | |
| 4180 | 4870 | ||
| 4871 | #### format | ||
| 4872 | |||
| 4873 | **Type:** Function. | ||
| 4874 | |||
| 4875 | **Description:** | ||
| 4876 | |||
| 4877 | Formats the YueScript code. | ||
| 4878 | |||
| 4879 | **Signature:** | ||
| 4880 | ```lua | ||
| 4881 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 4882 | ``` | ||
| 4883 | |||
| 4884 | **Parameters:** | ||
| 4885 | |||
| 4886 | | Parameter | Type | Description | | ||
| 4887 | | --- | --- | --- | | ||
| 4888 | | code | string | The code. | | ||
| 4889 | | tabSize | integer | [Optional] The tab size. Default is 4. | | ||
| 4890 | | reserveComment | boolean | [Optional] Whether to reserve the original comments. Default is true. | | ||
| 4891 | |||
| 4892 | **Returns:** | ||
| 4893 | |||
| 4894 | | Return Type | Description | | ||
| 4895 | | --- | --- | | ||
| 4896 | | string | The formatted code. | | ||
| 4897 | |||
| 4181 | #### __call | 4898 | #### __call |
| 4182 | 4899 | ||
| 4183 | **Type:** Metamethod. | 4900 | **Type:** Metamethod. |
| @@ -4249,6 +4966,19 @@ Whether the compiler should reserve the original line number in the compiled cod | |||
| 4249 | reserve_line_number: boolean | 4966 | reserve_line_number: boolean |
| 4250 | ``` | 4967 | ``` |
| 4251 | 4968 | ||
| 4969 | #### reserve_comment | ||
| 4970 | |||
| 4971 | **Type:** Field. | ||
| 4972 | |||
| 4973 | **Description:** | ||
| 4974 | |||
| 4975 | Whether the compiler should reserve the original comments in the compiled code. | ||
| 4976 | |||
| 4977 | **Signature:** | ||
| 4978 | ```lua | ||
| 4979 | reserve_comment: boolean | ||
| 4980 | ``` | ||
| 4981 | |||
| 4252 | #### space_over_tab | 4982 | #### space_over_tab |
| 4253 | 4983 | ||
| 4254 | **Type:** Field. | 4984 | **Type:** Field. |
| @@ -4299,11 +5029,11 @@ The target Lua version enumeration. | |||
| 4299 | **Signature:** | 5029 | **Signature:** |
| 4300 | ```lua | 5030 | ```lua |
| 4301 | enum LuaTarget | 5031 | enum LuaTarget |
| 4302 | "5.1" | 5032 | "5.1" |
| 4303 | "5.2" | 5033 | "5.2" |
| 4304 | "5.3" | 5034 | "5.3" |
| 4305 | "5.4" | 5035 | "5.4" |
| 4306 | "5.5" | 5036 | "5.5" |
| 4307 | end | 5037 | end |
| 4308 | ``` | 5038 | ``` |
| 4309 | 5039 | ||
| @@ -4380,7 +5110,7 @@ simplified: boolean | |||
| 4380 | 5110 | ||
| 4381 | ## Licence: MIT | 5111 | ## Licence: MIT |
| 4382 | 5112 | ||
| 4383 | Copyright (c) 2017-2025 Li Jin \<dragon-fly@qq.com\> | 5113 | Copyright (c) 2017-2026 Li Jin \<dragon-fly@qq.com\> |
| 4384 | 5114 | ||
| 4385 | Permission is hereby granted, free of charge, to any person obtaining a copy | 5115 | Permission is hereby granted, free of charge, to any person obtaining a copy |
| 4386 | of this software and associated documentation files (the "Software"), to deal | 5116 | 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 754566c..43713fe 100755 --- a/doc/docs/zh/doc/README.md +++ b/doc/docs/zh/doc/README.md | |||
| @@ -9,26 +9,36 @@ 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 | -- 列表推导 | ||
| 33 | map = (arr, action) -> | ||
| 34 | [action item for item in *arr] | ||
| 35 | |||
| 36 | filter = (arr, cond) -> | ||
| 37 | [item for item in *arr when cond item] | ||
| 38 | |||
| 39 | reduce = (arr, init, action): init -> | ||
| 40 | init = action init, item for item in *arr | ||
| 41 | |||
| 32 | -- ç®¡é“æ“作符 | 42 | -- ç®¡é“æ“作符 |
| 33 | [1, 2, 3] | 43 | [1, 2, 3] |
| 34 | |> map (x) -> x * 2 | 44 | |> map (x) -> x * 2 |
| @@ -51,19 +61,29 @@ export 🌛 = "月之脚本" | |||
| 51 | <YueDisplay> | 61 | <YueDisplay> |
| 52 | <pre> | 62 | <pre> |
| 53 | -- å¯¼å…¥è¯æ³• | 63 | -- å¯¼å…¥è¯æ³• |
| 54 | import "yue" as :p, :to_lua | 64 | import p, to_lua from "yue" |
| 55 | 65 | ||
| 56 | -- éšå¼å¯¹è±¡ | 66 | -- éšå¼å¯¹è±¡ |
| 57 | inventory = | 67 | inventory = |
| 58 | equipment: | 68 | equipment: |
| 59 | * "sword" | 69 | - "sword" |
| 60 | * "shield" | 70 | - "shield" |
| 61 | items: | 71 | items: |
| 62 | * name: "potion" | 72 | - name: "potion" |
| 63 | count: 10 | 73 | count: 10 |
| 64 | * name: "bread" | 74 | - name: "bread" |
| 65 | count: 3 | 75 | count: 3 |
| 66 | 76 | ||
| 77 | -- 列表推导 | ||
| 78 | map = (arr, action) -> | ||
| 79 | [action item for item in *arr] | ||
| 80 | |||
| 81 | filter = (arr, cond) -> | ||
| 82 | [item for item in *arr when cond item] | ||
| 83 | |||
| 84 | reduce = (arr, init, action): init -> | ||
| 85 | init = action init, item for item in *arr | ||
| 86 | |||
| 67 | -- ç®¡é“æ“作符 | 87 | -- ç®¡é“æ“作符 |
| 68 | [1, 2, 3] | 88 | [1, 2, 3] |
| 69 | |> map (x) -> x * 2 | 89 | |> map (x) -> x * 2 |
| @@ -89,7 +109,7 @@ export 🌛 = "月之脚本" | |||
| 89 | 109 | ||
| 90 | * **Lua 模å—** | 110 | * **Lua 模å—** |
| 91 | 111 | ||
| 92 |  安装 [luarocks](https://luarocks.org),一个Lua模å—的包管ç†å™¨ã€‚ç„¶åŽä½œä¸ºLua模å—å’Œå¯æ‰§è¡Œæ–‡ä»¶å®‰è£…它: | 112 |  安装 [luarocks](https://luarocks.org),一个 Lua 模å—的包管ç†å™¨ã€‚ç„¶åŽä½œä¸º Lua 模å—å’Œå¯æ‰§è¡Œæ–‡ä»¶å®‰è£…它: |
| 93 | 113 | ||
| 94 | ``` | 114 | ``` |
| 95 | > luarocks install yuescript | 115 | > luarocks install yuescript |
| @@ -122,7 +142,7 @@ export 🌛 = "月之脚本" | |||
| 122 | 142 | ||
| 123 | * **下载预编译的二进制程åº** | 143 | * **下载预编译的二进制程åº** |
| 124 | 144 | ||
| 125 |  您å¯ä»¥ä¸‹è½½é¢„编译的二进制程åºï¼ŒåŒ…括兼容ä¸åŒ Lua ç‰ˆæœ¬çš„äºŒè¿›åˆ¶å¯æ‰§è¡Œæ–‡ä»¶å’Œåº“文件。 | 145 |  ä½ å¯ä»¥ä¸‹è½½é¢„编译的二进制程åºï¼ŒåŒ…括兼容ä¸åŒ Lua ç‰ˆæœ¬çš„äºŒè¿›åˆ¶å¯æ‰§è¡Œæ–‡ä»¶å’Œåº“文件。 |
| 126 | 146 | ||
| 127 |  在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程åºã€‚ | 147 |  在[这里](https://github.com/IppClub/YueScript/releases)下载预编译的二进制程åºã€‚ |
| 128 | 148 | ||
| @@ -130,16 +150,16 @@ export 🌛 = "月之脚本" | |||
| 130 | 150 | ||
| 131 | ### Lua æ¨¡å— | 151 | ### Lua æ¨¡å— |
| 132 | 152 | ||
| 133 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: | 153 | 在 Lua ä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬æ¨¡å—: |
| 134 | 154 | ||
| 135 | * **用法 1** | 155 | * **用法 1** |
| 136 | 在Luaä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 | 156 | 在 Lua ä¸å¼•å…¥ "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue"。 |
| 137 | ```Lua | 157 | ```Lua |
| 138 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") | 158 | require("yue")("ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶") |
| 139 | ``` | 159 | ``` |
| 140 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import**进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ | 160 | å½“ä½ åœ¨åŒä¸€è·¯å¾„下把 "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.yue" 编译æˆäº† "ä½ çš„è„šæœ¬å…¥å£æ–‡ä»¶.lua" 时,ä»ç„¶å¯ä»¥ä½¿ç”¨è¿™ä¸ªä»£ç åŠ è½½ .lua ä»£ç æ–‡ä»¶ã€‚在其余的月之脚本文件ä¸ï¼Œåªéœ€æ£å¸¸ä½¿ç”¨ **require** 或 **import** 进行脚本引用å³å¯ã€‚错误消æ¯ä¸çš„代ç 行å·ä¹Ÿä¼šè¢«æ£ç¡®å¤„ç†ã€‚ |
| 141 | 161 | ||
| 142 | * **用法 2** | 162 | * **用法 2** |
| 143 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ | 163 | 手动引入月之脚本模å—å¹¶é‡å†™é”™è¯¯æ¶ˆæ¯æ¥å¸®åŠ©è°ƒè¯•ã€‚ |
| 144 | ```lua | 164 | ```lua |
| 145 | local yue = require("yue") | 165 | local yue = require("yue") |
| @@ -151,8 +171,8 @@ end, function(err) | |||
| 151 | end) | 171 | end) |
| 152 | ``` | 172 | ``` |
| 153 | 173 | ||
| 154 | * **用法 3** | 174 | * **用法 3** |
| 155 | 在Luaä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ | 175 | 在 Lua ä¸ä½¿ç”¨æœˆä¹‹è„šæœ¬ç¼–è¯‘å™¨åŠŸèƒ½ã€‚ |
| 156 | ```lua | 176 | ```lua |
| 157 | local yue = require("yue") | 177 | local yue = require("yue") |
| 158 | local codes, err, globals = yue.to_lua([[ | 178 | local codes, err, globals = yue.to_lua([[ |
| @@ -333,7 +353,7 @@ end | |||
| 333 | 353 | ||
| 334 | ### å¯¼å‡ºå® | 354 | ### å¯¼å‡ºå® |
| 335 | 355 | ||
| 336 | å®å‡½æ•°å¯ä»¥ä»Žä¸€ä¸ªæ¨¡å—ä¸å¯¼å‡ºï¼Œå¹¶åœ¨å¦ä¸€ä¸ªæ¨¡å—ä¸å¯¼å…¥ã€‚您必须将导出的å®å‡½æ•°æ”¾åœ¨ä¸€ä¸ªå•独的文件ä¸ä½¿ç”¨ï¼Œè€Œä¸”åªæœ‰å®å®šä¹‰ã€å®å¯¼å…¥å’Œå®å±•å¼€å¯ä»¥æ”¾å…¥è¿™ä¸ªå®å¯¼å‡ºæ¨¡å—ä¸ã€‚ | 356 | å®å‡½æ•°å¯ä»¥ä»Žä¸€ä¸ªæ¨¡å—ä¸å¯¼å‡ºï¼Œå¹¶åœ¨å¦ä¸€ä¸ªæ¨¡å—ä¸å¯¼å…¥ã€‚ä½ å¿…é¡»å°†å¯¼å‡ºçš„å®å‡½æ•°æ”¾åœ¨ä¸€ä¸ªå•独的文件ä¸ä½¿ç”¨ï¼Œè€Œä¸”åªæœ‰å®å®šä¹‰ã€å®å¯¼å…¥å’Œå®å±•å¼€å¯ä»¥æ”¾å…¥è¿™ä¸ªå®å¯¼å‡ºæ¨¡å—ä¸ã€‚ |
| 337 | ```moonscript | 357 | ```moonscript |
| 338 | -- 文件: utils.yue | 358 | -- 文件: utils.yue |
| 339 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" | 359 | export macro map = (items, action) -> "[#{action} for _ in *#{items}]" |
| @@ -387,16 +407,16 @@ print $LINE -- 获å–当å‰ä»£ç 行数:2 | |||
| 387 | 407 | ||
| 388 | ```moonscript | 408 | ```moonscript |
| 389 | macro Enum = (...) -> | 409 | macro Enum = (...) -> |
| 390 | items = {...} | 410 | items = {...} |
| 391 | itemSet = {item, true for item in *items} | 411 | itemSet = {item, true for item in *items} |
| 392 | (item) -> | 412 | (item) -> |
| 393 | 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] |
| 394 | "\"#{item}\"" | 414 | "\"#{item}\"" |
| 395 | 415 | ||
| 396 | macro BodyType = $Enum( | 416 | macro BodyType = $Enum( |
| 397 | Static | 417 | Static |
| 398 | Dynamic | 418 | Dynamic |
| 399 | Kinematic | 419 | Kinematic |
| 400 | ) | 420 | ) |
| 401 | 421 | ||
| 402 | print "有效的枚举类型:", $BodyType Static | 422 | print "有效的枚举类型:", $BodyType Static |
| @@ -405,16 +425,16 @@ print "有效的枚举类型:", $BodyType Static | |||
| 405 | <YueDisplay> | 425 | <YueDisplay> |
| 406 | <pre> | 426 | <pre> |
| 407 | macro Enum = (...) -> | 427 | macro Enum = (...) -> |
| 408 | items = {...} | 428 | items = {...} |
| 409 | itemSet = {item, true for item in *items} | 429 | itemSet = {item, true for item in *items} |
| 410 | (item) -> | 430 | (item) -> |
| 411 | 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] |
| 412 | "\"#{item}\"" | 432 | "\"#{item}\"" |
| 413 | 433 | ||
| 414 | macro BodyType = $Enum( | 434 | macro BodyType = $Enum( |
| 415 | Static | 435 | Static |
| 416 | Dynamic | 436 | Dynamic |
| 417 | Kinematic | 437 | Kinematic |
| 418 | ) | 438 | ) |
| 419 | 439 | ||
| 420 | print "有效的枚举类型:", $BodyType Static | 440 | print "有效的枚举类型:", $BodyType Static |
| @@ -422,9 +442,57 @@ print "有效的枚举类型:", $BodyType Static | |||
| 422 | </pre> | 442 | </pre> |
| 423 | </YueDisplay> | 443 | </YueDisplay> |
| 424 | 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 | |||
| 425 | ## æ“作符 | 493 | ## æ“作符 |
| 426 | 494 | ||
| 427 | Lua的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 | 495 | Lua 的所有二元和一元æ“作符在月之脚本ä¸éƒ½æ˜¯å¯ç”¨çš„。æ¤å¤–,**!=** ç¬¦å·æ˜¯ **~=** 的别å,而 **\\** 或 **::** å‡å¯ç”¨äºŽç¼–写链å¼å‡½æ•°è°ƒç”¨ï¼Œå¦‚写作 `tb\func!` 或 `tb::func!`。æ¤å¤–月之脚本还æä¾›äº†ä¸€äº›å…¶ä»–特殊的æ“作符,以编写更具表达力的代ç 。 |
| 428 | 496 | ||
| 429 | ```moonscript | 497 | ```moonscript |
| 430 | tb\func! if tb ~= nil | 498 | tb\func! if tb ~= nil |
| @@ -439,7 +507,7 @@ tb::func! if tb != nil | |||
| 439 | 507 | ||
| 440 | ### 链弿¯”较 | 508 | ### 链弿¯”较 |
| 441 | 509 | ||
| 442 | 您å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸è¿›è¡Œæ¯”较表达å¼çš„链å¼ä¹¦å†™ï¼š | 510 | ä½ å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸è¿›è¡Œæ¯”较表达å¼çš„链å¼ä¹¦å†™ï¼š |
| 443 | 511 | ||
| 444 | ```moonscript | 512 | ```moonscript |
| 445 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 | 513 | print 1 < 2 <= 2 < 3 == 3 > 2 >= 1 == 1 < 3 != 5 |
| @@ -464,56 +532,56 @@ print 1 <= a <= 10 | |||
| 464 | 532 | ||
| 465 | ```moonscript | 533 | ```moonscript |
| 466 | v = (x) -> | 534 | v = (x) -> |
| 467 | print x | 535 | print x |
| 468 | x | 536 | x |
| 469 | 537 | ||
| 470 | print v(1) < v(2) <= v(3) | 538 | print v(1) < v(2) <= v(3) |
| 471 | --[[ | 539 | --[[ |
| 472 | 输出: | 540 | 输出: |
| 473 | 2 | 541 | 2 |
| 474 | 1 | 542 | 1 |
| 475 | 3 | 543 | 3 |
| 476 | true | 544 | true |
| 477 | ]] | 545 | ]] |
| 478 | 546 | ||
| 479 | print v(1) > v(2) <= v(3) | 547 | print v(1) > v(2) <= v(3) |
| 480 | --[[ | 548 | --[[ |
| 481 | 输出: | 549 | 输出: |
| 482 | 2 | 550 | 2 |
| 483 | 1 | 551 | 1 |
| 484 | false | 552 | false |
| 485 | ]] | 553 | ]] |
| 486 | ``` | 554 | ``` |
| 487 | <YueDisplay> | 555 | <YueDisplay> |
| 488 | <pre> | 556 | <pre> |
| 489 | v = (x) -> | 557 | v = (x) -> |
| 490 | print x | 558 | print x |
| 491 | x | 559 | x |
| 492 | 560 | ||
| 493 | print v(1) < v(2) <= v(3) | 561 | print v(1) < v(2) <= v(3) |
| 494 | --[[ | 562 | --[[ |
| 495 | 输出: | 563 | 输出: |
| 496 | 2 | 564 | 2 |
| 497 | 1 | 565 | 1 |
| 498 | 3 | 566 | 3 |
| 499 | true | 567 | true |
| 500 | ]] | 568 | ]] |
| 501 | 569 | ||
| 502 | print v(1) > v(2) <= v(3) | 570 | print v(1) > v(2) <= v(3) |
| 503 | --[[ | 571 | --[[ |
| 504 | 输出: | 572 | 输出: |
| 505 | 2 | 573 | 2 |
| 506 | 1 | 574 | 1 |
| 507 | false | 575 | false |
| 508 | ]] | 576 | ]] |
| 509 | </pre> | 577 | </pre> |
| 510 | </YueDisplay> | 578 | </YueDisplay> |
| 511 | 579 | ||
| 512 | 在上é¢çš„例å里,ä¸é—´çš„表达å¼`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` è¿ç®—符æ¥åšè¿žæŽ¥ã€‚ |
| 513 | 581 | ||
| 514 | ### è¡¨è¿½åŠ | 582 | ### è¡¨è¿½åŠ |
| 515 | 583 | ||
| 516 | **[] =** æ“作符用于å‘Luaè¡¨çš„æœ€åŽæ’入值。 | 584 | **[] =** æ“ä½œç¬¦ç”¨äºŽå‘ Lua è¡¨çš„æœ€åŽæ’入值。 |
| 517 | 585 | ||
| 518 | ```moonscript | 586 | ```moonscript |
| 519 | tab = [] | 587 | tab = [] |
| @@ -526,19 +594,36 @@ tab[] = "Value" | |||
| 526 | </pre> | 594 | </pre> |
| 527 | </YueDisplay> | 595 | </YueDisplay> |
| 528 | 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 | |||
| 529 | ### 表扩展 | 614 | ### 表扩展 |
| 530 | 615 | ||
| 531 | 您å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在Luaè¡¨ä¸æ’入数组表或哈希表。 | 616 | ä½ å¯ä»¥ä½¿ç”¨å‰ç½® `...` æ“作符在 Lua è¡¨ä¸æ’入数组表或哈希表。 |
| 532 | 617 | ||
| 533 | ```moonscript | 618 | ```moonscript |
| 534 | parts = | 619 | parts = |
| 535 | * "shoulders" | 620 | * "shoulders" |
| 536 | * "knees" | 621 | * "knees" |
| 537 | lyrics = | 622 | lyrics = |
| 538 | * "head" | 623 | * "head" |
| 539 | * ...parts | 624 | * ...parts |
| 540 | * "and" | 625 | * "and" |
| 541 | * "toes" | 626 | * "toes" |
| 542 | 627 | ||
| 543 | copy = {...other} | 628 | copy = {...other} |
| 544 | 629 | ||
| @@ -549,13 +634,13 @@ merge = {...a, ...b} | |||
| 549 | <YueDisplay> | 634 | <YueDisplay> |
| 550 | <pre> | 635 | <pre> |
| 551 | parts = | 636 | parts = |
| 552 | * "shoulders" | 637 | * "shoulders" |
| 553 | * "knees" | 638 | * "knees" |
| 554 | lyrics = | 639 | lyrics = |
| 555 | * "head" | 640 | * "head" |
| 556 | * ...parts | 641 | * ...parts |
| 557 | * "and" | 642 | * "and" |
| 558 | * "toes" | 643 | * "toes" |
| 559 | 644 | ||
| 560 | copy = {...other} | 645 | copy = {...other} |
| 561 | 646 | ||
| @@ -565,12 +650,29 @@ merge = {...a, ...b} | |||
| 565 | </pre> | 650 | </pre> |
| 566 | </YueDisplay> | 651 | </YueDisplay> |
| 567 | 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 | |||
| 568 | ### 元表 | 670 | ### 元表 |
| 569 | 671 | ||
| 570 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ | 672 | **<>** æ“ä½œç¬¦å¯æä¾›å…ƒè¡¨æ“ä½œçš„å¿«æ·æ–¹å¼ã€‚ |
| 571 | 673 | ||
| 572 | * **元表创建** | 674 | * **元表创建** |
| 573 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的Lua表。 | 675 | ä½¿ç”¨ç©ºæ‹¬å· **<>** 或被 **<>** 包围的元方法键创建普通的 Lua 表。 |
| 574 | 676 | ||
| 575 | ```moonscript | 677 | ```moonscript |
| 576 | mt = {} | 678 | mt = {} |
| @@ -605,7 +707,7 @@ close _ = <close>: -> print "超出范围" | |||
| 605 | </pre> | 707 | </pre> |
| 606 | </YueDisplay> | 708 | </YueDisplay> |
| 607 | 709 | ||
| 608 | * **元表访问** | 710 | * **元表访问** |
| 609 | 使用 **<>** 或被 **<>** åŒ…å›´çš„å…ƒæ–¹æ³•åæˆ–在 **<>** ä¸ç¼–写æŸäº›è¡¨è¾¾å¼æ¥è®¿é—®å…ƒè¡¨ã€‚ | 711 | 使用 **<>** 或被 **<>** åŒ…å›´çš„å…ƒæ–¹æ³•åæˆ–在 **<>** ä¸ç¼–写æŸäº›è¡¨è¾¾å¼æ¥è®¿é—®å…ƒè¡¨ã€‚ |
| 610 | 712 | ||
| 611 | ```moonscript | 713 | ```moonscript |
| @@ -629,7 +731,7 @@ print tb.item | |||
| 629 | </pre> | 731 | </pre> |
| 630 | </YueDisplay> | 732 | </YueDisplay> |
| 631 | 733 | ||
| 632 | * **元表解构** | 734 | * **元表解构** |
| 633 | 使用被 **<>** 包围的元方法键解构元表。 | 735 | 使用被 **<>** 包围的元方法键解构元表。 |
| 634 | 736 | ||
| 635 | ```moonscript | 737 | ```moonscript |
| @@ -680,7 +782,7 @@ with? io.open "test.txt", "w" | |||
| 680 | 782 | ||
| 681 | ### ç®¡é“ | 783 | ### ç®¡é“ |
| 682 | 784 | ||
| 683 | 与其使用一系列嵌套的函数调用,您还å¯ä»¥è€ƒè™‘使用è¿ç®—符 **|>** æ¥ä¼ 递值。 | 785 | ä¸Žå…¶ä½¿ç”¨ä¸€ç³»åˆ—åµŒå¥—çš„å‡½æ•°è°ƒç”¨ï¼Œä½ è¿˜å¯ä»¥è€ƒè™‘使用è¿ç®—符 **|>** æ¥ä¼ 递值。 |
| 684 | 786 | ||
| 685 | ```moonscript | 787 | ```moonscript |
| 686 | "ä½ å¥½" |> print | 788 | "ä½ å¥½" |> print |
| @@ -712,7 +814,7 @@ readFile "example.txt" | |||
| 712 | 814 | ||
| 713 | ### 空值åˆå¹¶ | 815 | ### 空值åˆå¹¶ |
| 714 | 816 | ||
| 715 | 如果其左æ“ä½œæ•°ä¸æ˜¯**nil**,则nilåˆå¹¶è¿ç®—符 **??** 返回其左æ“作数的值;å¦åˆ™ï¼Œå®ƒå°†è®¡ç®—峿“作数并返回其结果。如果左æ“作数计算结果为éžnil的值,**??** è¿ç®—符将ä¸å†è®¡ç®—其峿“作数。 | 817 | 如果其左æ“ä½œæ•°ä¸æ˜¯ **nil**,则nilåˆå¹¶è¿ç®—符 **??** 返回其左æ“作数的值;å¦åˆ™ï¼Œå®ƒå°†è®¡ç®—峿“作数并返回其结果。如果左æ“ä½œæ•°è®¡ç®—ç»“æžœä¸ºéž nil 的值,**??** è¿ç®—符将ä¸å†è®¡ç®—其峿“作数。 |
| 716 | ```moonscript | 818 | ```moonscript |
| 717 | local a, b, c, d | 819 | local a, b, c, d |
| 718 | a = b ?? c ?? d | 820 | a = b ?? c ?? d |
| @@ -731,67 +833,87 @@ a ??= false | |||
| 731 | 833 | ||
| 732 | ### éšå¼å¯¹è±¡ | 834 | ### éšå¼å¯¹è±¡ |
| 733 | 835 | ||
| 734 | 您å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 开始编写一系列éšå¼ç»“构。如果您æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 | 836 | ä½ å¯ä»¥åœ¨è¡¨æ ¼å—å†…ä½¿ç”¨ç¬¦å· **\*** 或是 **-** 开始编写一系列éšå¼ç»“æž„ã€‚å¦‚æžœä½ æ£åœ¨åˆ›å»ºéšå¼å¯¹è±¡ï¼Œå¯¹è±¡çš„å—æ®µå¿…须具有相åŒçš„缩进。 |
| 837 | |||
| 735 | ```moonscript | 838 | ```moonscript |
| 839 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
| 736 | list = | 840 | list = |
| 737 | * 1 | 841 | * 1 |
| 738 | * 2 | 842 | * 2 |
| 739 | * 3 | 843 | * 3 |
| 740 | 844 | ||
| 845 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
| 741 | func | 846 | func |
| 742 | * 1 | 847 | * 1 |
| 743 | * 2 | 848 | * 2 |
| 744 | * 3 | 849 | * 3 |
| 745 | 850 | ||
| 851 | -- 返回时使用éšå¼å¯¹è±¡ | ||
| 852 | f = -> | ||
| 853 | return | ||
| 854 | * 1 | ||
| 855 | * 2 | ||
| 856 | * 3 | ||
| 857 | |||
| 858 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
| 746 | tb = | 859 | tb = |
| 747 | name: "abc" | 860 | name: "abc" |
| 748 | 861 | ||
| 749 | values: | 862 | values: |
| 750 | * "a" | 863 | - "a" |
| 751 | * "b" | 864 | - "b" |
| 752 | * "c" | 865 | - "c" |
| 753 | 866 | ||
| 754 | objects: | 867 | objects: |
| 755 | * name: "a" | 868 | - name: "a" |
| 756 | value: 1 | 869 | value: 1 |
| 757 | func: => @value + 1 | 870 | func: => @value + 1 |
| 758 | tb: | 871 | tb: |
| 759 | fieldA: 1 | 872 | fieldA: 1 |
| 760 | 873 | ||
| 761 | * name: "b" | 874 | - name: "b" |
| 762 | value: 2 | 875 | value: 2 |
| 763 | func: => @value + 2 | 876 | func: => @value + 2 |
| 764 | tb: { } | 877 | tb: { } |
| 765 | |||
| 766 | ``` | 878 | ``` |
| 767 | <YueDisplay> | 879 | <YueDisplay> |
| 768 | <pre> | 880 | <pre> |
| 881 | -- 赋值时使用éšå¼å¯¹è±¡ | ||
| 769 | list = | 882 | list = |
| 770 | * 1 | 883 | * 1 |
| 771 | * 2 | 884 | * 2 |
| 772 | * 3 | 885 | * 3 |
| 773 | 886 | ||
| 887 | -- 函数调用时使用éšå¼å¯¹è±¡ | ||
| 774 | func | 888 | func |
| 775 | * 1 | 889 | * 1 |
| 776 | * 2 | 890 | * 2 |
| 777 | * 3 | 891 | * 3 |
| 778 | 892 | ||
| 893 | -- 返回时使用éšå¼å¯¹è±¡ | ||
| 894 | f = -> | ||
| 895 | return | ||
| 896 | * 1 | ||
| 897 | * 2 | ||
| 898 | * 3 | ||
| 899 | |||
| 900 | -- è¡¨æ ¼æ—¶ä½¿ç”¨éšå¼å¯¹è±¡ | ||
| 779 | tb = | 901 | tb = |
| 780 | name: "abc" | 902 | name: "abc" |
| 781 | 903 | ||
| 782 | values: | 904 | values: |
| 783 | * "a" | 905 | - "a" |
| 784 | * "b" | 906 | - "b" |
| 785 | * "c" | 907 | - "c" |
| 786 | 908 | ||
| 787 | objects: | 909 | objects: |
| 788 | * name: "a" | 910 | - name: "a" |
| 789 | value: 1 | 911 | value: 1 |
| 790 | func: => @value + 1 | 912 | func: => @value + 1 |
| 791 | tb: | 913 | tb: |
| 792 | fieldA: 1 | 914 | fieldA: 1 |
| 793 | 915 | ||
| 794 | * name: "b" | 916 | - name: "b" |
| 795 | value: 2 | 917 | value: 2 |
| 796 | func: => @value + 2 | 918 | func: => @value + 2 |
| 797 | tb: { } | 919 | tb: { } |
| @@ -855,11 +977,67 @@ do | |||
| 855 | </pre> | 977 | </pre> |
| 856 | </YueDisplay> | 978 | </YueDisplay> |
| 857 | 979 | ||
| 980 | ### 导入全局å˜é‡ | ||
| 981 | |||
| 982 | ä½ å¯ä»¥ä½¿ç”¨ `import` 将指定的全局å˜é‡å¯¼å…¥åˆ°æœ¬åœ°å˜é‡ä¸ã€‚当导入一系列对全局å˜é‡çš„链å¼è®¿é—®æ—¶ï¼Œæœ€åŽä¸€ä¸ªè®¿é—®çš„å—æ®µå°†è¢«èµ‹å€¼ç»™æœ¬åœ°å˜é‡ã€‚ | ||
| 983 | |||
| 984 | ```moonscript | ||
| 985 | do | ||
| 986 | import tostring | ||
| 987 | import table.concat | ||
| 988 | print concat ["a", tostring 1] | ||
| 989 | ``` | ||
| 990 | <YueDisplay> | ||
| 991 | <pre> | ||
| 992 | do | ||
| 993 | import tostring | ||
| 994 | import table.concat | ||
| 995 | print concat ["a", tostring 1] | ||
| 996 | </pre> | ||
| 997 | </YueDisplay> | ||
| 998 | |||
| 999 | #### 自动导入 | ||
| 1000 | |||
| 1001 | 在一个代ç å—的顶部写 `import global`,会将当å‰ä½œç”¨åŸŸä¸å°šæœªæ˜¾å¼å£°æ˜Žæˆ–赋值过的å˜é‡å,自动导入为本地常é‡ï¼Œå¹¶åœ¨è¯¥è¯å¥çš„ä½ç½®ç»‘定到åŒå的全局å˜é‡ã€‚ | ||
| 1002 | |||
| 1003 | 但是在åŒä¸€ä½œç”¨åŸŸä¸è¢«æ˜¾å¼å£°æ˜Žä¸ºå…¨å±€çš„å˜é‡ä¸ä¼šè¢«è‡ªåŠ¨å¯¼å…¥ï¼Œå› æ¤å¯ä»¥ç»§ç»è¿›è¡Œèµ‹å€¼æ“作。 | ||
| 1004 | |||
| 1005 | ```moonscript | ||
| 1006 | do | ||
| 1007 | import global | ||
| 1008 | print "hello" | ||
| 1009 | math.random 3 | ||
| 1010 | -- print = nil -- 报错:自动导入的全局å˜é‡ä¸ºå¸¸é‡ | ||
| 1011 | |||
| 1012 | do | ||
| 1013 | -- 被显å¼å£°æ˜Žä¸ºå…¨å±€çš„å˜é‡ä¸ä¼šè¢«è‡ªåЍ坼入 | ||
| 1014 | import global | ||
| 1015 | global FLAG | ||
| 1016 | print FLAG | ||
| 1017 | FLAG = 123 | ||
| 1018 | ``` | ||
| 1019 | <YueDisplay> | ||
| 1020 | <pre> | ||
| 1021 | do | ||
| 1022 | import global | ||
| 1023 | print "hello" | ||
| 1024 | math.random 3 | ||
| 1025 | -- print = nil -- 报错:自动导入的全局å˜é‡æ˜¯å¸¸é‡ | ||
| 1026 | |||
| 1027 | do | ||
| 1028 | -- 被显å¼å£°æ˜Žä¸ºå…¨å±€çš„å˜é‡ä¸ä¼šè¢«è‡ªåЍ坼入 | ||
| 1029 | import global | ||
| 1030 | global FLAG | ||
| 1031 | print FLAG | ||
| 1032 | FLAG = 123 | ||
| 1033 | </pre> | ||
| 1034 | </YueDisplay> | ||
| 1035 | |||
| 858 | ### 导出 | 1036 | ### 导出 |
| 859 | 1037 | ||
| 860 | 导出è¯å¥æä¾›äº†ä¸€ç§ç®€æ´çš„æ–¹å¼æ¥å®šä¹‰å½“å‰çš„æ¨¡å—。 | 1038 | 导出è¯å¥æä¾›äº†ä¸€ç§ç®€æ´çš„æ–¹å¼æ¥å®šä¹‰å½“å‰çš„æ¨¡å—。 |
| 861 | 1039 | ||
| 862 | * **命å导出** | 1040 | * **命å导出** |
| 863 | 带命å的导出将定义一个局部å˜é‡ï¼Œå¹¶åœ¨å¯¼å‡ºçš„è¡¨ä¸æ·»åŠ ä¸€ä¸ªåŒåçš„å—æ®µã€‚ | 1041 | 带命å的导出将定义一个局部å˜é‡ï¼Œå¹¶åœ¨å¯¼å‡ºçš„è¡¨ä¸æ·»åŠ ä¸€ä¸ªåŒåçš„å—æ®µã€‚ |
| 864 | 1042 | ||
| 865 | ```moonscript | 1043 | ```moonscript |
| @@ -923,7 +1101,7 @@ export["a-b-c"] = 123 | |||
| 923 | </pre> | 1101 | </pre> |
| 924 | </YueDisplay> | 1102 | </YueDisplay> |
| 925 | 1103 | ||
| 926 | * **未命å导出** | 1104 | * **未命å导出** |
| 927 | 未命å导出会将è¦å¯¼å‡ºçš„ç›®æ ‡é¡¹ç›®æ·»åŠ åˆ°å¯¼å‡ºè¡¨çš„æ•°ç»„éƒ¨åˆ†ã€‚ | 1105 | 未命å导出会将è¦å¯¼å‡ºçš„ç›®æ ‡é¡¹ç›®æ·»åŠ åˆ°å¯¼å‡ºè¡¨çš„æ•°ç»„éƒ¨åˆ†ã€‚ |
| 928 | 1106 | ||
| 929 | ```moonscript | 1107 | ```moonscript |
| @@ -953,7 +1131,7 @@ export with tmp | |||
| 953 | </pre> | 1131 | </pre> |
| 954 | </YueDisplay> | 1132 | </YueDisplay> |
| 955 | 1133 | ||
| 956 | * **默认导出** | 1134 | * **默认导出** |
| 957 | 在导出è¯å¥ä¸ä½¿ç”¨ **default** 关键å—ï¼Œæ¥æ›¿æ¢å¯¼å‡ºçš„è¡¨ä¸ºä¸€ä¸ªç›®æ ‡çš„å¯¹è±¡ã€‚ | 1135 | 在导出è¯å¥ä¸ä½¿ç”¨ **default** 关键å—ï¼Œæ¥æ›¿æ¢å¯¼å‡ºçš„è¡¨ä¸ºä¸€ä¸ªç›®æ ‡çš„å¯¹è±¡ã€‚ |
| 958 | 1136 | ||
| 959 | ```moonscript | 1137 | ```moonscript |
| @@ -971,7 +1149,7 @@ export default -> | |||
| 971 | 1149 | ||
| 972 | ## 赋值 | 1150 | ## 赋值 |
| 973 | 1151 | ||
| 974 | 月之脚本ä¸å®šä¹‰çš„å˜é‡æ˜¯åЍæ€ç±»åž‹çš„,并默认为局部å˜é‡ã€‚ä½†ä½ å¯ä»¥é€šè¿‡**local**å’Œ**global**å£°æ˜Žæ¥æ”¹å˜å£°æ˜Žå˜é‡çš„作用范围。 | 1152 | 月之脚本ä¸å®šä¹‰çš„å˜é‡æ˜¯åЍæ€ç±»åž‹çš„,并默认为局部å˜é‡ã€‚ä½†ä½ å¯ä»¥é€šè¿‡ **local** å’Œ **global** å£°æ˜Žæ¥æ”¹å˜å£°æ˜Žå˜é‡çš„作用范围。 |
| 975 | 1153 | ||
| 976 | ```moonscript | 1154 | ```moonscript |
| 977 | hello = "world" | 1155 | hello = "world" |
| @@ -1100,9 +1278,9 @@ do | |||
| 1100 | 1278 | ||
| 1101 | ## 解构赋值 | 1279 | ## 解构赋值 |
| 1102 | 1280 | ||
| 1103 | 解构赋值是一ç§å¿«é€Ÿä»ŽLuaè¡¨ä¸æŒ‰å称或基于数组ä¸çš„ä½ç½®æå–值的方法。 | 1281 | 解构赋值是一ç§å¿«é€Ÿä»Ž Lua è¡¨ä¸æŒ‰å称或基于数组ä¸çš„ä½ç½®æå–值的方法。 |
| 1104 | 1282 | ||
| 1105 | é€šå¸¸å½“ä½ çœ‹åˆ°ä¸€ä¸ªå—é¢é‡çš„Lua表,比如{1,2,3},它ä½äºŽèµ‹å€¼çš„å³ä¾§ï¼Œå› 为它是一个值。解构赋值è¯å¥çš„写法就是交æ¢äº†å—é¢é‡Lua表的角色,并将其放在赋值è¯å¥çš„左侧。 | 1283 | é€šå¸¸å½“ä½ çœ‹åˆ°ä¸€ä¸ªå—é¢é‡çš„ Lua 表,比如 `{1,2,3}`,它ä½äºŽèµ‹å€¼çš„å³ä¾§ï¼Œå› 为它是一个值。解构赋值è¯å¥çš„写法就是交æ¢äº†å—é¢é‡ Lua 表的角色,并将其放在赋值è¯å¥çš„左侧。 |
| 1106 | 1284 | ||
| 1107 | 最好是通过示例æ¥è§£é‡Šã€‚ä»¥ä¸‹æ˜¯å¦‚ä½•ä»Žè¡¨æ ¼ä¸è§£åŒ…å‰ä¸¤ä¸ªå€¼çš„æ–¹æ³•: | 1285 | 最好是通过示例æ¥è§£é‡Šã€‚ä»¥ä¸‹æ˜¯å¦‚ä½•ä»Žè¡¨æ ¼ä¸è§£åŒ…å‰ä¸¤ä¸ªå€¼çš„æ–¹æ³•: |
| 1108 | 1286 | ||
| @@ -1201,7 +1379,7 @@ print first, second, color | |||
| 1201 | </pre> | 1379 | </pre> |
| 1202 | </YueDisplay> | 1380 | </YueDisplay> |
| 1203 | 1381 | ||
| 1204 | 有时候我们会需è¦ä»ŽLuaè¡¨ä¸æå–值并将它们赋给与键åŒå的局部å˜é‡ã€‚为了é¿å…编写é‡å¤ä»£ç ,我们å¯ä»¥ä½¿ç”¨ **:** å‰ç¼€æ“作符: | 1382 | 有时候我们会需è¦ä»Ž Lua è¡¨ä¸æå–值并将它们赋给与键åŒå的局部å˜é‡ã€‚为了é¿å…编写é‡å¤ä»£ç ,我们å¯ä»¥ä½¿ç”¨ **:** å‰ç¼€æ“作符: |
| 1205 | 1383 | ||
| 1206 | ```moonscript | 1384 | ```moonscript |
| 1207 | {:concat, :insert} = table | 1385 | {:concat, :insert} = table |
| @@ -1223,7 +1401,7 @@ print first, second, color | |||
| 1223 | </pre> | 1401 | </pre> |
| 1224 | </YueDisplay> | 1402 | </YueDisplay> |
| 1225 | 1403 | ||
| 1226 | 在进行解构时,您å¯ä»¥æŒ‡å®šé»˜è®¤å€¼ï¼Œå¦‚: | 1404 | åœ¨è¿›è¡Œè§£æž„æ—¶ï¼Œä½ å¯ä»¥æŒ‡å®šé»˜è®¤å€¼ï¼Œå¦‚: |
| 1227 | 1405 | ||
| 1228 | ```moonscript | 1406 | ```moonscript |
| 1229 | {:name = "nameless", :job = "jobless"} = person | 1407 | {:name = "nameless", :job = "jobless"} = person |
| @@ -1234,7 +1412,7 @@ print first, second, color | |||
| 1234 | </pre> | 1412 | </pre> |
| 1235 | </YueDisplay> | 1413 | </YueDisplay> |
| 1236 | 1414 | ||
| 1237 | 在进行列表解构时,您å¯ä»¥ä½¿ç”¨`_`作为å ä½ç¬¦ï¼š | 1415 | åœ¨è¿›è¡Œåˆ—è¡¨è§£æž„æ—¶ï¼Œä½ å¯ä»¥ä½¿ç”¨`_`作为å ä½ç¬¦ï¼š |
| 1238 | 1416 | ||
| 1239 | ```moonscript | 1417 | ```moonscript |
| 1240 | [_, two, _, four] = items | 1418 | [_, two, _, four] = items |
| @@ -1245,9 +1423,55 @@ print first, second, color | |||
| 1245 | </pre> | 1423 | </pre> |
| 1246 | </YueDisplay> | 1424 | </YueDisplay> |
| 1247 | 1425 | ||
| 1248 | ### 在其它地方的解构 | 1426 | ### 范围解构 |
| 1249 | 1427 | ||
| 1250 | 解构也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨for循环: | 1428 | ä½ å¯ä»¥ä½¿ç”¨å±•å¼€è¿ç®—符 `...` åœ¨åˆ—è¡¨è§£æž„ä¸æ¥æ•获一个范围的值到å列表ä¸ã€‚è¿™åœ¨å½“ä½ æƒ³è¦ä»Žåˆ—表的开头和结尾æå–ç‰¹å®šå…ƒç´ ï¼ŒåŒæ—¶æ”¶é›†ä¸é—´çš„å…ƒç´ æ—¶éžå¸¸æœ‰ç”¨ã€‚ |
| 1429 | |||
| 1430 | ```moonscript | ||
| 1431 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1432 | [first, ...bulk, last] = orders | ||
| 1433 | print first -- 打å°: first | ||
| 1434 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
| 1435 | print last -- 打å°: last | ||
| 1436 | ``` | ||
| 1437 | <YueDisplay> | ||
| 1438 | <pre> | ||
| 1439 | orders = ["first", "second", "third", "fourth", "last"] | ||
| 1440 | [first, ...bulk, last] = orders | ||
| 1441 | print first -- 打å°: first | ||
| 1442 | print bulk -- 打å°: {"second", "third", "fourth"} | ||
| 1443 | print last -- 打å°: last | ||
| 1444 | </pre> | ||
| 1445 | </YueDisplay> | ||
| 1446 | |||
| 1447 | 展开è¿ç®—符å¯ä»¥ç”¨åœ¨ä¸åŒçš„ä½ç½®æ¥æ•获ä¸åŒçš„èŒƒå›´ï¼Œå¹¶ä¸”ä½ å¯ä»¥ä½¿ç”¨ `_` 作为å ä½ç¬¦æ¥è¡¨ç¤ºä½ 想跳过对应范围的æ•获: | ||
| 1448 | |||
| 1449 | ```moonscript | ||
| 1450 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
| 1451 | [first, ...rest] = orders | ||
| 1452 | |||
| 1453 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
| 1454 | [...start, last] = orders | ||
| 1455 | |||
| 1456 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
| 1457 | [first, ..._, last] = orders | ||
| 1458 | ``` | ||
| 1459 | <YueDisplay> | ||
| 1460 | <pre> | ||
| 1461 | -- æ•èŽ·ç¬¬ä¸€ä¸ªå…ƒç´ ä¹‹åŽçš„æ‰€æœ‰å…ƒç´ | ||
| 1462 | [first, ...rest] = orders | ||
| 1463 | |||
| 1464 | -- æ•获最åŽä¸€ä¸ªå…ƒç´ 之å‰çš„æ‰€æœ‰å…ƒç´ | ||
| 1465 | [...start, last] = orders | ||
| 1466 | |||
| 1467 | -- 跳过ä¸é—´çš„å…ƒç´ ï¼Œåªæ•获第一个和最åŽä¸€ä¸ªå…ƒç´ | ||
| 1468 | [first, ..._, last] = orders | ||
| 1469 | </pre> | ||
| 1470 | </YueDisplay> | ||
| 1471 | |||
| 1472 | ### 在其它地方的解构赋值 | ||
| 1473 | |||
| 1474 | 解构赋值也å¯ä»¥å‡ºçŽ°åœ¨å…¶å®ƒéšå¼è¿›è¡Œèµ‹å€¼çš„åœ°æ–¹ã€‚ä¸€ä¸ªä¾‹åæ˜¯ç”¨åœ¨ for 循环ä¸ï¼š | ||
| 1251 | 1475 | ||
| 1252 | ```moonscript | 1476 | ```moonscript |
| 1253 | tuples = [ | 1477 | tuples = [ |
| @@ -1270,7 +1494,7 @@ for [left, right] in *tuples | |||
| 1270 | </pre> | 1494 | </pre> |
| 1271 | </YueDisplay> | 1495 | </YueDisplay> |
| 1272 | 1496 | ||
| 1273 | æˆ‘ä»¬çŸ¥é“æ•°ç»„表ä¸çš„æ¯ä¸ªå…ƒç´ éƒ½æ˜¯ä¸€ä¸ªä¸¤é¡¹çš„å…ƒç»„ï¼Œæ‰€ä»¥æˆ‘ä»¬å¯ä»¥ç›´æŽ¥åœ¨forè¯å¥çš„åç§°åå¥ä¸ä½¿ç”¨è§£æž„æ¥è§£åŒ…它。 | 1497 | æˆ‘ä»¬çŸ¥é“æ•°ç»„表ä¸çš„æ¯ä¸ªå…ƒç´ éƒ½æ˜¯ä¸€ä¸ªä¸¤é¡¹çš„å…ƒç»„ï¼Œæ‰€ä»¥æˆ‘ä»¬å¯ä»¥ç›´æŽ¥åœ¨ for è¯å¥çš„åç§°åå¥ä¸ä½¿ç”¨è§£æž„æ¥è§£åŒ…它。 |
| 1274 | 1498 | ||
| 1275 | ## If 赋值 | 1499 | ## If 赋值 |
| 1276 | 1500 | ||
| @@ -1322,7 +1546,7 @@ print "好的" | |||
| 1322 | 1546 | ||
| 1323 | ### While 赋值 | 1547 | ### While 赋值 |
| 1324 | 1548 | ||
| 1325 | 您å¯ä»¥åœ¨ while 循环ä¸åŒæ ·ä½¿ç”¨èµ‹å€¼æ¥èŽ·å–循环æ¡ä»¶çš„值。 | 1549 | ä½ å¯ä»¥åœ¨ while 循环ä¸åŒæ ·ä½¿ç”¨èµ‹å€¼æ¥èŽ·å–循环æ¡ä»¶çš„值。 |
| 1326 | ```moonscript | 1550 | ```moonscript |
| 1327 | while byte := stream\read_one! | 1551 | while byte := stream\read_one! |
| 1328 | -- 对 byte åšä¸€äº›æ“作 | 1552 | -- 对 byte åšä¸€äº›æ“作 |
| @@ -1338,7 +1562,7 @@ while byte := stream\read_one! | |||
| 1338 | 1562 | ||
| 1339 | ## å¯å˜å‚数赋值 | 1563 | ## å¯å˜å‚数赋值 |
| 1340 | 1564 | ||
| 1341 | 您å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨Lua的方å¼è®¿é—®å…¶å†…容。 | 1565 | ä½ å¯ä»¥å°†å‡½æ•°è¿”回的结果赋值给一个å¯å˜å‚æ•°ç¬¦å· `...`。然åŽä½¿ç”¨ Lua 的方å¼è®¿é—®å…¶å†…容。 |
| 1342 | ```moonscript | 1566 | ```moonscript |
| 1343 | list = [1, 2, 3, 4, 5] | 1567 | list = [1, 2, 3, 4, 5] |
| 1344 | fn = (ok) -> ok, table.unpack list | 1568 | fn = (ok) -> ok, table.unpack list |
| @@ -1360,7 +1584,20 @@ print ok, count, first | |||
| 1360 | 1584 | ||
| 1361 | ## 空白 | 1585 | ## 空白 |
| 1362 | 1586 | ||
| 1363 | æœˆä¹‹è„šæœ¬æ˜¯ä¸€ä¸ªå¯¹ç©ºç™½æ•æ„Ÿçš„è¯è¨€ã€‚您必须在相åŒçš„缩进ä¸ä½¿ç”¨ç©ºæ ¼ **' '** 或制表符 **'\t'** æ¥ç¼–写一些代ç å—,如函数体ã€å€¼åˆ—表和一些控制å—。包å«ä¸åŒç©ºç™½çš„表达å¼å¯èƒ½æ„味ç€ä¸åŒçš„事情。制表符被视为4ä¸ªç©ºæ ¼ï¼Œä½†æœ€å¥½ä¸è¦æ··åˆä½¿ç”¨ç©ºæ ¼å’Œåˆ¶è¡¨ç¬¦ã€‚ | 1587 | æœˆä¹‹è„šæœ¬æ˜¯ä¸€ä¸ªå¯¹ç©ºç™½æ•æ„Ÿçš„è¯è¨€ã€‚ä½ å¿…é¡»åœ¨ç›¸åŒçš„缩进ä¸ä½¿ç”¨ç©ºæ ¼ **' '** 或制表符 **'\t'** æ¥ç¼–写一些代ç å—,如函数体ã€å€¼åˆ—表和一些控制å—。包å«ä¸åŒç©ºç™½çš„表达å¼å¯èƒ½æ„味ç€ä¸åŒçš„事情。制表符被视为4ä¸ªç©ºæ ¼ï¼Œä½†æœ€å¥½ä¸è¦æ··åˆä½¿ç”¨ç©ºæ ¼å’Œåˆ¶è¡¨ç¬¦ã€‚ |
| 1588 | |||
| 1589 | ### è¯å¥åˆ†éš”符 | ||
| 1590 | |||
| 1591 | 一æ¡è¯å¥é€šå¸¸ä»¥æ¢è¡Œç»“æŸã€‚ä½ ä¹Ÿå¯ä»¥ä½¿ç”¨åˆ†å· `;` 显å¼ç»“æŸä¸€æ¡è¯å¥ï¼Œä»Žè€Œåœ¨åŒä¸€è¡Œä¸ç¼–写多æ¡è¯å¥ï¼š | ||
| 1592 | |||
| 1593 | ```moonscript | ||
| 1594 | a = 1; b = 2; print a + b | ||
| 1595 | ``` | ||
| 1596 | <YueDisplay> | ||
| 1597 | <pre> | ||
| 1598 | a = 1; b = 2; print a + b | ||
| 1599 | </pre> | ||
| 1600 | </YueDisplay> | ||
| 1364 | 1601 | ||
| 1365 | ### 多行链å¼è°ƒç”¨ | 1602 | ### 多行链å¼è°ƒç”¨ |
| 1366 | 1603 | ||
| @@ -1415,7 +1652,7 @@ func --[[端å£]] 3000, --[[ip]] "192.168.1.1" | |||
| 1415 | 1652 | ||
| 1416 | ## é”™è¯¯å¤„ç† | 1653 | ## é”™è¯¯å¤„ç† |
| 1417 | 1654 | ||
| 1418 | 用于统一进行Lua错误处ç†çš„便æ·è¯æ³•。 | 1655 | 用于统一进行 Lua 错误处ç†çš„便æ·è¯æ³•。 |
| 1419 | 1656 | ||
| 1420 | ```moonscript | 1657 | ```moonscript |
| 1421 | try | 1658 | try |
| @@ -1474,9 +1711,50 @@ catch err | |||
| 1474 | </pre> | 1711 | </pre> |
| 1475 | </YueDisplay> | 1712 | </YueDisplay> |
| 1476 | 1713 | ||
| 1714 | ### 错误处ç†ç®€åŒ– | ||
| 1715 | |||
| 1716 | `try?` 是 `try` çš„åŠŸèƒ½ç®€åŒ–è¯æ³•,它ä¸å†è¿”回 `try` è¯å¥çš„布尔状æ€ï¼Œå¹¶åœ¨æˆåŠŸæ—¶ç›´æŽ¥è¿”å›ž `try` 代ç å—的结果,失败时返回 `nil` 值而éžé”™è¯¯å¯¹è±¡ã€‚ | ||
| 1717 | |||
| 1718 | ```moonscript | ||
| 1719 | a, b, c = try? func! | ||
| 1720 | |||
| 1721 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
| 1722 | a = (try? func!) ?? "default" | ||
| 1723 | |||
| 1724 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
| 1725 | f try? func! | ||
| 1726 | |||
| 1727 | -- 带 catch å—çš„ try! | ||
| 1728 | f try? | ||
| 1729 | print 123 | ||
| 1730 | func! | ||
| 1731 | catch e | ||
| 1732 | print e | ||
| 1733 | e | ||
| 1734 | ``` | ||
| 1735 | <YueDisplay> | ||
| 1736 | <pre> | ||
| 1737 | a, b, c = try? func! | ||
| 1738 | |||
| 1739 | -- 与空值åˆå¹¶è¿ç®—符一起使用 | ||
| 1740 | a = (try? func!) ?? "default" | ||
| 1741 | |||
| 1742 | -- ä½œä¸ºå‡½æ•°å‚æ•° | ||
| 1743 | f try? func! | ||
| 1744 | |||
| 1745 | -- 带 catch å—çš„ try! | ||
| 1746 | f try? | ||
| 1747 | print 123 | ||
| 1748 | func! | ||
| 1749 | catch e | ||
| 1750 | print e | ||
| 1751 | e | ||
| 1752 | </pre> | ||
| 1753 | </YueDisplay> | ||
| 1754 | |||
| 1477 | ## 属性 | 1755 | ## 属性 |
| 1478 | 1756 | ||
| 1479 | 月之脚本现在æä¾›äº†Lua 5.4新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的Luaç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ5.4æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const`å’Œ`close`çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 | 1757 | 月之脚本现在æä¾›äº† Lua 5.4 新增的å«åšå±žæ€§çš„è¯æ³•支æŒã€‚在月之脚本编译到的 Lua ç›®æ ‡ç‰ˆæœ¬ä½ŽäºŽ 5.4 æ—¶ï¼Œä½ ä»ç„¶å¯ä»¥åŒæ—¶ä½¿ç”¨`const` å’Œ `close` çš„å±žæ€§å£°æ˜Žè¯æ³•ï¼Œå¹¶èŽ·å¾—å¸¸é‡æ£€æŸ¥å’Œä½œç”¨åŸŸå›žè°ƒçš„功能。 |
| 1480 | 1758 | ||
| 1481 | ```moonscript | 1759 | ```moonscript |
| 1482 | const a = 123 | 1760 | const a = 123 |
| @@ -1502,11 +1780,24 @@ const {:a, :b, c, d} = tb | |||
| 1502 | </pre> | 1780 | </pre> |
| 1503 | </YueDisplay> | 1781 | </YueDisplay> |
| 1504 | 1782 | ||
| 1783 | ä½ ä¹Ÿå¯ä»¥å£°æ˜Žå…¨å±€å˜é‡ä¸ºå¸¸é‡ã€‚ | ||
| 1784 | |||
| 1785 | ```moonscript | ||
| 1786 | global const Constant = 123 | ||
| 1787 | -- Constant = 1 | ||
| 1788 | ``` | ||
| 1789 | <YueDisplay> | ||
| 1790 | <pre> | ||
| 1791 | global const Constant = 123 | ||
| 1792 | -- Constant = 1 | ||
| 1793 | </pre> | ||
| 1794 | </YueDisplay> | ||
| 1795 | |||
| 1505 | ## å—é¢é‡ | 1796 | ## å—é¢é‡ |
| 1506 | 1797 | ||
| 1507 | Luaä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和**nil**。 | 1798 | Lua ä¸çš„æ‰€æœ‰åŸºæœ¬å—é¢é‡éƒ½å¯ä»¥åœ¨æœˆä¹‹è„šæœ¬ä¸ä½¿ç”¨ã€‚包括数å—ã€å—符串ã€å¸ƒå°”值和 **nil**。 |
| 1508 | 1799 | ||
| 1509 | 但与Luaä¸åŒçš„æ˜¯ï¼Œå•引å·å’ŒåŒå¼•å·å—符串内部å…许有æ¢è¡Œï¼š | 1800 | 但与 Lua ä¸åŒçš„æ˜¯ï¼Œå•引å·å’ŒåŒå¼•å·å—符串内部å…许有æ¢è¡Œï¼š |
| 1510 | 1801 | ||
| 1511 | ```moonscript | 1802 | ```moonscript |
| 1512 | some_string = "这是一个å—符串 | 1803 | some_string = "这是一个å—符串 |
| @@ -1529,17 +1820,78 @@ print "我有#{math.random! * 100}%的把æ¡ã€‚" | |||
| 1529 | 1820 | ||
| 1530 | ### æ•°å—å—é¢é‡ | 1821 | ### æ•°å—å—é¢é‡ |
| 1531 | 1822 | ||
| 1532 | 您å¯ä»¥åœ¨æ•°å—å—é¢é‡ä¸ä½¿ç”¨ä¸‹åˆ’线æ¥å¢žåŠ å¯è¯»æ€§ã€‚ | 1823 | ä½ å¯ä»¥åœ¨æ•°å—å—é¢é‡ä¸ä½¿ç”¨ä¸‹åˆ’线æ¥å¢žåŠ å¯è¯»æ€§ã€‚ |
| 1533 | 1824 | ||
| 1534 | ```moonscript | 1825 | ```moonscript |
| 1535 | integer = 1_000_000 | 1826 | integer = 1_000_000 |
| 1536 | hex = 0xEF_BB_BF | 1827 | hex = 0xEF_BB_BF |
| 1828 | binary = 0B10011 | ||
| 1537 | ``` | 1829 | ``` |
| 1538 | <YueDisplay> | 1830 | <YueDisplay> |
| 1539 | 1831 | ||
| 1540 | <pre> | 1832 | <pre> |
| 1541 | integer = 1_000_000 | 1833 | integer = 1_000_000 |
| 1542 | hex = 0xEF_BB_BF | 1834 | hex = 0xEF_BB_BF |
| 1835 | binary = 0B10011 | ||
| 1836 | </pre> | ||
| 1837 | </YueDisplay> | ||
| 1838 | |||
| 1839 | ### YAML é£Žæ ¼å—符串 | ||
| 1840 | |||
| 1841 | 使用 `|` å‰ç¼€æ ‡è®°ä¸€ä¸ªå¤šè¡Œ YAML é£Žæ ¼å—符串: | ||
| 1842 | |||
| 1843 | ```moonscript | ||
| 1844 | str = | | ||
| 1845 | key: value | ||
| 1846 | list: | ||
| 1847 | - item1 | ||
| 1848 | - #{expr} | ||
| 1849 | ``` | ||
| 1850 | <YueDisplay> | ||
| 1851 | <pre> | ||
| 1852 | str = | | ||
| 1853 | key: value | ||
| 1854 | list: | ||
| 1855 | - item1 | ||
| 1856 | - #{expr} | ||
| 1857 | </pre> | ||
| 1858 | </YueDisplay> | ||
| 1859 | |||
| 1860 | 其效果类似于原生 Lua çš„å¤šè¡Œæ‹¼æŽ¥ï¼Œæ‰€æœ‰æ–‡æœ¬ï¼ˆå«æ¢è¡Œï¼‰å°†è¢«ä¿ç•™ä¸‹æ¥ï¼Œå¹¶æ”¯æŒ `#{...}` è¯æ³•,通过 `tostring(expr)` æ’入表达å¼ç»“果。 | ||
| 1861 | |||
| 1862 | YAML é£Žæ ¼çš„å¤šè¡Œå—ç¬¦ä¸²ä¼šè‡ªåŠ¨æ£€æµ‹é¦–è¡ŒåŽæœ€å°çš„公共缩进,并从所有行ä¸åˆ 除该å‰ç¼€ç©ºç™½å—ç¬¦ã€‚è¿™è®©ä½ å¯ä»¥åœ¨ä»£ç ä¸å¯¹é½æ–‡æœ¬ï¼Œä½†è¾“出å—符串ä¸ä¼šå¸¦å¤šä½™ç¼©è¿›ã€‚ | ||
| 1863 | |||
| 1864 | ```moonscript | ||
| 1865 | fn = -> | ||
| 1866 | str = | | ||
| 1867 | foo: | ||
| 1868 | bar: baz | ||
| 1869 | return str | ||
| 1870 | ``` | ||
| 1871 | <YueDisplay> | ||
| 1872 | <pre> | ||
| 1873 | fn = -> | ||
| 1874 | str = | | ||
| 1875 | foo: | ||
| 1876 | bar: baz | ||
| 1877 | return str | ||
| 1878 | </pre> | ||
| 1879 | </YueDisplay> | ||
| 1880 | |||
| 1881 | 输出å—符串ä¸çš„ foo: 对é½åˆ°è¡Œé¦–,ä¸ä¼šå¸¦æœ‰å‡½æ•°ç¼©è¿›ç©ºæ ¼ã€‚ä¿ç•™å†…部缩进的相对结构,适åˆä¹¦å†™ç»“æž„åŒ–åµŒå¥—æ ·å¼çš„内容。 | ||
| 1882 | |||
| 1883 | 支æŒè‡ªåЍ处ç†å—符ä¸çš„引å·ã€åæ–œæ ç‰ç‰¹æ®Šç¬¦å·ï¼Œæ— 需手动转义: | ||
| 1884 | |||
| 1885 | ```moonscript | ||
| 1886 | str = | | ||
| 1887 | path: "C:\Program Files\App" | ||
| 1888 | note: 'He said: "#{Hello}!"' | ||
| 1889 | ``` | ||
| 1890 | <YueDisplay> | ||
| 1891 | <pre> | ||
| 1892 | str = | | ||
| 1893 | path: "C:\Program Files\App" | ||
| 1894 | note: 'He said: "#{Hello}!"' | ||
| 1543 | </pre> | 1895 | </pre> |
| 1544 | </YueDisplay> | 1896 | </YueDisplay> |
| 1545 | 1897 | ||
| @@ -1644,7 +1996,7 @@ print "æ•°å—的和是", sum 10, 20 | |||
| 1644 | </pre> | 1996 | </pre> |
| 1645 | </YueDisplay> | 1997 | </YueDisplay> |
| 1646 | 1998 | ||
| 1647 | 如果您需è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨return关键å—: | 1999 | å¦‚æžœä½ éœ€è¦åšæ˜¾å¼è¿”回,å¯ä»¥ä½¿ç”¨ return 关键å—: |
| 1648 | 2000 | ||
| 1649 | ```moonscript | 2001 | ```moonscript |
| 1650 | sum = (x, y) -> return x + y | 2002 | sum = (x, y) -> return x + y |
| @@ -1670,7 +2022,7 @@ a, b = mystery 10, 20 | |||
| 1670 | 2022 | ||
| 1671 | ### ç²—ç®å¤´ | 2023 | ### ç²—ç®å¤´ |
| 1672 | 2024 | ||
| 1673 | å› ä¸ºåœ¨Luaä¸è°ƒç”¨æ–¹æ³•时,ç»å¸¸ä¹ æƒ¯å°†å¯¹è±¡ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 入,所以月之脚本æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥åˆ›å»ºè‡ªåŠ¨åŒ…å«self傿•°çš„函数。 | 2025 | å› ä¸ºåœ¨ Lua ä¸è°ƒç”¨æ–¹æ³•时,ç»å¸¸ä¹ æƒ¯å°†å¯¹è±¡ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 入,所以月之脚本æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥åˆ›å»ºè‡ªåŠ¨åŒ…å« self 傿•°çš„函数。 |
| 1674 | 2026 | ||
| 1675 | ```moonscript | 2027 | ```moonscript |
| 1676 | func = (num) => @value + num | 2028 | func = (num) => @value + num |
| @@ -1683,7 +2035,7 @@ func = (num) => @value + num | |||
| 1683 | 2035 | ||
| 1684 | ### 傿•°é»˜è®¤å€¼ | 2036 | ### 傿•°é»˜è®¤å€¼ |
| 1685 | 2037 | ||
| 1686 | å¯ä»¥ä¸ºå‡½æ•°çš„傿•°æä¾›é»˜è®¤å€¼ã€‚å¦‚æžœå‚æ•°çš„值为nilï¼Œåˆ™ç¡®å®šè¯¥å‚æ•°ä¸ºç©ºã€‚任何具有默认值的nil傿•°åœ¨å‡½æ•°ä½“è¿è¡Œä¹‹å‰éƒ½ä¼šè¢«æ›¿æ¢ã€‚ | 2038 | å¯ä»¥ä¸ºå‡½æ•°çš„傿•°æä¾›é»˜è®¤å€¼ã€‚å¦‚æžœå‚æ•°çš„值为 nilï¼Œåˆ™ç¡®å®šè¯¥å‚æ•°ä¸ºç©ºã€‚任何具有默认值的 nil 傿•°åœ¨å‡½æ•°ä½“è¿è¡Œä¹‹å‰éƒ½ä¼šè¢«æ›¿æ¢ã€‚ |
| 1687 | 2039 | ||
| 1688 | ```moonscript | 2040 | ```moonscript |
| 1689 | my_function = (name = "æŸç‰©", height = 100) -> | 2041 | my_function = (name = "æŸç‰©", height = 100) -> |
| @@ -1755,7 +2107,7 @@ my_func 5, 6, 7, | |||
| 1755 | </pre> | 2107 | </pre> |
| 1756 | </YueDisplay> | 2108 | </YueDisplay> |
| 1757 | 2109 | ||
| 1758 | å› ä¸ºLua表也使用逗å·ä½œä¸ºåˆ†éš”符,这ç§ç¼©è¿›è¯æ³•有助于让值æˆä¸ºå‚æ•°åˆ—è¡¨çš„ä¸€éƒ¨åˆ†ï¼Œè€Œä¸æ˜¯Lua表的一部分。 | 2110 | å› ä¸º Lua 表也使用逗å·ä½œä¸ºåˆ†éš”符,这ç§ç¼©è¿›è¯æ³•有助于让值æˆä¸ºå‚æ•°åˆ—è¡¨çš„ä¸€éƒ¨åˆ†ï¼Œè€Œä¸æ˜¯ Lua 表的一部分。 |
| 1759 | 2111 | ||
| 1760 | ```moonscript | 2112 | ```moonscript |
| 1761 | x = [ | 2113 | x = [ |
| @@ -1822,6 +2174,138 @@ if func 1, 2, 3, | |||
| 1822 | </pre> | 2174 | </pre> |
| 1823 | </YueDisplay> | 2175 | </YueDisplay> |
| 1824 | 2176 | ||
| 2177 | ### 傿•°è§£æž„ | ||
| 2178 | |||
| 2179 | 月之脚本支æŒåœ¨å‡½æ•°å½¢å‚ä½ç½®å¯¹ä¼ 入对象进行解构。适用两类解构表åé¢é‡ï¼š | ||
| 2180 | |||
| 2181 | - 使用 {} 包裹的å—é¢é‡/对象形å‚ï¼Œæ”¯æŒæä¾›èŽ·å¾—ç©ºå—æ®µæ—¶çš„默认值(例如 {:a, :b}ã€{a: a1 = 123})。 | ||
| 2182 | |||
| 2183 | - æ— {} 包裹ã€ä»¥é”®å€¼/简写键åºåˆ—开头,直至é‡åˆ°å…¶å®ƒè¡¨è¾¾å¼ç»ˆæ¢ï¼ˆä¾‹å¦‚ :a, b: b1, :c),表示从åŒä¸€ä¸ªå¯¹è±¡ä¸è§£æž„å¤šä¸ªå—æ®µã€‚ | ||
| 2184 | |||
| 2185 | ```moonscript | ||
| 2186 | f1 = (:a, :b, :c) -> | ||
| 2187 | print a, b, c | ||
| 2188 | |||
| 2189 | f1 a: 1, b: "2", c: {} | ||
| 2190 | |||
| 2191 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2192 | print a1, b, c | ||
| 2193 | |||
| 2194 | arg1 = {a: 0} | ||
| 2195 | f2 arg1, arg2 | ||
| 2196 | ``` | ||
| 2197 | <YueDisplay> | ||
| 2198 | <pre> | ||
| 2199 | f1 = (:a, :b, :c) -> | ||
| 2200 | print a, b, c | ||
| 2201 | |||
| 2202 | f1 a: 1, b: "2", c: {} | ||
| 2203 | |||
| 2204 | f2 = ({a: a1 = 123, :b = 'abc'}, c = {}) -> | ||
| 2205 | print a1, b, c | ||
| 2206 | |||
| 2207 | arg1 = {a: 0} | ||
| 2208 | f2 arg1, arg2 | ||
| 2209 | </pre> | ||
| 2210 | </YueDisplay> | ||
| 2211 | |||
| 2212 | ### å‰ç½®è¿”å›žè¡¨è¾¾å¼ | ||
| 2213 | |||
| 2214 | 在深度嵌套的函数体ä¸ï¼Œä¸ºäº†æå‡è¿”回值的å¯è¯»æ€§åŠç¼–写便利性,我们新增了 “å‰ç½®è¿”回表达å¼â€ è¯æ³•。其形å¼å¦‚下: | ||
| 2215 | |||
| 2216 | ```moon | ||
| 2217 | findFirstEven = (list): nil -> | ||
| 2218 | for item in *list | ||
| 2219 | if type(item) == "table" | ||
| 2220 | for sub in *item | ||
| 2221 | if sub % 2 == 0 | ||
| 2222 | return sub | ||
| 2223 | ``` | ||
| 2224 | <YueDisplay> | ||
| 2225 | <pre> | ||
| 2226 | findFirstEven = (list): nil -> | ||
| 2227 | for item in *list | ||
| 2228 | if type(item) == "table" | ||
| 2229 | for sub in *item | ||
| 2230 | if sub % 2 == 0 | ||
| 2231 | return sub | ||
| 2232 | </pre> | ||
| 2233 | </YueDisplay> | ||
| 2234 | |||
| 2235 | 这个写法ç‰ä»·äºŽï¼š | ||
| 2236 | |||
| 2237 | ```moon | ||
| 2238 | findFirstEven = (list) -> | ||
| 2239 | for item in *list | ||
| 2240 | if type(item) == "table" | ||
| 2241 | for sub in *item | ||
| 2242 | if sub % 2 == 0 | ||
| 2243 | return sub | ||
| 2244 | nil | ||
| 2245 | ``` | ||
| 2246 | <YueDisplay> | ||
| 2247 | <pre> | ||
| 2248 | findFirstEven = (list) -> | ||
| 2249 | for item in *list | ||
| 2250 | if type(item) == "table" | ||
| 2251 | for sub in *item | ||
| 2252 | if sub % 2 == 0 | ||
| 2253 | return sub | ||
| 2254 | nil | ||
| 2255 | </pre> | ||
| 2256 | </YueDisplay> | ||
| 2257 | |||
| 2258 | å”¯ä¸€çš„åŒºåˆ«åœ¨äºŽï¼šä½ å¯ä»¥å°†å‡½æ•°çš„è¿”å›žå€¼è¡¨è¾¾å¼æå‰å†™åœ¨ `->` 或 `=>` å‰ï¼Œç”¨ä»¥æŒ‡ç¤ºè¯¥å‡½æ•°åº”éšå¼è¿”回该表达å¼çš„å€¼ã€‚è¿™æ ·å³ä½¿åœ¨å¤šå±‚循环或æ¡ä»¶åˆ¤æ–çš„åœºæ™¯ä¸‹ï¼Œä¹Ÿæ— éœ€ç¼–å†™å°¾è¡Œæ‚¬æŒ‚çš„è¿”å›žè¡¨è¾¾å¼ï¼Œé€»è¾‘ç»“æž„ä¼šæ›´åŠ ç›´è§‚æ¸…æ™°ã€‚ | ||
| 2259 | |||
| 2260 | ### 命åå˜é•¿å‚æ•° | ||
| 2261 | |||
| 2262 | ä½ å¯ä»¥ä½¿ç”¨ `(...t) ->` è¯æ³•æ¥å°†å˜é•¿å‚数自动å˜å‚¨åˆ°ä¸€ä¸ªå‘½å表ä¸ã€‚è¿™ä¸ªè¡¨ä¼šåŒ…å«æ‰€æœ‰ä¼ å…¥çš„å‚æ•°ï¼ˆåŒ…括 `nil` 值),并且会在表的 `n` å—æ®µä¸å˜å‚¨å®žé™…ä¼ å…¥çš„å‚æ•°ä¸ªæ•°ï¼ˆåŒ…括 `nil` 值在内的个数)。 | ||
| 2263 | |||
| 2264 | ```moonscript | ||
| 2265 | f = (...t) -> | ||
| 2266 | print "傿•°ä¸ªæ•°:", t.n | ||
| 2267 | print "表长度:", #t | ||
| 2268 | for i = 1, t.n | ||
| 2269 | print t[i] | ||
| 2270 | |||
| 2271 | f 1, 2, 3 | ||
| 2272 | f "a", "b", "c", "d" | ||
| 2273 | f! | ||
| 2274 | |||
| 2275 | -- 处ç†åŒ…å« nil 的情况 | ||
| 2276 | process = (...args) -> | ||
| 2277 | sum = 0 | ||
| 2278 | for i = 1, args.n | ||
| 2279 | if args[i] != nil and type(args[i]) == "number" | ||
| 2280 | sum += args[i] | ||
| 2281 | sum | ||
| 2282 | |||
| 2283 | process 1, nil, 3, nil, 5 | ||
| 2284 | ``` | ||
| 2285 | <YueDisplay> | ||
| 2286 | <pre> | ||
| 2287 | f = (...t) -> | ||
| 2288 | print "傿•°ä¸ªæ•°:", t.n | ||
| 2289 | print "表长度:", #t | ||
| 2290 | for i = 1, t.n | ||
| 2291 | print t[i] | ||
| 2292 | |||
| 2293 | f 1, 2, 3 | ||
| 2294 | f "a", "b", "c", "d" | ||
| 2295 | f! | ||
| 2296 | |||
| 2297 | -- 处ç†åŒ…å« nil 的情况 | ||
| 2298 | process = (...args) -> | ||
| 2299 | sum = 0 | ||
| 2300 | for i = 1, args.n | ||
| 2301 | if args[i] != nil and type(args[i]) == "number" | ||
| 2302 | sum += args[i] | ||
| 2303 | sum | ||
| 2304 | |||
| 2305 | process 1, nil, 3, nil, 5 | ||
| 2306 | </pre> | ||
| 2307 | </YueDisplay> | ||
| 2308 | |||
| 1825 | ## åå‘回调 | 2309 | ## åå‘回调 |
| 1826 | 2310 | ||
| 1827 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ | 2311 | åå‘回调用于å‡å°‘函数回调的嵌套。它们使用指å‘左侧的ç®å¤´ï¼Œå¹¶ä¸”é»˜è®¤ä¼šè¢«å®šä¹‰ä¸ºä¼ å…¥åŽç»å‡½æ•°è°ƒç”¨çš„æœ€åŽä¸€ä¸ªå‚æ•°ã€‚å®ƒçš„è¯æ³•大部分与常规ç®å¤´å‡½æ•°ç›¸åŒï¼Œåªæ˜¯å®ƒæŒ‡å‘å¦ä¸€æ–¹å‘,并且åŽç»çš„函数体ä¸éœ€è¦è¿›è¡Œç¼©è¿›ã€‚ |
| @@ -1850,7 +2334,7 @@ print @value | |||
| 1850 | </pre> | 2334 | </pre> |
| 1851 | </YueDisplay> | 2335 | </YueDisplay> |
| 1852 | 2336 | ||
| 1853 | 您å¯ä»¥é€šè¿‡ä¸€ä¸ªå ä½ç¬¦æŒ‡å®šå›žè°ƒå‡½æ•°çš„ä¼ å‚ä½ç½®ã€‚ | 2337 | ä½ å¯ä»¥é€šè¿‡ä¸€ä¸ªå ä½ç¬¦æŒ‡å®šå›žè°ƒå‡½æ•°çš„ä¼ å‚ä½ç½®ã€‚ |
| 1854 | 2338 | ||
| 1855 | ```moonscript | 2339 | ```moonscript |
| 1856 | (x) <- map _, [1, 2, 3] | 2340 | (x) <- map _, [1, 2, 3] |
| @@ -1863,22 +2347,22 @@ x * 2 | |||
| 1863 | </pre> | 2347 | </pre> |
| 1864 | </YueDisplay> | 2348 | </YueDisplay> |
| 1865 | 2349 | ||
| 1866 | 如果您希望在åå‘回调处ç†åŽç»§ç»ç¼–写更多其它的代ç ,您å¯ä»¥ä½¿ç”¨doè¯å¥å°†ä¸å½’属åå‘回调的代ç 分开。 | 2350 | å¦‚æžœä½ å¸Œæœ›åœ¨åå‘回调处ç†åŽç»§ç»ç¼–写更多其它的代ç ,å¯ä»¥ä½¿ç”¨ do è¯å¥å°†ä¸å±žäºŽåå‘回调的代ç 分隔开。对于éžç²—ç®å¤´å‡½æ•°çš„åå‘回调,回调返回值的括å·ä¹Ÿæ˜¯å¯ä»¥çœç•¥çš„。 |
| 1867 | 2351 | ||
| 1868 | ```moonscript | 2352 | ```moonscript |
| 1869 | result, msg = do | 2353 | result, msg = do |
| 1870 | (data) <- readAsync "文件å.txt" | 2354 | data <- readAsync "文件å.txt" |
| 1871 | print data | 2355 | print data |
| 1872 | (info) <- processAsync data | 2356 | info <- processAsync data |
| 1873 | check info | 2357 | check info |
| 1874 | print result, msg | 2358 | print result, msg |
| 1875 | ``` | 2359 | ``` |
| 1876 | <YueDisplay> | 2360 | <YueDisplay> |
| 1877 | <pre> | 2361 | <pre> |
| 1878 | result, msg = do | 2362 | result, msg = do |
| 1879 | (data) <- readAsync "文件å.txt" | 2363 | data <- readAsync "文件å.txt" |
| 1880 | print data | 2364 | print data |
| 1881 | (info) <- processAsync data | 2365 | info <- processAsync data |
| 1882 | check info | 2366 | check info |
| 1883 | print result, msg | 2367 | print result, msg |
| 1884 | </pre> | 2368 | </pre> |
| @@ -1886,7 +2370,7 @@ print result, msg | |||
| 1886 | 2370 | ||
| 1887 | ## è¡¨æ ¼å—é¢é‡ | 2371 | ## è¡¨æ ¼å—é¢é‡ |
| 1888 | 2372 | ||
| 1889 | å’ŒLuaä¸€æ ·ï¼Œè¡¨æ ¼å¯ä»¥é€šè¿‡èŠ±æ‹¬å·è¿›è¡Œå®šä¹‰ã€‚ | 2373 | å’Œ Lua ä¸€æ ·ï¼Œè¡¨æ ¼å¯ä»¥é€šè¿‡èŠ±æ‹¬å·è¿›è¡Œå®šä¹‰ã€‚ |
| 1890 | 2374 | ||
| 1891 | ```moonscript | 2375 | ```moonscript |
| 1892 | some_values = [1, 2, 3, 4] | 2376 | some_values = [1, 2, 3, 4] |
| @@ -1969,7 +2453,7 @@ y = type: "ç‹—", legs: 4, tails: 1 | |||
| 1969 | </pre> | 2453 | </pre> |
| 1970 | </YueDisplay> | 2454 | </YueDisplay> |
| 1971 | 2455 | ||
| 1972 | è¡¨æ ¼å—é¢é‡çš„é”®å¯ä»¥ä½¿ç”¨Luaè¯è¨€çš„关键å—ï¼Œè€Œæ— éœ€è½¬ä¹‰ï¼š | 2456 | è¡¨æ ¼å—é¢é‡çš„é”®å¯ä»¥ä½¿ç”¨ Lua è¯è¨€çš„关键å—ï¼Œè€Œæ— éœ€è½¬ä¹‰ï¼š |
| 1973 | 2457 | ||
| 1974 | ```moonscript | 2458 | ```moonscript |
| 1975 | tbl = { | 2459 | tbl = { |
| @@ -2005,7 +2489,7 @@ print_table :hair, :height | |||
| 2005 | </pre> | 2489 | </pre> |
| 2006 | </YueDisplay> | 2490 | </YueDisplay> |
| 2007 | 2491 | ||
| 2008 | å¦‚æžœä½ å¸Œæœ›è¡¨ä¸å—段的键是æŸä¸ªè¡¨è¾¾å¼çš„结果,那么å¯ä»¥ç”¨ **[ ]** 包裹它,就åƒåœ¨Luaä¸ä¸€æ ·ã€‚å¦‚æžœé”®ä¸æœ‰ä»»ä½•特殊å—符,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨å—符串å—é¢é‡ä½œä¸ºé”®ï¼Œçœç•¥æ–¹æ‹¬å·ã€‚ | 2492 | å¦‚æžœä½ å¸Œæœ›è¡¨ä¸å—段的键是æŸä¸ªè¡¨è¾¾å¼çš„结果,那么å¯ä»¥ç”¨ **[ ]** 包裹它,就åƒåœ¨ Lua ä¸ä¸€æ ·ã€‚å¦‚æžœé”®ä¸æœ‰ä»»ä½•特殊å—符,也å¯ä»¥ç›´æŽ¥ä½¿ç”¨å—符串å—é¢é‡ä½œä¸ºé”®ï¼Œçœç•¥æ–¹æ‹¬å·ã€‚ |
| 2009 | 2493 | ||
| 2010 | ```moonscript | 2494 | ```moonscript |
| 2011 | t = { | 2495 | t = { |
| @@ -2022,7 +2506,7 @@ t = { | |||
| 2022 | </pre> | 2506 | </pre> |
| 2023 | </YueDisplay> | 2507 | </YueDisplay> |
| 2024 | 2508 | ||
| 2025 | Luaçš„è¡¨åŒæ—¶å…·æœ‰æ•°ç»„éƒ¨åˆ†å’Œå“ˆå¸Œéƒ¨åˆ†ï¼Œä½†æœ‰æ—¶å€™ä½ ä¼šå¸Œæœ›åœ¨ä¹¦å†™Lua表时,对Luaè¡¨åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„è¯ä¹‰åŒºåˆ†ã€‚ç„¶åŽä½ å¯ä»¥ç”¨ **[ ]** è€Œä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表ä¸å†™å…¥ä»»ä½•键值对。 | 2509 | Lua çš„è¡¨åŒæ—¶å…·æœ‰æ•°ç»„éƒ¨åˆ†å’Œå“ˆå¸Œéƒ¨åˆ†ï¼Œä½†æœ‰æ—¶å€™ä½ ä¼šå¸Œæœ›åœ¨ä¹¦å†™ Lua 表时,对 Lua è¡¨åšæ•°ç»„和哈希ä¸åŒç”¨æ³•çš„è¯ä¹‰åŒºåˆ†ã€‚ç„¶åŽä½ å¯ä»¥ç”¨ **[ ]** è€Œä¸æ˜¯ **{ }** æ¥ç¼–写表示数组的 Lua 表,并且ä¸å…许在数组 Lua 表ä¸å†™å…¥ä»»ä½•键值对。 |
| 2026 | 2510 | ||
| 2027 | ```moonscript | 2511 | ```moonscript |
| 2028 | some_values = [ 1, 2, 3, 4 ] | 2512 | some_values = [ 1, 2, 3, 4 ] |
| @@ -2037,11 +2521,11 @@ list_with_one_element = [ 1, ] | |||
| 2037 | 2521 | ||
| 2038 | ## æŽ¨å¯¼å¼ | 2522 | ## æŽ¨å¯¼å¼ |
| 2039 | 2523 | ||
| 2040 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生Luaè¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸æ‚¨åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ | 2524 | 推导å¼ä¸ºæˆ‘们æä¾›äº†ä¸€ç§ä¾¿æ·çš„è¯æ³•,通过éåŽ†çŽ°æœ‰å¯¹è±¡å¹¶å¯¹å…¶å€¼åº”ç”¨è¡¨è¾¾å¼æ¥æž„é€ å‡ºæ–°çš„è¡¨æ ¼ã€‚æœˆä¹‹è„šæœ¬æœ‰ä¸¤ç§æŽ¨å¯¼å¼ï¼šåˆ—表推导å¼å’Œè¡¨æ ¼æŽ¨å¯¼å¼ã€‚它们最终都是产生 Lua è¡¨æ ¼ï¼›åˆ—è¡¨æŽ¨å¯¼å¼å°†å€¼ç´¯ç§¯åˆ°ç±»ä¼¼æ•°ç»„çš„è¡¨æ ¼ä¸ï¼Œè€Œè¡¨æ ¼æŽ¨å¯¼å¼å…è®¸ä½ åœ¨æ¯æ¬¡éåŽ†æ—¶è®¾ç½®æ–°è¡¨æ ¼çš„é”®å’Œå€¼ã€‚ |
| 2041 | 2525 | ||
| 2042 | ### åˆ—è¡¨æŽ¨å¯¼å¼ | 2526 | ### åˆ—è¡¨æŽ¨å¯¼å¼ |
| 2043 | 2527 | ||
| 2044 | 以下æ“作创建了一个items表的副本,但所有包å«çš„值都翻å€äº†ã€‚ | 2528 | 以下æ“作创建了一个 items 表的副本,但所有包å«çš„值都翻å€äº†ã€‚ |
| 2045 | 2529 | ||
| 2046 | ```moonscript | 2530 | ```moonscript |
| 2047 | items = [1, 2, 3, 4] | 2531 | items = [1, 2, 3, 4] |
| @@ -2054,7 +2538,7 @@ doubled = [item * 2 for i, item in ipairs items] | |||
| 2054 | </pre> | 2538 | </pre> |
| 2055 | </YueDisplay> | 2539 | </YueDisplay> |
| 2056 | 2540 | ||
| 2057 | å¯ä»¥ä½¿ç”¨whenåå¥ç›é€‰æ–°è¡¨ä¸åŒ…å«çš„项目: | 2541 | å¯ä»¥ä½¿ç”¨ `when` åå¥ç›é€‰æ–°è¡¨ä¸åŒ…å«çš„项目: |
| 2058 | 2542 | ||
| 2059 | ```moonscript | 2543 | ```moonscript |
| 2060 | slice = [item for i, item in ipairs items when i > 1 and i < 3] | 2544 | slice = [item for i, item in ipairs items when i > 1 and i < 3] |
| @@ -2065,7 +2549,7 @@ slice = [item for i, item in ipairs items when i > 1 and i < 3] | |||
| 2065 | </pre> | 2549 | </pre> |
| 2066 | </YueDisplay> | 2550 | </YueDisplay> |
| 2067 | 2551 | ||
| 2068 | å› ä¸ºæˆ‘ä»¬å¸¸å¸¸éœ€è¦è¿ä»£æ•°å€¼ç´¢å¼•表的值,所以引入了 **\*** æ“作符æ¥åšè¯æ³•简化。doubled示例å¯ä»¥é‡å†™ä¸ºï¼š | 2552 | å› ä¸ºæˆ‘ä»¬å¸¸å¸¸éœ€è¦è¿ä»£æ•°å€¼ç´¢å¼•表的值,所以引入了 **\*** æ“作符æ¥åšè¯æ³•简化。doubled 示例å¯ä»¥é‡å†™ä¸ºï¼š |
| 2069 | 2553 | ||
| 2070 | ```moonscript | 2554 | ```moonscript |
| 2071 | doubled = [item * 2 for item in *items] | 2555 | doubled = [item * 2 for item in *items] |
| @@ -2076,9 +2560,30 @@ doubled = [item * 2 for item in *items] | |||
| 2076 | </pre> | 2560 | </pre> |
| 2077 | </YueDisplay> | 2561 | </YueDisplay> |
| 2078 | 2562 | ||
| 2079 | forå’Œwhenåå¥å¯ä»¥æ ¹æ®éœ€è¦è¿›è¡Œé“¾å¼æ“ä½œã€‚å”¯ä¸€çš„è¦æ±‚是推导å¼ä¸è‡³å°‘è¦æœ‰ä¸€ä¸ªforåå¥ã€‚ | 2563 | 在列表推导å¼ä¸ï¼Œä½ 还å¯ä»¥ä½¿ç”¨å±•å¼€æ“作符 `...` æ¥å®žçŽ°å¯¹åˆ—è¡¨åµŒå¥—å±‚çº§è¿›è¡Œæ‰å¹³åŒ–的处ç†ï¼š |
| 2564 | |||
| 2565 | ```moonscript | ||
| 2566 | data = | ||
| 2567 | a: [1, 2, 3] | ||
| 2568 | b: [4, 5, 6] | ||
| 2569 | |||
| 2570 | flat = [...v for k,v in pairs data] | ||
| 2571 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2572 | ``` | ||
| 2573 | <YueDisplay> | ||
| 2574 | <pre> | ||
| 2575 | data = | ||
| 2576 | a: [1, 2, 3] | ||
| 2577 | b: [4, 5, 6] | ||
| 2578 | |||
| 2579 | flat = [...v for k,v in pairs data] | ||
| 2580 | -- flat 现在为 [1, 2, 3, 4, 5, 6] | ||
| 2581 | </pre> | ||
| 2582 | </YueDisplay> | ||
| 2583 | |||
| 2584 | for å’Œ when åå¥å¯ä»¥æ ¹æ®éœ€è¦è¿›è¡Œé“¾å¼æ“ä½œã€‚å”¯ä¸€çš„è¦æ±‚是推导å¼ä¸è‡³å°‘è¦æœ‰ä¸€ä¸ª for åå¥ã€‚ | ||
| 2080 | 2585 | ||
| 2081 | 使用多个foråå¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„æ•ˆæžœç›¸åŒï¼š | 2586 | 使用多个 for åå¥ä¸Žä½¿ç”¨å¤šé‡å¾ªçŽ¯çš„æ•ˆæžœç›¸åŒï¼š |
| 2082 | 2587 | ||
| 2083 | ```moonscript | 2588 | ```moonscript |
| 2084 | x_coords = [4, 5, 6, 7] | 2589 | x_coords = [4, 5, 6, 7] |
| @@ -2097,7 +2602,7 @@ for y in *y_coords] | |||
| 2097 | </pre> | 2602 | </pre> |
| 2098 | </YueDisplay> | 2603 | </YueDisplay> |
| 2099 | 2604 | ||
| 2100 | 在推导å¼ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨ç®€å•的数值for循环: | 2605 | 在推导å¼ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨ç®€å•的数值 for 循环: |
| 2101 | 2606 | ||
| 2102 | ```moonscript | 2607 | ```moonscript |
| 2103 | evens = [i for i = 1, 100 when i % 2 == 0] | 2608 | evens = [i for i = 1, 100 when i % 2 == 0] |
| @@ -2112,7 +2617,7 @@ evens = [i for i = 1, 100 when i % 2 == 0] | |||
| 2112 | 2617 | ||
| 2113 | è¡¨æ ¼æŽ¨å¯¼å¼å’Œåˆ—表推导å¼çš„è¯æ³•éžå¸¸ç›¸ä¼¼ï¼Œåªæ˜¯è¦ä½¿ç”¨ **{** å’Œ **}** å¹¶ä»Žæ¯æ¬¡è¿ä»£ä¸å–两个值。 | 2618 | è¡¨æ ¼æŽ¨å¯¼å¼å’Œåˆ—表推导å¼çš„è¯æ³•éžå¸¸ç›¸ä¼¼ï¼Œåªæ˜¯è¦ä½¿ç”¨ **{** å’Œ **}** å¹¶ä»Žæ¯æ¬¡è¿ä»£ä¸å–两个值。 |
| 2114 | 2619 | ||
| 2115 | 以下示例生æˆäº†è¡¨æ ¼thing的副本: | 2620 | 以下示例生æˆäº†è¡¨æ ¼ thing 的副本: |
| 2116 | 2621 | ||
| 2117 | ```moonscript | 2622 | ```moonscript |
| 2118 | thing = { | 2623 | thing = { |
| @@ -2174,9 +2679,9 @@ tbl = {unpack tuple for tuple in *tuples} | |||
| 2174 | 2679 | ||
| 2175 | ### 切片 | 2680 | ### 切片 |
| 2176 | 2681 | ||
| 2177 | 当使用 **\*** æ“作符时,月之脚本还æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥é™åˆ¶è¦éåŽ†çš„åˆ—è¡¨èŒƒå›´ã€‚è¿™ä¸ªè¯æ³•也相当于在for循环ä¸è®¾ç½®è¿ä»£è¾¹ç•Œå’Œæ¥é•¿ã€‚ | 2682 | 当使用 **\*** æ“作符时,月之脚本还æä¾›äº†ä¸€ç§ç‰¹æ®Šçš„è¯æ³•æ¥é™åˆ¶è¦éåŽ†çš„åˆ—è¡¨èŒƒå›´ã€‚è¿™ä¸ªè¯æ³•也相当于在 for 循环ä¸è®¾ç½®è¿ä»£è¾¹ç•Œå’Œæ¥é•¿ã€‚ |
| 2178 | 2683 | ||
| 2179 | 下é¢çš„æ¡ˆä¾‹ä¸ï¼Œæˆ‘们在切片ä¸è®¾ç½®æœ€å°å’Œæœ€å¤§è¾¹ç•Œï¼Œå–索引在1到5之间(包括1å’Œ5)的所有项目: | 2684 | 下é¢çš„æ¡ˆä¾‹ä¸ï¼Œæˆ‘们在切片ä¸è®¾ç½®æœ€å°å’Œæœ€å¤§è¾¹ç•Œï¼Œå–索引在 1 到 5 之间(包括 1 å’Œ 5)的所有项目: |
| 2180 | 2685 | ||
| 2181 | ```moonscript | 2686 | ```moonscript |
| 2182 | slice = [item for item in *items[1, 5]] | 2687 | slice = [item for item in *items[1, 5]] |
| @@ -2198,7 +2703,7 @@ slice = [item for item in *items[2,]] | |||
| 2198 | </pre> | 2703 | </pre> |
| 2199 | </YueDisplay> | 2704 | </YueDisplay> |
| 2200 | 2705 | ||
| 2201 | 如果çœç•¥äº†æœ€å°è¾¹ç•Œï¼Œä¾¿é»˜è®¤ä¼šè®¾ç½®ä¸º1ã€‚è¿™é‡Œæˆ‘ä»¬åªæä¾›ä¸€ä¸ªæ¥é•¿ï¼Œå¹¶ç•™ä¸‹å…¶ä»–è¾¹ç•Œä¸ºç©ºã€‚è¿™æ ·ä¼šä½¿å¾—ä»£ç å–出所有奇数索引的项目:(1, 3, 5, …) | 2706 | 如果çœç•¥äº†æœ€å°è¾¹ç•Œï¼Œä¾¿é»˜è®¤ä¼šè®¾ç½®ä¸º 1ã€‚è¿™é‡Œæˆ‘ä»¬åªæä¾›ä¸€ä¸ªæ¥é•¿ï¼Œå¹¶ç•™ä¸‹å…¶ä»–è¾¹ç•Œä¸ºç©ºã€‚è¿™æ ·ä¼šä½¿å¾—ä»£ç å–出所有奇数索引的项目:(1, 3, 5, …) |
| 2202 | 2707 | ||
| 2203 | ```moonscript | 2708 | ```moonscript |
| 2204 | slice = [item for item in *items[,,2]] | 2709 | slice = [item for item in *items[,,2]] |
| @@ -2210,9 +2715,48 @@ slice = [item for item in *items[,,2]] | |||
| 2210 | </pre> | 2715 | </pre> |
| 2211 | </YueDisplay> | 2716 | </YueDisplay> |
| 2212 | 2717 | ||
| 2718 | 最å°å’Œæœ€å¤§è¾¹ç•Œéƒ½å¯ä»¥æ˜¯è´Ÿæ•°ï¼Œä½¿ç”¨è´Ÿæ•°æ„味ç€è¾¹ç•Œæ˜¯ä»Žè¡¨çš„æœ«å°¾å¼€å§‹è®¡ç®—的。 | ||
| 2719 | |||
| 2720 | ```moonscript | ||
| 2721 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
| 2722 | slice = [item for item in *items[-4,-1]] | ||
| 2723 | ``` | ||
| 2724 | <YueDisplay> | ||
| 2725 | <pre> | ||
| 2726 | -- å–æœ€åŽ4ä¸ªå…ƒç´ | ||
| 2727 | slice = [item for item in *items[-4,-1]] | ||
| 2728 | </pre> | ||
| 2729 | </YueDisplay> | ||
| 2730 | |||
| 2731 | 切片的æ¥é•¿ä¹Ÿå¯ä»¥æ˜¯è´Ÿæ•°ï¼Œè¿™æ„味ç€å…ƒç´ 会以相å的顺åºè¢«å–出。 | ||
| 2732 | |||
| 2733 | ```moonscript | ||
| 2734 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2735 | ``` | ||
| 2736 | <YueDisplay> | ||
| 2737 | <pre> | ||
| 2738 | reverse_slice = [item for item in *items[-1,1,-1]] | ||
| 2739 | </pre> | ||
| 2740 | </YueDisplay> | ||
| 2741 | |||
| 2742 | #### åˆ‡ç‰‡è¡¨è¾¾å¼ | ||
| 2743 | |||
| 2744 | 切片也å¯ä»¥ä½œä¸ºè¡¨è¾¾å¼æ¥ä½¿ç”¨ã€‚å¯ä»¥ç”¨äºŽèŽ·å–一个表包å«çš„å列表。 | ||
| 2745 | |||
| 2746 | ```moonscript | ||
| 2747 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
| 2748 | sub_list = items[2, 4] | ||
| 2749 | ``` | ||
| 2750 | <YueDisplay> | ||
| 2751 | <pre> | ||
| 2752 | -- å–第2和第4ä¸ªå…ƒç´ ä½œä¸ºæ–°çš„åˆ—è¡¨ | ||
| 2753 | sub_list = items[2, 4] | ||
| 2754 | </pre> | ||
| 2755 | </YueDisplay> | ||
| 2756 | |||
| 2213 | ## for 循环 | 2757 | ## for 循环 |
| 2214 | 2758 | ||
| 2215 | Lua䏿œ‰ä¸¤ç§for循环形å¼ï¼Œæ•°å—型和通用型: | 2759 | Lua 䏿œ‰ä¸¤ç§ for 循环形å¼ï¼Œæ•°å—型和通用型: |
| 2216 | 2760 | ||
| 2217 | ```moonscript | 2761 | ```moonscript |
| 2218 | for i = 10, 20 | 2762 | for i = 10, 20 |
| @@ -2265,7 +2809,7 @@ for j = 1, 10, 3 do print j | |||
| 2265 | </pre> | 2809 | </pre> |
| 2266 | </YueDisplay> | 2810 | </YueDisplay> |
| 2267 | 2811 | ||
| 2268 | for循环也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚for循环主体ä¸çš„æœ€åŽä¸€æ¡è¯å¥ä¼šè¢«å¼ºåˆ¶è½¬æ¢ä¸ºä¸€ä¸ªè¿”回值的表达å¼ï¼Œå¹¶ä¼šå°†è¡¨è¾¾å¼è®¡ç®—ç»“æžœçš„å€¼è¿½åŠ åˆ°ä¸€ä¸ªä½œä¸ºç»“æžœçš„æ•°ç»„è¡¨ä¸ã€‚ | 2812 | for 循环也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚for 循环主体ä¸çš„æœ€åŽä¸€æ¡è¯å¥ä¼šè¢«å¼ºåˆ¶è½¬æ¢ä¸ºä¸€ä¸ªè¿”回值的表达å¼ï¼Œå¹¶ä¼šå°†è¡¨è¾¾å¼è®¡ç®—ç»“æžœçš„å€¼è¿½åŠ åˆ°ä¸€ä¸ªä½œä¸ºç»“æžœçš„æ•°ç»„è¡¨ä¸ã€‚ |
| 2269 | 2813 | ||
| 2270 | å°†æ¯ä¸ªå¶æ•°åŠ å€ï¼š | 2814 | å°†æ¯ä¸ªå¶æ•°åŠ å€ï¼š |
| 2271 | 2815 | ||
| @@ -2286,9 +2830,24 @@ doubled_evens = for i = 1, 20 | |||
| 2286 | </pre> | 2830 | </pre> |
| 2287 | </YueDisplay> | 2831 | </YueDisplay> |
| 2288 | 2832 | ||
| 2289 | 您还å¯ä»¥ç»“åˆfor循环表达å¼ä¸Žcontinueè¯å¥æ¥è¿‡æ»¤å€¼ã€‚ | 2833 | æ¤å¤–,for 循环还支æŒå¸¦è¿”回值的 break è¯å¥ï¼Œè¿™æ ·å¾ªçŽ¯æœ¬èº«å°±å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œåœ¨æ»¡è¶³æ¡ä»¶æ—¶æå‰é€€å‡ºå¹¶è¿”回有æ„义的结果。 |
| 2834 | |||
| 2835 | 例如,查找第一个大于 10 的数å—: | ||
| 2836 | |||
| 2837 | ```moonscript | ||
| 2838 | first_large = for n in *numbers | ||
| 2839 | break n if n > 10 | ||
| 2840 | ``` | ||
| 2841 | <YueDisplay> | ||
| 2842 | <pre> | ||
| 2843 | first_large = for n in *numbers | ||
| 2844 | break n if n > 10 | ||
| 2845 | </pre> | ||
| 2846 | </YueDisplay> | ||
| 2847 | |||
| 2848 | ä½ è¿˜å¯ä»¥ç»“åˆ for 循环表达å¼ä¸Ž continue è¯å¥æ¥è¿‡æ»¤å€¼ã€‚ | ||
| 2290 | 2849 | ||
| 2291 | 注æ„出现在函数体末尾的for循环,ä¸ä¼šè¢«å½“作是一个表达å¼ï¼Œå¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥ä½¿ç”¨è¿”回è¯å¥åŠ for循环表达å¼ã€‚ | 2850 | 注æ„出现在函数体末尾的 for 循环,ä¸ä¼šè¢«å½“作是一个表达å¼å¹¶å°†å¾ªçŽ¯ç»“æžœç´¯ç§¯åˆ°ä¸€ä¸ªåˆ—è¡¨ä¸ä½œä¸ºè¿”回值(相å,函数将返回 nil)。如果è¦å‡½æ•°æœ«å°¾çš„循环转æ¢ä¸ºåˆ—表表达å¼ï¼Œå¯ä»¥æ˜¾å¼åœ°ä½¿ç”¨è¿”回è¯å¥åŠ for 循环表达å¼ã€‚ |
| 2292 | 2851 | ||
| 2293 | ```moonscript | 2852 | ```moonscript |
| 2294 | func_a = -> for i = 1, 10 do print i | 2853 | func_a = -> for i = 1, 10 do print i |
| @@ -2311,7 +2870,7 @@ print func_b! -- æ‰“å° table 对象 | |||
| 2311 | 2870 | ||
| 2312 | ## repeat 循环 | 2871 | ## repeat 循环 |
| 2313 | 2872 | ||
| 2314 | repeat循环是从Luaè¯è¨€ä¸æ¬è¿‡æ¥çš„ç›¸ä¼¼è¯æ³•: | 2873 | repeat 循环是从 Lua è¯è¨€ä¸æ¬è¿‡æ¥çš„ç›¸ä¼¼è¯æ³•: |
| 2315 | 2874 | ||
| 2316 | ```moonscript | 2875 | ```moonscript |
| 2317 | i = 10 | 2876 | i = 10 |
| @@ -2332,7 +2891,7 @@ until i == 0 | |||
| 2332 | 2891 | ||
| 2333 | ## while 循环 | 2892 | ## while 循环 |
| 2334 | 2893 | ||
| 2335 | 在月之脚本ä¸çš„while循环有四ç§å†™æ³•: | 2894 | 在月之脚本ä¸çš„ while 循环有四ç§å†™æ³•: |
| 2336 | 2895 | ||
| 2337 | ```moonscript | 2896 | ```moonscript |
| 2338 | i = 10 | 2897 | i = 10 |
| @@ -2371,7 +2930,7 @@ until running == false do my_function! | |||
| 2371 | </pre> | 2930 | </pre> |
| 2372 | </YueDisplay> | 2931 | </YueDisplay> |
| 2373 | 2932 | ||
| 2374 | åƒforå¾ªçŽ¯çš„è¯æ³•ä¸€æ ·ï¼Œwhile循环也å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ä½¿ç”¨ã€‚为了使函数返回while循环的累积列表值,必须明确使用返回è¯å¥è¿”回while循环表达å¼ã€‚ | 2933 | åƒ for å¾ªçŽ¯çš„è¯æ³•ä¸€æ ·ï¼Œwhile 循环也å¯ä»¥ä½œä¸ºä¸€ä¸ªè¡¨è¾¾å¼ä½¿ç”¨ã€‚为了使函数返回 while 循环的累积列表值,必须明确使用返回è¯å¥è¿”回 while 循环表达å¼ã€‚ |
| 2375 | 2934 | ||
| 2376 | ## ç»§ç» | 2935 | ## ç»§ç» |
| 2377 | 2936 | ||
| @@ -2489,13 +3048,14 @@ print message -- 打å°: 我很高 | |||
| 2489 | </pre> | 3048 | </pre> |
| 2490 | </YueDisplay> | 3049 | </YueDisplay> |
| 2491 | 3050 | ||
| 2492 | ifçš„åä¹‰è¯æ˜¯unless(相当于if not,如果 vs 除éžï¼‰ï¼š | 3051 | if çš„åä¹‰è¯æ˜¯ unless(相当于 if not,æ£å¦‚“如果â€å¯¹åº”“除éžâ€ï¼‰ï¼š |
| 2493 | 3052 | ||
| 2494 | ```moonscript | 3053 | ```moonscript |
| 2495 | unless os.date("%A") == "Monday" | 3054 | unless os.date("%A") == "Monday" |
| 2496 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" | 3055 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" |
| 2497 | ``` | 3056 | ``` |
| 2498 | <YueDisplay> | 3057 | <YueDisplay> |
| 3058 | |||
| 2499 | <pre> | 3059 | <pre> |
| 2500 | unless os.date("%A") == "Monday" | 3060 | unless os.date("%A") == "Monday" |
| 2501 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" | 3061 | print "ä»Šå¤©ä¸æ˜¯æ˜ŸæœŸä¸€ï¼" |
| @@ -2513,7 +3073,7 @@ print "ä½ çœŸå¹¸è¿ï¼" unless math.random! > 0.1 | |||
| 2513 | 3073 | ||
| 2514 | ### èŒƒå›´è¡¨è¾¾å¼ | 3074 | ### èŒƒå›´è¡¨è¾¾å¼ |
| 2515 | 3075 | ||
| 2516 | 您å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行范围检查的代ç 。 | 3076 | ä½ å¯ä»¥ä½¿ç”¨èŒƒå›´è¡¨è¾¾å¼æ¥ç¼–写进行范围检查的代ç 。 |
| 2517 | 3077 | ||
| 2518 | ```moonscript | 3078 | ```moonscript |
| 2519 | a = 5 | 3079 | a = 5 |
| @@ -2547,7 +3107,7 @@ print "ä½ å¾ˆå¹¸è¿!" unless math.random! > 0.1 | |||
| 2547 | 3107 | ||
| 2548 | ## 代ç 行修饰符 | 3108 | ## 代ç 行修饰符 |
| 2549 | 3109 | ||
| 2550 | 为了方便编写代ç ,循环è¯å¥å’Œifè¯å¥å¯ä»¥åº”用于å•行代ç è¯å¥çš„æœ«å°¾ï¼š | 3110 | 为了方便编写代ç ,循环è¯å¥å’Œ if è¯å¥å¯ä»¥åº”用于å•行代ç è¯å¥çš„æœ«å°¾ï¼š |
| 2551 | 3111 | ||
| 2552 | ```moonscript | 3112 | ```moonscript |
| 2553 | print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" | 3113 | print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" |
| @@ -2558,7 +3118,7 @@ print "ä½ å¥½ï¼Œä¸–ç•Œ" if name == "Rob" | |||
| 2558 | </pre> | 3118 | </pre> |
| 2559 | </YueDisplay> | 3119 | </YueDisplay> |
| 2560 | 3120 | ||
| 2561 | 修饰for循环的示例: | 3121 | 修饰 for 循环的示例: |
| 2562 | 3122 | ||
| 2563 | ```moonscript | 3123 | ```moonscript |
| 2564 | print "项目: ", item for item in *items | 3124 | print "项目: ", item for item in *items |
| @@ -2569,7 +3129,7 @@ print "项目: ", item for item in *items | |||
| 2569 | </pre> | 3129 | </pre> |
| 2570 | </YueDisplay> | 3130 | </YueDisplay> |
| 2571 | 3131 | ||
| 2572 | 修饰while循环的示例: | 3132 | 修饰 while 循环的示例: |
| 2573 | 3133 | ||
| 2574 | ```moonscript | 3134 | ```moonscript |
| 2575 | game\update! while game\isRunning! | 3135 | game\update! while game\isRunning! |
| @@ -2586,34 +3146,32 @@ reader\parse_line! until reader\eof! | |||
| 2586 | 3146 | ||
| 2587 | ## switch è¯å¥ | 3147 | ## switch è¯å¥ |
| 2588 | 3148 | ||
| 2589 | switchè¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和ifè¯å¥ä¸€æ ·ï¼Œswitchè¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ªelse代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„Lua代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用==æ“作符完æˆçš„。 | 3149 | switch è¯å¥æ˜¯ä¸ºäº†ç®€åŒ–检查一系列相åŒå€¼çš„ifè¯å¥è€Œæä¾›çš„ç®€å†™è¯æ³•ã€‚è¦æ³¨æ„ç”¨äºŽæ¯”è¾ƒæ£€æŸ¥çš„ç›®æ ‡å€¼åªä¼šè®¡ç®—一次。和 if è¯å¥ä¸€æ ·ï¼Œswitch è¯å¥åœ¨æœ€åŽå¯ä»¥æŽ¥ä¸€ä¸ª else 代ç å—æ¥å¤„ç†æ²¡æœ‰åŒ¹é…的情况。在生æˆçš„ Lua 代ç ä¸ï¼Œè¿›è¡Œæ¯”较是使用 == æ“作符完æˆçš„。switch è¯å¥ä¸ä¹Ÿå¯ä»¥ä½¿ç”¨èµ‹å€¼è¡¨è¾¾å¼æ¥å‚¨å˜ä¸´æ—¶å˜é‡å€¼ã€‚ |
| 2590 | 3150 | ||
| 2591 | ```moonscript | 3151 | ```moonscript |
| 2592 | name = "Dan" | 3152 | switch name := "Dan" |
| 2593 | switch name | ||
| 2594 | when "Robert" | 3153 | when "Robert" |
| 2595 | print "ä½ æ˜¯Robert" | 3154 | print "ä½ æ˜¯Robert" |
| 2596 | when "Dan", "Daniel" | 3155 | when "Dan", "Daniel" |
| 2597 | print "ä½ çš„åå—æ˜¯Dan" | 3156 | print "ä½ çš„åå—æ˜¯Dan" |
| 2598 | else | 3157 | else |
| 2599 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 3158 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
| 2600 | ``` | 3159 | ``` |
| 2601 | <YueDisplay> | 3160 | <YueDisplay> |
| 2602 | <pre> | 3161 | <pre> |
| 2603 | name = "Dan" | 3162 | switch name := "Dan" |
| 2604 | switch name | ||
| 2605 | when "Robert" | 3163 | when "Robert" |
| 2606 | print "ä½ æ˜¯Robert" | 3164 | print "ä½ æ˜¯Robert" |
| 2607 | when "Dan", "Daniel" | 3165 | when "Dan", "Daniel" |
| 2608 | print "ä½ çš„åå—æ˜¯Dan" | 3166 | print "ä½ çš„åå—æ˜¯Dan" |
| 2609 | else | 3167 | else |
| 2610 | print "我ä¸çŸ¥é“ä½ çš„åå—" | 3168 | print "我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯#{name}" |
| 2611 | </pre> | 3169 | </pre> |
| 2612 | </YueDisplay> | 3170 | </YueDisplay> |
| 2613 | 3171 | ||
| 2614 | switchè¯å¥çš„whenåå¥ä¸å¯ä»¥é€šè¿‡ä½¿ç”¨é€—å·åˆ†éš”的列表æ¥åŒ¹é…多个值。 | 3172 | switch è¯å¥çš„ when åå¥ä¸å¯ä»¥é€šè¿‡ä½¿ç”¨é€—å·åˆ†éš”的列表æ¥åŒ¹é…多个值。 |
| 2615 | 3173 | ||
| 2616 | switchè¯å¥ä¹Ÿå¯ä»¥ä½œä¸ºè¡¨è¾¾å¼ä½¿ç”¨ï¼Œä¸‹é¢æˆ‘们å¯ä»¥å°†switchè¯å¥è¿”回的结果分é…给一个å˜é‡ï¼š | 3174 | switch è¯å¥ä¹Ÿå¯ä»¥ä½œä¸ºè¡¨è¾¾å¼ä½¿ç”¨ï¼Œä¸‹é¢æˆ‘们å¯ä»¥å°† switch è¯å¥è¿”回的结果分é…给一个å˜é‡ï¼š |
| 2617 | 3175 | ||
| 2618 | ```moonscript | 3176 | ```moonscript |
| 2619 | b = 1 | 3177 | b = 1 |
| @@ -2638,7 +3196,7 @@ next_number = switch b | |||
| 2638 | </pre> | 3196 | </pre> |
| 2639 | </YueDisplay> | 3197 | </YueDisplay> |
| 2640 | 3198 | ||
| 2641 | 我们å¯ä»¥ä½¿ç”¨then关键å—在whenåå¥çš„åŒä¸€è¡Œä¸Šç¼–写处ç†ä»£ç 。else代ç å—çš„åŽç»ä»£ç ä¸è¦å†™åœ¨åŒä¸€è¡Œä¸Šä¸éœ€è¦é¢å¤–的关键å—。 | 3199 | 我们å¯ä»¥ä½¿ç”¨ then 关键å—在 when åå¥çš„åŒä¸€è¡Œä¸Šç¼–写处ç†ä»£ç 。else 代ç å—çš„åŽç»ä»£ç ä¸è¦å†™åœ¨åŒä¸€è¡Œä¸Šä¸éœ€è¦é¢å¤–的关键å—。 |
| 2642 | 3200 | ||
| 2643 | ```moonscript | 3201 | ```moonscript |
| 2644 | msg = switch math.random(1, 5) | 3202 | msg = switch math.random(1, 5) |
| @@ -2655,7 +3213,7 @@ msg = switch math.random(1, 5) | |||
| 2655 | </pre> | 3213 | </pre> |
| 2656 | </YueDisplay> | 3214 | </YueDisplay> |
| 2657 | 3215 | ||
| 2658 | 如果在编写switchè¯å¥æ—¶å¸Œæœ›å°‘å†™ä¸€ä¸ªç¼©è¿›ï¼Œé‚£ä¹ˆä½ å¯ä»¥æŠŠç¬¬ä¸€ä¸ªwhenå奿”¾åœ¨switch开始è¯å¥çš„第一行,然åŽåŽç»çš„åè¯å¥å°±éƒ½å¯ä»¥éƒ½å°‘写一个缩进。 | 3216 | 如果在编写 switch è¯å¥æ—¶å¸Œæœ›å°‘å†™ä¸€ä¸ªç¼©è¿›ï¼Œé‚£ä¹ˆä½ å¯ä»¥æŠŠç¬¬ä¸€ä¸ª when å奿”¾åœ¨ switch 开始è¯å¥çš„第一行,然åŽåŽç»çš„åè¯å¥å°±éƒ½å¯ä»¥éƒ½å°‘写一个缩进。 |
| 2659 | 3217 | ||
| 2660 | ```moonscript | 3218 | ```moonscript |
| 2661 | switch math.random(1, 5) | 3219 | switch math.random(1, 5) |
| @@ -2684,11 +3242,11 @@ else | |||
| 2684 | </pre> | 3242 | </pre> |
| 2685 | </YueDisplay> | 3243 | </YueDisplay> |
| 2686 | 3244 | ||
| 2687 | 值得注æ„的是,在生æˆLuaä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨==表达å¼çš„å³ä¾§ã€‚当您希望给whenåå¥çš„æ¯”较对象定义一个\_\_eq元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ | 3245 | 值得注æ„çš„æ˜¯ï¼Œåœ¨ç”Ÿæˆ Lua ä»£ç æ—¶ï¼Œæˆ‘们è¦åšæ£€æŸ¥çš„ç›®æ ‡å˜é‡ä¼šæ”¾åœ¨ == 表达å¼çš„å³ä¾§ã€‚å½“ä½ å¸Œæœ›ç»™ when åå¥çš„æ¯”较对象定义一个 \_\_eq 元方法æ¥é‡è½½åˆ¤æ–逻辑时,å¯èƒ½ä¼šæœ‰ç”¨ã€‚ |
| 2688 | 3246 | ||
| 2689 | ### è¡¨æ ¼åŒ¹é… | 3247 | ### è¡¨æ ¼åŒ¹é… |
| 2690 | 3248 | ||
| 2691 | 在switchçš„whenåå¥ä¸ï¼Œå¦‚æžœæœŸå¾…æ£€æŸ¥ç›®æ ‡æ˜¯ä¸€ä¸ªè¡¨æ ¼ï¼Œä¸”å¯ä»¥é€šè¿‡ç‰¹å®šçš„结构进行解构并获得éžnilå€¼ï¼Œé‚£ä¹ˆä½ å¯ä»¥å°è¯•ä½¿ç”¨è¡¨æ ¼åŒ¹é…çš„è¯æ³•。 | 3249 | 在 switch çš„ when åå¥ä¸ï¼Œå¦‚æžœæœŸå¾…æ£€æŸ¥ç›®æ ‡æ˜¯ä¸€ä¸ªè¡¨æ ¼ï¼Œä¸”å¯ä»¥é€šè¿‡ç‰¹å®šçš„ç»“æž„è¿›è¡Œè§£æž„å¹¶èŽ·å¾—éž nil å€¼ï¼Œé‚£ä¹ˆä½ å¯ä»¥å°è¯•ä½¿ç”¨è¡¨æ ¼åŒ¹é…çš„è¯æ³•。 |
| 2692 | 3250 | ||
| 2693 | ```moonscript | 3251 | ```moonscript |
| 2694 | items = | 3252 | items = |
| @@ -2744,9 +3302,126 @@ switch item | |||
| 2744 | </pre> | 3302 | </pre> |
| 2745 | </YueDisplay> | 3303 | </YueDisplay> |
| 2746 | 3304 | ||
| 3305 | ä½ ä¹Ÿå¯ä»¥åŒ¹é…æ•°ç»„å…ƒç´ ã€è¡¨æ ¼å—æ®µï¼Œç”šè‡³ä½¿ç”¨æ•°ç»„æˆ–è¡¨æ ¼å—é¢é‡æ¥åŒ¹é…嵌套的结构。 | ||
| 3306 | |||
| 3307 | åŒ¹é…æ•°ç»„å…ƒç´ ã€‚ | ||
| 3308 | |||
| 3309 | ```moonscript | ||
| 3310 | switch tb | ||
| 3311 | when [1, 2, 3] | ||
| 3312 | print "1, 2, 3" | ||
| 3313 | when [1, b, 3] | ||
| 3314 | print "1, #{b}, 3" | ||
| 3315 | when [1, 2, b = 3] -- å˜é‡b有默认值 | ||
| 3316 | print "1, 2, #{b}" | ||
| 3317 | ``` | ||
| 3318 | <YueDisplay> | ||
| 3319 | <pre> | ||
| 3320 | switch tb | ||
| 3321 | when [1, 2, 3] | ||
| 3322 | print "1, 2, 3" | ||
| 3323 | when [1, b, 3] | ||
| 3324 | print "1, #{b}, 3" | ||
| 3325 | when [1, 2, b = 3] -- å˜é‡b有默认值 | ||
| 3326 | print "1, 2, #{b}" | ||
| 3327 | </pre> | ||
| 3328 | </YueDisplay> | ||
| 3329 | |||
| 3330 | 匹é…è¡¨æ ¼å—æ®µã€‚ | ||
| 3331 | |||
| 3332 | ```moonscript | ||
| 3333 | switch tb | ||
| 3334 | when success: true, :result | ||
| 3335 | print "æˆåŠŸ", result | ||
| 3336 | when success: false | ||
| 3337 | print "失败", result | ||
| 3338 | else | ||
| 3339 | print "æ— æ•ˆå€¼" | ||
| 3340 | ``` | ||
| 3341 | <YueDisplay> | ||
| 3342 | <pre> | ||
| 3343 | switch tb | ||
| 3344 | when success: true, :result | ||
| 3345 | print "æˆåŠŸ", result | ||
| 3346 | when success: false | ||
| 3347 | print "失败", result | ||
| 3348 | else | ||
| 3349 | print "æ— æ•ˆå€¼" | ||
| 3350 | </pre> | ||
| 3351 | </YueDisplay> | ||
| 3352 | |||
| 3353 | 匹é…åµŒå¥—çš„è¡¨æ ¼ç»“æž„ã€‚ | ||
| 3354 | |||
| 3355 | ```moonscript | ||
| 3356 | switch tb | ||
| 3357 | when data: {type: "success", :content} | ||
| 3358 | print "æˆåŠŸ", content | ||
| 3359 | when data: {type: "error", :content} | ||
| 3360 | print "失败", content | ||
| 3361 | else | ||
| 3362 | print "æ— æ•ˆå€¼" | ||
| 3363 | ``` | ||
| 3364 | <YueDisplay> | ||
| 3365 | <pre> | ||
| 3366 | switch tb | ||
| 3367 | when data: {type: "success", :content} | ||
| 3368 | print "æˆåŠŸ", content | ||
| 3369 | when data: {type: "error", :content} | ||
| 3370 | print "失败", content | ||
| 3371 | else | ||
| 3372 | print "æ— æ•ˆå€¼" | ||
| 3373 | </pre> | ||
| 3374 | </YueDisplay> | ||
| 3375 | |||
| 3376 | 匹é…è¡¨æ ¼æ•°ç»„ã€‚ | ||
| 3377 | |||
| 3378 | ```moonscript | ||
| 3379 | switch tb | ||
| 3380 | when [ | ||
| 3381 | {a: 1, b: 2} | ||
| 3382 | {a: 3, b: 4} | ||
| 3383 | {a: 5, b: 6} | ||
| 3384 | fourth | ||
| 3385 | ] | ||
| 3386 | print "åŒ¹é…æˆåŠŸ", fourth | ||
| 3387 | ``` | ||
| 3388 | <YueDisplay> | ||
| 3389 | <pre> | ||
| 3390 | switch tb | ||
| 3391 | when [ | ||
| 3392 | {a: 1, b: 2} | ||
| 3393 | {a: 3, b: 4} | ||
| 3394 | {a: 5, b: 6} | ||
| 3395 | fourth | ||
| 3396 | ] | ||
| 3397 | print "åŒ¹é…æˆåŠŸ", fourth | ||
| 3398 | </pre> | ||
| 3399 | </YueDisplay> | ||
| 3400 | |||
| 3401 | 匹é…一个列表并æ•èŽ·ç‰¹å®šèŒƒå›´å†…çš„å…ƒç´ ã€‚ | ||
| 3402 | |||
| 3403 | ```moonscript | ||
| 3404 | segments = ["admin", "users", "logs", "view"] | ||
| 3405 | switch segments | ||
| 3406 | when [...groups, resource, action] | ||
| 3407 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
| 3408 | print "Resource:", resource -- 打å°: "logs" | ||
| 3409 | print "Action:", action -- 打å°: "view" | ||
| 3410 | ``` | ||
| 3411 | <YueDisplay> | ||
| 3412 | <pre> | ||
| 3413 | segments = ["admin", "users", "logs", "view"] | ||
| 3414 | switch segments | ||
| 3415 | when [...groups, resource, action] | ||
| 3416 | print "Group:", groups -- 打å°: {"admin", "users"} | ||
| 3417 | print "Resource:", resource -- 打å°: "logs" | ||
| 3418 | print "Action:", action -- 打å°: "view" | ||
| 3419 | </pre> | ||
| 3420 | </YueDisplay> | ||
| 3421 | |||
| 2747 | ## é¢å‘对象编程 | 3422 | ## é¢å‘对象编程 |
| 2748 | 3423 | ||
| 2749 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„Lua代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚果您想知é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹Lua代ç 。 | 3424 | 在以下的示例ä¸ï¼Œæœˆä¹‹è„šæœ¬ç”Ÿæˆçš„ Lua 代ç å¯èƒ½çœ‹èµ·æ¥ä¼šå¾ˆå¤æ‚。所以最好主è¦å…³æ³¨æœˆä¹‹è„šæœ¬ä»£ç 层é¢çš„æ„ä¹‰ï¼Œç„¶åŽå¦‚æžœä½ æƒ³çŸ¥é“关于é¢å‘å¯¹è±¡åŠŸèƒ½çš„å®žçŽ°ç»†èŠ‚ï¼Œå†æŸ¥çœ‹ Lua 代ç 。 |
| 2750 | 3425 | ||
| 2751 | 一个简å•的类: | 3426 | 一个简å•的类: |
| 2752 | 3427 | ||
| @@ -2775,11 +3450,11 @@ class Inventory | |||
| 2775 | </pre> | 3450 | </pre> |
| 2776 | </YueDisplay> | 3451 | </YueDisplay> |
| 2777 | 3452 | ||
| 2778 | 在月之脚本ä¸é‡‡ç”¨é¢å‘å¯¹è±¡çš„ç¼–ç¨‹æ–¹å¼æ—¶ï¼Œé€šå¸¸ä¼šä½¿ç”¨ç±»å£°æ˜Žè¯å¥ç»“åˆLuaè¡¨æ ¼å—é¢é‡æ¥åšç±»å®šä¹‰ã€‚这个类的定义包å«äº†å®ƒçš„æ‰€æœ‰æ–¹æ³•和属性。在这ç§ç»“æž„ä¸ï¼Œé”®å为“newâ€çš„æˆå‘˜æ‰®æ¼”äº†ä¸€ä¸ªé‡è¦çš„è§’è‰²ï¼Œæ˜¯ä½œä¸ºæž„é€ å‡½æ•°æ¥ä½¿ç”¨ã€‚ | 3453 | 在月之脚本ä¸é‡‡ç”¨é¢å‘å¯¹è±¡çš„ç¼–ç¨‹æ–¹å¼æ—¶ï¼Œé€šå¸¸ä¼šä½¿ç”¨ç±»å£°æ˜Žè¯å¥ç»“åˆ Lua è¡¨æ ¼å—é¢é‡æ¥åšç±»å®šä¹‰ã€‚这个类的定义包å«äº†å®ƒçš„æ‰€æœ‰æ–¹æ³•和属性。在这ç§ç»“æž„ä¸ï¼Œé”®å为 “new†的æˆå‘˜æ‰®æ¼”了一个é‡è¦çš„è§’è‰²ï¼Œæ˜¯ä½œä¸ºæž„é€ å‡½æ•°æ¥ä½¿ç”¨ã€‚ |
| 2779 | 3454 | ||
| 2780 | 值得注æ„的是,类ä¸çš„æ–¹æ³•都采用了粗ç®å¤´å‡½æ•°è¯æ³•ã€‚å½“åœ¨ç±»çš„å®žä¾‹ä¸Šè°ƒç”¨æ–¹æ³•æ—¶ï¼Œè¯¥å®žä¾‹ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°è¢«ä¼ å…¥ï¼Œå› æ¤ç²—ç®å¤´å‡½æ•°ç”¨äºŽç”Ÿæˆä¸€ä¸ªå为“selfâ€çš„傿•°ã€‚ | 3455 | 值得注æ„的是,类ä¸çš„æ–¹æ³•都采用了粗ç®å¤´å‡½æ•°è¯æ³•ã€‚å½“åœ¨ç±»çš„å®žä¾‹ä¸Šè°ƒç”¨æ–¹æ³•æ—¶ï¼Œè¯¥å®žä¾‹ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°è¢«ä¼ å…¥ï¼Œå› æ¤ç²—ç®å¤´å‡½æ•°ç”¨äºŽç”Ÿæˆä¸€ä¸ªå为 “selfâ€ çš„å‚æ•°ã€‚ |
| 2781 | 3456 | ||
| 2782 | æ¤å¤–,“@â€å‰ç¼€åœ¨å˜é‡å上起到了简化作用,代表“selfâ€ã€‚例如,`@items` å°±ç‰åŒäºŽ `self.items`。 | 3457 | æ¤å¤–,“@†å‰ç¼€åœ¨å˜é‡å上起到了简化作用,代表 “selfâ€ã€‚例如,`@items` å°±ç‰åŒäºŽ `self.items`。 |
| 2783 | 3458 | ||
| 2784 | 为了创建类的一个新实例,å¯ä»¥å°†ç±»å当作一个函数æ¥è°ƒç”¨ï¼Œè¿™æ ·å°±å¯ä»¥ç”Ÿæˆå¹¶è¿”回一个新的实例。 | 3459 | 为了创建类的一个新实例,å¯ä»¥å°†ç±»å当作一个函数æ¥è°ƒç”¨ï¼Œè¿™æ ·å°±å¯ä»¥ç”Ÿæˆå¹¶è¿”回一个新的实例。 |
| 2785 | 3460 | ||
| @@ -2801,7 +3476,7 @@ inv\add_item "pants" | |||
| 2801 | 3476 | ||
| 2802 | 需è¦ç‰¹åˆ«æ³¨æ„的是,类的所有属性在其实例之间是共享的。这对于函数类型的æˆå‘˜å±žæ€§é€šå¸¸ä¸ä¼šé€ æˆé—®é¢˜ï¼Œä½†å¯¹äºŽå…¶ä»–类型的属性,å¯èƒ½ä¼šå¯¼è‡´æ„外的结果。 | 3477 | 需è¦ç‰¹åˆ«æ³¨æ„的是,类的所有属性在其实例之间是共享的。这对于函数类型的æˆå‘˜å±žæ€§é€šå¸¸ä¸ä¼šé€ æˆé—®é¢˜ï¼Œä½†å¯¹äºŽå…¶ä»–类型的属性,å¯èƒ½ä¼šå¯¼è‡´æ„外的结果。 |
| 2803 | 3478 | ||
| 2804 | 例如,在下é¢çš„示例ä¸ï¼Œclotheså±žæ€§åœ¨æ‰€æœ‰å®žä¾‹ä¹‹é—´å…±äº«ã€‚å› æ¤ï¼Œå¯¹è¿™ä¸ªå±žæ€§åœ¨ä¸€ä¸ªå®žä¾‹ä¸çš„修改,将会影å“到其他所有实例。 | 3479 | 例如,在下é¢çš„示例ä¸ï¼Œclothes å±žæ€§åœ¨æ‰€æœ‰å®žä¾‹ä¹‹é—´å…±äº«ã€‚å› æ¤ï¼Œå¯¹è¿™ä¸ªå±žæ€§åœ¨ä¸€ä¸ªå®žä¾‹ä¸çš„修改,将会影å“到其他所有实例。 |
| 2805 | 3480 | ||
| 2806 | ```moonscript | 3481 | ```moonscript |
| 2807 | class Person | 3482 | class Person |
| @@ -2853,7 +3528,7 @@ class Person | |||
| 2853 | 3528 | ||
| 2854 | ### 继承 | 3529 | ### 继承 |
| 2855 | 3530 | ||
| 2856 | `extends`关键å—å¯ä»¥åœ¨ç±»å£°æ˜Žä¸ä½¿ç”¨ï¼Œä»¥ç»§æ‰¿å¦ä¸€ä¸ªç±»çš„属性和方法。 | 3531 | `extends` 关键å—å¯ä»¥åœ¨ç±»å£°æ˜Žä¸ä½¿ç”¨ï¼Œä»¥ç»§æ‰¿å¦ä¸€ä¸ªç±»çš„属性和方法。 |
| 2857 | 3532 | ||
| 2858 | ```moonscript | 3533 | ```moonscript |
| 2859 | class BackPack extends Inventory | 3534 | class BackPack extends Inventory |
| @@ -2873,11 +3548,11 @@ class BackPack extends Inventory | |||
| 2873 | </YueDisplay> | 3548 | </YueDisplay> |
| 2874 | 3549 | ||
| 2875 | 3550 | ||
| 2876 | 在这一部分,我们对月之脚本ä¸çš„`Inventory`ç±»è¿›è¡Œäº†æ‰©å±•ï¼ŒåŠ å…¥äº†å¯¹å¯ä»¥æºå¸¦ç‰©å“æ•°é‡çš„é™åˆ¶ã€‚ | 3551 | 在这一部分,我们对月之脚本ä¸çš„ `Inventory` ç±»è¿›è¡Œäº†æ‰©å±•ï¼ŒåŠ å…¥äº†å¯¹å¯ä»¥æºå¸¦ç‰©å“æ•°é‡çš„é™åˆ¶ã€‚ |
| 2877 | 3552 | ||
| 2878 | 在这个特定的例åä¸ï¼Œåç±»å¹¶æ²¡æœ‰å®šä¹‰è‡ªå·±çš„æž„é€ å‡½æ•°ã€‚å› æ¤ï¼Œå½“åˆ›å»ºä¸€ä¸ªæ–°çš„å®žä¾‹æ—¶ï¼Œç³»ç»Ÿä¼šé»˜è®¤è°ƒç”¨çˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ä½†å¦‚æžœæˆ‘ä»¬åœ¨åç±»ä¸å®šä¹‰äº†æž„é€ å‡½æ•°ï¼Œæˆ‘ä»¬å¯ä»¥åˆ©ç”¨`super`方法æ¥è°ƒç”¨å¹¶æ‰§è¡Œçˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ | 3553 | 在这个特定的例åä¸ï¼Œåç±»å¹¶æ²¡æœ‰å®šä¹‰è‡ªå·±çš„æž„é€ å‡½æ•°ã€‚å› æ¤ï¼Œå½“åˆ›å»ºä¸€ä¸ªæ–°çš„å®žä¾‹æ—¶ï¼Œç³»ç»Ÿä¼šé»˜è®¤è°ƒç”¨çˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ä½†å¦‚æžœæˆ‘ä»¬åœ¨åç±»ä¸å®šä¹‰äº†æž„é€ å‡½æ•°ï¼Œæˆ‘ä»¬å¯ä»¥åˆ©ç”¨ `super` 方法æ¥è°ƒç”¨å¹¶æ‰§è¡Œçˆ¶ç±»çš„æž„é€ å‡½æ•°ã€‚ |
| 2879 | 3554 | ||
| 2880 | æ¤å¤–,当一个类继承自å¦ä¸€ä¸ªç±»æ—¶ï¼Œå®ƒä¼šå°è¯•调用父类上的`__inherited`方法(如果这个方法å˜åœ¨çš„è¯ï¼‰ï¼Œä»¥æ¤æ¥å‘父类å‘é€é€šçŸ¥ã€‚这个`__inherited`函数接å—ä¸¤ä¸ªå‚æ•°ï¼šè¢«ç»§æ‰¿çš„父类和继承的å类。 | 3555 | æ¤å¤–,当一个类继承自å¦ä¸€ä¸ªç±»æ—¶ï¼Œå®ƒä¼šå°è¯•调用父类上的 `__inherited` 方法(如果这个方法å˜åœ¨çš„è¯ï¼‰ï¼Œä»¥æ¤æ¥å‘父类å‘é€é€šçŸ¥ã€‚这个 `__inherited` 函数接å—ä¸¤ä¸ªå‚æ•°ï¼šè¢«ç»§æ‰¿çš„父类和继承的å类。 |
| 2881 | 3556 | ||
| 2882 | ```moonscript | 3557 | ```moonscript |
| 2883 | class Shelf | 3558 | class Shelf |
| @@ -2900,15 +3575,15 @@ class Cupboard extends Shelf | |||
| 2900 | 3575 | ||
| 2901 | ### super å…³é”®å— | 3576 | ### super å…³é”®å— |
| 2902 | 3577 | ||
| 2903 | `super`是一个特别的关键å—,它有两ç§ä¸åŒçš„使用方å¼ï¼šæ—¢å¯ä»¥å½“作一个对象æ¥çœ‹å¾…,也å¯ä»¥åƒè°ƒç”¨å‡½æ•°é‚£æ ·ä½¿ç”¨ã€‚它仅在类的内部使用时具有特殊的功能。 | 3578 | `super` 是一个特别的关键å—,它有两ç§ä¸åŒçš„使用方å¼ï¼šæ—¢å¯ä»¥å½“作一个对象æ¥çœ‹å¾…,也å¯ä»¥åƒè°ƒç”¨å‡½æ•°é‚£æ ·ä½¿ç”¨ã€‚它仅在类的内部使用时具有特殊的功能。 |
| 2904 | 3579 | ||
| 2905 | 当`super`被作为一个函数调用时,它将调用父类ä¸ä¸Žä¹‹åŒåçš„å‡½æ•°ã€‚æ¤æ—¶ï¼Œå½“å‰çš„`self`ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 递,æ£å¦‚ä¸Šé¢æåˆ°çš„ç»§æ‰¿ç¤ºä¾‹æ‰€å±•ç¤ºçš„é‚£æ ·ã€‚ | 3580 | 当 `super` 被作为一个函数调用时,它将调用父类ä¸ä¸Žä¹‹åŒåçš„å‡½æ•°ã€‚æ¤æ—¶ï¼Œå½“å‰çš„ `self` ä¼šè‡ªåŠ¨ä½œä¸ºç¬¬ä¸€ä¸ªå‚æ•°ä¼ 递,æ£å¦‚ä¸Šé¢æåˆ°çš„ç»§æ‰¿ç¤ºä¾‹æ‰€å±•ç¤ºçš„é‚£æ ·ã€‚ |
| 2906 | 3581 | ||
| 2907 | 在将`super`å½“ä½œæ™®é€šå€¼ä½¿ç”¨æ—¶ï¼Œå®ƒå®žé™…ä¸Šæ˜¯å¯¹çˆ¶ç±»å¯¹è±¡çš„å¼•ç”¨ã€‚é€šè¿‡è¿™ç§æ–¹å¼ï¼Œæˆ‘们å¯ä»¥è®¿é—®çˆ¶ç±»ä¸å¯èƒ½è¢«å类覆盖的值,就åƒè®¿é—®ä»»ä½•æ™®é€šå¯¹è±¡ä¸€æ ·ã€‚ | 3582 | 在将 `super` å½“ä½œæ™®é€šå€¼ä½¿ç”¨æ—¶ï¼Œå®ƒå®žé™…ä¸Šæ˜¯å¯¹çˆ¶ç±»å¯¹è±¡çš„å¼•ç”¨ã€‚é€šè¿‡è¿™ç§æ–¹å¼ï¼Œæˆ‘们å¯ä»¥è®¿é—®çˆ¶ç±»ä¸å¯èƒ½è¢«å类覆盖的值,就åƒè®¿é—®ä»»ä½•æ™®é€šå¯¹è±¡ä¸€æ ·ã€‚ |
| 2908 | 3583 | ||
| 2909 | æ¤å¤–,当使用`\`æ“作符与`super`一起使用时,`self`将被æ’å…¥ä¸ºç¬¬ä¸€ä¸ªå‚æ•°ï¼Œè€Œä¸æ˜¯ä½¿ç”¨`super`本身的值。而在使用`.`æ“ä½œç¬¦æ¥æ£€ç´¢å‡½æ•°æ—¶ï¼Œåˆ™ä¼šè¿”回父类ä¸çš„原始函数。 | 3584 | æ¤å¤–,当使用 `\` æ“作符与 `super` 一起使用时,`self`将被æ’å…¥ä¸ºç¬¬ä¸€ä¸ªå‚æ•°ï¼Œè€Œä¸æ˜¯ä½¿ç”¨ `super` 本身的值。而在使用`.`æ“ä½œç¬¦æ¥æ£€ç´¢å‡½æ•°æ—¶ï¼Œåˆ™ä¼šè¿”回父类ä¸çš„原始函数。 |
| 2910 | 3585 | ||
| 2911 | 䏋颿˜¯ä¸€äº›ä½¿ç”¨`super`çš„ä¸åŒæ–¹æ³•的示例: | 3586 | 䏋颿˜¯ä¸€äº›ä½¿ç”¨ `super` çš„ä¸åŒæ–¹æ³•的示例: |
| 2912 | 3587 | ||
| 2913 | ```moonscript | 3588 | ```moonscript |
| 2914 | class MyClass extends ParentClass | 3589 | class MyClass extends ParentClass |
| @@ -2967,9 +3642,9 @@ print BackPack.size -- æ‰“å° 10 | |||
| 2967 | 3642 | ||
| 2968 | å¦‚æžœåœ¨ç±»å¯¹è±¡çš„å…ƒè¡¨ä¸æ‰¾ä¸åˆ°æŸä¸ªå±žæ€§ï¼Œç³»ç»Ÿä¼šä»ŽåŸºè¡¨ä¸æ£€ç´¢è¯¥å±žæ€§ã€‚这就æ„å‘³ç€æˆ‘们å¯ä»¥ç›´æŽ¥ä»Žç±»æœ¬èº«è®¿é—®åˆ°å…¶æ–¹æ³•和属性。 | 3643 | å¦‚æžœåœ¨ç±»å¯¹è±¡çš„å…ƒè¡¨ä¸æ‰¾ä¸åˆ°æŸä¸ªå±žæ€§ï¼Œç³»ç»Ÿä¼šä»ŽåŸºè¡¨ä¸æ£€ç´¢è¯¥å±žæ€§ã€‚这就æ„å‘³ç€æˆ‘们å¯ä»¥ç›´æŽ¥ä»Žç±»æœ¬èº«è®¿é—®åˆ°å…¶æ–¹æ³•和属性。 |
| 2969 | 3644 | ||
| 2970 | 需è¦ç‰¹åˆ«æ³¨æ„的是,对类对象的赋值并ä¸ä¼šå½±å“åˆ°åŸºè¡¨ï¼Œå› æ¤è¿™ä¸æ˜¯å‘å®žä¾‹æ·»åŠ æ–°æ–¹æ³•çš„æ£ç¡®æ–¹å¼ã€‚相å,需è¦ç›´æŽ¥ä¿®æ”¹åŸºè¡¨ã€‚关于这点,å¯ä»¥å‚考下é¢çš„“__baseâ€å—段。 | 3645 | 需è¦ç‰¹åˆ«æ³¨æ„的是,对类对象的赋值并ä¸ä¼šå½±å“åˆ°åŸºè¡¨ï¼Œå› æ¤è¿™ä¸æ˜¯å‘å®žä¾‹æ·»åŠ æ–°æ–¹æ³•çš„æ£ç¡®æ–¹å¼ã€‚相å,需è¦ç›´æŽ¥ä¿®æ”¹åŸºè¡¨ã€‚关于这点,å¯ä»¥å‚考下é¢çš„ “__baseâ€ å—æ®µã€‚ |
| 2971 | 3646 | ||
| 2972 | æ¤å¤–,类对象包å«å‡ 个特殊的属性:当类被声明时,类的å称会作为一个å—符串å˜å‚¨åœ¨ç±»å¯¹è±¡çš„“__nameâ€å—段ä¸ã€‚ | 3647 | æ¤å¤–,类对象包å«å‡ 个特殊的属性:当类被声明时,类的å称会作为一个å—符串å˜å‚¨åœ¨ç±»å¯¹è±¡çš„ “__nameâ€ å—æ®µä¸ã€‚ |
| 2973 | 3648 | ||
| 2974 | ```moonscript | 3649 | ```moonscript |
| 2975 | print BackPack.__name -- æ‰“å° Backpack | 3650 | print BackPack.__name -- æ‰“å° Backpack |
| @@ -3051,7 +3726,7 @@ print Counter.count -- 输出 2 | |||
| 3051 | 3726 | ||
| 3052 | ### 类声明è¯å¥ | 3727 | ### 类声明è¯å¥ |
| 3053 | 3728 | ||
| 3054 | 在类声明的主体ä¸ï¼Œé™¤äº†é”®/值对外,我们还å¯ä»¥ç¼–写普通的表达å¼ã€‚在这ç§ç±»å£°æ˜Žä½“ä¸çš„æ™®é€šä»£ç 的上下文ä¸ï¼Œselfç‰äºŽç±»å¯¹è±¡ï¼Œè€Œä¸æ˜¯å®žä¾‹å¯¹è±¡ã€‚ | 3729 | 在类声明的主体ä¸ï¼Œé™¤äº†é”®/值对外,我们还å¯ä»¥ç¼–写普通的表达å¼ã€‚在这ç§ç±»å£°æ˜Žä½“ä¸çš„æ™®é€šä»£ç 的上下文ä¸ï¼Œself ç‰äºŽç±»å¯¹è±¡ï¼Œè€Œä¸æ˜¯å®žä¾‹å¯¹è±¡ã€‚ |
| 3055 | 3730 | ||
| 3056 | 以下是创建类å˜é‡çš„å¦ä¸€ç§æ–¹æ³•: | 3731 | 以下是创建类å˜é‡çš„å¦ä¸€ç§æ–¹æ³•: |
| 3057 | 3732 | ||
| @@ -3091,9 +3766,9 @@ class MoreThings | |||
| 3091 | 3766 | ||
| 3092 | ### @ 和 @@ 值 | 3767 | ### @ 和 @@ 值 |
| 3093 | 3768 | ||
| 3094 | 当@å’Œ@@å‰ç¼€åœ¨ä¸€ä¸ªåå—剿—¶ï¼Œå®ƒä»¬åˆ†åˆ«ä»£è¡¨åœ¨selfå’Œself.\_\_classä¸è®¿é—®çš„那个åå—。 | 3769 | 当 @ å’Œ @@ å‰ç¼€åœ¨ä¸€ä¸ªåå—剿—¶ï¼Œå®ƒä»¬åˆ†åˆ«ä»£è¡¨åœ¨ self å’Œ self.\_\_class ä¸è®¿é—®çš„那个åå—。 |
| 3095 | 3770 | ||
| 3096 | 如果它们å•独使用,它们是selfå’Œself.\_\_class的别å。 | 3771 | 如果它们å•独使用,它们是 self å’Œ self.\_\_class 的别å。 |
| 3097 | 3772 | ||
| 3098 | ```moonscript | 3773 | ```moonscript |
| 3099 | assert @ == self | 3774 | assert @ == self |
| @@ -3106,7 +3781,7 @@ assert @@ == self.__class | |||
| 3106 | </pre> | 3781 | </pre> |
| 3107 | </YueDisplay> | 3782 | </YueDisplay> |
| 3108 | 3783 | ||
| 3109 | 例如,使用@@从实例方法快速创建åŒä¸€ç±»çš„æ–°å®žä¾‹çš„æ–¹æ³•: | 3784 | 例如,使用 @@ 从实例方法快速创建åŒä¸€ç±»çš„æ–°å®žä¾‹çš„æ–¹æ³•: |
| 3110 | 3785 | ||
| 3111 | ```moonscript | 3786 | ```moonscript |
| 3112 | some_instance_method = (...) => @@ ... | 3787 | some_instance_method = (...) => @@ ... |
| @@ -3184,7 +3859,7 @@ x = class Bucket | |||
| 3184 | 3859 | ||
| 3185 | ### 匿åç±» | 3860 | ### 匿åç±» |
| 3186 | 3861 | ||
| 3187 | 声明类时å¯ä»¥çœç•¥å称。如果类的表达å¼ä¸åœ¨èµ‹å€¼è¯å¥ä¸ï¼Œ\_\_name属性将为nil。如果出现在赋值è¯å¥ä¸ï¼Œèµ‹å€¼æ“作左侧的å称将代替nil。 | 3862 | 声明类时å¯ä»¥çœç•¥å称。如果类的表达å¼ä¸åœ¨èµ‹å€¼è¯å¥ä¸ï¼Œ\_\_name 属性将为 nil。如果出现在赋值è¯å¥ä¸ï¼Œèµ‹å€¼æ“作左侧的å称将代替 nil。 |
| 3188 | 3863 | ||
| 3189 | ```moonscript | 3864 | ```moonscript |
| 3190 | BigBucket = class extends Bucket | 3865 | BigBucket = class extends Bucket |
| @@ -3214,7 +3889,7 @@ x = class | |||
| 3214 | 3889 | ||
| 3215 | ### ç±»æ··åˆ | 3890 | ### ç±»æ··åˆ |
| 3216 | 3891 | ||
| 3217 | 您å¯ä»¥é€šè¿‡ä½¿ç”¨ `using` 关键嗿¥å®žçŽ°ç±»æ··åˆã€‚è¿™æ„å‘³ç€æ‚¨å¯ä»¥ä»Žä¸€ä¸ªæ™®é€š Lua è¡¨æ ¼æˆ–å·²å®šä¹‰çš„ç±»å¯¹è±¡ä¸ï¼Œå¤åˆ¶å‡½æ•°åˆ°æ‚¨åˆ›å»ºçš„æ–°ç±»ä¸ã€‚当您使用普通 Lua è¡¨æ ¼è¿›è¡Œç±»æ··åˆæ—¶ï¼Œæ‚¨æœ‰æœºä¼šç”¨è‡ªå·±çš„实现æ¥é‡å†™ç±»çš„索引方法(例如元方法 `__index`ï¼‰ã€‚ç„¶è€Œï¼Œå½“æ‚¨ä»Žä¸€ä¸ªç±»å¯¹è±¡åšæ··åˆæ—¶ï¼Œéœ€è¦æ³¨æ„的是该类对象的元方法将ä¸ä¼šè¢«å¤åˆ¶åˆ°æ–°ç±»ã€‚ | 3892 | ä½ å¯ä»¥é€šè¿‡ä½¿ç”¨ `using` 关键嗿¥å®žçŽ°ç±»æ··åˆã€‚è¿™æ„味ç€ä½ å¯ä»¥ä»Žä¸€ä¸ªæ™®é€š Lua è¡¨æ ¼æˆ–å·²å®šä¹‰çš„ç±»å¯¹è±¡ä¸ï¼Œå¤åˆ¶å‡½æ•°åˆ°ä½ 创建的新类ä¸ã€‚å½“ä½ ä½¿ç”¨æ™®é€š Lua è¡¨æ ¼è¿›è¡Œç±»æ··åˆæ—¶ï¼Œä½ 有机会用自己的实现æ¥é‡å†™ç±»çš„索引方法(例如元方法 `__index`ï¼‰ã€‚ç„¶è€Œï¼Œå½“ä½ ä»Žä¸€ä¸ªç±»å¯¹è±¡åšæ··åˆæ—¶ï¼Œéœ€è¦æ³¨æ„的是该类对象的元方法将ä¸ä¼šè¢«å¤åˆ¶åˆ°æ–°ç±»ã€‚ |
| 3218 | 3893 | ||
| 3219 | ```moonscript | 3894 | ```moonscript |
| 3220 | MyIndex = __index: var: 1 | 3895 | MyIndex = __index: var: 1 |
| @@ -3255,11 +3930,11 @@ assert y.__class.__parent ~= X -- X 䏿˜¯ Y 的父类 | |||
| 3255 | 3930 | ||
| 3256 | ## with è¯å¥ | 3931 | ## with è¯å¥ |
| 3257 | 3932 | ||
| 3258 | 在编写Luaä»£ç æ—¶ï¼Œæˆ‘们在创建对象åŽçš„å¸¸è§æ“作是立å³è°ƒç”¨è¿™ä¸ªå¯¹è±¡ä¸€ç³»åˆ—æ“作函数并设置一系列属性。 | 3933 | 在编写 Lua ä»£ç æ—¶ï¼Œæˆ‘们在创建对象åŽçš„å¸¸è§æ“作是立å³è°ƒç”¨è¿™ä¸ªå¯¹è±¡ä¸€ç³»åˆ—æ“作函数并设置一系列属性。 |
| 3259 | 3934 | ||
| 3260 | 这导致在代ç ä¸å¤šæ¬¡é‡å¤å¼•用对象的åç§°ï¼Œå¢žåŠ äº†ä¸å¿…è¦çš„æ–‡æœ¬å™ªéŸ³ã€‚一个常è§çš„è§£å†³æ–¹æ¡ˆæ˜¯åœ¨åˆ›å»ºå¯¹è±¡æ—¶ï¼Œåœ¨æž„é€ å‡½æ•°ä¼ å…¥ä¸€ä¸ªè¡¨ï¼Œè¯¥è¡¨åŒ…å«è¦è¦†ç›–设置的键和值的集åˆã€‚è¿™æ ·åšçš„ç¼ºç‚¹æ˜¯è¯¥å¯¹è±¡çš„æž„é€ å‡½æ•°å¿…é¡»æ”¯æŒè¿™ç§åˆå§‹åŒ–å½¢å¼ã€‚ | 3935 | 这导致在代ç ä¸å¤šæ¬¡é‡å¤å¼•用对象的åç§°ï¼Œå¢žåŠ äº†ä¸å¿…è¦çš„æ–‡æœ¬å™ªéŸ³ã€‚一个常è§çš„è§£å†³æ–¹æ¡ˆæ˜¯åœ¨åˆ›å»ºå¯¹è±¡æ—¶ï¼Œåœ¨æž„é€ å‡½æ•°ä¼ å…¥ä¸€ä¸ªè¡¨ï¼Œè¯¥è¡¨åŒ…å«è¦è¦†ç›–设置的键和值的集åˆã€‚è¿™æ ·åšçš„ç¼ºç‚¹æ˜¯è¯¥å¯¹è±¡çš„æž„é€ å‡½æ•°å¿…é¡»æ”¯æŒè¿™ç§åˆå§‹åŒ–å½¢å¼ã€‚ |
| 3261 | 3936 | ||
| 3262 | withå—æœ‰åŠ©äºŽç®€åŒ–ç¼–å†™è¿™æ ·çš„ä»£ç 。在withå—内,我们å¯ä»¥ä½¿ç”¨ä»¥.或\开头的特殊è¯å¥ï¼Œè¿™äº›è¯å¥ä»£è¡¨æˆ‘们æ£åœ¨ä½¿ç”¨çš„对象的æ“作。 | 3937 | with å—æœ‰åŠ©äºŽç®€åŒ–ç¼–å†™è¿™æ ·çš„ä»£ç 。在 with å—内,我们å¯ä»¥ä½¿ç”¨ä»¥ . 或 \ 开头的特殊è¯å¥ï¼Œè¿™äº›è¯å¥ä»£è¡¨æˆ‘们æ£åœ¨ä½¿ç”¨çš„对象的æ“作。 |
| 3263 | 3938 | ||
| 3264 | 例如,我们å¯ä»¥è¿™æ ·å¤„ç†ä¸€ä¸ªæ–°åˆ›å»ºçš„对象: | 3939 | 例如,我们å¯ä»¥è¿™æ ·å¤„ç†ä¸€ä¸ªæ–°åˆ›å»ºçš„对象: |
| 3265 | 3940 | ||
| @@ -3280,7 +3955,7 @@ with Person! | |||
| 3280 | </pre> | 3955 | </pre> |
| 3281 | </YueDisplay> | 3956 | </YueDisplay> |
| 3282 | 3957 | ||
| 3283 | withè¯å¥ä¹Ÿå¯ä»¥ç”¨ä½œä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶è¿”回它的代ç å—æ£åœ¨å¤„ç†çš„对象。 | 3958 | with è¯å¥ä¹Ÿå¯ä»¥ç”¨ä½œä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶è¿”回它的代ç å—æ£åœ¨å¤„ç†çš„对象。 |
| 3284 | 3959 | ||
| 3285 | ```moonscript | 3960 | ```moonscript |
| 3286 | file = with File "favorite_foods.txt" | 3961 | file = with File "favorite_foods.txt" |
| @@ -3314,24 +3989,24 @@ me = create_person "Leaf", [dad, mother, sister] | |||
| 3314 | </pre> | 3989 | </pre> |
| 3315 | </YueDisplay> | 3990 | </YueDisplay> |
| 3316 | 3991 | ||
| 3317 | 在æ¤ç”¨æ³•ä¸ï¼Œwithå¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ | 3992 | 在æ¤ç”¨æ³•ä¸ï¼Œwith å¯ä»¥è¢«è§†ä¸ºK组åˆå(k-combinator)的一ç§ç‰¹æ®Šå½¢å¼ã€‚ |
| 3318 | 3993 | ||
| 3319 | 如果您想给表达å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwithè¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ | 3994 | å¦‚æžœä½ æƒ³ç»™è¡¨è¾¾å¼å¦å¤–起一个åç§°çš„è¯ï¼Œwith è¯å¥ä¸çš„表达å¼ä¹Ÿå¯ä»¥æ˜¯ä¸€ä¸ªèµ‹å€¼è¯å¥ã€‚ |
| 3320 | 3995 | ||
| 3321 | ```moonscript | 3996 | ```moonscript |
| 3322 | with str = "ä½ å¥½" | 3997 | with str := "ä½ å¥½" |
| 3323 | print "原始:", str | 3998 | print "原始:", str |
| 3324 | print "大写:", \upper! | 3999 | print "大写:", \upper! |
| 3325 | ``` | 4000 | ``` |
| 3326 | <YueDisplay> | 4001 | <YueDisplay> |
| 3327 | <pre> | 4002 | <pre> |
| 3328 | with str = "ä½ å¥½" | 4003 | with str := "ä½ å¥½" |
| 3329 | print "原始:", str | 4004 | print "原始:", str |
| 3330 | print "大写:", \upper! | 4005 | print "大写:", \upper! |
| 3331 | </pre> | 4006 | </pre> |
| 3332 | </YueDisplay> | 4007 | </YueDisplay> |
| 3333 | 4008 | ||
| 3334 | 在withè¯å¥ä¸å¯ä»¥ä½¿ç”¨`[]`访问特殊键。 | 4009 | ä½ å¯ä»¥åœ¨ `with` è¯å¥ä¸ä½¿ç”¨ `[]` 访问特殊键。 |
| 3335 | 4010 | ||
| 3336 | ```moonscript | 4011 | ```moonscript |
| 3337 | with tb | 4012 | with tb |
| @@ -3354,9 +4029,22 @@ with tb | |||
| 3354 | </pre> | 4029 | </pre> |
| 3355 | </YueDisplay> | 4030 | </YueDisplay> |
| 3356 | 4031 | ||
| 4032 | `with?` 是 `with` è¯æ³•的一个增强版本,引入了å˜åœ¨æ€§æ£€æŸ¥ï¼Œç”¨äºŽåœ¨ä¸æ˜¾å¼åˆ¤ç©ºçš„æƒ…况下安全访问å¯èƒ½ä¸º nil 的对象。 | ||
| 4033 | |||
| 4034 | ```moonscript | ||
| 4035 | with? obj | ||
| 4036 | print obj.name | ||
| 4037 | ``` | ||
| 4038 | <YueDisplay> | ||
| 4039 | <pre> | ||
| 4040 | with? obj | ||
| 4041 | print obj.name | ||
| 4042 | </pre> | ||
| 4043 | </YueDisplay> | ||
| 4044 | |||
| 3357 | ## do è¯å¥ | 4045 | ## do è¯å¥ |
| 3358 | 4046 | ||
| 3359 | 当用作è¯å¥æ—¶ï¼Œdoè¯å¥çš„作用就åƒåœ¨Luaä¸å·®ä¸å¤šã€‚ | 4047 | 当用作è¯å¥æ—¶ï¼Œdo è¯å¥çš„作用就åƒåœ¨ Lua ä¸å·®ä¸å¤šã€‚ |
| 3360 | 4048 | ||
| 3361 | ```moonscript | 4049 | ```moonscript |
| 3362 | do | 4050 | do |
| @@ -3373,7 +4061,7 @@ print var -- 这里是nil | |||
| 3373 | </pre> | 4061 | </pre> |
| 3374 | </YueDisplay> | 4062 | </YueDisplay> |
| 3375 | 4063 | ||
| 3376 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…许您将多行代ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°†doè¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 | 4064 | 月之脚本的 **do** 也å¯ä»¥ç”¨ä½œè¡¨è¾¾å¼ã€‚å…è®¸ä½ å°†å¤šè¡Œä»£ç 的处ç†åˆå¹¶ä¸ºä¸€ä¸ªè¡¨è¾¾å¼ï¼Œå¹¶å°† do è¯å¥ä»£ç å—的最åŽä¸€ä¸ªè¯å¥ä½œä¸ºè¡¨è¾¾å¼è¿”回的结果。 |
| 3377 | 4065 | ||
| 3378 | ```moonscript | 4066 | ```moonscript |
| 3379 | counter = do | 4067 | counter = do |
| @@ -3557,7 +4245,7 @@ print i, k -- 这些已ç»è¢«æ›´æ–° | |||
| 3557 | 4245 | ||
| 3558 | ## 月之脚本è¯è¨€åº“ | 4246 | ## 月之脚本è¯è¨€åº“ |
| 3559 | 4247 | ||
| 3560 | 使用`require("yue")`æ¥è®¿é—®ã€‚ | 4248 | 使用 `require("yue")` æ¥è®¿é—®ã€‚ |
| 3561 | 4249 | ||
| 3562 | ### yue | 4250 | ### yue |
| 3563 | 4251 | ||
| @@ -3615,9 +4303,9 @@ yue_compiled: {string: string} | |||
| 3615 | **ç¾å:** | 4303 | **ç¾å:** |
| 3616 | ```lua | 4304 | ```lua |
| 3617 | to_lua: function(code: string, config?: Config): | 4305 | to_lua: function(code: string, config?: Config): |
| 3618 | --[[codes]] string | nil, | 4306 | --[[codes]] string | nil, |
| 3619 | --[[error]] string | nil, | 4307 | --[[error]] string | nil, |
| 3620 | --[[globals]] {{string, integer, integer}} | nil | 4308 | --[[globals]] {{string, integer, integer}} | nil |
| 3621 | ``` | 4309 | ``` |
| 3622 | 4310 | ||
| 3623 | **傿•°ï¼š** | 4311 | **傿•°ï¼š** |
| @@ -3740,8 +4428,8 @@ remove_loader: function(): boolean | |||
| 3740 | **ç¾å:** | 4428 | **ç¾å:** |
| 3741 | ```lua | 4429 | ```lua |
| 3742 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): | 4430 | loadstring: function(input: string, chunkname: string, env: table, config?: Config): |
| 3743 | --[[loaded function]] nil | function(...: any): (any...), | 4431 | --[[loaded function]] nil | function(...: any): (any...), |
| 3744 | --[[error]] string | nil | 4432 | --[[error]] string | nil |
| 3745 | ``` | 4433 | ``` |
| 3746 | 4434 | ||
| 3747 | **傿•°ï¼š** | 4435 | **傿•°ï¼š** |
| @@ -3771,8 +4459,8 @@ loadstring: function(input: string, chunkname: string, env: table, config?: Conf | |||
| 3771 | **ç¾å:** | 4459 | **ç¾å:** |
| 3772 | ```lua | 4460 | ```lua |
| 3773 | loadstring: function(input: string, chunkname: string, config?: Config): | 4461 | loadstring: function(input: string, chunkname: string, config?: Config): |
| 3774 | --[[loaded function]] nil | function(...: any): (any...), | 4462 | --[[loaded function]] nil | function(...: any): (any...), |
| 3775 | --[[error]] string | nil | 4463 | --[[error]] string | nil |
| 3776 | ``` | 4464 | ``` |
| 3777 | 4465 | ||
| 3778 | **傿•°ï¼š** | 4466 | **傿•°ï¼š** |
| @@ -3801,8 +4489,8 @@ loadstring: function(input: string, chunkname: string, config?: Config): | |||
| 3801 | **ç¾å:** | 4489 | **ç¾å:** |
| 3802 | ```lua | 4490 | ```lua |
| 3803 | loadstring: function(input: string, config?: Config): | 4491 | loadstring: function(input: string, config?: Config): |
| 3804 | --[[loaded function]] nil | function(...: any): (any...), | 4492 | --[[loaded function]] nil | function(...: any): (any...), |
| 3805 | --[[error]] string | nil | 4493 | --[[error]] string | nil |
| 3806 | ``` | 4494 | ``` |
| 3807 | 4495 | ||
| 3808 | **傿•°ï¼š** | 4496 | **傿•°ï¼š** |
| @@ -3830,8 +4518,8 @@ loadstring: function(input: string, config?: Config): | |||
| 3830 | **ç¾å:** | 4518 | **ç¾å:** |
| 3831 | ```lua | 4519 | ```lua |
| 3832 | loadfile: function(filename: string, env: table, config?: Config): | 4520 | loadfile: function(filename: string, env: table, config?: Config): |
| 3833 | nil | function(...: any): (any...), | 4521 | nil | function(...: any): (any...), |
| 3834 | string | nil | 4522 | string | nil |
| 3835 | ``` | 4523 | ``` |
| 3836 | 4524 | ||
| 3837 | **傿•°ï¼š** | 4525 | **傿•°ï¼š** |
| @@ -3860,8 +4548,8 @@ loadfile: function(filename: string, env: table, config?: Config): | |||
| 3860 | **ç¾å:** | 4548 | **ç¾å:** |
| 3861 | ```lua | 4549 | ```lua |
| 3862 | loadfile: function(filename: string, config?: Config): | 4550 | loadfile: function(filename: string, config?: Config): |
| 3863 | nil | function(...: any): (any...), | 4551 | nil | function(...: any): (any...), |
| 3864 | string | nil | 4552 | string | nil |
| 3865 | ``` | 4553 | ``` |
| 3866 | 4554 | ||
| 3867 | **傿•°ï¼š** | 4555 | **傿•°ï¼š** |
| @@ -4116,9 +4804,9 @@ type AST = {string, integer, integer, any} | |||
| 4116 | 4804 | ||
| 4117 | **ç¾å:** | 4805 | **ç¾å:** |
| 4118 | ```lua | 4806 | ```lua |
| 4119 | to_ast: function(code: string, flattenLevel?: number, astName?: string): | 4807 | to_ast: function(code: string, flattenLevel?: number, astName?: string, reserveComment?: boolean): |
| 4120 | --[[AST]] AST | nil, | 4808 | --[[AST]] AST | nil, |
| 4121 | --[[error]] nil | string | 4809 | --[[error]] nil | string |
| 4122 | ``` | 4810 | ``` |
| 4123 | 4811 | ||
| 4124 | **傿•°ï¼š** | 4812 | **傿•°ï¼š** |
| @@ -4127,6 +4815,42 @@ to_ast: function(code: string, flattenLevel?: number, astName?: string): | |||
| 4127 | | --- | --- | --- | | 4815 | | --- | --- | --- | |
| 4128 | | code | string | 代ç 。 | | 4816 | | code | string | 代ç 。 | |
| 4129 | | flattenLevel | integer | [å¯é€‰] æ‰å¹³åŒ–级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | | 4817 | | flattenLevel | integer | [å¯é€‰] æ‰å¹³åŒ–级别。级别越高,会消除更多的 AST 结构的嵌套。默认为 0。最大为 2。 | |
| 4818 | | astName | string | [å¯é€‰] AST å称。默认为 "File"。 | | ||
| 4819 | | reserveComment | boolean | [å¯é€‰] 是å¦ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚é»˜è®¤ä¸º false。 | | ||
| 4820 | |||
| 4821 | **返回值:** | ||
| 4822 | |||
| 4823 | | 返回类型 | æè¿° | | ||
| 4824 | | --- | --- | | ||
| 4825 | | AST \| nil | AST,如果转æ¢å¤±è´¥åˆ™ä¸º nil。 | | ||
| 4826 | | string \| nil | 错误消æ¯ï¼Œå¦‚æžœè½¬æ¢æˆåŠŸåˆ™ä¸º nil。 | | ||
| 4827 | |||
| 4828 | #### format | ||
| 4829 | |||
| 4830 | **类型:** 函数。 | ||
| 4831 | |||
| 4832 | **æè¿°ï¼š** | ||
| 4833 | |||
| 4834 | æ ¼å¼åŒ– YueScript 代ç 。 | ||
| 4835 | |||
| 4836 | **ç¾å:** | ||
| 4837 | ```lua | ||
| 4838 | format: function(code: string, tabSize?: number, reserveComment?: boolean): string | ||
| 4839 | ``` | ||
| 4840 | |||
| 4841 | **傿•°ï¼š** | ||
| 4842 | |||
| 4843 | | 傿•°å | 类型 | æè¿° | | ||
| 4844 | | --- | --- | --- | | ||
| 4845 | | code | string | 代ç 。 | | ||
| 4846 | | tabSize | integer | [å¯é€‰] 制表符大å°ã€‚默认为 4。 | | ||
| 4847 | | reserveComment | boolean | [å¯é€‰] 是å¦ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚é»˜è®¤ä¸º true。 | | ||
| 4848 | |||
| 4849 | **返回值:** | ||
| 4850 | |||
| 4851 | | 返回类型 | æè¿° | | ||
| 4852 | | --- | --- | | ||
| 4853 | | string | æ ¼å¼åŒ–åŽçš„代ç 。 | | ||
| 4130 | 4854 | ||
| 4131 | #### __call | 4855 | #### __call |
| 4132 | 4856 | ||
| @@ -4199,6 +4923,19 @@ implicit_return_root: boolean | |||
| 4199 | reserve_line_number: boolean | 4923 | reserve_line_number: boolean |
| 4200 | ``` | 4924 | ``` |
| 4201 | 4925 | ||
| 4926 | #### reserve_comment | ||
| 4927 | |||
| 4928 | **类型:** æˆå‘˜å˜é‡ã€‚ | ||
| 4929 | |||
| 4930 | **æè¿°ï¼š** | ||
| 4931 | |||
| 4932 | 编译器是å¦åº”该在编译åŽçš„代ç ä¸ä¿ç•™åŽŸå§‹æ³¨é‡Šã€‚ | ||
| 4933 | |||
| 4934 | **ç¾å:** | ||
| 4935 | ```lua | ||
| 4936 | reserve_comment: boolean | ||
| 4937 | ``` | ||
| 4938 | |||
| 4202 | #### space_over_tab | 4939 | #### space_over_tab |
| 4203 | 4940 | ||
| 4204 | **类型:** æˆå‘˜å˜é‡ã€‚ | 4941 | **类型:** æˆå‘˜å˜é‡ã€‚ |
| @@ -4249,11 +4986,11 @@ line_offset: integer | |||
| 4249 | **ç¾å:** | 4986 | **ç¾å:** |
| 4250 | ```lua | 4987 | ```lua |
| 4251 | enum LuaTarget | 4988 | enum LuaTarget |
| 4252 | "5.1" | 4989 | "5.1" |
| 4253 | "5.2" | 4990 | "5.2" |
| 4254 | "5.3" | 4991 | "5.3" |
| 4255 | "5.4" | 4992 | "5.4" |
| 4256 | "5.5" | 4993 | "5.5" |
| 4257 | end | 4994 | end |
| 4258 | ``` | 4995 | ``` |
| 4259 | 4996 | ||
| @@ -4332,8 +5069,8 @@ simplified: boolean | |||
| 4332 | 5069 | ||
| 4333 | ç‰ˆæƒ (c) 2017-2025 æŽç‘¾ \<dragon-fly@qq.com\> | 5070 | ç‰ˆæƒ (c) 2017-2025 æŽç‘¾ \<dragon-fly@qq.com\> |
| 4334 | 5071 | ||
| 4335 | 特æ¤å…费授予任何获得本软件副本和相关文档文件(下称“软件â€ï¼‰çš„人ä¸å—é™åˆ¶åœ°å¤„置该软件的æƒåˆ©ï¼ŒåŒ…括ä¸å—é™åˆ¶åœ°ä½¿ç”¨ã€å¤åˆ¶ã€ä¿®æ”¹ã€åˆå¹¶ã€å‘布ã€åˆ†å‘ã€è½¬æŽˆè®¸å¯å’Œ/或出售该软件副本,以åŠå†æŽˆæƒè¢«é…å‘了本软件的人如上的æƒåˆ©ï¼Œé¡»åœ¨ä¸‹åˆ—æ¡ä»¶ä¸‹ï¼š | 5072 | 特æ¤å…费授予任何获得本软件副本和相关文档文件(下称“软件â€ï¼‰çš„人ä¸å—é™åˆ¶åœ°å¤„置该软件的æƒåˆ©ï¼ŒåŒ…括ä¸å—é™åˆ¶åœ°ä½¿ç”¨ã€å¤åˆ¶ã€ä¿®æ”¹ã€åˆå¹¶ã€å‘布ã€åˆ†å‘ã€è½¬æŽˆè®¸å¯å’Œ/或出售该软件副本,以åŠå†æŽˆæƒè¢«é…å‘了本软件的人如上的æƒåˆ©ï¼Œé¡»åœ¨ä¸‹åˆ—æ¡ä»¶ä¸‹ï¼š |
| 4336 | 上述版æƒå£°æ˜Žå’Œæœ¬è®¸å¯å£°æ˜Žåº”包å«åœ¨è¯¥è½¯ä»¶çš„æ‰€æœ‰å‰¯æœ¬æˆ–实质æˆåˆ†ä¸ã€‚ | 5073 | 上述版æƒå£°æ˜Žå’Œæœ¬è®¸å¯å£°æ˜Žåº”包å«åœ¨è¯¥è½¯ä»¶çš„æ‰€æœ‰å‰¯æœ¬æˆ–实质æˆåˆ†ä¸ã€‚ |
| 4337 | 本软件是“如æ¤â€æä¾›çš„,没有任何形å¼çš„æ˜Žç¤ºæˆ–暗示的ä¿è¯ï¼ŒåŒ…括但ä¸é™äºŽå¯¹é€‚销性ã€ç‰¹å®šç”¨é€”的适用性和ä¸ä¾µæƒçš„ä¿è¯ã€‚åœ¨ä»»ä½•æƒ…å†µä¸‹ï¼Œä½œè€…æˆ–ç‰ˆæƒæŒæœ‰äººéƒ½ä¸å¯¹ä»»ä½•ç´¢èµ”ã€æŸå®³æˆ–å…¶ä»–è´£ä»»è´Ÿè´£ï¼Œæ— è®ºè¿™äº›è¿½è´£æ¥è‡ªåˆåŒã€ä¾µæƒæˆ–其它行为ä¸ï¼Œè¿˜æ˜¯äº§ç”ŸäºŽã€æºäºŽæˆ–æœ‰å…³äºŽæœ¬è½¯ä»¶ä»¥åŠæœ¬è½¯ä»¶çš„使用或其它处置。 | 5074 | 本软件是“如æ¤â€æä¾›çš„,没有任何形å¼çš„æ˜Žç¤ºæˆ–暗示的ä¿è¯ï¼ŒåŒ…括但ä¸é™äºŽå¯¹é€‚销性ã€ç‰¹å®šç”¨é€”的适用性和ä¸ä¾µæƒçš„ä¿è¯ã€‚åœ¨ä»»ä½•æƒ…å†µä¸‹ï¼Œä½œè€…æˆ–ç‰ˆæƒæŒæœ‰äººéƒ½ä¸å¯¹ä»»ä½•ç´¢èµ”ã€æŸå®³æˆ–å…¶ä»–è´£ä»»è´Ÿè´£ï¼Œæ— è®ºè¿™äº›è¿½è´£æ¥è‡ªåˆåŒã€ä¾µæƒæˆ–其它行为ä¸ï¼Œè¿˜æ˜¯äº§ç”ŸäºŽã€æºäºŽæˆ–æœ‰å…³äºŽæœ¬è½¯ä»¶ä»¥åŠæœ¬è½¯ä»¶çš„使用或其它处置。 |
| 4338 | 5075 | ||
| 4339 | <CompilerModal /> | 5076 | <CompilerModal /> |
| @@ -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 |
| @@ -390,8 +435,8 @@ test: debug | |||
| 390 | @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(TEST_OUTPUT)/5.1/loops.lua --target=5.1 | 435 | @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(TEST_OUTPUT)/5.1/loops.lua --target=5.1 |
| 391 | @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(TEST_OUTPUT)/5.1/try_catch.lua --target=5.1 | 436 | @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(TEST_OUTPUT)/5.1/try_catch.lua --target=5.1 |
| 392 | @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(TEST_OUTPUT)/5.1/attrib.lua --target=5.1 | 437 | @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(TEST_OUTPUT)/5.1/attrib.lua --target=5.1 |
| 438 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(TEST_OUTPUT)/5.1/import_global.lua --target=5.1 | ||
| 393 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 | 439 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(TEST_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 |
| 394 | @./$(BIN_NAME) $(TEST_INPUT)/literals.yue -o $(TEST_OUTPUT)/5.1/literals.lua --target=5.1 | ||
| 395 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT) | 440 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(TEST_OUTPUT) |
| 396 | @echo -en "Compile time: " | 441 | @echo -en "Compile time: " |
| 397 | @$(END_TIME) | 442 | @$(END_TIME) |
| @@ -410,7 +455,7 @@ gen: release | |||
| 410 | @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(GEN_OUTPUT)/5.1/loops.lua --target=5.1 | 455 | @./$(BIN_NAME) $(TEST_INPUT)/loops.yue -o $(GEN_OUTPUT)/5.1/loops.lua --target=5.1 |
| 411 | @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(GEN_OUTPUT)/5.1/try_catch.lua --target=5.1 | 456 | @./$(BIN_NAME) $(TEST_INPUT)/try_catch.yue -o $(GEN_OUTPUT)/5.1/try_catch.lua --target=5.1 |
| 412 | @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(GEN_OUTPUT)/5.1/attrib.lua --target=5.1 | 457 | @./$(BIN_NAME) $(TEST_INPUT)/attrib.yue -o $(GEN_OUTPUT)/5.1/attrib.lua --target=5.1 |
| 413 | @./$(BIN_NAME) $(TEST_INPUT)/literals.yue -o $(GEN_OUTPUT)/5.1/literals.lua --target=5.1 | 458 | @./$(BIN_NAME) $(TEST_INPUT)/import_global.yue -o $(GEN_OUTPUT)/5.1/import_global.lua --target=5.1 |
| 414 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 | 459 | @./$(BIN_NAME) $(TEST_INPUT)/test/loops_spec.yue -o $(GEN_OUTPUT)/5.1/test/loops_spec.lua --target=5.1 |
| 415 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT) | 460 | @./$(BIN_NAME) -e spec/inputs/compile_doc.yue $(GEN_OUTPUT) |
| 416 | @echo -en "Compile time: " | 461 | @echo -en "Compile time: " |
| @@ -442,3 +487,11 @@ $(BUILD_PATH)/%.o: $(SRC_PATH)/%.$(SRC_EXT) | |||
| 442 | $(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ | 487 | $(CMD_PREFIX)$(CXX) $(CXXFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ |
| 443 | @echo -en "\t Compile time: " | 488 | @echo -en "\t Compile time: " |
| 444 | @$(END_TIME) | 489 | @$(END_TIME) |
| 490 | |||
| 491 | # C source file rules | ||
| 492 | $(BUILD_PATH)/%.o: $(SRC_PATH)/%.c | ||
| 493 | @echo "Compiling: $< -> $@" | ||
| 494 | @$(START_TIME) | ||
| 495 | $(CMD_PREFIX)$(CC) $(CFLAGS) $(INCLUDES) -MP -MMD -c $< -o $@ | ||
| 496 | @echo -en "\t Compile time: " | ||
| 497 | @$(END_TIME) | ||
diff --git a/spec/inputs/backcall.yue b/spec/inputs/backcall.yue index 8aadc71..e6b8c21 100644 --- a/spec/inputs/backcall.yue +++ b/spec/inputs/backcall.yue | |||
| @@ -13,9 +13,9 @@ do | |||
| 13 | x > 2 | 13 | x > 2 |
| 14 | 14 | ||
| 15 | do | 15 | do |
| 16 | (data) <- http?.get "ajaxtest" | 16 | data <- http?.get "ajaxtest" |
| 17 | body[".result"]\html data | 17 | body[".result"]\html data |
| 18 | (processed) <- http.post "ajaxprocess", data | 18 | processed <- http.post "ajaxprocess", data |
| 19 | body[".result"]\append processed | 19 | body[".result"]\append processed |
| 20 | <- setTimeout 1000 | 20 | <- setTimeout 1000 |
| 21 | print "done" | 21 | print "done" |
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/global.yue b/spec/inputs/global.yue index ce1cc15..4e3b8aa 100644 --- a/spec/inputs/global.yue +++ b/spec/inputs/global.yue | |||
| @@ -82,3 +82,9 @@ do | |||
| 82 | FooBar = "pascal case" | 82 | FooBar = "pascal case" |
| 83 | FOOBAR = "all uppercase" | 83 | FOOBAR = "all uppercase" |
| 84 | 84 | ||
| 85 | do | ||
| 86 | global const class A | ||
| 87 | global const Flag = 1 | ||
| 88 | global const const, x, y = "const", 1, 2 | ||
| 89 | global const math, table | ||
| 90 | |||
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/import_global.yue b/spec/inputs/import_global.yue new file mode 100644 index 0000000..18f0e85 --- /dev/null +++ b/spec/inputs/import_global.yue | |||
| @@ -0,0 +1,93 @@ | |||
| 1 | |||
| 2 | do | ||
| 3 | import global | ||
| 4 | print "hello" | ||
| 5 | math.random 10 | ||
| 6 | |||
| 7 | do | ||
| 8 | import global | ||
| 9 | value = 1 | ||
| 10 | value += 2 | ||
| 11 | print value | ||
| 12 | |||
| 13 | do | ||
| 14 | local print = (msg) -> | ||
| 15 | return msg | ||
| 16 | do | ||
| 17 | import global | ||
| 18 | print "local" | ||
| 19 | math.random 1 | ||
| 20 | |||
| 21 | do | ||
| 22 | import global | ||
| 23 | local tostring = (v) -> "local" | ||
| 24 | tostring "value" | ||
| 25 | print tostring 123 | ||
| 26 | |||
| 27 | do | ||
| 28 | func = (x, y) -> | ||
| 29 | import global | ||
| 30 | return type x, tostring y, print | ||
| 31 | func 1, 2 | ||
| 32 | |||
| 33 | do | ||
| 34 | import global | ||
| 35 | try | ||
| 36 | func "hello #{world}" | ||
| 37 | catch err | ||
| 38 | print err | ||
| 39 | |||
| 40 | do | ||
| 41 | import global | ||
| 42 | global FLAG | ||
| 43 | print FLAG | ||
| 44 | FLAG = 123 | ||
| 45 | |||
| 46 | do | ||
| 47 | import global | ||
| 48 | global Foo = 10 | ||
| 49 | print Foo | ||
| 50 | Foo += 2 | ||
| 51 | |||
| 52 | do | ||
| 53 | import global | ||
| 54 | global Bar, Baz | ||
| 55 | Bar = 1 | ||
| 56 | Baz = 2 | ||
| 57 | print Bar, Baz | ||
| 58 | |||
| 59 | do | ||
| 60 | import global | ||
| 61 | global * | ||
| 62 | x = 3434 | ||
| 63 | if y then | ||
| 64 | x = 10 | ||
| 65 | |||
| 66 | do | ||
| 67 | import global | ||
| 68 | global ^ | ||
| 69 | foobar = "all #{lowercase}" | ||
| 70 | FooBar = "pascal case" | ||
| 71 | FOOBAR = "all #{Uppercase}" | ||
| 72 | |||
| 73 | do | ||
| 74 | import global | ||
| 75 | global const class A | ||
| 76 | global const Flag = 1 | ||
| 77 | global const const, x, y = "const", 1, 2 | ||
| 78 | global const math, table | ||
| 79 | print math, table | ||
| 80 | |||
| 81 | do | ||
| 82 | import global | ||
| 83 | with X | ||
| 84 | \func 1, 2, 3 | ||
| 85 | .tag = "abc" | ||
| 86 | |||
| 87 | do | ||
| 88 | import global | ||
| 89 | |||
| 90 | f = -> | ||
| 91 | func! | ||
| 92 | try func | ||
| 93 | |||
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 c5b28b3..5df10ca 100644 --- a/spec/inputs/loops.yue +++ b/spec/inputs/loops.yue | |||
| @@ -213,3 +213,55 @@ do | |||
| 213 | do | 213 | do |
| 214 | until x := func 'a', b do | 214 | until x := func 'a', b do |
| 215 | print "false expected" | 215 | print "false expected" |
| 216 | |||
| 217 | do | ||
| 218 | index = for i = 1, #tb | ||
| 219 | break i if tb[i] | ||
| 220 | |||
| 221 | f for i = 1, #tb | ||
| 222 | break i if tb[i] | ||
| 223 | |||
| 224 | f for i = 1, #tb | ||
| 225 | i if tb[i] | ||
| 226 | |||
| 227 | i = 1 | ||
| 228 | ids = while tb[i] | ||
| 229 | i += 1 | ||
| 230 | i - 1 | ||
| 231 | |||
| 232 | i = 1 | ||
| 233 | idx = while tb[i] | ||
| 234 | i += 1 | ||
| 235 | break i - 1 | ||
| 236 | |||
| 237 | f1 = -> | ||
| 238 | i = 1 | ||
| 239 | f while tb[i] | ||
| 240 | i += 1 | ||
| 241 | i - 1 | ||
| 242 | |||
| 243 | i = 1 | ||
| 244 | f while tb[i] | ||
| 245 | i += 1 | ||
| 246 | break i - 1 | ||
| 247 | |||
| 248 | list = for item in *items | ||
| 249 | switch item | ||
| 250 | when type: "A", :value | ||
| 251 | if value > 5 | ||
| 252 | item | ||
| 253 | |||
| 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 49d47f3..2b0669c 100644 --- a/spec/inputs/switch.yue +++ b/spec/inputs/switch.yue | |||
| @@ -165,5 +165,128 @@ do | |||
| 165 | print item | 165 | print item |
| 166 | when [a = 1, b = "abc"] | 166 | when [a = 1, b = "abc"] |
| 167 | print a, b | 167 | print a, b |
| 168 | nil | ||
| 169 | 168 | ||
| 169 | do | ||
| 170 | switch tb | ||
| 171 | when [1, 2, 3] | ||
| 172 | print "1, 2, 3" | ||
| 173 | when [1, b, 3] | ||
| 174 | print "1, #{b}, 3" | ||
| 175 | when [1, 2, b = 3] | ||
| 176 | print "1, 2, #{b}" | ||
| 177 | |||
| 178 | do | ||
| 179 | switch tb | ||
| 180 | when success: true, :result | ||
| 181 | print "success", result | ||
| 182 | when success: false | ||
| 183 | print "failed", result | ||
| 184 | else | ||
| 185 | print "invalid" | ||
| 186 | |||
| 187 | do | ||
| 188 | switch tb | ||
| 189 | when {type: "success", :content} | ||
| 190 | print "success", content | ||
| 191 | when {type: "error", :content} | ||
| 192 | print "failed", content | ||
| 193 | else | ||
| 194 | print "invalid" | ||
| 195 | |||
| 196 | do | ||
| 197 | switch tb | ||
| 198 | when [ | ||
| 199 | {a: 1, b: 2} | ||
| 200 | {a: 3, b: 4} | ||
| 201 | {a: 5, b: 6} | ||
| 202 | fourth | ||
| 203 | ] | ||
| 204 | print "matched", fourth | ||
| 205 | |||
| 206 | switch tb | ||
| 207 | when [ | ||
| 208 | {c: 1, d: 2} | ||
| 209 | {c: 3, d: 4} | ||
| 210 | {c: 5, d: 6} | ||
| 211 | ] | ||
| 212 | print "OK" | ||
| 213 | when [ | ||
| 214 | _ | ||
| 215 | _ | ||
| 216 | {a: 1, b: 2} | ||
| 217 | {a: 3, b: 4} | ||
| 218 | {a: 5, b: 6} | ||
| 219 | sixth | ||
| 220 | ] | ||
| 221 | print "matched", sixth | ||
| 222 | |||
| 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..a63f629 100644 --- a/spec/inputs/syntax.yue +++ b/spec/inputs/syntax.yue | |||
| @@ -7,7 +7,7 @@ a, bunch, go, here = another, world, nil, nil | |||
| 7 | func arg1, arg2, another, arg3 | 7 | func arg1, arg2, another, arg3 |
| 8 | 8 | ||
| 9 | here, we = () ->, yeah | 9 | here, we = () ->, yeah |
| 10 | the, different = () -> approach; yeah | 10 | the, different = (() -> approach), yeah |
| 11 | 11 | ||
| 12 | dad() | 12 | dad() |
| 13 | dad(lord) | 13 | dad(lord) |
| @@ -321,7 +321,7 @@ ajax url, | |||
| 321 | (error) -> | 321 | (error) -> |
| 322 | print error | 322 | print error |
| 323 | 323 | ||
| 324 | -- | 324 | -- |
| 325 | a += 3 - 5 | 325 | a += 3 - 5 |
| 326 | a *= 3 + 5 | 326 | a *= 3 + 5 |
| 327 | a *= 3 | 327 | a *= 3 |
| @@ -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,65 @@ 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 | |||
| 489 | do | ||
| 490 | -- Simple one-liners | ||
| 491 | x = 1; y = 2 | ||
| 492 | |||
| 493 | -- Short related statements | ||
| 494 | i += 1; j += 1 | ||
| 495 | |||
| 496 | if condition | ||
| 497 | setup!; run!; cleanup! | ||
| 498 | |||
| 499 | a = 1; b = 2; c = a + b | ||
| 500 | print a; print b; print c | ||
| 501 | |||
| 502 | f = -> | ||
| 503 | a = 1; b = 2; a + b | ||
| 504 | |||
| 505 | a = 1; | ||
| 506 | b = 2; | ||
| 507 | |||
| 508 | success, result = try func!; print result if success | ||
| 509 | |||
| 510 | value = "foo"; print value; value = value .. "bar"; print value | ||
| 511 | |||
| 512 | do | ||
| 513 | if ok then print "ok!"; return 42 | ||
| 514 | |||
| 515 | for i=1,3 | ||
| 516 | print i; continue | ||
| 517 | |||
| 518 | n = 0 | ||
| 519 | while n < 2 | ||
| 520 | print "n=", n; n += 1 | ||
| 521 | |||
| 522 | obj = {} | ||
| 523 | obj\set 10; obj\get!; print "done" | ||
| 524 | |||
| 525 | with tbl | ||
| 526 | \push 1; print "push" | ||
| 527 | |||
| 528 | a = 5 | ||
| 529 | if a > 3 | ||
| 530 | print "big"; b = a * 2; print b | ||
| 531 | else | ||
| 532 | print "small"; b = a | ||
| 533 | |||
| 534 | try | ||
| 535 | x = 1; y = 2; print x + y | ||
| 536 | catch err | ||
| 537 | print "error:", err | ||
| 538 | |||
| 539 | q = 1 --[[it's q]]; --[[got w]] w = 2; e = 3; print --[[param q]] q, w, e; --[[here]] -- line ends | ||
| 540 | |||
| 481 | nil | 541 | nil |
| 482 | 542 | ||
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..939579b 100644 --- a/spec/inputs/unicode/syntax.yue +++ b/spec/inputs/unicode/syntax.yue | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | 函数 傿•°1, 傿•°2, å¦å¤–, 傿•°3 | 7 | 函数 傿•°1, 傿•°2, å¦å¤–, 傿•°3 |
| 8 | 8 | ||
| 9 | 这里, 我们 = () ->, 是的 | 9 | 这里, 我们 = () ->, 是的 |
| 10 | 这个, ä¸åŒ = () -> 方法; 是的 | 10 | 这个, ä¸åŒ = (() -> 方法), 是的 |
| 11 | 11 | ||
| 12 | 爸爸() | 12 | 爸爸() |
| 13 | 爸爸(主) | 13 | 爸爸(主) |
| @@ -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/whitespace.yue b/spec/inputs/unicode/whitespace.yue index efe55ce..151789a 100644 --- a/spec/inputs/unicode/whitespace.yue +++ b/spec/inputs/unicode/whitespace.yue | |||
| @@ -97,19 +97,19 @@ v = -> | |||
| 97 | å˜é‡c -- v3 | 97 | å˜é‡c -- v3 |
| 98 | 98 | ||
| 99 | v1, v2, \ | 99 | v1, v2, \ |
| 100 | v3 = -> | 100 | v3 = (-> |
| 101 | å˜é‡a; \-- 函数结æŸäºŽv1 | 101 | å˜é‡a), \-- 函数结æŸäºŽv1 |
| 102 | å˜é‡b, \-- v2 | 102 | å˜é‡b, \-- v2 |
| 103 | å˜é‡c -- v3 | 103 | å˜é‡c -- v3 |
| 104 | 104 | ||
| 105 | å˜é‡a, å˜é‡b, \ | 105 | å˜é‡a, å˜é‡b, \ |
| 106 | å˜é‡c, å˜é‡d, \ | 106 | å˜é‡c, å˜é‡d, \ |
| 107 | å˜é‡e, å˜é‡f = 1, \ | 107 | å˜é‡e, å˜é‡f = 1, \ |
| 108 | f2 | 108 | (f2 |
| 109 | :abc; \-- 傿•°2 | 109 | :abc), \-- 傿•°2 |
| 110 | 3, \ | 110 | 3, \ |
| 111 | 4, \ | 111 | 4, \ |
| 112 | 函数5 abc; \-- 傿•°5 | 112 | 函数5(abc), \-- 傿•°5 |
| 113 | 6 | 113 | 6 |
| 114 | 114 | ||
| 115 | for å˜é‡a, \-- 解构1 | 115 | for å˜é‡a, \-- 解构1 |
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/whitespace.yue b/spec/inputs/whitespace.yue index 2655961..e501d3d 100644 --- a/spec/inputs/whitespace.yue +++ b/spec/inputs/whitespace.yue | |||
| @@ -128,19 +128,19 @@ v = -> | |||
| 128 | c -- v3 | 128 | c -- v3 |
| 129 | 129 | ||
| 130 | v1, v2, \ | 130 | v1, v2, \ |
| 131 | v3 = -> | 131 | v3 = (-> |
| 132 | a; \-- end of function for v1 | 132 | a), \-- end of function for v1 |
| 133 | b, \-- v2 | 133 | b, \-- v2 |
| 134 | c -- v3 | 134 | c -- v3 |
| 135 | 135 | ||
| 136 | a, b, \ | 136 | a, b, \ |
| 137 | c, d, \ | 137 | c, d, \ |
| 138 | e, f = 1, \ | 138 | e, f = 1, \ |
| 139 | f2 | 139 | (f2 |
| 140 | :abc; \-- arg2 | 140 | :abc), \-- arg2 |
| 141 | 3, \ | 141 | 3, \ |
| 142 | 4, \ | 142 | 4, \ |
| 143 | f5 abc; \-- arg5 | 143 | f5(abc), \-- arg5 |
| 144 | 6 | 144 | 6 |
| 145 | 145 | ||
| 146 | for a, \-- destruct 1 | 146 | for a, \-- destruct 1 |
diff --git a/spec/inputs/with.yue b/spec/inputs/with.yue index 19b7be1..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 | ||
| @@ -152,4 +152,22 @@ do | |||
| 152 | return with {} | 152 | return with {} |
| 153 | return [123] | 153 | return [123] |
| 154 | 154 | ||
| 155 | do | ||
| 156 | f with item | ||
| 157 | if .id > 0 | ||
| 158 | break .content | ||
| 159 | |||
| 160 | a = with tb | ||
| 161 | if .v | ||
| 162 | break .a | ||
| 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 | |||
| 155 | nil | 173 | nil |
diff --git a/spec/outputs/5.1/import_global.lua b/spec/outputs/5.1/import_global.lua new file mode 100644 index 0000000..3b8334a --- /dev/null +++ b/spec/outputs/5.1/import_global.lua | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | do | ||
| 2 | local print = print | ||
| 3 | local math = math | ||
| 4 | print("hello") | ||
| 5 | math.random(10) | ||
| 6 | end | ||
| 7 | do | ||
| 8 | local print = print | ||
| 9 | local value = 1 | ||
| 10 | value = value + 2 | ||
| 11 | print(value) | ||
| 12 | end | ||
| 13 | do | ||
| 14 | local print | ||
| 15 | print = function(msg) | ||
| 16 | return msg | ||
| 17 | end | ||
| 18 | do | ||
| 19 | local math = math | ||
| 20 | print("local") | ||
| 21 | math.random(1) | ||
| 22 | end | ||
| 23 | end | ||
| 24 | do | ||
| 25 | local print = print | ||
| 26 | local tostring | ||
| 27 | tostring = function(v) | ||
| 28 | return "local" | ||
| 29 | end | ||
| 30 | tostring("value") | ||
| 31 | print(tostring(123)) | ||
| 32 | end | ||
| 33 | do | ||
| 34 | local func | ||
| 35 | func = function(x, y) | ||
| 36 | local type = type | ||
| 37 | local tostring = tostring | ||
| 38 | local print = print | ||
| 39 | return type(x, tostring(y, print)) | ||
| 40 | end | ||
| 41 | func(1, 2) | ||
| 42 | end | ||
| 43 | do | ||
| 44 | local xpcall = xpcall | ||
| 45 | local func = func | ||
| 46 | local world = world | ||
| 47 | local tostring = tostring | ||
| 48 | local print = print | ||
| 49 | xpcall(function() | ||
| 50 | return func("hello " .. tostring(world)) | ||
| 51 | end, function(err) | ||
| 52 | return print(err) | ||
| 53 | end) | ||
| 54 | end | ||
| 55 | do | ||
| 56 | local print = print | ||
| 57 | print(FLAG) | ||
| 58 | FLAG = 123 | ||
| 59 | end | ||
| 60 | do | ||
| 61 | local print = print | ||
| 62 | Foo = 10 | ||
| 63 | print(Foo) | ||
| 64 | Foo = Foo + 2 | ||
| 65 | end | ||
| 66 | do | ||
| 67 | local print = print | ||
| 68 | Bar = 1 | ||
| 69 | Baz = 2 | ||
| 70 | print(Bar, Baz) | ||
| 71 | end | ||
| 72 | do | ||
| 73 | local y = y | ||
| 74 | x = 3434 | ||
| 75 | if y then | ||
| 76 | x = 10 | ||
| 77 | end | ||
| 78 | end | ||
| 79 | do | ||
| 80 | local lowercase = lowercase | ||
| 81 | local tostring = tostring | ||
| 82 | local Uppercase = Uppercase | ||
| 83 | local foobar = "all " .. tostring(lowercase) | ||
| 84 | FooBar = "pascal case" | ||
| 85 | FOOBAR = "all " .. tostring(Uppercase) | ||
| 86 | end | ||
| 87 | do | ||
| 88 | local setmetatable = setmetatable | ||
| 89 | local print = print | ||
| 90 | do | ||
| 91 | local _class_0 | ||
| 92 | local _base_0 = { } | ||
| 93 | if _base_0.__index == nil then | ||
| 94 | _base_0.__index = _base_0 | ||
| 95 | end | ||
| 96 | _class_0 = setmetatable({ | ||
| 97 | __init = function() end, | ||
| 98 | __base = _base_0, | ||
| 99 | __name = "A" | ||
| 100 | }, { | ||
| 101 | __index = _base_0, | ||
| 102 | __call = function(cls, ...) | ||
| 103 | local _self_0 = setmetatable({ }, _base_0) | ||
| 104 | cls.__init(_self_0, ...) | ||
| 105 | return _self_0 | ||
| 106 | end | ||
| 107 | }) | ||
| 108 | _base_0.__class = _class_0 | ||
| 109 | A = _class_0 | ||
| 110 | end | ||
| 111 | Flag = 1 | ||
| 112 | const, x, y = "const", 1, 2 | ||
| 113 | print(math, table) | ||
| 114 | end | ||
| 115 | do | ||
| 116 | local X = X | ||
| 117 | X:func(1, 2, 3) | ||
| 118 | X.tag = "abc" | ||
| 119 | end | ||
| 120 | local _anon_func_0 = function(func) | ||
| 121 | return func | ||
| 122 | end | ||
| 123 | do | ||
| 124 | local func = func | ||
| 125 | local pcall = pcall | ||
| 126 | local f | ||
| 127 | f = function() | ||
| 128 | func() | ||
| 129 | return pcall(_anon_func_0, func) | ||
| 130 | end | ||
| 131 | end | ||
diff --git a/spec/outputs/5.1/literals.lua b/spec/outputs/5.1/literals.lua deleted file mode 100644 index 36c705a..0000000 --- a/spec/outputs/5.1/literals.lua +++ /dev/null | |||
| @@ -1,44 +0,0 @@ | |||
| 1 | local _ = { | ||
| 2 | 121, | ||
| 3 | 121.2323, | ||
| 4 | 121.2323e-1, | ||
| 5 | 121.2323e13434, | ||
| 6 | 2323E34, | ||
| 7 | 0x12323, | ||
| 8 | 0xfF2323, | ||
| 9 | 0xabcdef, | ||
| 10 | 0xABCDEF, | ||
| 11 | 0XFBC400, | ||
| 12 | 2.7365508487142853e-35, | ||
| 13 | 0xABCP321, | ||
| 14 | 2.4074124304840448e-35, | ||
| 15 | 6.4326233113470805e-94, | ||
| 16 | 0.1171875, | ||
| 17 | 162.1875, | ||
| 18 | 3.1415926535897931, | ||
| 19 | 1, | ||
| 20 | 8, | ||
| 21 | 15, | ||
| 22 | 201, | ||
| 23 | .2323, | ||
| 24 | .2323e-1, | ||
| 25 | .2323e13434, | ||
| 26 | 1LL, | ||
| 27 | 1ULL, | ||
| 28 | 9332LL, | ||
| 29 | 9332, | ||
| 30 | 0x2aLL, | ||
| 31 | 0x2aULL, | ||
| 32 | 1000000.0000001, | ||
| 33 | 1234e5678, | ||
| 34 | 1234E-5678, | ||
| 35 | 0xDEADBEEF, | ||
| 36 | [[ hello world ]], | ||
| 37 | [=[ hello world ]=], | ||
| 38 | [====[ hello world ]====], | ||
| 39 | "another world", | ||
| 40 | 'what world', | ||
| 41 | "\n hello world\n ", | ||
| 42 | 'yeah\n what is going on\n here is something cool' | ||
| 43 | } | ||
| 44 | return nil | ||
diff --git a/spec/outputs/5.1/loops.lua b/spec/outputs/5.1/loops.lua index 57b19be..e4f2871 100644 --- a/spec/outputs/5.1/loops.lua +++ b/spec/outputs/5.1/loops.lua | |||
| @@ -60,8 +60,8 @@ do | |||
| 60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
| 61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
| 62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
| 63 | _len_0 = _len_0 + 1 | ||
| 63 | end | 64 | end |
| 64 | _len_0 = _len_0 + 1 | ||
| 65 | end | 65 | end |
| 66 | x = _accum_0 | 66 | x = _accum_0 |
| 67 | end | 67 | end |
| @@ -132,13 +132,11 @@ do | |||
| 132 | end | 132 | end |
| 133 | do | 133 | do |
| 134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
| 135 | local _len_0 = 1 | ||
| 136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
| 137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
| 138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
| 139 | y = "hello" | 138 | y = "hello" |
| 140 | break | 139 | break |
| 141 | _len_0 = _len_0 + 1 | ||
| 142 | end | 140 | end |
| 143 | x = _accum_0 | 141 | x = _accum_0 |
| 144 | end | 142 | end |
| @@ -489,3 +487,131 @@ do | |||
| 489 | end | 487 | end |
| 490 | until false | 488 | until false |
| 491 | end | 489 | end |
| 490 | local _anon_func_0 = function(i, tb) | ||
| 491 | local _accum_0 = { } | ||
| 492 | local _len_0 = 1 | ||
| 493 | while tb[i] do | ||
| 494 | i = i + 1 | ||
| 495 | _accum_0[_len_0] = i - 1 | ||
| 496 | _len_0 = _len_0 + 1 | ||
| 497 | end | ||
| 498 | return _accum_0 | ||
| 499 | end | ||
| 500 | do | ||
| 501 | local index | ||
| 502 | do | ||
| 503 | local _accum_0 | ||
| 504 | for i = 1, #tb do | ||
| 505 | if tb[i] then | ||
| 506 | _accum_0 = i | ||
| 507 | break | ||
| 508 | end | ||
| 509 | end | ||
| 510 | index = _accum_0 | ||
| 511 | end | ||
| 512 | f((function() | ||
| 513 | local _accum_0 | ||
| 514 | for i = 1, #tb do | ||
| 515 | if tb[i] then | ||
| 516 | _accum_0 = i | ||
| 517 | break | ||
| 518 | end | ||
| 519 | end | ||
| 520 | return _accum_0 | ||
| 521 | end)()) | ||
| 522 | f((function() | ||
| 523 | local _accum_0 = { } | ||
| 524 | local _len_0 = 1 | ||
| 525 | for i = 1, #tb do | ||
| 526 | if tb[i] then | ||
| 527 | _accum_0[_len_0] = i | ||
| 528 | _len_0 = _len_0 + 1 | ||
| 529 | end | ||
| 530 | end | ||
| 531 | return _accum_0 | ||
| 532 | end)()) | ||
| 533 | i = 1 | ||
| 534 | local ids | ||
| 535 | do | ||
| 536 | local _accum_0 = { } | ||
| 537 | local _len_0 = 1 | ||
| 538 | while tb[i] do | ||
| 539 | i = i + 1 | ||
| 540 | _accum_0[_len_0] = i - 1 | ||
| 541 | _len_0 = _len_0 + 1 | ||
| 542 | end | ||
| 543 | ids = _accum_0 | ||
| 544 | end | ||
| 545 | i = 1 | ||
| 546 | local idx | ||
| 547 | do | ||
| 548 | local _accum_0 | ||
| 549 | while tb[i] do | ||
| 550 | i = i + 1 | ||
| 551 | _accum_0 = i - 1 | ||
| 552 | break | ||
| 553 | end | ||
| 554 | idx = _accum_0 | ||
| 555 | end | ||
| 556 | local f1 | ||
| 557 | f1 = function() | ||
| 558 | i = 1 | ||
| 559 | return f(_anon_func_0(i, tb)) | ||
| 560 | end | ||
| 561 | i = 1 | ||
| 562 | f((function() | ||
| 563 | local _accum_0 | ||
| 564 | while tb[i] do | ||
| 565 | i = i + 1 | ||
| 566 | _accum_0 = i - 1 | ||
| 567 | break | ||
| 568 | end | ||
| 569 | return _accum_0 | ||
| 570 | end)()) | ||
| 571 | local _accum_0 = { } | ||
| 572 | local _len_0 = 1 | ||
| 573 | local _list_3 = items | ||
| 574 | for _index_0 = 1, #_list_3 do | ||
| 575 | local item = _list_3[_index_0] | ||
| 576 | local _type_0 = type(item) | ||
| 577 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 578 | if _tab_0 then | ||
| 579 | local value = item.value | ||
| 580 | if "A" == item.type and value ~= nil then | ||
| 581 | if value > 5 then | ||
| 582 | _accum_0[_len_0] = item | ||
| 583 | _len_0 = _len_0 + 1 | ||
| 584 | end | ||
| 585 | end | ||
| 586 | end | ||
| 587 | end | ||
| 588 | list = _accum_0 | ||
| 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 f6d5d61..3b0724a 100644 --- a/spec/outputs/codes_from_doc.lua +++ b/spec/outputs/codes_from_doc.lua | |||
| @@ -20,6 +20,38 @@ local inventory = { | |||
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | } | 22 | } |
| 23 | local map | ||
| 24 | map = function(arr, action) | ||
| 25 | local _accum_0 = { } | ||
| 26 | local _len_0 = 1 | ||
| 27 | for _index_0 = 1, #arr do | ||
| 28 | local item = arr[_index_0] | ||
| 29 | _accum_0[_len_0] = action(item) | ||
| 30 | _len_0 = _len_0 + 1 | ||
| 31 | end | ||
| 32 | return _accum_0 | ||
| 33 | end | ||
| 34 | local filter | ||
| 35 | filter = function(arr, cond) | ||
| 36 | local _accum_0 = { } | ||
| 37 | local _len_0 = 1 | ||
| 38 | for _index_0 = 1, #arr do | ||
| 39 | local item = arr[_index_0] | ||
| 40 | if cond(item) then | ||
| 41 | _accum_0[_len_0] = item | ||
| 42 | _len_0 = _len_0 + 1 | ||
| 43 | end | ||
| 44 | end | ||
| 45 | return _accum_0 | ||
| 46 | end | ||
| 47 | local reduce | ||
| 48 | reduce = function(arr, init, action) | ||
| 49 | for _index_0 = 1, #arr do | ||
| 50 | local item = arr[_index_0] | ||
| 51 | init = action(init, item) | ||
| 52 | end | ||
| 53 | return init | ||
| 54 | end | ||
| 23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
| 24 | 1, | 56 | 1, |
| 25 | 2, | 57 | 2, |
| @@ -41,8 +73,8 @@ local apple = setmetatable({ | |||
| 41 | if (getmetatable(apple) ~= nil) then | 73 | if (getmetatable(apple) ~= nil) then |
| 42 | p(apple.size, apple.color, getmetatable(apple).__index) | 74 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 43 | end | 75 | end |
| 44 | local _ud83c_udf1b = "月之脚本" | 76 | local _u1f31b = "月之脚本" |
| 45 | _module_0["🌛"] = _ud83c_udf1b | 77 | _module_0["🌛"] = _u1f31b |
| 46 | return _module_0 | 78 | return _module_0 |
| 47 | local area = 6.2831853071796 * 5 | 79 | local area = 6.2831853071796 * 5 |
| 48 | print('hello world') | 80 | print('hello world') |
| @@ -77,6 +109,12 @@ end | |||
| 77 | print("yuescript") | 109 | print("yuescript") |
| 78 | print(3) | 110 | print(3) |
| 79 | 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 | ||
| 80 | if tb ~= nil then | 118 | if tb ~= nil then |
| 81 | tb:func() | 119 | tb:func() |
| 82 | end | 120 | end |
| @@ -109,6 +147,21 @@ print((function() | |||
| 109 | end)()) | 147 | end)()) |
| 110 | local tab = { } | 148 | local tab = { } |
| 111 | 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 | ||
| 112 | local parts = { | 165 | local parts = { |
| 113 | "shoulders", | 166 | "shoulders", |
| 114 | "knees" | 167 | "knees" |
| @@ -177,6 +230,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 177 | end | 230 | end |
| 178 | end | 231 | end |
| 179 | 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 | ||
| 180 | local mt = { } | 245 | local mt = { } |
| 181 | local add | 246 | local add |
| 182 | add = function(self, right) | 247 | add = function(self, right) |
| @@ -307,6 +372,14 @@ func({ | |||
| 307 | 2, | 372 | 2, |
| 308 | 3 | 373 | 3 |
| 309 | }) | 374 | }) |
| 375 | local f | ||
| 376 | f = function() | ||
| 377 | return { | ||
| 378 | 1, | ||
| 379 | 2, | ||
| 380 | 3 | ||
| 381 | } | ||
| 382 | end | ||
| 310 | local tb = { | 383 | local tb = { |
| 311 | name = "abc", | 384 | name = "abc", |
| 312 | values = { | 385 | values = { |
| @@ -368,6 +441,25 @@ do | |||
| 368 | local _obj_0 = require("export") | 441 | local _obj_0 = require("export") |
| 369 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] | 442 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] |
| 370 | end | 443 | end |
| 444 | do | ||
| 445 | local tostring <const> = tostring | ||
| 446 | local concat <const> = table.concat | ||
| 447 | print(concat({ | ||
| 448 | "a", | ||
| 449 | tostring(1) | ||
| 450 | })) | ||
| 451 | end | ||
| 452 | do | ||
| 453 | local print <const> = print | ||
| 454 | local math <const> = math | ||
| 455 | print("hello") | ||
| 456 | math.random(3) | ||
| 457 | end | ||
| 458 | do | ||
| 459 | local print <const> = print | ||
| 460 | print(FLAG) | ||
| 461 | FLAG = 123 | ||
| 462 | end | ||
| 371 | local _module_0 = { } | 463 | local _module_0 = { } |
| 372 | local a, b, c = 1, 2, 3 | 464 | local a, b, c = 1, 2, 3 |
| 373 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c | 465 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c |
| @@ -547,6 +639,59 @@ end | |||
| 547 | local two, four | 639 | local two, four |
| 548 | local _obj_0 = items | 640 | local _obj_0 = items |
| 549 | two, four = _obj_0[2], _obj_0[4] | 641 | two, four = _obj_0[2], _obj_0[4] |
| 642 | local orders = { | ||
| 643 | "first", | ||
| 644 | "second", | ||
| 645 | "third", | ||
| 646 | "fourth", | ||
| 647 | "last" | ||
| 648 | } | ||
| 649 | local first, bulk, last = orders[1], (function() | ||
| 650 | local _accum_0 = { } | ||
| 651 | local _len_0 = 1 | ||
| 652 | local _max_0 = #orders + -2 + 1 | ||
| 653 | for _index_0 = 2, _max_0 do | ||
| 654 | local _item_0 = orders[_index_0] | ||
| 655 | _accum_0[_len_0] = _item_0 | ||
| 656 | _len_0 = _len_0 + 1 | ||
| 657 | end | ||
| 658 | return _accum_0 | ||
| 659 | end)(), orders[#orders] | ||
| 660 | print(first) | ||
| 661 | print(bulk) | ||
| 662 | print(last) | ||
| 663 | local first, rest | ||
| 664 | do | ||
| 665 | local _obj_0 = orders | ||
| 666 | first, rest = _obj_0[1], (function() | ||
| 667 | local _accum_0 = { } | ||
| 668 | local _len_0 = 1 | ||
| 669 | local _max_0 = #_obj_0 | ||
| 670 | for _index_0 = 2, _max_0 do | ||
| 671 | local _item_0 = _obj_0[_index_0] | ||
| 672 | _accum_0[_len_0] = _item_0 | ||
| 673 | _len_0 = _len_0 + 1 | ||
| 674 | end | ||
| 675 | return _accum_0 | ||
| 676 | end)() | ||
| 677 | end | ||
| 678 | local start, last | ||
| 679 | do | ||
| 680 | local _obj_0 = orders | ||
| 681 | start, last = (function() | ||
| 682 | local _accum_0 = { } | ||
| 683 | local _len_0 = 1 | ||
| 684 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 685 | for _index_0 = 1, _max_0 do | ||
| 686 | local _item_0 = _obj_0[_index_0] | ||
| 687 | _accum_0[_len_0] = _item_0 | ||
| 688 | _len_0 = _len_0 + 1 | ||
| 689 | end | ||
| 690 | return _accum_0 | ||
| 691 | end)(), _obj_0[#_obj_0] | ||
| 692 | end | ||
| 693 | local _obj_0 = orders | ||
| 694 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 550 | local tuples = { | 695 | local tuples = { |
| 551 | { | 696 | { |
| 552 | "hello", | 697 | "hello", |
| @@ -611,6 +756,9 @@ end | |||
| 611 | local first = select(1, ...) | 756 | local first = select(1, ...) |
| 612 | return print(ok, count, first) | 757 | return print(ok, count, first) |
| 613 | end)(fn(true)) | 758 | end)(fn(true)) |
| 759 | local a = 1 | ||
| 760 | local b = 2 | ||
| 761 | print(a + b) | ||
| 614 | Rx.Observable.fromRange(1, 8):filter(function(x) | 762 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 615 | return x % 2 == 0 | 763 | return x % 2 == 0 |
| 616 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 764 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -648,6 +796,56 @@ end) | |||
| 648 | if success then | 796 | if success then |
| 649 | print(result) | 797 | print(result) |
| 650 | end | 798 | end |
| 799 | local a, b, c | ||
| 800 | do | ||
| 801 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 802 | return func() | ||
| 803 | end) | ||
| 804 | if _ok_0 then | ||
| 805 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 806 | end | ||
| 807 | end | ||
| 808 | do | ||
| 809 | local _exp_0 = ((function() | ||
| 810 | return (function(_arg_0, ...) | ||
| 811 | local _ok_0 = _arg_0 | ||
| 812 | if _ok_0 then | ||
| 813 | return ... | ||
| 814 | end | ||
| 815 | end)(pcall(function() | ||
| 816 | return func() | ||
| 817 | end)) | ||
| 818 | end)()) | ||
| 819 | if _exp_0 ~= nil then | ||
| 820 | a = _exp_0 | ||
| 821 | else | ||
| 822 | a = "default" | ||
| 823 | end | ||
| 824 | end | ||
| 825 | f((function() | ||
| 826 | return (function(_arg_0, ...) | ||
| 827 | local _ok_0 = _arg_0 | ||
| 828 | if _ok_0 then | ||
| 829 | return ... | ||
| 830 | end | ||
| 831 | end)(pcall(function() | ||
| 832 | return func() | ||
| 833 | end)) | ||
| 834 | end)()) | ||
| 835 | f((function() | ||
| 836 | return (function(_arg_0, ...) | ||
| 837 | local _ok_0 = _arg_0 | ||
| 838 | if _ok_0 then | ||
| 839 | return ... | ||
| 840 | end | ||
| 841 | end)(xpcall(function() | ||
| 842 | print(123) | ||
| 843 | return func() | ||
| 844 | end, function(e) | ||
| 845 | print(e) | ||
| 846 | return e | ||
| 847 | end)) | ||
| 848 | end)()) | ||
| 651 | local a <const> = 123 | 849 | local a <const> = 123 |
| 652 | local _ <close> = setmetatable({ }, { | 850 | local _ <close> = setmetatable({ }, { |
| 653 | __close = function() | 851 | __close = function() |
| @@ -657,10 +855,19 @@ local _ <close> = setmetatable({ }, { | |||
| 657 | local a, b, c, d | 855 | local a, b, c, d |
| 658 | local _obj_0 = tb | 856 | local _obj_0 = tb |
| 659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 857 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
| 858 | Constant = 123 | ||
| 660 | local some_string = "Here is a string\n that has a line break in it." | 859 | local some_string = "Here is a string\n that has a line break in it." |
| 661 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 860 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
| 662 | local integer = 1000000 | 861 | local integer = 1000000 |
| 663 | local hex = 0xEFBBBF | 862 | local hex = 0xEFBBBF |
| 863 | local binary = 19 | ||
| 864 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 865 | local fn | ||
| 866 | fn = function() | ||
| 867 | local str = "foo:\n bar: baz" | ||
| 868 | return str | ||
| 869 | end | ||
| 870 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 664 | local my_function | 871 | local my_function |
| 665 | my_function = function() end | 872 | my_function = function() end |
| 666 | my_function() | 873 | my_function() |
| @@ -755,6 +962,66 @@ if func(1, 2, 3, "hello", "world") then | |||
| 755 | print("hello") | 962 | print("hello") |
| 756 | print("I am inside if") | 963 | print("I am inside if") |
| 757 | end | 964 | end |
| 965 | local f1 | ||
| 966 | f1 = function(_arg_0) | ||
| 967 | local a, b, c | ||
| 968 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 969 | return print(a, b, c) | ||
| 970 | end | ||
| 971 | f1({ | ||
| 972 | a = 1, | ||
| 973 | b = "2", | ||
| 974 | c = { } | ||
| 975 | }) | ||
| 976 | local f2 | ||
| 977 | f2 = function(_arg_0, c) | ||
| 978 | local a1, b | ||
| 979 | a1, b = _arg_0.a, _arg_0.b | ||
| 980 | if a1 == nil then | ||
| 981 | a1 = 123 | ||
| 982 | end | ||
| 983 | if b == nil then | ||
| 984 | b = 'abc' | ||
| 985 | end | ||
| 986 | if c == nil then | ||
| 987 | c = { } | ||
| 988 | end | ||
| 989 | return print(a1, b, c) | ||
| 990 | end | ||
| 991 | local arg1 = { | ||
| 992 | a = 0 | ||
| 993 | } | ||
| 994 | f2(arg1, arg2) | ||
| 995 | local f | ||
| 996 | f = function(...) | ||
| 997 | local t = { | ||
| 998 | n = select("#", ...), | ||
| 999 | ... | ||
| 1000 | } | ||
| 1001 | print("argument count:", t.n) | ||
| 1002 | print("table length:", #t) | ||
| 1003 | for i = 1, t.n do | ||
| 1004 | print(t[i]) | ||
| 1005 | end | ||
| 1006 | end | ||
| 1007 | f(1, 2, 3) | ||
| 1008 | f("a", "b", "c", "d") | ||
| 1009 | f() | ||
| 1010 | local process | ||
| 1011 | process = function(...) | ||
| 1012 | local args = { | ||
| 1013 | n = select("#", ...), | ||
| 1014 | ... | ||
| 1015 | } | ||
| 1016 | local sum = 0 | ||
| 1017 | for i = 1, args.n do | ||
| 1018 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 1019 | sum = sum + args[i] | ||
| 1020 | end | ||
| 1021 | end | ||
| 1022 | return sum | ||
| 1023 | end | ||
| 1024 | process(1, nil, 3, nil, 5) | ||
| 758 | f(function() | 1025 | f(function() |
| 759 | return print("hello") | 1026 | return print("hello") |
| 760 | end) | 1027 | end) |
| @@ -880,6 +1147,28 @@ for _index_0 = 1, #_list_0 do | |||
| 880 | _len_0 = _len_0 + 1 | 1147 | _len_0 = _len_0 + 1 |
| 881 | end | 1148 | end |
| 882 | doubled = _accum_0 | 1149 | doubled = _accum_0 |
| 1150 | local data = { | ||
| 1151 | a = { | ||
| 1152 | 1, | ||
| 1153 | 2, | ||
| 1154 | 3 | ||
| 1155 | }, | ||
| 1156 | b = { | ||
| 1157 | 4, | ||
| 1158 | 5, | ||
| 1159 | 6 | ||
| 1160 | } | ||
| 1161 | } | ||
| 1162 | local flat | ||
| 1163 | local _accum_0 = { } | ||
| 1164 | for k, v in pairs(data) do | ||
| 1165 | local _len_0 = #_accum_0 + 1 | ||
| 1166 | for _index_0 = 1, #v do | ||
| 1167 | local _elm_0 = v[_index_0] | ||
| 1168 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 1169 | end | ||
| 1170 | end | ||
| 1171 | flat = _accum_0 | ||
| 883 | local x_coords = { | 1172 | local x_coords = { |
| 884 | 4, | 1173 | 4, |
| 885 | 5, | 1174 | 5, |
| @@ -970,8 +1259,18 @@ local slice | |||
| 970 | local _accum_0 = { } | 1259 | local _accum_0 = { } |
| 971 | local _len_0 = 1 | 1260 | local _len_0 = 1 |
| 972 | local _list_0 = items | 1261 | local _list_0 = items |
| 973 | local _max_0 = 5 | 1262 | for _index_0 = 1, 5 do |
| 974 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | 1263 | local item = _list_0[_index_0] |
| 1264 | _accum_0[_len_0] = item | ||
| 1265 | _len_0 = _len_0 + 1 | ||
| 1266 | end | ||
| 1267 | slice = _accum_0 | ||
| 1268 | local slice | ||
| 1269 | local _accum_0 = { } | ||
| 1270 | local _len_0 = 1 | ||
| 1271 | local _list_0 = items | ||
| 1272 | local _max_0 = #_list_0 | ||
| 1273 | for _index_0 = 2, _max_0 do | ||
| 975 | local item = _list_0[_index_0] | 1274 | local item = _list_0[_index_0] |
| 976 | _accum_0[_len_0] = item | 1275 | _accum_0[_len_0] = item |
| 977 | _len_0 = _len_0 + 1 | 1276 | _len_0 = _len_0 + 1 |
| @@ -981,7 +1280,8 @@ local slice | |||
| 981 | local _accum_0 = { } | 1280 | local _accum_0 = { } |
| 982 | local _len_0 = 1 | 1281 | local _len_0 = 1 |
| 983 | local _list_0 = items | 1282 | local _list_0 = items |
| 984 | for _index_0 = 2, #_list_0 do | 1283 | local _max_0 = #_list_0 |
| 1284 | for _index_0 = 1, _max_0, 2 do | ||
| 985 | local item = _list_0[_index_0] | 1285 | local item = _list_0[_index_0] |
| 986 | _accum_0[_len_0] = item | 1286 | _accum_0[_len_0] = item |
| 987 | _len_0 = _len_0 + 1 | 1287 | _len_0 = _len_0 + 1 |
| @@ -991,12 +1291,35 @@ local slice | |||
| 991 | local _accum_0 = { } | 1291 | local _accum_0 = { } |
| 992 | local _len_0 = 1 | 1292 | local _len_0 = 1 |
| 993 | local _list_0 = items | 1293 | local _list_0 = items |
| 994 | for _index_0 = 1, #_list_0, 2 do | 1294 | local _min_0 = #_list_0 + -4 + 1 |
| 1295 | local _max_0 = #_list_0 + -1 + 1 | ||
| 1296 | for _index_0 = _min_0, _max_0 do | ||
| 995 | local item = _list_0[_index_0] | 1297 | local item = _list_0[_index_0] |
| 996 | _accum_0[_len_0] = item | 1298 | _accum_0[_len_0] = item |
| 997 | _len_0 = _len_0 + 1 | 1299 | _len_0 = _len_0 + 1 |
| 998 | end | 1300 | end |
| 999 | slice = _accum_0 | 1301 | slice = _accum_0 |
| 1302 | local reverse_slice | ||
| 1303 | local _accum_0 = { } | ||
| 1304 | local _len_0 = 1 | ||
| 1305 | local _list_0 = items | ||
| 1306 | local _min_0 = #_list_0 + -1 + 1 | ||
| 1307 | for _index_0 = _min_0, 1, -1 do | ||
| 1308 | local item = _list_0[_index_0] | ||
| 1309 | _accum_0[_len_0] = item | ||
| 1310 | _len_0 = _len_0 + 1 | ||
| 1311 | end | ||
| 1312 | reverse_slice = _accum_0 | ||
| 1313 | local sub_list | ||
| 1314 | local _accum_0 = { } | ||
| 1315 | local _len_0 = 1 | ||
| 1316 | local _list_0 = items | ||
| 1317 | for _index_0 = 2, 4 do | ||
| 1318 | local _item_0 = _list_0[_index_0] | ||
| 1319 | _accum_0[_len_0] = _item_0 | ||
| 1320 | _len_0 = _len_0 + 1 | ||
| 1321 | end | ||
| 1322 | sub_list = _accum_0 | ||
| 1000 | for i = 10, 20 do | 1323 | for i = 10, 20 do |
| 1001 | print(i) | 1324 | print(i) |
| 1002 | end | 1325 | end |
| @@ -1007,8 +1330,7 @@ for key, value in pairs(object) do | |||
| 1007 | print(key, value) | 1330 | print(key, value) |
| 1008 | end | 1331 | end |
| 1009 | local _list_0 = items | 1332 | local _list_0 = items |
| 1010 | local _max_0 = 4 | 1333 | for _index_0 = 2, 4 do |
| 1011 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 1012 | local item = _list_0[_index_0] | 1334 | local item = _list_0[_index_0] |
| 1013 | print(item) | 1335 | print(item) |
| 1014 | end | 1336 | end |
| @@ -1026,12 +1348,24 @@ local _len_0 = 1 | |||
| 1026 | for i = 1, 20 do | 1348 | for i = 1, 20 do |
| 1027 | if i % 2 == 0 then | 1349 | if i % 2 == 0 then |
| 1028 | _accum_0[_len_0] = i * 2 | 1350 | _accum_0[_len_0] = i * 2 |
| 1351 | _len_0 = _len_0 + 1 | ||
| 1029 | else | 1352 | else |
| 1030 | _accum_0[_len_0] = i | 1353 | _accum_0[_len_0] = i |
| 1354 | _len_0 = _len_0 + 1 | ||
| 1031 | end | 1355 | end |
| 1032 | _len_0 = _len_0 + 1 | ||
| 1033 | end | 1356 | end |
| 1034 | doubled_evens = _accum_0 | 1357 | doubled_evens = _accum_0 |
| 1358 | local first_large | ||
| 1359 | local _accum_0 | ||
| 1360 | local _list_0 = numbers | ||
| 1361 | for _index_0 = 1, #_list_0 do | ||
| 1362 | local n = _list_0[_index_0] | ||
| 1363 | if n > 10 then | ||
| 1364 | _accum_0 = n | ||
| 1365 | break | ||
| 1366 | end | ||
| 1367 | end | ||
| 1368 | first_large = _accum_0 | ||
| 1035 | local func_a | 1369 | local func_a |
| 1036 | func_a = function() | 1370 | func_a = function() |
| 1037 | for i = 1, 10 do | 1371 | for i = 1, 10 do |
| @@ -1180,7 +1514,7 @@ if "Robert" == name then | |||
| 1180 | elseif "Dan" == name or "Daniel" == name then | 1514 | elseif "Dan" == name or "Daniel" == name then |
| 1181 | print("Your name, it's Dan") | 1515 | print("Your name, it's Dan") |
| 1182 | else | 1516 | else |
| 1183 | print("I don't know about your name") | 1517 | print("I don't know about you with name " .. tostring(name)) |
| 1184 | end | 1518 | end |
| 1185 | local b = 1 | 1519 | local b = 1 |
| 1186 | local next_number | 1520 | local next_number |
| @@ -1280,6 +1614,192 @@ if _tab_0 then | |||
| 1280 | end | 1614 | end |
| 1281 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1615 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
| 1282 | end | 1616 | end |
| 1617 | local _exp_0 = tb | ||
| 1618 | local _type_0 = type(_exp_0) | ||
| 1619 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1620 | local _match_0 = false | ||
| 1621 | if _tab_0 then | ||
| 1622 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
| 1623 | _match_0 = true | ||
| 1624 | print("1, 2, 3") | ||
| 1625 | end | ||
| 1626 | end | ||
| 1627 | if not _match_0 then | ||
| 1628 | local _match_1 = false | ||
| 1629 | if _tab_0 then | ||
| 1630 | local b = _exp_0[2] | ||
| 1631 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
| 1632 | _match_1 = true | ||
| 1633 | print("1, " .. tostring(b) .. ", 3") | ||
| 1634 | end | ||
| 1635 | end | ||
| 1636 | if not _match_1 then | ||
| 1637 | if _tab_0 then | ||
| 1638 | local b = _exp_0[3] | ||
| 1639 | if b == nil then | ||
| 1640 | b = 3 | ||
| 1641 | end | ||
| 1642 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
| 1643 | print("1, 2, " .. tostring(b)) | ||
| 1644 | end | ||
| 1645 | end | ||
| 1646 | end | ||
| 1647 | end | ||
| 1648 | local _exp_0 = tb | ||
| 1649 | local _type_0 = type(_exp_0) | ||
| 1650 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1651 | local _match_0 = false | ||
| 1652 | if _tab_0 then | ||
| 1653 | local result = _exp_0.result | ||
| 1654 | if true == _exp_0.success and result ~= nil then | ||
| 1655 | _match_0 = true | ||
| 1656 | print("success", result) | ||
| 1657 | end | ||
| 1658 | end | ||
| 1659 | if not _match_0 then | ||
| 1660 | local _match_1 = false | ||
| 1661 | if _tab_0 then | ||
| 1662 | if false == _exp_0.success then | ||
| 1663 | _match_1 = true | ||
| 1664 | print("failed", result) | ||
| 1665 | end | ||
| 1666 | end | ||
| 1667 | if not _match_1 then | ||
| 1668 | print("invalid") | ||
| 1669 | end | ||
| 1670 | end | ||
| 1671 | local _exp_0 = tb | ||
| 1672 | local _type_0 = type(_exp_0) | ||
| 1673 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1674 | local _match_0 = false | ||
| 1675 | if _tab_0 then | ||
| 1676 | local content | ||
| 1677 | do | ||
| 1678 | local _obj_0 = _exp_0.data | ||
| 1679 | local _type_1 = type(_obj_0) | ||
| 1680 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 1681 | content = _obj_0.content | ||
| 1682 | end | ||
| 1683 | end | ||
| 1684 | local _val_0 | ||
| 1685 | do | ||
| 1686 | local _obj_0 = _exp_0.data | ||
| 1687 | if _obj_0 ~= nil then | ||
| 1688 | _val_0 = _obj_0.type | ||
| 1689 | end | ||
| 1690 | end | ||
| 1691 | if "success" == _val_0 and content ~= nil then | ||
| 1692 | _match_0 = true | ||
| 1693 | print("success", content) | ||
| 1694 | end | ||
| 1695 | end | ||
| 1696 | if not _match_0 then | ||
| 1697 | local _match_1 = false | ||
| 1698 | if _tab_0 then | ||
| 1699 | local content | ||
| 1700 | do | ||
| 1701 | local _obj_0 = _exp_0.data | ||
| 1702 | local _type_1 = type(_obj_0) | ||
| 1703 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 1704 | content = _obj_0.content | ||
| 1705 | end | ||
| 1706 | end | ||
| 1707 | local _val_0 | ||
| 1708 | do | ||
| 1709 | local _obj_0 = _exp_0.data | ||
| 1710 | if _obj_0 ~= nil then | ||
| 1711 | _val_0 = _obj_0.type | ||
| 1712 | end | ||
| 1713 | end | ||
| 1714 | if "error" == _val_0 and content ~= nil then | ||
| 1715 | _match_1 = true | ||
| 1716 | print("failed", content) | ||
| 1717 | end | ||
| 1718 | end | ||
| 1719 | if not _match_1 then | ||
| 1720 | print("invalid") | ||
| 1721 | end | ||
| 1722 | end | ||
| 1723 | local _exp_0 = tb | ||
| 1724 | local _type_0 = type(_exp_0) | ||
| 1725 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1726 | if _tab_0 then | ||
| 1727 | local fourth = _exp_0[4] | ||
| 1728 | local _val_0 | ||
| 1729 | do | ||
| 1730 | local _obj_0 = _exp_0[1] | ||
| 1731 | if _obj_0 ~= nil then | ||
| 1732 | _val_0 = _obj_0.a | ||
| 1733 | end | ||
| 1734 | end | ||
| 1735 | local _val_1 | ||
| 1736 | do | ||
| 1737 | local _obj_0 = _exp_0[1] | ||
| 1738 | if _obj_0 ~= nil then | ||
| 1739 | _val_1 = _obj_0.b | ||
| 1740 | end | ||
| 1741 | end | ||
| 1742 | local _val_2 | ||
| 1743 | do | ||
| 1744 | local _obj_0 = _exp_0[2] | ||
| 1745 | if _obj_0 ~= nil then | ||
| 1746 | _val_2 = _obj_0.a | ||
| 1747 | end | ||
| 1748 | end | ||
| 1749 | local _val_3 | ||
| 1750 | do | ||
| 1751 | local _obj_0 = _exp_0[2] | ||
| 1752 | if _obj_0 ~= nil then | ||
| 1753 | _val_3 = _obj_0.b | ||
| 1754 | end | ||
| 1755 | end | ||
| 1756 | local _val_4 | ||
| 1757 | do | ||
| 1758 | local _obj_0 = _exp_0[3] | ||
| 1759 | if _obj_0 ~= nil then | ||
| 1760 | _val_4 = _obj_0.a | ||
| 1761 | end | ||
| 1762 | end | ||
| 1763 | local _val_5 | ||
| 1764 | do | ||
| 1765 | local _obj_0 = _exp_0[3] | ||
| 1766 | if _obj_0 ~= nil then | ||
| 1767 | _val_5 = _obj_0.b | ||
| 1768 | end | ||
| 1769 | end | ||
| 1770 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
| 1771 | print("matched", fourth) | ||
| 1772 | end | ||
| 1773 | end | ||
| 1774 | local segments = { | ||
| 1775 | "admin", | ||
| 1776 | "users", | ||
| 1777 | "logs", | ||
| 1778 | "view" | ||
| 1779 | } | ||
| 1780 | local _type_0 = type(segments) | ||
| 1781 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1782 | if _tab_0 then | ||
| 1783 | local groups | ||
| 1784 | do | ||
| 1785 | local _accum_0 = { } | ||
| 1786 | local _len_0 = 1 | ||
| 1787 | local _max_0 = #segments + -3 + 1 | ||
| 1788 | for _index_0 = 1, _max_0 do | ||
| 1789 | local _item_0 = segments[_index_0] | ||
| 1790 | _accum_0[_len_0] = _item_0 | ||
| 1791 | _len_0 = _len_0 + 1 | ||
| 1792 | end | ||
| 1793 | groups = _accum_0 | ||
| 1794 | end | ||
| 1795 | local resource = segments[#segments - 1] | ||
| 1796 | local action = segments[#segments] | ||
| 1797 | if resource ~= nil and action ~= nil then | ||
| 1798 | print("Group:", groups) | ||
| 1799 | print("Resource:", resource) | ||
| 1800 | print("Action:", action) | ||
| 1801 | end | ||
| 1802 | end | ||
| 1283 | local Inventory | 1803 | local Inventory |
| 1284 | local _class_0 | 1804 | local _class_0 |
| 1285 | local _base_0 = { | 1805 | local _base_0 = { |
| @@ -1936,6 +2456,10 @@ do | |||
| 1936 | _with_1["key-name"] = value | 2456 | _with_1["key-name"] = value |
| 1937 | end | 2457 | end |
| 1938 | _with_0[#_with_0 + 1] = "abc" | 2458 | _with_0[#_with_0 + 1] = "abc" |
| 2459 | local _with_0 = obj | ||
| 2460 | if _with_0 ~= nil then | ||
| 2461 | print(obj.name) | ||
| 2462 | end | ||
| 1939 | do | 2463 | do |
| 1940 | local var = "hello" | 2464 | local var = "hello" |
| 1941 | print(var) | 2465 | print(var) |
| @@ -2026,6 +2550,38 @@ local inventory = { | |||
| 2026 | } | 2550 | } |
| 2027 | } | 2551 | } |
| 2028 | } | 2552 | } |
| 2553 | local map | ||
| 2554 | map = function(arr, action) | ||
| 2555 | local _accum_0 = { } | ||
| 2556 | local _len_0 = 1 | ||
| 2557 | for _index_0 = 1, #arr do | ||
| 2558 | local item = arr[_index_0] | ||
| 2559 | _accum_0[_len_0] = action(item) | ||
| 2560 | _len_0 = _len_0 + 1 | ||
| 2561 | end | ||
| 2562 | return _accum_0 | ||
| 2563 | end | ||
| 2564 | local filter | ||
| 2565 | filter = function(arr, cond) | ||
| 2566 | local _accum_0 = { } | ||
| 2567 | local _len_0 = 1 | ||
| 2568 | for _index_0 = 1, #arr do | ||
| 2569 | local item = arr[_index_0] | ||
| 2570 | if cond(item) then | ||
| 2571 | _accum_0[_len_0] = item | ||
| 2572 | _len_0 = _len_0 + 1 | ||
| 2573 | end | ||
| 2574 | end | ||
| 2575 | return _accum_0 | ||
| 2576 | end | ||
| 2577 | local reduce | ||
| 2578 | reduce = function(arr, init, action) | ||
| 2579 | for _index_0 = 1, #arr do | ||
| 2580 | local item = arr[_index_0] | ||
| 2581 | init = action(init, item) | ||
| 2582 | end | ||
| 2583 | return init | ||
| 2584 | end | ||
| 2029 | print(reduce(filter(map({ | 2585 | print(reduce(filter(map({ |
| 2030 | 1, | 2586 | 1, |
| 2031 | 2, | 2587 | 2, |
| @@ -2047,8 +2603,8 @@ local apple = setmetatable({ | |||
| 2047 | if (getmetatable(apple) ~= nil) then | 2603 | if (getmetatable(apple) ~= nil) then |
| 2048 | p(apple.size, apple.color, getmetatable(apple).__index) | 2604 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 2049 | end | 2605 | end |
| 2050 | local _ud83c_udf1b = "月之脚本" | 2606 | local _u1f31b = "月之脚本" |
| 2051 | _module_0["🌛"] = _ud83c_udf1b | 2607 | _module_0["🌛"] = _u1f31b |
| 2052 | return _module_0 | 2608 | return _module_0 |
| 2053 | local area = 6.2831853071796 * 5 | 2609 | local area = 6.2831853071796 * 5 |
| 2054 | print('hello world') | 2610 | print('hello world') |
| @@ -2083,6 +2639,12 @@ end | |||
| 2083 | print("yuescript") | 2639 | print("yuescript") |
| 2084 | print(3) | 2640 | print(3) |
| 2085 | print("Valid enum type:", "Static") | 2641 | print("Valid enum type:", "Static") |
| 2642 | do | ||
| 2643 | print(123, "hello") | ||
| 2644 | end | ||
| 2645 | do | ||
| 2646 | print(123, "hello") | ||
| 2647 | end | ||
| 2086 | if tb ~= nil then | 2648 | if tb ~= nil then |
| 2087 | tb:func() | 2649 | tb:func() |
| 2088 | end | 2650 | end |
| @@ -2115,6 +2677,21 @@ print((function() | |||
| 2115 | end)()) | 2677 | end)()) |
| 2116 | local tab = { } | 2678 | local tab = { } |
| 2117 | tab[#tab + 1] = "Value" | 2679 | tab[#tab + 1] = "Value" |
| 2680 | local tbA = { | ||
| 2681 | 1, | ||
| 2682 | 2, | ||
| 2683 | 3 | ||
| 2684 | } | ||
| 2685 | local tbB = { | ||
| 2686 | 4, | ||
| 2687 | 5, | ||
| 2688 | 6 | ||
| 2689 | } | ||
| 2690 | local _len_0 = #tbA + 1 | ||
| 2691 | for _index_0 = 1, #tbB do | ||
| 2692 | local _elm_0 = tbB[_index_0] | ||
| 2693 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2694 | end | ||
| 2118 | local parts = { | 2695 | local parts = { |
| 2119 | "shoulders", | 2696 | "shoulders", |
| 2120 | "knees" | 2697 | "knees" |
| @@ -2183,6 +2760,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 2183 | end | 2760 | end |
| 2184 | end | 2761 | end |
| 2185 | merge = _tab_0 | 2762 | merge = _tab_0 |
| 2763 | local last | ||
| 2764 | do | ||
| 2765 | local _item_0 = data.items | ||
| 2766 | last = _item_0[#_item_0] | ||
| 2767 | end | ||
| 2768 | local second_last | ||
| 2769 | do | ||
| 2770 | local _item_0 = data.items | ||
| 2771 | second_last = _item_0[#_item_0 - 1] | ||
| 2772 | end | ||
| 2773 | local _obj_0 = data.items | ||
| 2774 | _obj_0[#_obj_0] = 1 | ||
| 2186 | local mt = { } | 2775 | local mt = { } |
| 2187 | local add | 2776 | local add |
| 2188 | add = function(self, right) | 2777 | add = function(self, right) |
| @@ -2313,6 +2902,14 @@ func({ | |||
| 2313 | 2, | 2902 | 2, |
| 2314 | 3 | 2903 | 3 |
| 2315 | }) | 2904 | }) |
| 2905 | local f | ||
| 2906 | f = function() | ||
| 2907 | return { | ||
| 2908 | 1, | ||
| 2909 | 2, | ||
| 2910 | 3 | ||
| 2911 | } | ||
| 2912 | end | ||
| 2316 | local tb = { | 2913 | local tb = { |
| 2317 | name = "abc", | 2914 | name = "abc", |
| 2318 | values = { | 2915 | values = { |
| @@ -2374,6 +2971,25 @@ do | |||
| 2374 | local _obj_0 = require("export") | 2971 | local _obj_0 = require("export") |
| 2375 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] | 2972 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] |
| 2376 | end | 2973 | end |
| 2974 | do | ||
| 2975 | local tostring <const> = tostring | ||
| 2976 | local concat <const> = table.concat | ||
| 2977 | print(concat({ | ||
| 2978 | "a", | ||
| 2979 | tostring(1) | ||
| 2980 | })) | ||
| 2981 | end | ||
| 2982 | do | ||
| 2983 | local print <const> = print | ||
| 2984 | local math <const> = math | ||
| 2985 | print("hello") | ||
| 2986 | math.random(3) | ||
| 2987 | end | ||
| 2988 | do | ||
| 2989 | local print <const> = print | ||
| 2990 | print(FLAG) | ||
| 2991 | FLAG = 123 | ||
| 2992 | end | ||
| 2377 | local _module_0 = { } | 2993 | local _module_0 = { } |
| 2378 | local a, b, c = 1, 2, 3 | 2994 | local a, b, c = 1, 2, 3 |
| 2379 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c | 2995 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c |
| @@ -2553,6 +3169,59 @@ end | |||
| 2553 | local two, four | 3169 | local two, four |
| 2554 | local _obj_0 = items | 3170 | local _obj_0 = items |
| 2555 | two, four = _obj_0[2], _obj_0[4] | 3171 | two, four = _obj_0[2], _obj_0[4] |
| 3172 | local orders = { | ||
| 3173 | "first", | ||
| 3174 | "second", | ||
| 3175 | "third", | ||
| 3176 | "fourth", | ||
| 3177 | "last" | ||
| 3178 | } | ||
| 3179 | local first, bulk, last = orders[1], (function() | ||
| 3180 | local _accum_0 = { } | ||
| 3181 | local _len_0 = 1 | ||
| 3182 | local _max_0 = #orders + -2 + 1 | ||
| 3183 | for _index_0 = 2, _max_0 do | ||
| 3184 | local _item_0 = orders[_index_0] | ||
| 3185 | _accum_0[_len_0] = _item_0 | ||
| 3186 | _len_0 = _len_0 + 1 | ||
| 3187 | end | ||
| 3188 | return _accum_0 | ||
| 3189 | end)(), orders[#orders] | ||
| 3190 | print(first) | ||
| 3191 | print(bulk) | ||
| 3192 | print(last) | ||
| 3193 | local first, rest | ||
| 3194 | do | ||
| 3195 | local _obj_0 = orders | ||
| 3196 | first, rest = _obj_0[1], (function() | ||
| 3197 | local _accum_0 = { } | ||
| 3198 | local _len_0 = 1 | ||
| 3199 | local _max_0 = #_obj_0 | ||
| 3200 | for _index_0 = 2, _max_0 do | ||
| 3201 | local _item_0 = _obj_0[_index_0] | ||
| 3202 | _accum_0[_len_0] = _item_0 | ||
| 3203 | _len_0 = _len_0 + 1 | ||
| 3204 | end | ||
| 3205 | return _accum_0 | ||
| 3206 | end)() | ||
| 3207 | end | ||
| 3208 | local start, last | ||
| 3209 | do | ||
| 3210 | local _obj_0 = orders | ||
| 3211 | start, last = (function() | ||
| 3212 | local _accum_0 = { } | ||
| 3213 | local _len_0 = 1 | ||
| 3214 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 3215 | for _index_0 = 1, _max_0 do | ||
| 3216 | local _item_0 = _obj_0[_index_0] | ||
| 3217 | _accum_0[_len_0] = _item_0 | ||
| 3218 | _len_0 = _len_0 + 1 | ||
| 3219 | end | ||
| 3220 | return _accum_0 | ||
| 3221 | end)(), _obj_0[#_obj_0] | ||
| 3222 | end | ||
| 3223 | local _obj_0 = orders | ||
| 3224 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 2556 | local tuples = { | 3225 | local tuples = { |
| 2557 | { | 3226 | { |
| 2558 | "hello", | 3227 | "hello", |
| @@ -2617,6 +3286,9 @@ end | |||
| 2617 | local first = select(1, ...) | 3286 | local first = select(1, ...) |
| 2618 | return print(ok, count, first) | 3287 | return print(ok, count, first) |
| 2619 | end)(fn(true)) | 3288 | end)(fn(true)) |
| 3289 | local a = 1 | ||
| 3290 | local b = 2 | ||
| 3291 | print(a + b) | ||
| 2620 | Rx.Observable.fromRange(1, 8):filter(function(x) | 3292 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 2621 | return x % 2 == 0 | 3293 | return x % 2 == 0 |
| 2622 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 3294 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -2654,6 +3326,56 @@ end) | |||
| 2654 | if success then | 3326 | if success then |
| 2655 | print(result) | 3327 | print(result) |
| 2656 | end | 3328 | end |
| 3329 | local a, b, c | ||
| 3330 | do | ||
| 3331 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 3332 | return func() | ||
| 3333 | end) | ||
| 3334 | if _ok_0 then | ||
| 3335 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 3336 | end | ||
| 3337 | end | ||
| 3338 | do | ||
| 3339 | local _exp_0 = ((function() | ||
| 3340 | return (function(_arg_0, ...) | ||
| 3341 | local _ok_0 = _arg_0 | ||
| 3342 | if _ok_0 then | ||
| 3343 | return ... | ||
| 3344 | end | ||
| 3345 | end)(pcall(function() | ||
| 3346 | return func() | ||
| 3347 | end)) | ||
| 3348 | end)()) | ||
| 3349 | if _exp_0 ~= nil then | ||
| 3350 | a = _exp_0 | ||
| 3351 | else | ||
| 3352 | a = "default" | ||
| 3353 | end | ||
| 3354 | end | ||
| 3355 | f((function() | ||
| 3356 | return (function(_arg_0, ...) | ||
| 3357 | local _ok_0 = _arg_0 | ||
| 3358 | if _ok_0 then | ||
| 3359 | return ... | ||
| 3360 | end | ||
| 3361 | end)(pcall(function() | ||
| 3362 | return func() | ||
| 3363 | end)) | ||
| 3364 | end)()) | ||
| 3365 | f((function() | ||
| 3366 | return (function(_arg_0, ...) | ||
| 3367 | local _ok_0 = _arg_0 | ||
| 3368 | if _ok_0 then | ||
| 3369 | return ... | ||
| 3370 | end | ||
| 3371 | end)(xpcall(function() | ||
| 3372 | print(123) | ||
| 3373 | return func() | ||
| 3374 | end, function(e) | ||
| 3375 | print(e) | ||
| 3376 | return e | ||
| 3377 | end)) | ||
| 3378 | end)()) | ||
| 2657 | local a <const> = 123 | 3379 | local a <const> = 123 |
| 2658 | local _ <close> = setmetatable({ }, { | 3380 | local _ <close> = setmetatable({ }, { |
| 2659 | __close = function() | 3381 | __close = function() |
| @@ -2663,10 +3385,19 @@ local _ <close> = setmetatable({ }, { | |||
| 2663 | local a, b, c, d | 3385 | local a, b, c, d |
| 2664 | local _obj_0 = tb | 3386 | local _obj_0 = tb |
| 2665 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3387 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
| 3388 | Constant = 123 | ||
| 2666 | local some_string = "Here is a string\n that has a line break in it." | 3389 | local some_string = "Here is a string\n that has a line break in it." |
| 2667 | print("I am " .. tostring(math.random() * 100) .. "% sure.") | 3390 | print("I am " .. tostring(math.random() * 100) .. "% sure.") |
| 2668 | local integer = 1000000 | 3391 | local integer = 1000000 |
| 2669 | local hex = 0xEFBBBF | 3392 | local hex = 0xEFBBBF |
| 3393 | local binary = 19 | ||
| 3394 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 3395 | local fn | ||
| 3396 | fn = function() | ||
| 3397 | local str = "foo:\n bar: baz" | ||
| 3398 | return str | ||
| 3399 | end | ||
| 3400 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 2670 | local my_function | 3401 | local my_function |
| 2671 | my_function = function() end | 3402 | my_function = function() end |
| 2672 | my_function() | 3403 | my_function() |
| @@ -2761,6 +3492,96 @@ if func(1, 2, 3, "hello", "world") then | |||
| 2761 | print("hello") | 3492 | print("hello") |
| 2762 | print("I am inside if") | 3493 | print("I am inside if") |
| 2763 | end | 3494 | end |
| 3495 | local f1 | ||
| 3496 | f1 = function(_arg_0) | ||
| 3497 | local a, b, c | ||
| 3498 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 3499 | return print(a, b, c) | ||
| 3500 | end | ||
| 3501 | f1({ | ||
| 3502 | a = 1, | ||
| 3503 | b = "2", | ||
| 3504 | c = { } | ||
| 3505 | }) | ||
| 3506 | local f2 | ||
| 3507 | f2 = function(_arg_0, c) | ||
| 3508 | local a1, b | ||
| 3509 | a1, b = _arg_0.a, _arg_0.b | ||
| 3510 | if a1 == nil then | ||
| 3511 | a1 = 123 | ||
| 3512 | end | ||
| 3513 | if b == nil then | ||
| 3514 | b = 'abc' | ||
| 3515 | end | ||
| 3516 | if c == nil then | ||
| 3517 | c = { } | ||
| 3518 | end | ||
| 3519 | end | ||
| 3520 | print(a1, b, c) | ||
| 3521 | local arg1 = { | ||
| 3522 | a = 0 | ||
| 3523 | } | ||
| 3524 | f2(arg1, arg2) | ||
| 3525 | local findFirstEven | ||
| 3526 | findFirstEven = function(list) | ||
| 3527 | for _index_0 = 1, #list do | ||
| 3528 | local item = list[_index_0] | ||
| 3529 | if type(item) == "table" then | ||
| 3530 | for _index_1 = 1, #item do | ||
| 3531 | local sub = item[_index_1] | ||
| 3532 | if sub % 2 == 0 then | ||
| 3533 | return sub | ||
| 3534 | end | ||
| 3535 | end | ||
| 3536 | end | ||
| 3537 | end | ||
| 3538 | return nil | ||
| 3539 | end | ||
| 3540 | local findFirstEven | ||
| 3541 | findFirstEven = function(list) | ||
| 3542 | for _index_0 = 1, #list do | ||
| 3543 | local item = list[_index_0] | ||
| 3544 | if type(item) == "table" then | ||
| 3545 | for _index_1 = 1, #item do | ||
| 3546 | local sub = item[_index_1] | ||
| 3547 | if sub % 2 == 0 then | ||
| 3548 | return sub | ||
| 3549 | end | ||
| 3550 | end | ||
| 3551 | end | ||
| 3552 | end | ||
| 3553 | return nil | ||
| 3554 | end | ||
| 3555 | local f | ||
| 3556 | f = function(...) | ||
| 3557 | local t = { | ||
| 3558 | n = select("#", ...), | ||
| 3559 | ... | ||
| 3560 | } | ||
| 3561 | print("argument count:", t.n) | ||
| 3562 | print("table length:", #t) | ||
| 3563 | for i = 1, t.n do | ||
| 3564 | print(t[i]) | ||
| 3565 | end | ||
| 3566 | end | ||
| 3567 | f(1, 2, 3) | ||
| 3568 | f("a", "b", "c", "d") | ||
| 3569 | f() | ||
| 3570 | local process | ||
| 3571 | process = function(...) | ||
| 3572 | local args = { | ||
| 3573 | n = select("#", ...), | ||
| 3574 | ... | ||
| 3575 | } | ||
| 3576 | local sum = 0 | ||
| 3577 | for i = 1, args.n do | ||
| 3578 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 3579 | sum = sum + args[i] | ||
| 3580 | end | ||
| 3581 | end | ||
| 3582 | return sum | ||
| 3583 | end | ||
| 3584 | process(1, nil, 3, nil, 5) | ||
| 2764 | f(function() | 3585 | f(function() |
| 2765 | return print("hello") | 3586 | return print("hello") |
| 2766 | end) | 3587 | end) |
| @@ -2886,6 +3707,28 @@ for _index_0 = 1, #_list_0 do | |||
| 2886 | _len_0 = _len_0 + 1 | 3707 | _len_0 = _len_0 + 1 |
| 2887 | end | 3708 | end |
| 2888 | doubled = _accum_0 | 3709 | doubled = _accum_0 |
| 3710 | local data = { | ||
| 3711 | a = { | ||
| 3712 | 1, | ||
| 3713 | 2, | ||
| 3714 | 3 | ||
| 3715 | }, | ||
| 3716 | b = { | ||
| 3717 | 4, | ||
| 3718 | 5, | ||
| 3719 | 6 | ||
| 3720 | } | ||
| 3721 | } | ||
| 3722 | local flat | ||
| 3723 | local _accum_0 = { } | ||
| 3724 | for k, v in pairs(data) do | ||
| 3725 | local _len_0 = #_accum_0 + 1 | ||
| 3726 | for _index_0 = 1, #v do | ||
| 3727 | local _elm_0 = v[_index_0] | ||
| 3728 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 3729 | end | ||
| 3730 | end | ||
| 3731 | flat = _accum_0 | ||
| 2889 | local x_coords = { | 3732 | local x_coords = { |
| 2890 | 4, | 3733 | 4, |
| 2891 | 5, | 3734 | 5, |
| @@ -2976,8 +3819,7 @@ local slice | |||
| 2976 | local _accum_0 = { } | 3819 | local _accum_0 = { } |
| 2977 | local _len_0 = 1 | 3820 | local _len_0 = 1 |
| 2978 | local _list_0 = items | 3821 | local _list_0 = items |
| 2979 | local _max_0 = 5 | 3822 | for _index_0 = 1, 5 do |
| 2980 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 2981 | local item = _list_0[_index_0] | 3823 | local item = _list_0[_index_0] |
| 2982 | _accum_0[_len_0] = item | 3824 | _accum_0[_len_0] = item |
| 2983 | _len_0 = _len_0 + 1 | 3825 | _len_0 = _len_0 + 1 |
| @@ -2987,7 +3829,8 @@ local slice | |||
| 2987 | local _accum_0 = { } | 3829 | local _accum_0 = { } |
| 2988 | local _len_0 = 1 | 3830 | local _len_0 = 1 |
| 2989 | local _list_0 = items | 3831 | local _list_0 = items |
| 2990 | for _index_0 = 2, #_list_0 do | 3832 | local _max_0 = #_list_0 |
| 3833 | for _index_0 = 2, _max_0 do | ||
| 2991 | local item = _list_0[_index_0] | 3834 | local item = _list_0[_index_0] |
| 2992 | _accum_0[_len_0] = item | 3835 | _accum_0[_len_0] = item |
| 2993 | _len_0 = _len_0 + 1 | 3836 | _len_0 = _len_0 + 1 |
| @@ -2997,12 +3840,46 @@ local slice | |||
| 2997 | local _accum_0 = { } | 3840 | local _accum_0 = { } |
| 2998 | local _len_0 = 1 | 3841 | local _len_0 = 1 |
| 2999 | local _list_0 = items | 3842 | local _list_0 = items |
| 3000 | for _index_0 = 1, #_list_0, 2 do | 3843 | local _max_0 = #_list_0 |
| 3844 | for _index_0 = 1, _max_0, 2 do | ||
| 3001 | local item = _list_0[_index_0] | 3845 | local item = _list_0[_index_0] |
| 3002 | _accum_0[_len_0] = item | 3846 | _accum_0[_len_0] = item |
| 3003 | _len_0 = _len_0 + 1 | 3847 | _len_0 = _len_0 + 1 |
| 3004 | end | 3848 | end |
| 3005 | slice = _accum_0 | 3849 | slice = _accum_0 |
| 3850 | local slice | ||
| 3851 | local _accum_0 = { } | ||
| 3852 | local _len_0 = 1 | ||
| 3853 | local _list_0 = items | ||
| 3854 | local _min_0 = #_list_0 + -4 + 1 | ||
| 3855 | local _max_0 = #_list_0 + -1 + 1 | ||
| 3856 | for _index_0 = _min_0, _max_0 do | ||
| 3857 | local item = _list_0[_index_0] | ||
| 3858 | _accum_0[_len_0] = item | ||
| 3859 | _len_0 = _len_0 + 1 | ||
| 3860 | end | ||
| 3861 | slice = _accum_0 | ||
| 3862 | local reverse_slice | ||
| 3863 | local _accum_0 = { } | ||
| 3864 | local _len_0 = 1 | ||
| 3865 | local _list_0 = items | ||
| 3866 | local _min_0 = #_list_0 + -1 + 1 | ||
| 3867 | for _index_0 = _min_0, 1, -1 do | ||
| 3868 | local item = _list_0[_index_0] | ||
| 3869 | _accum_0[_len_0] = item | ||
| 3870 | _len_0 = _len_0 + 1 | ||
| 3871 | end | ||
| 3872 | reverse_slice = _accum_0 | ||
| 3873 | local sub_list | ||
| 3874 | local _accum_0 = { } | ||
| 3875 | local _len_0 = 1 | ||
| 3876 | local _list_0 = items | ||
| 3877 | for _index_0 = 2, 4 do | ||
| 3878 | local _item_0 = _list_0[_index_0] | ||
| 3879 | _accum_0[_len_0] = _item_0 | ||
| 3880 | _len_0 = _len_0 + 1 | ||
| 3881 | end | ||
| 3882 | sub_list = _accum_0 | ||
| 3006 | for i = 10, 20 do | 3883 | for i = 10, 20 do |
| 3007 | print(i) | 3884 | print(i) |
| 3008 | end | 3885 | end |
| @@ -3013,8 +3890,7 @@ for key, value in pairs(object) do | |||
| 3013 | print(key, value) | 3890 | print(key, value) |
| 3014 | end | 3891 | end |
| 3015 | local _list_0 = items | 3892 | local _list_0 = items |
| 3016 | local _max_0 = 4 | 3893 | for _index_0 = 2, 4 do |
| 3017 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3018 | local item = _list_0[_index_0] | 3894 | local item = _list_0[_index_0] |
| 3019 | print(item) | 3895 | print(item) |
| 3020 | end | 3896 | end |
| @@ -3032,12 +3908,24 @@ local _len_0 = 1 | |||
| 3032 | for i = 1, 20 do | 3908 | for i = 1, 20 do |
| 3033 | if i % 2 == 0 then | 3909 | if i % 2 == 0 then |
| 3034 | _accum_0[_len_0] = i * 2 | 3910 | _accum_0[_len_0] = i * 2 |
| 3911 | _len_0 = _len_0 + 1 | ||
| 3035 | else | 3912 | else |
| 3036 | _accum_0[_len_0] = i | 3913 | _accum_0[_len_0] = i |
| 3914 | _len_0 = _len_0 + 1 | ||
| 3037 | end | 3915 | end |
| 3038 | _len_0 = _len_0 + 1 | ||
| 3039 | end | 3916 | end |
| 3040 | doubled_evens = _accum_0 | 3917 | doubled_evens = _accum_0 |
| 3918 | local first_large | ||
| 3919 | local _accum_0 | ||
| 3920 | local _list_0 = numbers | ||
| 3921 | for _index_0 = 1, #_list_0 do | ||
| 3922 | local n = _list_0[_index_0] | ||
| 3923 | if n > 10 then | ||
| 3924 | _accum_0 = n | ||
| 3925 | break | ||
| 3926 | end | ||
| 3927 | end | ||
| 3928 | first_large = _accum_0 | ||
| 3041 | local func_a | 3929 | local func_a |
| 3042 | func_a = function() | 3930 | func_a = function() |
| 3043 | for i = 1, 10 do | 3931 | for i = 1, 10 do |
| @@ -3186,7 +4074,7 @@ if "Robert" == name then | |||
| 3186 | elseif "Dan" == name or "Daniel" == name then | 4074 | elseif "Dan" == name or "Daniel" == name then |
| 3187 | print("Your name, it's Dan") | 4075 | print("Your name, it's Dan") |
| 3188 | else | 4076 | else |
| 3189 | print("I don't know about your name") | 4077 | print("I don't know about you with name " .. tostring(name)) |
| 3190 | end | 4078 | end |
| 3191 | local b = 1 | 4079 | local b = 1 |
| 3192 | local next_number | 4080 | local next_number |
| @@ -3286,6 +4174,192 @@ if _tab_0 then | |||
| 3286 | end | 4174 | end |
| 3287 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 4175 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
| 3288 | end | 4176 | end |
| 4177 | local _exp_0 = tb | ||
| 4178 | local _type_0 = type(_exp_0) | ||
| 4179 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4180 | local _match_0 = false | ||
| 4181 | if _tab_0 then | ||
| 4182 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
| 4183 | _match_0 = true | ||
| 4184 | print("1, 2, 3") | ||
| 4185 | end | ||
| 4186 | end | ||
| 4187 | if not _match_0 then | ||
| 4188 | local _match_1 = false | ||
| 4189 | if _tab_0 then | ||
| 4190 | local b = _exp_0[2] | ||
| 4191 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
| 4192 | _match_1 = true | ||
| 4193 | print("1, " .. tostring(b) .. ", 3") | ||
| 4194 | end | ||
| 4195 | end | ||
| 4196 | if not _match_1 then | ||
| 4197 | if _tab_0 then | ||
| 4198 | local b = _exp_0[3] | ||
| 4199 | if b == nil then | ||
| 4200 | b = 3 | ||
| 4201 | end | ||
| 4202 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
| 4203 | print("1, 2, " .. tostring(b)) | ||
| 4204 | end | ||
| 4205 | end | ||
| 4206 | end | ||
| 4207 | end | ||
| 4208 | local _exp_0 = tb | ||
| 4209 | local _type_0 = type(_exp_0) | ||
| 4210 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4211 | local _match_0 = false | ||
| 4212 | if _tab_0 then | ||
| 4213 | local result = _exp_0.result | ||
| 4214 | if true == _exp_0.success and result ~= nil then | ||
| 4215 | _match_0 = true | ||
| 4216 | print("success", result) | ||
| 4217 | end | ||
| 4218 | end | ||
| 4219 | if not _match_0 then | ||
| 4220 | local _match_1 = false | ||
| 4221 | if _tab_0 then | ||
| 4222 | if false == _exp_0.success then | ||
| 4223 | _match_1 = true | ||
| 4224 | print("failed", result) | ||
| 4225 | end | ||
| 4226 | end | ||
| 4227 | if not _match_1 then | ||
| 4228 | print("invalid") | ||
| 4229 | end | ||
| 4230 | end | ||
| 4231 | local _exp_0 = tb | ||
| 4232 | local _type_0 = type(_exp_0) | ||
| 4233 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4234 | local _match_0 = false | ||
| 4235 | if _tab_0 then | ||
| 4236 | local content | ||
| 4237 | do | ||
| 4238 | local _obj_0 = _exp_0.data | ||
| 4239 | local _type_1 = type(_obj_0) | ||
| 4240 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 4241 | content = _obj_0.content | ||
| 4242 | end | ||
| 4243 | end | ||
| 4244 | local _val_0 | ||
| 4245 | do | ||
| 4246 | local _obj_0 = _exp_0.data | ||
| 4247 | if _obj_0 ~= nil then | ||
| 4248 | _val_0 = _obj_0.type | ||
| 4249 | end | ||
| 4250 | end | ||
| 4251 | if "success" == _val_0 and content ~= nil then | ||
| 4252 | _match_0 = true | ||
| 4253 | print("success", content) | ||
| 4254 | end | ||
| 4255 | end | ||
| 4256 | if not _match_0 then | ||
| 4257 | local _match_1 = false | ||
| 4258 | if _tab_0 then | ||
| 4259 | local content | ||
| 4260 | do | ||
| 4261 | local _obj_0 = _exp_0.data | ||
| 4262 | local _type_1 = type(_obj_0) | ||
| 4263 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 4264 | content = _obj_0.content | ||
| 4265 | end | ||
| 4266 | end | ||
| 4267 | local _val_0 | ||
| 4268 | do | ||
| 4269 | local _obj_0 = _exp_0.data | ||
| 4270 | if _obj_0 ~= nil then | ||
| 4271 | _val_0 = _obj_0.type | ||
| 4272 | end | ||
| 4273 | end | ||
| 4274 | if "error" == _val_0 and content ~= nil then | ||
| 4275 | _match_1 = true | ||
| 4276 | print("failed", content) | ||
| 4277 | end | ||
| 4278 | end | ||
| 4279 | if not _match_1 then | ||
| 4280 | print("invalid") | ||
| 4281 | end | ||
| 4282 | end | ||
| 4283 | local _exp_0 = tb | ||
| 4284 | local _type_0 = type(_exp_0) | ||
| 4285 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4286 | if _tab_0 then | ||
| 4287 | local fourth = _exp_0[4] | ||
| 4288 | local _val_0 | ||
| 4289 | do | ||
| 4290 | local _obj_0 = _exp_0[1] | ||
| 4291 | if _obj_0 ~= nil then | ||
| 4292 | _val_0 = _obj_0.a | ||
| 4293 | end | ||
| 4294 | end | ||
| 4295 | local _val_1 | ||
| 4296 | do | ||
| 4297 | local _obj_0 = _exp_0[1] | ||
| 4298 | if _obj_0 ~= nil then | ||
| 4299 | _val_1 = _obj_0.b | ||
| 4300 | end | ||
| 4301 | end | ||
| 4302 | local _val_2 | ||
| 4303 | do | ||
| 4304 | local _obj_0 = _exp_0[2] | ||
| 4305 | if _obj_0 ~= nil then | ||
| 4306 | _val_2 = _obj_0.a | ||
| 4307 | end | ||
| 4308 | end | ||
| 4309 | local _val_3 | ||
| 4310 | do | ||
| 4311 | local _obj_0 = _exp_0[2] | ||
| 4312 | if _obj_0 ~= nil then | ||
| 4313 | _val_3 = _obj_0.b | ||
| 4314 | end | ||
| 4315 | end | ||
| 4316 | local _val_4 | ||
| 4317 | do | ||
| 4318 | local _obj_0 = _exp_0[3] | ||
| 4319 | if _obj_0 ~= nil then | ||
| 4320 | _val_4 = _obj_0.a | ||
| 4321 | end | ||
| 4322 | end | ||
| 4323 | local _val_5 | ||
| 4324 | do | ||
| 4325 | local _obj_0 = _exp_0[3] | ||
| 4326 | if _obj_0 ~= nil then | ||
| 4327 | _val_5 = _obj_0.b | ||
| 4328 | end | ||
| 4329 | end | ||
| 4330 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
| 4331 | print("matched", fourth) | ||
| 4332 | end | ||
| 4333 | end | ||
| 4334 | local segments = { | ||
| 4335 | "admin", | ||
| 4336 | "users", | ||
| 4337 | "logs", | ||
| 4338 | "view" | ||
| 4339 | } | ||
| 4340 | local _type_0 = type(segments) | ||
| 4341 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4342 | if _tab_0 then | ||
| 4343 | local groups | ||
| 4344 | do | ||
| 4345 | local _accum_0 = { } | ||
| 4346 | local _len_0 = 1 | ||
| 4347 | local _max_0 = #segments + -3 + 1 | ||
| 4348 | for _index_0 = 1, _max_0 do | ||
| 4349 | local _item_0 = segments[_index_0] | ||
| 4350 | _accum_0[_len_0] = _item_0 | ||
| 4351 | _len_0 = _len_0 + 1 | ||
| 4352 | end | ||
| 4353 | groups = _accum_0 | ||
| 4354 | end | ||
| 4355 | local resource = segments[#segments - 1] | ||
| 4356 | local action = segments[#segments] | ||
| 4357 | if resource ~= nil and action ~= nil then | ||
| 4358 | print("Group:", groups) | ||
| 4359 | print("Resource:", resource) | ||
| 4360 | print("Action:", action) | ||
| 4361 | end | ||
| 4362 | end | ||
| 3289 | local Inventory | 4363 | local Inventory |
| 3290 | local _class_0 | 4364 | local _class_0 |
| 3291 | local _base_0 = { | 4365 | local _base_0 = { |
| @@ -3942,6 +5016,10 @@ do | |||
| 3942 | _with_1["key-name"] = value | 5016 | _with_1["key-name"] = value |
| 3943 | end | 5017 | end |
| 3944 | _with_0[#_with_0 + 1] = "abc" | 5018 | _with_0[#_with_0 + 1] = "abc" |
| 5019 | local _with_0 = obj | ||
| 5020 | if _with_0 ~= nil then | ||
| 5021 | print(obj.name) | ||
| 5022 | end | ||
| 3945 | do | 5023 | do |
| 3946 | local var = "hello" | 5024 | local var = "hello" |
| 3947 | print(var) | 5025 | print(var) |
diff --git a/spec/outputs/codes_from_doc_zh.lua b/spec/outputs/codes_from_doc_zh.lua index acd41a0..89335c9 100644 --- a/spec/outputs/codes_from_doc_zh.lua +++ b/spec/outputs/codes_from_doc_zh.lua | |||
| @@ -20,6 +20,38 @@ local inventory = { | |||
| 20 | } | 20 | } |
| 21 | } | 21 | } |
| 22 | } | 22 | } |
| 23 | local map | ||
| 24 | map = function(arr, action) | ||
| 25 | local _accum_0 = { } | ||
| 26 | local _len_0 = 1 | ||
| 27 | for _index_0 = 1, #arr do | ||
| 28 | local item = arr[_index_0] | ||
| 29 | _accum_0[_len_0] = action(item) | ||
| 30 | _len_0 = _len_0 + 1 | ||
| 31 | end | ||
| 32 | return _accum_0 | ||
| 33 | end | ||
| 34 | local filter | ||
| 35 | filter = function(arr, cond) | ||
| 36 | local _accum_0 = { } | ||
| 37 | local _len_0 = 1 | ||
| 38 | for _index_0 = 1, #arr do | ||
| 39 | local item = arr[_index_0] | ||
| 40 | if cond(item) then | ||
| 41 | _accum_0[_len_0] = item | ||
| 42 | _len_0 = _len_0 + 1 | ||
| 43 | end | ||
| 44 | end | ||
| 45 | return _accum_0 | ||
| 46 | end | ||
| 47 | local reduce | ||
| 48 | reduce = function(arr, init, action) | ||
| 49 | for _index_0 = 1, #arr do | ||
| 50 | local item = arr[_index_0] | ||
| 51 | init = action(init, item) | ||
| 52 | end | ||
| 53 | return init | ||
| 54 | end | ||
| 23 | print(reduce(filter(map({ | 55 | print(reduce(filter(map({ |
| 24 | 1, | 56 | 1, |
| 25 | 2, | 57 | 2, |
| @@ -41,8 +73,8 @@ local apple = setmetatable({ | |||
| 41 | if (getmetatable(apple) ~= nil) then | 73 | if (getmetatable(apple) ~= nil) then |
| 42 | p(apple.size, apple.color, getmetatable(apple).__index) | 74 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 43 | end | 75 | end |
| 44 | local _ud83c_udf1b = "月之脚本" | 76 | local _u1f31b = "月之脚本" |
| 45 | _module_0["🌛"] = _ud83c_udf1b | 77 | _module_0["🌛"] = _u1f31b |
| 46 | return _module_0 | 78 | return _module_0 |
| 47 | local area = 6.2831853071796 * 5 | 79 | local area = 6.2831853071796 * 5 |
| 48 | print('ä½ å¥½ 世界') | 80 | print('ä½ å¥½ 世界') |
| @@ -77,6 +109,12 @@ end | |||
| 77 | print("yuescript") | 109 | print("yuescript") |
| 78 | print(3) | 110 | print(3) |
| 79 | print("有效的枚举类型:", "Static") | 111 | print("有效的枚举类型:", "Static") |
| 112 | do | ||
| 113 | print(123, "hello") | ||
| 114 | end | ||
| 115 | do | ||
| 116 | print(123, "hello") | ||
| 117 | end | ||
| 80 | if tb ~= nil then | 118 | if tb ~= nil then |
| 81 | tb:func() | 119 | tb:func() |
| 82 | end | 120 | end |
| @@ -109,6 +147,21 @@ print((function() | |||
| 109 | end)()) | 147 | end)()) |
| 110 | local tab = { } | 148 | local tab = { } |
| 111 | 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 | ||
| 112 | local parts = { | 165 | local parts = { |
| 113 | "shoulders", | 166 | "shoulders", |
| 114 | "knees" | 167 | "knees" |
| @@ -177,6 +230,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 177 | end | 230 | end |
| 178 | end | 231 | end |
| 179 | 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 | ||
| 180 | local mt = { } | 245 | local mt = { } |
| 181 | local add | 246 | local add |
| 182 | add = function(self, right) | 247 | add = function(self, right) |
| @@ -307,6 +372,14 @@ func({ | |||
| 307 | 2, | 372 | 2, |
| 308 | 3 | 373 | 3 |
| 309 | }) | 374 | }) |
| 375 | local f | ||
| 376 | f = function() | ||
| 377 | return { | ||
| 378 | 1, | ||
| 379 | 2, | ||
| 380 | 3 | ||
| 381 | } | ||
| 382 | end | ||
| 310 | local tb = { | 383 | local tb = { |
| 311 | name = "abc", | 384 | name = "abc", |
| 312 | values = { | 385 | values = { |
| @@ -368,6 +441,25 @@ do | |||
| 368 | local _obj_0 = require("export") | 441 | local _obj_0 = require("export") |
| 369 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] | 442 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] |
| 370 | end | 443 | end |
| 444 | do | ||
| 445 | local tostring <const> = tostring | ||
| 446 | local concat <const> = table.concat | ||
| 447 | print(concat({ | ||
| 448 | "a", | ||
| 449 | tostring(1) | ||
| 450 | })) | ||
| 451 | end | ||
| 452 | do | ||
| 453 | local print <const> = print | ||
| 454 | local math <const> = math | ||
| 455 | print("hello") | ||
| 456 | math.random(3) | ||
| 457 | end | ||
| 458 | do | ||
| 459 | local print <const> = print | ||
| 460 | print(FLAG) | ||
| 461 | FLAG = 123 | ||
| 462 | end | ||
| 371 | local _module_0 = { } | 463 | local _module_0 = { } |
| 372 | local a, b, c = 1, 2, 3 | 464 | local a, b, c = 1, 2, 3 |
| 373 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c | 465 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c |
| @@ -547,6 +639,59 @@ end | |||
| 547 | local two, four | 639 | local two, four |
| 548 | local _obj_0 = items | 640 | local _obj_0 = items |
| 549 | two, four = _obj_0[2], _obj_0[4] | 641 | two, four = _obj_0[2], _obj_0[4] |
| 642 | local orders = { | ||
| 643 | "first", | ||
| 644 | "second", | ||
| 645 | "third", | ||
| 646 | "fourth", | ||
| 647 | "last" | ||
| 648 | } | ||
| 649 | local first, bulk, last = orders[1], (function() | ||
| 650 | local _accum_0 = { } | ||
| 651 | local _len_0 = 1 | ||
| 652 | local _max_0 = #orders + -2 + 1 | ||
| 653 | for _index_0 = 2, _max_0 do | ||
| 654 | local _item_0 = orders[_index_0] | ||
| 655 | _accum_0[_len_0] = _item_0 | ||
| 656 | _len_0 = _len_0 + 1 | ||
| 657 | end | ||
| 658 | return _accum_0 | ||
| 659 | end)(), orders[#orders] | ||
| 660 | print(first) | ||
| 661 | print(bulk) | ||
| 662 | print(last) | ||
| 663 | local first, rest | ||
| 664 | do | ||
| 665 | local _obj_0 = orders | ||
| 666 | first, rest = _obj_0[1], (function() | ||
| 667 | local _accum_0 = { } | ||
| 668 | local _len_0 = 1 | ||
| 669 | local _max_0 = #_obj_0 | ||
| 670 | for _index_0 = 2, _max_0 do | ||
| 671 | local _item_0 = _obj_0[_index_0] | ||
| 672 | _accum_0[_len_0] = _item_0 | ||
| 673 | _len_0 = _len_0 + 1 | ||
| 674 | end | ||
| 675 | return _accum_0 | ||
| 676 | end)() | ||
| 677 | end | ||
| 678 | local start, last | ||
| 679 | do | ||
| 680 | local _obj_0 = orders | ||
| 681 | start, last = (function() | ||
| 682 | local _accum_0 = { } | ||
| 683 | local _len_0 = 1 | ||
| 684 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 685 | for _index_0 = 1, _max_0 do | ||
| 686 | local _item_0 = _obj_0[_index_0] | ||
| 687 | _accum_0[_len_0] = _item_0 | ||
| 688 | _len_0 = _len_0 + 1 | ||
| 689 | end | ||
| 690 | return _accum_0 | ||
| 691 | end)(), _obj_0[#_obj_0] | ||
| 692 | end | ||
| 693 | local _obj_0 = orders | ||
| 694 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 550 | local tuples = { | 695 | local tuples = { |
| 551 | { | 696 | { |
| 552 | "hello", | 697 | "hello", |
| @@ -611,6 +756,9 @@ end | |||
| 611 | local first = select(1, ...) | 756 | local first = select(1, ...) |
| 612 | return print(ok, count, first) | 757 | return print(ok, count, first) |
| 613 | end)(fn(true)) | 758 | end)(fn(true)) |
| 759 | local a = 1 | ||
| 760 | local b = 2 | ||
| 761 | print(a + b) | ||
| 614 | Rx.Observable.fromRange(1, 8):filter(function(x) | 762 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 615 | return x % 2 == 0 | 763 | return x % 2 == 0 |
| 616 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 764 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -648,6 +796,56 @@ end) | |||
| 648 | if success then | 796 | if success then |
| 649 | print(result) | 797 | print(result) |
| 650 | end | 798 | end |
| 799 | local a, b, c | ||
| 800 | do | ||
| 801 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 802 | return func() | ||
| 803 | end) | ||
| 804 | if _ok_0 then | ||
| 805 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 806 | end | ||
| 807 | end | ||
| 808 | do | ||
| 809 | local _exp_0 = ((function() | ||
| 810 | return (function(_arg_0, ...) | ||
| 811 | local _ok_0 = _arg_0 | ||
| 812 | if _ok_0 then | ||
| 813 | return ... | ||
| 814 | end | ||
| 815 | end)(pcall(function() | ||
| 816 | return func() | ||
| 817 | end)) | ||
| 818 | end)()) | ||
| 819 | if _exp_0 ~= nil then | ||
| 820 | a = _exp_0 | ||
| 821 | else | ||
| 822 | a = "default" | ||
| 823 | end | ||
| 824 | end | ||
| 825 | f((function() | ||
| 826 | return (function(_arg_0, ...) | ||
| 827 | local _ok_0 = _arg_0 | ||
| 828 | if _ok_0 then | ||
| 829 | return ... | ||
| 830 | end | ||
| 831 | end)(pcall(function() | ||
| 832 | return func() | ||
| 833 | end)) | ||
| 834 | end)()) | ||
| 835 | f((function() | ||
| 836 | return (function(_arg_0, ...) | ||
| 837 | local _ok_0 = _arg_0 | ||
| 838 | if _ok_0 then | ||
| 839 | return ... | ||
| 840 | end | ||
| 841 | end)(xpcall(function() | ||
| 842 | print(123) | ||
| 843 | return func() | ||
| 844 | end, function(e) | ||
| 845 | print(e) | ||
| 846 | return e | ||
| 847 | end)) | ||
| 848 | end)()) | ||
| 651 | local a <const> = 123 | 849 | local a <const> = 123 |
| 652 | local _ <close> = setmetatable({ }, { | 850 | local _ <close> = setmetatable({ }, { |
| 653 | __close = function() | 851 | __close = function() |
| @@ -657,10 +855,19 @@ local _ <close> = setmetatable({ }, { | |||
| 657 | local a, b, c, d | 855 | local a, b, c, d |
| 658 | local _obj_0 = tb | 856 | local _obj_0 = tb |
| 659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 857 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
| 858 | Constant = 123 | ||
| 660 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" | 859 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" |
| 661 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | 860 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") |
| 662 | local integer = 1000000 | 861 | local integer = 1000000 |
| 663 | local hex = 0xEFBBBF | 862 | local hex = 0xEFBBBF |
| 863 | local binary = 19 | ||
| 864 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 865 | local fn | ||
| 866 | fn = function() | ||
| 867 | local str = "foo:\n bar: baz" | ||
| 868 | return str | ||
| 869 | end | ||
| 870 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 664 | local my_function | 871 | local my_function |
| 665 | my_function = function() end | 872 | my_function = function() end |
| 666 | my_function() | 873 | my_function() |
| @@ -749,6 +956,66 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
| 749 | print("hello") | 956 | print("hello") |
| 750 | print("我在if内部") | 957 | print("我在if内部") |
| 751 | end | 958 | end |
| 959 | local f1 | ||
| 960 | f1 = function(_arg_0) | ||
| 961 | local a, b, c | ||
| 962 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 963 | return print(a, b, c) | ||
| 964 | end | ||
| 965 | f1({ | ||
| 966 | a = 1, | ||
| 967 | b = "2", | ||
| 968 | c = { } | ||
| 969 | }) | ||
| 970 | local f2 | ||
| 971 | f2 = function(_arg_0, c) | ||
| 972 | local a1, b | ||
| 973 | a1, b = _arg_0.a, _arg_0.b | ||
| 974 | if a1 == nil then | ||
| 975 | a1 = 123 | ||
| 976 | end | ||
| 977 | if b == nil then | ||
| 978 | b = 'abc' | ||
| 979 | end | ||
| 980 | if c == nil then | ||
| 981 | c = { } | ||
| 982 | end | ||
| 983 | return print(a1, b, c) | ||
| 984 | end | ||
| 985 | local arg1 = { | ||
| 986 | a = 0 | ||
| 987 | } | ||
| 988 | f2(arg1, arg2) | ||
| 989 | local f | ||
| 990 | f = function(...) | ||
| 991 | local t = { | ||
| 992 | n = select("#", ...), | ||
| 993 | ... | ||
| 994 | } | ||
| 995 | print("傿•°ä¸ªæ•°:", t.n) | ||
| 996 | print("表长度:", #t) | ||
| 997 | for i = 1, t.n do | ||
| 998 | print(t[i]) | ||
| 999 | end | ||
| 1000 | end | ||
| 1001 | f(1, 2, 3) | ||
| 1002 | f("a", "b", "c", "d") | ||
| 1003 | f() | ||
| 1004 | local process | ||
| 1005 | process = function(...) | ||
| 1006 | local args = { | ||
| 1007 | n = select("#", ...), | ||
| 1008 | ... | ||
| 1009 | } | ||
| 1010 | local sum = 0 | ||
| 1011 | for i = 1, args.n do | ||
| 1012 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 1013 | sum = sum + args[i] | ||
| 1014 | end | ||
| 1015 | end | ||
| 1016 | return sum | ||
| 1017 | end | ||
| 1018 | process(1, nil, 3, nil, 5) | ||
| 752 | f(function() | 1019 | f(function() |
| 753 | return print("hello") | 1020 | return print("hello") |
| 754 | end) | 1021 | end) |
| @@ -874,6 +1141,28 @@ for _index_0 = 1, #_list_0 do | |||
| 874 | _len_0 = _len_0 + 1 | 1141 | _len_0 = _len_0 + 1 |
| 875 | end | 1142 | end |
| 876 | doubled = _accum_0 | 1143 | doubled = _accum_0 |
| 1144 | local data = { | ||
| 1145 | a = { | ||
| 1146 | 1, | ||
| 1147 | 2, | ||
| 1148 | 3 | ||
| 1149 | }, | ||
| 1150 | b = { | ||
| 1151 | 4, | ||
| 1152 | 5, | ||
| 1153 | 6 | ||
| 1154 | } | ||
| 1155 | } | ||
| 1156 | local flat | ||
| 1157 | local _accum_0 = { } | ||
| 1158 | for k, v in pairs(data) do | ||
| 1159 | local _len_0 = #_accum_0 + 1 | ||
| 1160 | for _index_0 = 1, #v do | ||
| 1161 | local _elm_0 = v[_index_0] | ||
| 1162 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 1163 | end | ||
| 1164 | end | ||
| 1165 | flat = _accum_0 | ||
| 877 | local x_coords = { | 1166 | local x_coords = { |
| 878 | 4, | 1167 | 4, |
| 879 | 5, | 1168 | 5, |
| @@ -964,8 +1253,18 @@ local slice | |||
| 964 | local _accum_0 = { } | 1253 | local _accum_0 = { } |
| 965 | local _len_0 = 1 | 1254 | local _len_0 = 1 |
| 966 | local _list_0 = items | 1255 | local _list_0 = items |
| 967 | local _max_0 = 5 | 1256 | for _index_0 = 1, 5 do |
| 968 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | 1257 | local item = _list_0[_index_0] |
| 1258 | _accum_0[_len_0] = item | ||
| 1259 | _len_0 = _len_0 + 1 | ||
| 1260 | end | ||
| 1261 | slice = _accum_0 | ||
| 1262 | local slice | ||
| 1263 | local _accum_0 = { } | ||
| 1264 | local _len_0 = 1 | ||
| 1265 | local _list_0 = items | ||
| 1266 | local _max_0 = #_list_0 | ||
| 1267 | for _index_0 = 2, _max_0 do | ||
| 969 | local item = _list_0[_index_0] | 1268 | local item = _list_0[_index_0] |
| 970 | _accum_0[_len_0] = item | 1269 | _accum_0[_len_0] = item |
| 971 | _len_0 = _len_0 + 1 | 1270 | _len_0 = _len_0 + 1 |
| @@ -975,7 +1274,8 @@ local slice | |||
| 975 | local _accum_0 = { } | 1274 | local _accum_0 = { } |
| 976 | local _len_0 = 1 | 1275 | local _len_0 = 1 |
| 977 | local _list_0 = items | 1276 | local _list_0 = items |
| 978 | for _index_0 = 2, #_list_0 do | 1277 | local _max_0 = #_list_0 |
| 1278 | for _index_0 = 1, _max_0, 2 do | ||
| 979 | local item = _list_0[_index_0] | 1279 | local item = _list_0[_index_0] |
| 980 | _accum_0[_len_0] = item | 1280 | _accum_0[_len_0] = item |
| 981 | _len_0 = _len_0 + 1 | 1281 | _len_0 = _len_0 + 1 |
| @@ -985,12 +1285,35 @@ local slice | |||
| 985 | local _accum_0 = { } | 1285 | local _accum_0 = { } |
| 986 | local _len_0 = 1 | 1286 | local _len_0 = 1 |
| 987 | local _list_0 = items | 1287 | local _list_0 = items |
| 988 | for _index_0 = 1, #_list_0, 2 do | 1288 | local _min_0 = #_list_0 + -4 + 1 |
| 1289 | local _max_0 = #_list_0 + -1 + 1 | ||
| 1290 | for _index_0 = _min_0, _max_0 do | ||
| 989 | local item = _list_0[_index_0] | 1291 | local item = _list_0[_index_0] |
| 990 | _accum_0[_len_0] = item | 1292 | _accum_0[_len_0] = item |
| 991 | _len_0 = _len_0 + 1 | 1293 | _len_0 = _len_0 + 1 |
| 992 | end | 1294 | end |
| 993 | slice = _accum_0 | 1295 | slice = _accum_0 |
| 1296 | local reverse_slice | ||
| 1297 | local _accum_0 = { } | ||
| 1298 | local _len_0 = 1 | ||
| 1299 | local _list_0 = items | ||
| 1300 | local _min_0 = #_list_0 + -1 + 1 | ||
| 1301 | for _index_0 = _min_0, 1, -1 do | ||
| 1302 | local item = _list_0[_index_0] | ||
| 1303 | _accum_0[_len_0] = item | ||
| 1304 | _len_0 = _len_0 + 1 | ||
| 1305 | end | ||
| 1306 | reverse_slice = _accum_0 | ||
| 1307 | local sub_list | ||
| 1308 | local _accum_0 = { } | ||
| 1309 | local _len_0 = 1 | ||
| 1310 | local _list_0 = items | ||
| 1311 | for _index_0 = 2, 4 do | ||
| 1312 | local _item_0 = _list_0[_index_0] | ||
| 1313 | _accum_0[_len_0] = _item_0 | ||
| 1314 | _len_0 = _len_0 + 1 | ||
| 1315 | end | ||
| 1316 | sub_list = _accum_0 | ||
| 994 | for i = 10, 20 do | 1317 | for i = 10, 20 do |
| 995 | print(i) | 1318 | print(i) |
| 996 | end | 1319 | end |
| @@ -1001,8 +1324,7 @@ for key, value in pairs(object) do | |||
| 1001 | print(key, value) | 1324 | print(key, value) |
| 1002 | end | 1325 | end |
| 1003 | local _list_0 = items | 1326 | local _list_0 = items |
| 1004 | local _max_0 = 4 | 1327 | for _index_0 = 2, 4 do |
| 1005 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 1006 | local item = _list_0[_index_0] | 1328 | local item = _list_0[_index_0] |
| 1007 | print(item) | 1329 | print(item) |
| 1008 | end | 1330 | end |
| @@ -1020,12 +1342,24 @@ local _len_0 = 1 | |||
| 1020 | for i = 1, 20 do | 1342 | for i = 1, 20 do |
| 1021 | if i % 2 == 0 then | 1343 | if i % 2 == 0 then |
| 1022 | _accum_0[_len_0] = i * 2 | 1344 | _accum_0[_len_0] = i * 2 |
| 1345 | _len_0 = _len_0 + 1 | ||
| 1023 | else | 1346 | else |
| 1024 | _accum_0[_len_0] = i | 1347 | _accum_0[_len_0] = i |
| 1348 | _len_0 = _len_0 + 1 | ||
| 1025 | end | 1349 | end |
| 1026 | _len_0 = _len_0 + 1 | ||
| 1027 | end | 1350 | end |
| 1028 | doubled_evens = _accum_0 | 1351 | doubled_evens = _accum_0 |
| 1352 | local first_large | ||
| 1353 | local _accum_0 | ||
| 1354 | local _list_0 = numbers | ||
| 1355 | for _index_0 = 1, #_list_0 do | ||
| 1356 | local n = _list_0[_index_0] | ||
| 1357 | if n > 10 then | ||
| 1358 | _accum_0 = n | ||
| 1359 | break | ||
| 1360 | end | ||
| 1361 | end | ||
| 1362 | first_large = _accum_0 | ||
| 1029 | local func_a | 1363 | local func_a |
| 1030 | func_a = function() | 1364 | func_a = function() |
| 1031 | for i = 1, 10 do | 1365 | for i = 1, 10 do |
| @@ -1174,7 +1508,7 @@ if "Robert" == name then | |||
| 1174 | elseif "Dan" == name or "Daniel" == name then | 1508 | elseif "Dan" == name or "Daniel" == name then |
| 1175 | print("ä½ çš„åå—æ˜¯Dan") | 1509 | print("ä½ çš„åå—æ˜¯Dan") |
| 1176 | else | 1510 | else |
| 1177 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 1511 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
| 1178 | end | 1512 | end |
| 1179 | local b = 1 | 1513 | local b = 1 |
| 1180 | local next_number | 1514 | local next_number |
| @@ -1274,6 +1608,192 @@ if _tab_0 then | |||
| 1274 | end | 1608 | end |
| 1275 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 1609 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
| 1276 | end | 1610 | end |
| 1611 | local _exp_0 = tb | ||
| 1612 | local _type_0 = type(_exp_0) | ||
| 1613 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1614 | local _match_0 = false | ||
| 1615 | if _tab_0 then | ||
| 1616 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
| 1617 | _match_0 = true | ||
| 1618 | print("1, 2, 3") | ||
| 1619 | end | ||
| 1620 | end | ||
| 1621 | if not _match_0 then | ||
| 1622 | local _match_1 = false | ||
| 1623 | if _tab_0 then | ||
| 1624 | local b = _exp_0[2] | ||
| 1625 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
| 1626 | _match_1 = true | ||
| 1627 | print("1, " .. tostring(b) .. ", 3") | ||
| 1628 | end | ||
| 1629 | end | ||
| 1630 | if not _match_1 then | ||
| 1631 | if _tab_0 then | ||
| 1632 | local b = _exp_0[3] | ||
| 1633 | if b == nil then | ||
| 1634 | b = 3 | ||
| 1635 | end | ||
| 1636 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
| 1637 | print("1, 2, " .. tostring(b)) | ||
| 1638 | end | ||
| 1639 | end | ||
| 1640 | end | ||
| 1641 | end | ||
| 1642 | local _exp_0 = tb | ||
| 1643 | local _type_0 = type(_exp_0) | ||
| 1644 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1645 | local _match_0 = false | ||
| 1646 | if _tab_0 then | ||
| 1647 | local result = _exp_0.result | ||
| 1648 | if true == _exp_0.success and result ~= nil then | ||
| 1649 | _match_0 = true | ||
| 1650 | print("æˆåŠŸ", result) | ||
| 1651 | end | ||
| 1652 | end | ||
| 1653 | if not _match_0 then | ||
| 1654 | local _match_1 = false | ||
| 1655 | if _tab_0 then | ||
| 1656 | if false == _exp_0.success then | ||
| 1657 | _match_1 = true | ||
| 1658 | print("失败", result) | ||
| 1659 | end | ||
| 1660 | end | ||
| 1661 | if not _match_1 then | ||
| 1662 | print("æ— æ•ˆå€¼") | ||
| 1663 | end | ||
| 1664 | end | ||
| 1665 | local _exp_0 = tb | ||
| 1666 | local _type_0 = type(_exp_0) | ||
| 1667 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1668 | local _match_0 = false | ||
| 1669 | if _tab_0 then | ||
| 1670 | local content | ||
| 1671 | do | ||
| 1672 | local _obj_0 = _exp_0.data | ||
| 1673 | local _type_1 = type(_obj_0) | ||
| 1674 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 1675 | content = _obj_0.content | ||
| 1676 | end | ||
| 1677 | end | ||
| 1678 | local _val_0 | ||
| 1679 | do | ||
| 1680 | local _obj_0 = _exp_0.data | ||
| 1681 | if _obj_0 ~= nil then | ||
| 1682 | _val_0 = _obj_0.type | ||
| 1683 | end | ||
| 1684 | end | ||
| 1685 | if "success" == _val_0 and content ~= nil then | ||
| 1686 | _match_0 = true | ||
| 1687 | print("æˆåŠŸ", content) | ||
| 1688 | end | ||
| 1689 | end | ||
| 1690 | if not _match_0 then | ||
| 1691 | local _match_1 = false | ||
| 1692 | if _tab_0 then | ||
| 1693 | local content | ||
| 1694 | do | ||
| 1695 | local _obj_0 = _exp_0.data | ||
| 1696 | local _type_1 = type(_obj_0) | ||
| 1697 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 1698 | content = _obj_0.content | ||
| 1699 | end | ||
| 1700 | end | ||
| 1701 | local _val_0 | ||
| 1702 | do | ||
| 1703 | local _obj_0 = _exp_0.data | ||
| 1704 | if _obj_0 ~= nil then | ||
| 1705 | _val_0 = _obj_0.type | ||
| 1706 | end | ||
| 1707 | end | ||
| 1708 | if "error" == _val_0 and content ~= nil then | ||
| 1709 | _match_1 = true | ||
| 1710 | print("失败", content) | ||
| 1711 | end | ||
| 1712 | end | ||
| 1713 | if not _match_1 then | ||
| 1714 | print("æ— æ•ˆå€¼") | ||
| 1715 | end | ||
| 1716 | end | ||
| 1717 | local _exp_0 = tb | ||
| 1718 | local _type_0 = type(_exp_0) | ||
| 1719 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1720 | if _tab_0 then | ||
| 1721 | local fourth = _exp_0[4] | ||
| 1722 | local _val_0 | ||
| 1723 | do | ||
| 1724 | local _obj_0 = _exp_0[1] | ||
| 1725 | if _obj_0 ~= nil then | ||
| 1726 | _val_0 = _obj_0.a | ||
| 1727 | end | ||
| 1728 | end | ||
| 1729 | local _val_1 | ||
| 1730 | do | ||
| 1731 | local _obj_0 = _exp_0[1] | ||
| 1732 | if _obj_0 ~= nil then | ||
| 1733 | _val_1 = _obj_0.b | ||
| 1734 | end | ||
| 1735 | end | ||
| 1736 | local _val_2 | ||
| 1737 | do | ||
| 1738 | local _obj_0 = _exp_0[2] | ||
| 1739 | if _obj_0 ~= nil then | ||
| 1740 | _val_2 = _obj_0.a | ||
| 1741 | end | ||
| 1742 | end | ||
| 1743 | local _val_3 | ||
| 1744 | do | ||
| 1745 | local _obj_0 = _exp_0[2] | ||
| 1746 | if _obj_0 ~= nil then | ||
| 1747 | _val_3 = _obj_0.b | ||
| 1748 | end | ||
| 1749 | end | ||
| 1750 | local _val_4 | ||
| 1751 | do | ||
| 1752 | local _obj_0 = _exp_0[3] | ||
| 1753 | if _obj_0 ~= nil then | ||
| 1754 | _val_4 = _obj_0.a | ||
| 1755 | end | ||
| 1756 | end | ||
| 1757 | local _val_5 | ||
| 1758 | do | ||
| 1759 | local _obj_0 = _exp_0[3] | ||
| 1760 | if _obj_0 ~= nil then | ||
| 1761 | _val_5 = _obj_0.b | ||
| 1762 | end | ||
| 1763 | end | ||
| 1764 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
| 1765 | print("åŒ¹é…æˆåŠŸ", fourth) | ||
| 1766 | end | ||
| 1767 | end | ||
| 1768 | local segments = { | ||
| 1769 | "admin", | ||
| 1770 | "users", | ||
| 1771 | "logs", | ||
| 1772 | "view" | ||
| 1773 | } | ||
| 1774 | local _type_0 = type(segments) | ||
| 1775 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 1776 | if _tab_0 then | ||
| 1777 | local groups | ||
| 1778 | do | ||
| 1779 | local _accum_0 = { } | ||
| 1780 | local _len_0 = 1 | ||
| 1781 | local _max_0 = #segments + -3 + 1 | ||
| 1782 | for _index_0 = 1, _max_0 do | ||
| 1783 | local _item_0 = segments[_index_0] | ||
| 1784 | _accum_0[_len_0] = _item_0 | ||
| 1785 | _len_0 = _len_0 + 1 | ||
| 1786 | end | ||
| 1787 | groups = _accum_0 | ||
| 1788 | end | ||
| 1789 | local resource = segments[#segments - 1] | ||
| 1790 | local action = segments[#segments] | ||
| 1791 | if resource ~= nil and action ~= nil then | ||
| 1792 | print("Group:", groups) | ||
| 1793 | print("Resource:", resource) | ||
| 1794 | print("Action:", action) | ||
| 1795 | end | ||
| 1796 | end | ||
| 1277 | local Inventory | 1797 | local Inventory |
| 1278 | local _class_0 | 1798 | local _class_0 |
| 1279 | local _base_0 = { | 1799 | local _base_0 = { |
| @@ -1930,6 +2450,10 @@ do | |||
| 1930 | _with_1["key-name"] = value | 2450 | _with_1["key-name"] = value |
| 1931 | end | 2451 | end |
| 1932 | _with_0[#_with_0 + 1] = "abc" | 2452 | _with_0[#_with_0 + 1] = "abc" |
| 2453 | local _with_0 = obj | ||
| 2454 | if _with_0 ~= nil then | ||
| 2455 | print(obj.name) | ||
| 2456 | end | ||
| 1933 | do | 2457 | do |
| 1934 | local var = "hello" | 2458 | local var = "hello" |
| 1935 | print(var) | 2459 | print(var) |
| @@ -2020,6 +2544,38 @@ local inventory = { | |||
| 2020 | } | 2544 | } |
| 2021 | } | 2545 | } |
| 2022 | } | 2546 | } |
| 2547 | local map | ||
| 2548 | map = function(arr, action) | ||
| 2549 | local _accum_0 = { } | ||
| 2550 | local _len_0 = 1 | ||
| 2551 | for _index_0 = 1, #arr do | ||
| 2552 | local item = arr[_index_0] | ||
| 2553 | _accum_0[_len_0] = action(item) | ||
| 2554 | _len_0 = _len_0 + 1 | ||
| 2555 | end | ||
| 2556 | return _accum_0 | ||
| 2557 | end | ||
| 2558 | local filter | ||
| 2559 | filter = function(arr, cond) | ||
| 2560 | local _accum_0 = { } | ||
| 2561 | local _len_0 = 1 | ||
| 2562 | for _index_0 = 1, #arr do | ||
| 2563 | local item = arr[_index_0] | ||
| 2564 | if cond(item) then | ||
| 2565 | _accum_0[_len_0] = item | ||
| 2566 | _len_0 = _len_0 + 1 | ||
| 2567 | end | ||
| 2568 | end | ||
| 2569 | return _accum_0 | ||
| 2570 | end | ||
| 2571 | local reduce | ||
| 2572 | reduce = function(arr, init, action) | ||
| 2573 | for _index_0 = 1, #arr do | ||
| 2574 | local item = arr[_index_0] | ||
| 2575 | init = action(init, item) | ||
| 2576 | end | ||
| 2577 | return init | ||
| 2578 | end | ||
| 2023 | print(reduce(filter(map({ | 2579 | print(reduce(filter(map({ |
| 2024 | 1, | 2580 | 1, |
| 2025 | 2, | 2581 | 2, |
| @@ -2041,8 +2597,8 @@ local apple = setmetatable({ | |||
| 2041 | if (getmetatable(apple) ~= nil) then | 2597 | if (getmetatable(apple) ~= nil) then |
| 2042 | p(apple.size, apple.color, getmetatable(apple).__index) | 2598 | p(apple.size, apple.color, getmetatable(apple).__index) |
| 2043 | end | 2599 | end |
| 2044 | local _ud83c_udf1b = "月之脚本" | 2600 | local _u1f31b = "月之脚本" |
| 2045 | _module_0["🌛"] = _ud83c_udf1b | 2601 | _module_0["🌛"] = _u1f31b |
| 2046 | return _module_0 | 2602 | return _module_0 |
| 2047 | local area = 6.2831853071796 * 5 | 2603 | local area = 6.2831853071796 * 5 |
| 2048 | print('ä½ å¥½ 世界') | 2604 | print('ä½ å¥½ 世界') |
| @@ -2077,6 +2633,12 @@ end | |||
| 2077 | print("yuescript") | 2633 | print("yuescript") |
| 2078 | print(3) | 2634 | print(3) |
| 2079 | print("有效的枚举类型:", "Static") | 2635 | print("有效的枚举类型:", "Static") |
| 2636 | do | ||
| 2637 | print(123, "hello") | ||
| 2638 | end | ||
| 2639 | do | ||
| 2640 | print(123, "hello") | ||
| 2641 | end | ||
| 2080 | if tb ~= nil then | 2642 | if tb ~= nil then |
| 2081 | tb:func() | 2643 | tb:func() |
| 2082 | end | 2644 | end |
| @@ -2109,6 +2671,21 @@ print((function() | |||
| 2109 | end)()) | 2671 | end)()) |
| 2110 | local tab = { } | 2672 | local tab = { } |
| 2111 | tab[#tab + 1] = "Value" | 2673 | tab[#tab + 1] = "Value" |
| 2674 | local tbA = { | ||
| 2675 | 1, | ||
| 2676 | 2, | ||
| 2677 | 3 | ||
| 2678 | } | ||
| 2679 | local tbB = { | ||
| 2680 | 4, | ||
| 2681 | 5, | ||
| 2682 | 6 | ||
| 2683 | } | ||
| 2684 | local _len_0 = #tbA + 1 | ||
| 2685 | for _index_0 = 1, #tbB do | ||
| 2686 | local _elm_0 = tbB[_index_0] | ||
| 2687 | tbA[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 2688 | end | ||
| 2112 | local parts = { | 2689 | local parts = { |
| 2113 | "shoulders", | 2690 | "shoulders", |
| 2114 | "knees" | 2691 | "knees" |
| @@ -2177,6 +2754,18 @@ for _key_0, _value_0 in pairs(b) do | |||
| 2177 | end | 2754 | end |
| 2178 | end | 2755 | end |
| 2179 | merge = _tab_0 | 2756 | merge = _tab_0 |
| 2757 | local last | ||
| 2758 | do | ||
| 2759 | local _item_0 = data.items | ||
| 2760 | last = _item_0[#_item_0] | ||
| 2761 | end | ||
| 2762 | local second_last | ||
| 2763 | do | ||
| 2764 | local _item_0 = data.items | ||
| 2765 | second_last = _item_0[#_item_0 - 1] | ||
| 2766 | end | ||
| 2767 | local _obj_0 = data.items | ||
| 2768 | _obj_0[#_obj_0] = 1 | ||
| 2180 | local mt = { } | 2769 | local mt = { } |
| 2181 | local add | 2770 | local add |
| 2182 | add = function(self, right) | 2771 | add = function(self, right) |
| @@ -2307,6 +2896,14 @@ func({ | |||
| 2307 | 2, | 2896 | 2, |
| 2308 | 3 | 2897 | 3 |
| 2309 | }) | 2898 | }) |
| 2899 | local f | ||
| 2900 | f = function() | ||
| 2901 | return { | ||
| 2902 | 1, | ||
| 2903 | 2, | ||
| 2904 | 3 | ||
| 2905 | } | ||
| 2906 | end | ||
| 2310 | local tb = { | 2907 | local tb = { |
| 2311 | name = "abc", | 2908 | name = "abc", |
| 2312 | values = { | 2909 | values = { |
| @@ -2368,6 +2965,25 @@ do | |||
| 2368 | local _obj_0 = require("export") | 2965 | local _obj_0 = require("export") |
| 2369 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] | 2966 | one, two, ch = _obj_0[1], _obj_0[2], _obj_0.Something.umm[1] |
| 2370 | end | 2967 | end |
| 2968 | do | ||
| 2969 | local tostring <const> = tostring | ||
| 2970 | local concat <const> = table.concat | ||
| 2971 | print(concat({ | ||
| 2972 | "a", | ||
| 2973 | tostring(1) | ||
| 2974 | })) | ||
| 2975 | end | ||
| 2976 | do | ||
| 2977 | local print <const> = print | ||
| 2978 | local math <const> = math | ||
| 2979 | print("hello") | ||
| 2980 | math.random(3) | ||
| 2981 | end | ||
| 2982 | do | ||
| 2983 | local print <const> = print | ||
| 2984 | print(FLAG) | ||
| 2985 | FLAG = 123 | ||
| 2986 | end | ||
| 2371 | local _module_0 = { } | 2987 | local _module_0 = { } |
| 2372 | local a, b, c = 1, 2, 3 | 2988 | local a, b, c = 1, 2, 3 |
| 2373 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c | 2989 | _module_0["a"], _module_0["b"], _module_0["c"] = a, b, c |
| @@ -2547,6 +3163,59 @@ end | |||
| 2547 | local two, four | 3163 | local two, four |
| 2548 | local _obj_0 = items | 3164 | local _obj_0 = items |
| 2549 | two, four = _obj_0[2], _obj_0[4] | 3165 | two, four = _obj_0[2], _obj_0[4] |
| 3166 | local orders = { | ||
| 3167 | "first", | ||
| 3168 | "second", | ||
| 3169 | "third", | ||
| 3170 | "fourth", | ||
| 3171 | "last" | ||
| 3172 | } | ||
| 3173 | local first, bulk, last = orders[1], (function() | ||
| 3174 | local _accum_0 = { } | ||
| 3175 | local _len_0 = 1 | ||
| 3176 | local _max_0 = #orders + -2 + 1 | ||
| 3177 | for _index_0 = 2, _max_0 do | ||
| 3178 | local _item_0 = orders[_index_0] | ||
| 3179 | _accum_0[_len_0] = _item_0 | ||
| 3180 | _len_0 = _len_0 + 1 | ||
| 3181 | end | ||
| 3182 | return _accum_0 | ||
| 3183 | end)(), orders[#orders] | ||
| 3184 | print(first) | ||
| 3185 | print(bulk) | ||
| 3186 | print(last) | ||
| 3187 | local first, rest | ||
| 3188 | do | ||
| 3189 | local _obj_0 = orders | ||
| 3190 | first, rest = _obj_0[1], (function() | ||
| 3191 | local _accum_0 = { } | ||
| 3192 | local _len_0 = 1 | ||
| 3193 | local _max_0 = #_obj_0 | ||
| 3194 | for _index_0 = 2, _max_0 do | ||
| 3195 | local _item_0 = _obj_0[_index_0] | ||
| 3196 | _accum_0[_len_0] = _item_0 | ||
| 3197 | _len_0 = _len_0 + 1 | ||
| 3198 | end | ||
| 3199 | return _accum_0 | ||
| 3200 | end)() | ||
| 3201 | end | ||
| 3202 | local start, last | ||
| 3203 | do | ||
| 3204 | local _obj_0 = orders | ||
| 3205 | start, last = (function() | ||
| 3206 | local _accum_0 = { } | ||
| 3207 | local _len_0 = 1 | ||
| 3208 | local _max_0 = #_obj_0 + -2 + 1 | ||
| 3209 | for _index_0 = 1, _max_0 do | ||
| 3210 | local _item_0 = _obj_0[_index_0] | ||
| 3211 | _accum_0[_len_0] = _item_0 | ||
| 3212 | _len_0 = _len_0 + 1 | ||
| 3213 | end | ||
| 3214 | return _accum_0 | ||
| 3215 | end)(), _obj_0[#_obj_0] | ||
| 3216 | end | ||
| 3217 | local _obj_0 = orders | ||
| 3218 | first, last = _obj_0[1], _obj_0[#_obj_0] | ||
| 2550 | local tuples = { | 3219 | local tuples = { |
| 2551 | { | 3220 | { |
| 2552 | "hello", | 3221 | "hello", |
| @@ -2611,6 +3280,9 @@ end | |||
| 2611 | local first = select(1, ...) | 3280 | local first = select(1, ...) |
| 2612 | return print(ok, count, first) | 3281 | return print(ok, count, first) |
| 2613 | end)(fn(true)) | 3282 | end)(fn(true)) |
| 3283 | local a = 1 | ||
| 3284 | local b = 2 | ||
| 3285 | print(a + b) | ||
| 2614 | Rx.Observable.fromRange(1, 8):filter(function(x) | 3286 | Rx.Observable.fromRange(1, 8):filter(function(x) |
| 2615 | return x % 2 == 0 | 3287 | return x % 2 == 0 |
| 2616 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) | 3288 | end):concat(Rx.Observable.of('who do we appreciate')):map(function(value) |
| @@ -2648,6 +3320,56 @@ end) | |||
| 2648 | if success then | 3320 | if success then |
| 2649 | print(result) | 3321 | print(result) |
| 2650 | end | 3322 | end |
| 3323 | local a, b, c | ||
| 3324 | do | ||
| 3325 | local _ok_0, _ret_0, _ret_1, _ret_2 = pcall(function() | ||
| 3326 | return func() | ||
| 3327 | end) | ||
| 3328 | if _ok_0 then | ||
| 3329 | a, b, c = _ret_0, _ret_1, _ret_2 | ||
| 3330 | end | ||
| 3331 | end | ||
| 3332 | do | ||
| 3333 | local _exp_0 = ((function() | ||
| 3334 | return (function(_arg_0, ...) | ||
| 3335 | local _ok_0 = _arg_0 | ||
| 3336 | if _ok_0 then | ||
| 3337 | return ... | ||
| 3338 | end | ||
| 3339 | end)(pcall(function() | ||
| 3340 | return func() | ||
| 3341 | end)) | ||
| 3342 | end)()) | ||
| 3343 | if _exp_0 ~= nil then | ||
| 3344 | a = _exp_0 | ||
| 3345 | else | ||
| 3346 | a = "default" | ||
| 3347 | end | ||
| 3348 | end | ||
| 3349 | f((function() | ||
| 3350 | return (function(_arg_0, ...) | ||
| 3351 | local _ok_0 = _arg_0 | ||
| 3352 | if _ok_0 then | ||
| 3353 | return ... | ||
| 3354 | end | ||
| 3355 | end)(pcall(function() | ||
| 3356 | return func() | ||
| 3357 | end)) | ||
| 3358 | end)()) | ||
| 3359 | f((function() | ||
| 3360 | return (function(_arg_0, ...) | ||
| 3361 | local _ok_0 = _arg_0 | ||
| 3362 | if _ok_0 then | ||
| 3363 | return ... | ||
| 3364 | end | ||
| 3365 | end)(xpcall(function() | ||
| 3366 | print(123) | ||
| 3367 | return func() | ||
| 3368 | end, function(e) | ||
| 3369 | print(e) | ||
| 3370 | return e | ||
| 3371 | end)) | ||
| 3372 | end)()) | ||
| 2651 | local a <const> = 123 | 3373 | local a <const> = 123 |
| 2652 | local _ <close> = setmetatable({ }, { | 3374 | local _ <close> = setmetatable({ }, { |
| 2653 | __close = function() | 3375 | __close = function() |
| @@ -2657,10 +3379,19 @@ local _ <close> = setmetatable({ }, { | |||
| 2657 | local a, b, c, d | 3379 | local a, b, c, d |
| 2658 | local _obj_0 = tb | 3380 | local _obj_0 = tb |
| 2659 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] | 3381 | a, b, c, d = _obj_0.a, _obj_0.b, _obj_0[1], _obj_0[2] |
| 3382 | Constant = 123 | ||
| 2660 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" | 3383 | local some_string = "这是一个å—符串\n 并包括一个æ¢è¡Œã€‚" |
| 2661 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") | 3384 | print("我有" .. tostring(math.random() * 100) .. "%的把æ¡ã€‚") |
| 2662 | local integer = 1000000 | 3385 | local integer = 1000000 |
| 2663 | local hex = 0xEFBBBF | 3386 | local hex = 0xEFBBBF |
| 3387 | local binary = 19 | ||
| 3388 | local str = "key: value\nlist:\n - item1\n - " .. tostring(expr) | ||
| 3389 | local fn | ||
| 3390 | fn = function() | ||
| 3391 | local str = "foo:\n bar: baz" | ||
| 3392 | return str | ||
| 3393 | end | ||
| 3394 | local str = "path: \"C:\\Program Files\\App\"\nnote: 'He said: \"" .. tostring(Hello) .. "!\"'" | ||
| 2664 | local my_function | 3395 | local my_function |
| 2665 | my_function = function() end | 3396 | my_function = function() end |
| 2666 | my_function() | 3397 | my_function() |
| @@ -2749,6 +3480,96 @@ if func(1, 2, 3, "ä½ å¥½", "世界") then | |||
| 2749 | print("ä½ å¥½") | 3480 | print("ä½ å¥½") |
| 2750 | print("我在if内部") | 3481 | print("我在if内部") |
| 2751 | end | 3482 | end |
| 3483 | local f1 | ||
| 3484 | f1 = function(_arg_0) | ||
| 3485 | local a, b, c | ||
| 3486 | a, b, c = _arg_0.a, _arg_0.b, _arg_0.c | ||
| 3487 | return print(a, b, c) | ||
| 3488 | end | ||
| 3489 | f1({ | ||
| 3490 | a = 1, | ||
| 3491 | b = "2", | ||
| 3492 | c = { } | ||
| 3493 | }) | ||
| 3494 | local f2 | ||
| 3495 | f2 = function(_arg_0, c) | ||
| 3496 | local a1, b | ||
| 3497 | a1, b = _arg_0.a, _arg_0.b | ||
| 3498 | if a1 == nil then | ||
| 3499 | a1 = 123 | ||
| 3500 | end | ||
| 3501 | if b == nil then | ||
| 3502 | b = 'abc' | ||
| 3503 | end | ||
| 3504 | if c == nil then | ||
| 3505 | c = { } | ||
| 3506 | end | ||
| 3507 | return print(a1, b, c) | ||
| 3508 | end | ||
| 3509 | local arg1 = { | ||
| 3510 | a = 0 | ||
| 3511 | } | ||
| 3512 | f2(arg1, arg2) | ||
| 3513 | local findFirstEven | ||
| 3514 | findFirstEven = function(list) | ||
| 3515 | for _index_0 = 1, #list do | ||
| 3516 | local item = list[_index_0] | ||
| 3517 | if type(item) == "table" then | ||
| 3518 | for _index_1 = 1, #item do | ||
| 3519 | local sub = item[_index_1] | ||
| 3520 | if sub % 2 == 0 then | ||
| 3521 | return sub | ||
| 3522 | end | ||
| 3523 | end | ||
| 3524 | end | ||
| 3525 | end | ||
| 3526 | return nil | ||
| 3527 | end | ||
| 3528 | local findFirstEven | ||
| 3529 | findFirstEven = function(list) | ||
| 3530 | for _index_0 = 1, #list do | ||
| 3531 | local item = list[_index_0] | ||
| 3532 | if type(item) == "table" then | ||
| 3533 | for _index_1 = 1, #item do | ||
| 3534 | local sub = item[_index_1] | ||
| 3535 | if sub % 2 == 0 then | ||
| 3536 | return sub | ||
| 3537 | end | ||
| 3538 | end | ||
| 3539 | end | ||
| 3540 | end | ||
| 3541 | return nil | ||
| 3542 | end | ||
| 3543 | local f | ||
| 3544 | f = function(...) | ||
| 3545 | local t = { | ||
| 3546 | n = select("#", ...), | ||
| 3547 | ... | ||
| 3548 | } | ||
| 3549 | print("傿•°ä¸ªæ•°:", t.n) | ||
| 3550 | print("表长度:", #t) | ||
| 3551 | for i = 1, t.n do | ||
| 3552 | print(t[i]) | ||
| 3553 | end | ||
| 3554 | end | ||
| 3555 | f(1, 2, 3) | ||
| 3556 | f("a", "b", "c", "d") | ||
| 3557 | f() | ||
| 3558 | local process | ||
| 3559 | process = function(...) | ||
| 3560 | local args = { | ||
| 3561 | n = select("#", ...), | ||
| 3562 | ... | ||
| 3563 | } | ||
| 3564 | local sum = 0 | ||
| 3565 | for i = 1, args.n do | ||
| 3566 | if args[i] ~= nil and type(args[i]) == "number" then | ||
| 3567 | sum = sum + args[i] | ||
| 3568 | end | ||
| 3569 | end | ||
| 3570 | return sum | ||
| 3571 | end | ||
| 3572 | process(1, nil, 3, nil, 5) | ||
| 2752 | f(function() | 3573 | f(function() |
| 2753 | return print("hello") | 3574 | return print("hello") |
| 2754 | end) | 3575 | end) |
| @@ -2874,6 +3695,28 @@ for _index_0 = 1, #_list_0 do | |||
| 2874 | _len_0 = _len_0 + 1 | 3695 | _len_0 = _len_0 + 1 |
| 2875 | end | 3696 | end |
| 2876 | doubled = _accum_0 | 3697 | doubled = _accum_0 |
| 3698 | local data = { | ||
| 3699 | a = { | ||
| 3700 | 1, | ||
| 3701 | 2, | ||
| 3702 | 3 | ||
| 3703 | }, | ||
| 3704 | b = { | ||
| 3705 | 4, | ||
| 3706 | 5, | ||
| 3707 | 6 | ||
| 3708 | } | ||
| 3709 | } | ||
| 3710 | local flat | ||
| 3711 | local _accum_0 = { } | ||
| 3712 | for k, v in pairs(data) do | ||
| 3713 | local _len_0 = #_accum_0 + 1 | ||
| 3714 | for _index_0 = 1, #v do | ||
| 3715 | local _elm_0 = v[_index_0] | ||
| 3716 | _accum_0[_len_0], _len_0 = _elm_0, _len_0 + 1 | ||
| 3717 | end | ||
| 3718 | end | ||
| 3719 | flat = _accum_0 | ||
| 2877 | local x_coords = { | 3720 | local x_coords = { |
| 2878 | 4, | 3721 | 4, |
| 2879 | 5, | 3722 | 5, |
| @@ -2964,8 +3807,7 @@ local slice | |||
| 2964 | local _accum_0 = { } | 3807 | local _accum_0 = { } |
| 2965 | local _len_0 = 1 | 3808 | local _len_0 = 1 |
| 2966 | local _list_0 = items | 3809 | local _list_0 = items |
| 2967 | local _max_0 = 5 | 3810 | for _index_0 = 1, 5 do |
| 2968 | for _index_0 = 1, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 2969 | local item = _list_0[_index_0] | 3811 | local item = _list_0[_index_0] |
| 2970 | _accum_0[_len_0] = item | 3812 | _accum_0[_len_0] = item |
| 2971 | _len_0 = _len_0 + 1 | 3813 | _len_0 = _len_0 + 1 |
| @@ -2975,7 +3817,8 @@ local slice | |||
| 2975 | local _accum_0 = { } | 3817 | local _accum_0 = { } |
| 2976 | local _len_0 = 1 | 3818 | local _len_0 = 1 |
| 2977 | local _list_0 = items | 3819 | local _list_0 = items |
| 2978 | for _index_0 = 2, #_list_0 do | 3820 | local _max_0 = #_list_0 |
| 3821 | for _index_0 = 2, _max_0 do | ||
| 2979 | local item = _list_0[_index_0] | 3822 | local item = _list_0[_index_0] |
| 2980 | _accum_0[_len_0] = item | 3823 | _accum_0[_len_0] = item |
| 2981 | _len_0 = _len_0 + 1 | 3824 | _len_0 = _len_0 + 1 |
| @@ -2985,12 +3828,46 @@ local slice | |||
| 2985 | local _accum_0 = { } | 3828 | local _accum_0 = { } |
| 2986 | local _len_0 = 1 | 3829 | local _len_0 = 1 |
| 2987 | local _list_0 = items | 3830 | local _list_0 = items |
| 2988 | for _index_0 = 1, #_list_0, 2 do | 3831 | local _max_0 = #_list_0 |
| 3832 | for _index_0 = 1, _max_0, 2 do | ||
| 2989 | local item = _list_0[_index_0] | 3833 | local item = _list_0[_index_0] |
| 2990 | _accum_0[_len_0] = item | 3834 | _accum_0[_len_0] = item |
| 2991 | _len_0 = _len_0 + 1 | 3835 | _len_0 = _len_0 + 1 |
| 2992 | end | 3836 | end |
| 2993 | slice = _accum_0 | 3837 | slice = _accum_0 |
| 3838 | local slice | ||
| 3839 | local _accum_0 = { } | ||
| 3840 | local _len_0 = 1 | ||
| 3841 | local _list_0 = items | ||
| 3842 | local _min_0 = #_list_0 + -4 + 1 | ||
| 3843 | local _max_0 = #_list_0 + -1 + 1 | ||
| 3844 | for _index_0 = _min_0, _max_0 do | ||
| 3845 | local item = _list_0[_index_0] | ||
| 3846 | _accum_0[_len_0] = item | ||
| 3847 | _len_0 = _len_0 + 1 | ||
| 3848 | end | ||
| 3849 | slice = _accum_0 | ||
| 3850 | local reverse_slice | ||
| 3851 | local _accum_0 = { } | ||
| 3852 | local _len_0 = 1 | ||
| 3853 | local _list_0 = items | ||
| 3854 | local _min_0 = #_list_0 + -1 + 1 | ||
| 3855 | for _index_0 = _min_0, 1, -1 do | ||
| 3856 | local item = _list_0[_index_0] | ||
| 3857 | _accum_0[_len_0] = item | ||
| 3858 | _len_0 = _len_0 + 1 | ||
| 3859 | end | ||
| 3860 | reverse_slice = _accum_0 | ||
| 3861 | local sub_list | ||
| 3862 | local _accum_0 = { } | ||
| 3863 | local _len_0 = 1 | ||
| 3864 | local _list_0 = items | ||
| 3865 | for _index_0 = 2, 4 do | ||
| 3866 | local _item_0 = _list_0[_index_0] | ||
| 3867 | _accum_0[_len_0] = _item_0 | ||
| 3868 | _len_0 = _len_0 + 1 | ||
| 3869 | end | ||
| 3870 | sub_list = _accum_0 | ||
| 2994 | for i = 10, 20 do | 3871 | for i = 10, 20 do |
| 2995 | print(i) | 3872 | print(i) |
| 2996 | end | 3873 | end |
| @@ -3001,8 +3878,7 @@ for key, value in pairs(object) do | |||
| 3001 | print(key, value) | 3878 | print(key, value) |
| 3002 | end | 3879 | end |
| 3003 | local _list_0 = items | 3880 | local _list_0 = items |
| 3004 | local _max_0 = 4 | 3881 | for _index_0 = 2, 4 do |
| 3005 | for _index_0 = 2, _max_0 < 0 and #_list_0 + _max_0 or _max_0 do | ||
| 3006 | local item = _list_0[_index_0] | 3882 | local item = _list_0[_index_0] |
| 3007 | print(item) | 3883 | print(item) |
| 3008 | end | 3884 | end |
| @@ -3020,12 +3896,24 @@ local _len_0 = 1 | |||
| 3020 | for i = 1, 20 do | 3896 | for i = 1, 20 do |
| 3021 | if i % 2 == 0 then | 3897 | if i % 2 == 0 then |
| 3022 | _accum_0[_len_0] = i * 2 | 3898 | _accum_0[_len_0] = i * 2 |
| 3899 | _len_0 = _len_0 + 1 | ||
| 3023 | else | 3900 | else |
| 3024 | _accum_0[_len_0] = i | 3901 | _accum_0[_len_0] = i |
| 3902 | _len_0 = _len_0 + 1 | ||
| 3025 | end | 3903 | end |
| 3026 | _len_0 = _len_0 + 1 | ||
| 3027 | end | 3904 | end |
| 3028 | doubled_evens = _accum_0 | 3905 | doubled_evens = _accum_0 |
| 3906 | local first_large | ||
| 3907 | local _accum_0 | ||
| 3908 | local _list_0 = numbers | ||
| 3909 | for _index_0 = 1, #_list_0 do | ||
| 3910 | local n = _list_0[_index_0] | ||
| 3911 | if n > 10 then | ||
| 3912 | _accum_0 = n | ||
| 3913 | break | ||
| 3914 | end | ||
| 3915 | end | ||
| 3916 | first_large = _accum_0 | ||
| 3029 | local func_a | 3917 | local func_a |
| 3030 | func_a = function() | 3918 | func_a = function() |
| 3031 | for i = 1, 10 do | 3919 | for i = 1, 10 do |
| @@ -3174,7 +4062,7 @@ if "Robert" == name then | |||
| 3174 | elseif "Dan" == name or "Daniel" == name then | 4062 | elseif "Dan" == name or "Daniel" == name then |
| 3175 | print("ä½ çš„åå—æ˜¯Dan") | 4063 | print("ä½ çš„åå—æ˜¯Dan") |
| 3176 | else | 4064 | else |
| 3177 | print("我ä¸çŸ¥é“ä½ çš„åå—") | 4065 | print("我ä¸è®¤è¯†ä½ ï¼Œä½ çš„åå—æ˜¯" .. tostring(name)) |
| 3178 | end | 4066 | end |
| 3179 | local b = 1 | 4067 | local b = 1 |
| 3180 | local next_number | 4068 | local next_number |
| @@ -3274,6 +4162,192 @@ if _tab_0 then | |||
| 3274 | end | 4162 | end |
| 3275 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) | 4163 | print("Vec2 " .. tostring(x) .. ", " .. tostring(y)) |
| 3276 | end | 4164 | end |
| 4165 | local _exp_0 = tb | ||
| 4166 | local _type_0 = type(_exp_0) | ||
| 4167 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4168 | local _match_0 = false | ||
| 4169 | if _tab_0 then | ||
| 4170 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
| 4171 | _match_0 = true | ||
| 4172 | print("1, 2, 3") | ||
| 4173 | end | ||
| 4174 | end | ||
| 4175 | if not _match_0 then | ||
| 4176 | local _match_1 = false | ||
| 4177 | if _tab_0 then | ||
| 4178 | local b = _exp_0[2] | ||
| 4179 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
| 4180 | _match_1 = true | ||
| 4181 | print("1, " .. tostring(b) .. ", 3") | ||
| 4182 | end | ||
| 4183 | end | ||
| 4184 | if not _match_1 then | ||
| 4185 | if _tab_0 then | ||
| 4186 | local b = _exp_0[3] | ||
| 4187 | if b == nil then | ||
| 4188 | b = 3 | ||
| 4189 | end | ||
| 4190 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
| 4191 | print("1, 2, " .. tostring(b)) | ||
| 4192 | end | ||
| 4193 | end | ||
| 4194 | end | ||
| 4195 | end | ||
| 4196 | local _exp_0 = tb | ||
| 4197 | local _type_0 = type(_exp_0) | ||
| 4198 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4199 | local _match_0 = false | ||
| 4200 | if _tab_0 then | ||
| 4201 | local result = _exp_0.result | ||
| 4202 | if true == _exp_0.success and result ~= nil then | ||
| 4203 | _match_0 = true | ||
| 4204 | print("æˆåŠŸ", result) | ||
| 4205 | end | ||
| 4206 | end | ||
| 4207 | if not _match_0 then | ||
| 4208 | local _match_1 = false | ||
| 4209 | if _tab_0 then | ||
| 4210 | if false == _exp_0.success then | ||
| 4211 | _match_1 = true | ||
| 4212 | print("失败", result) | ||
| 4213 | end | ||
| 4214 | end | ||
| 4215 | if not _match_1 then | ||
| 4216 | print("æ— æ•ˆå€¼") | ||
| 4217 | end | ||
| 4218 | end | ||
| 4219 | local _exp_0 = tb | ||
| 4220 | local _type_0 = type(_exp_0) | ||
| 4221 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4222 | local _match_0 = false | ||
| 4223 | if _tab_0 then | ||
| 4224 | local content | ||
| 4225 | do | ||
| 4226 | local _obj_0 = _exp_0.data | ||
| 4227 | local _type_1 = type(_obj_0) | ||
| 4228 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 4229 | content = _obj_0.content | ||
| 4230 | end | ||
| 4231 | end | ||
| 4232 | local _val_0 | ||
| 4233 | do | ||
| 4234 | local _obj_0 = _exp_0.data | ||
| 4235 | if _obj_0 ~= nil then | ||
| 4236 | _val_0 = _obj_0.type | ||
| 4237 | end | ||
| 4238 | end | ||
| 4239 | if "success" == _val_0 and content ~= nil then | ||
| 4240 | _match_0 = true | ||
| 4241 | print("æˆåŠŸ", content) | ||
| 4242 | end | ||
| 4243 | end | ||
| 4244 | if not _match_0 then | ||
| 4245 | local _match_1 = false | ||
| 4246 | if _tab_0 then | ||
| 4247 | local content | ||
| 4248 | do | ||
| 4249 | local _obj_0 = _exp_0.data | ||
| 4250 | local _type_1 = type(_obj_0) | ||
| 4251 | if "table" == _type_1 or "userdata" == _type_1 then | ||
| 4252 | content = _obj_0.content | ||
| 4253 | end | ||
| 4254 | end | ||
| 4255 | local _val_0 | ||
| 4256 | do | ||
| 4257 | local _obj_0 = _exp_0.data | ||
| 4258 | if _obj_0 ~= nil then | ||
| 4259 | _val_0 = _obj_0.type | ||
| 4260 | end | ||
| 4261 | end | ||
| 4262 | if "error" == _val_0 and content ~= nil then | ||
| 4263 | _match_1 = true | ||
| 4264 | print("失败", content) | ||
| 4265 | end | ||
| 4266 | end | ||
| 4267 | if not _match_1 then | ||
| 4268 | print("æ— æ•ˆå€¼") | ||
| 4269 | end | ||
| 4270 | end | ||
| 4271 | local _exp_0 = tb | ||
| 4272 | local _type_0 = type(_exp_0) | ||
| 4273 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4274 | if _tab_0 then | ||
| 4275 | local fourth = _exp_0[4] | ||
| 4276 | local _val_0 | ||
| 4277 | do | ||
| 4278 | local _obj_0 = _exp_0[1] | ||
| 4279 | if _obj_0 ~= nil then | ||
| 4280 | _val_0 = _obj_0.a | ||
| 4281 | end | ||
| 4282 | end | ||
| 4283 | local _val_1 | ||
| 4284 | do | ||
| 4285 | local _obj_0 = _exp_0[1] | ||
| 4286 | if _obj_0 ~= nil then | ||
| 4287 | _val_1 = _obj_0.b | ||
| 4288 | end | ||
| 4289 | end | ||
| 4290 | local _val_2 | ||
| 4291 | do | ||
| 4292 | local _obj_0 = _exp_0[2] | ||
| 4293 | if _obj_0 ~= nil then | ||
| 4294 | _val_2 = _obj_0.a | ||
| 4295 | end | ||
| 4296 | end | ||
| 4297 | local _val_3 | ||
| 4298 | do | ||
| 4299 | local _obj_0 = _exp_0[2] | ||
| 4300 | if _obj_0 ~= nil then | ||
| 4301 | _val_3 = _obj_0.b | ||
| 4302 | end | ||
| 4303 | end | ||
| 4304 | local _val_4 | ||
| 4305 | do | ||
| 4306 | local _obj_0 = _exp_0[3] | ||
| 4307 | if _obj_0 ~= nil then | ||
| 4308 | _val_4 = _obj_0.a | ||
| 4309 | end | ||
| 4310 | end | ||
| 4311 | local _val_5 | ||
| 4312 | do | ||
| 4313 | local _obj_0 = _exp_0[3] | ||
| 4314 | if _obj_0 ~= nil then | ||
| 4315 | _val_5 = _obj_0.b | ||
| 4316 | end | ||
| 4317 | end | ||
| 4318 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
| 4319 | print("åŒ¹é…æˆåŠŸ", fourth) | ||
| 4320 | end | ||
| 4321 | end | ||
| 4322 | local segments = { | ||
| 4323 | "admin", | ||
| 4324 | "users", | ||
| 4325 | "logs", | ||
| 4326 | "view" | ||
| 4327 | } | ||
| 4328 | local _type_0 = type(segments) | ||
| 4329 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 4330 | if _tab_0 then | ||
| 4331 | local groups | ||
| 4332 | do | ||
| 4333 | local _accum_0 = { } | ||
| 4334 | local _len_0 = 1 | ||
| 4335 | local _max_0 = #segments + -3 + 1 | ||
| 4336 | for _index_0 = 1, _max_0 do | ||
| 4337 | local _item_0 = segments[_index_0] | ||
| 4338 | _accum_0[_len_0] = _item_0 | ||
| 4339 | _len_0 = _len_0 + 1 | ||
| 4340 | end | ||
| 4341 | groups = _accum_0 | ||
| 4342 | end | ||
| 4343 | local resource = segments[#segments - 1] | ||
| 4344 | local action = segments[#segments] | ||
| 4345 | if resource ~= nil and action ~= nil then | ||
| 4346 | print("Group:", groups) | ||
| 4347 | print("Resource:", resource) | ||
| 4348 | print("Action:", action) | ||
| 4349 | end | ||
| 4350 | end | ||
| 3277 | local Inventory | 4351 | local Inventory |
| 3278 | local _class_0 | 4352 | local _class_0 |
| 3279 | local _base_0 = { | 4353 | local _base_0 = { |
| @@ -3930,6 +5004,10 @@ do | |||
| 3930 | _with_1["key-name"] = value | 5004 | _with_1["key-name"] = value |
| 3931 | end | 5005 | end |
| 3932 | _with_0[#_with_0 + 1] = "abc" | 5006 | _with_0[#_with_0 + 1] = "abc" |
| 5007 | local _with_0 = obj | ||
| 5008 | if _with_0 ~= nil then | ||
| 5009 | print(obj.name) | ||
| 5010 | end | ||
| 3933 | do | 5011 | do |
| 3934 | local var = "hello" | 5012 | local var = "hello" |
| 3935 | print(var) | 5013 | 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/global.lua b/spec/outputs/global.lua index 54a21a9..3918f85 100644 --- a/spec/outputs/global.lua +++ b/spec/outputs/global.lua | |||
| @@ -93,3 +93,28 @@ do | |||
| 93 | FooBar = "pascal case" | 93 | FooBar = "pascal case" |
| 94 | FOOBAR = "all uppercase" | 94 | FOOBAR = "all uppercase" |
| 95 | end | 95 | end |
| 96 | do | ||
| 97 | do | ||
| 98 | local _class_0 | ||
| 99 | local _base_0 = { } | ||
| 100 | if _base_0.__index == nil then | ||
| 101 | _base_0.__index = _base_0 | ||
| 102 | end | ||
| 103 | _class_0 = setmetatable({ | ||
| 104 | __init = function() end, | ||
| 105 | __base = _base_0, | ||
| 106 | __name = "A" | ||
| 107 | }, { | ||
| 108 | __index = _base_0, | ||
| 109 | __call = function(cls, ...) | ||
| 110 | local _self_0 = setmetatable({ }, _base_0) | ||
| 111 | cls.__init(_self_0, ...) | ||
| 112 | return _self_0 | ||
| 113 | end | ||
| 114 | }) | ||
| 115 | _base_0.__class = _class_0 | ||
| 116 | A = _class_0 | ||
| 117 | end | ||
| 118 | Flag = 1 | ||
| 119 | const, x, y = "const", 1, 2 | ||
| 120 | end | ||
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/import_global.lua b/spec/outputs/import_global.lua new file mode 100644 index 0000000..895daf9 --- /dev/null +++ b/spec/outputs/import_global.lua | |||
| @@ -0,0 +1,131 @@ | |||
| 1 | do | ||
| 2 | local print <const> = print | ||
| 3 | local math <const> = math | ||
| 4 | print("hello") | ||
| 5 | math.random(10) | ||
| 6 | end | ||
| 7 | do | ||
| 8 | local print <const> = print | ||
| 9 | local value = 1 | ||
| 10 | value = value + 2 | ||
| 11 | print(value) | ||
| 12 | end | ||
| 13 | do | ||
| 14 | local print | ||
| 15 | print = function(msg) | ||
| 16 | return msg | ||
| 17 | end | ||
| 18 | do | ||
| 19 | local math <const> = math | ||
| 20 | print("local") | ||
| 21 | math.random(1) | ||
| 22 | end | ||
| 23 | end | ||
| 24 | do | ||
| 25 | local print <const> = print | ||
| 26 | local tostring | ||
| 27 | tostring = function(v) | ||
| 28 | return "local" | ||
| 29 | end | ||
| 30 | tostring("value") | ||
| 31 | print(tostring(123)) | ||
| 32 | end | ||
| 33 | do | ||
| 34 | local func | ||
| 35 | func = function(x, y) | ||
| 36 | local type <const> = type | ||
| 37 | local tostring <const> = tostring | ||
| 38 | local print <const> = print | ||
| 39 | return type(x, tostring(y, print)) | ||
| 40 | end | ||
| 41 | func(1, 2) | ||
| 42 | end | ||
| 43 | do | ||
| 44 | local xpcall <const> = xpcall | ||
| 45 | local func <const> = func | ||
| 46 | local world <const> = world | ||
| 47 | local tostring <const> = tostring | ||
| 48 | local print <const> = print | ||
| 49 | xpcall(function() | ||
| 50 | return func("hello " .. tostring(world)) | ||
| 51 | end, function(err) | ||
| 52 | return print(err) | ||
| 53 | end) | ||
| 54 | end | ||
| 55 | do | ||
| 56 | local print <const> = print | ||
| 57 | print(FLAG) | ||
| 58 | FLAG = 123 | ||
| 59 | end | ||
| 60 | do | ||
| 61 | local print <const> = print | ||
| 62 | Foo = 10 | ||
| 63 | print(Foo) | ||
| 64 | Foo = Foo + 2 | ||
| 65 | end | ||
| 66 | do | ||
| 67 | local print <const> = print | ||
| 68 | Bar = 1 | ||
| 69 | Baz = 2 | ||
| 70 | print(Bar, Baz) | ||
| 71 | end | ||
| 72 | do | ||
| 73 | local y <const> = y | ||
| 74 | x = 3434 | ||
| 75 | if y then | ||
| 76 | x = 10 | ||
| 77 | end | ||
| 78 | end | ||
| 79 | do | ||
| 80 | local lowercase <const> = lowercase | ||
| 81 | local tostring <const> = tostring | ||
| 82 | local Uppercase <const> = Uppercase | ||
| 83 | local foobar = "all " .. tostring(lowercase) | ||
| 84 | FooBar = "pascal case" | ||
| 85 | FOOBAR = "all " .. tostring(Uppercase) | ||
| 86 | end | ||
| 87 | do | ||
| 88 | local setmetatable <const> = setmetatable | ||
| 89 | local print <const> = print | ||
| 90 | do | ||
| 91 | local _class_0 | ||
| 92 | local _base_0 = { } | ||
| 93 | if _base_0.__index == nil then | ||
| 94 | _base_0.__index = _base_0 | ||
| 95 | end | ||
| 96 | _class_0 = setmetatable({ | ||
| 97 | __init = function() end, | ||
| 98 | __base = _base_0, | ||
| 99 | __name = "A" | ||
| 100 | }, { | ||
| 101 | __index = _base_0, | ||
| 102 | __call = function(cls, ...) | ||
| 103 | local _self_0 = setmetatable({ }, _base_0) | ||
| 104 | cls.__init(_self_0, ...) | ||
| 105 | return _self_0 | ||
| 106 | end | ||
| 107 | }) | ||
| 108 | _base_0.__class = _class_0 | ||
| 109 | A = _class_0 | ||
| 110 | end | ||
| 111 | Flag = 1 | ||
| 112 | const, x, y = "const", 1, 2 | ||
| 113 | print(math, table) | ||
| 114 | end | ||
| 115 | do | ||
| 116 | local X <const> = X | ||
| 117 | X:func(1, 2, 3) | ||
| 118 | X.tag = "abc" | ||
| 119 | end | ||
| 120 | local _anon_func_0 = function(func) | ||
| 121 | return func | ||
| 122 | end | ||
| 123 | do | ||
| 124 | local func <const> = func | ||
| 125 | local pcall <const> = pcall | ||
| 126 | local f | ||
| 127 | f = function() | ||
| 128 | func() | ||
| 129 | return pcall(_anon_func_0, func) | ||
| 130 | end | ||
| 131 | 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 8624d49..6ab4bbb 100644 --- a/spec/outputs/loops.lua +++ b/spec/outputs/loops.lua | |||
| @@ -60,8 +60,8 @@ do | |||
| 60 | local y = hello[_index_0] | 60 | local y = hello[_index_0] |
| 61 | if y % 2 == 0 then | 61 | if y % 2 == 0 then |
| 62 | _accum_0[_len_0] = y | 62 | _accum_0[_len_0] = y |
| 63 | _len_0 = _len_0 + 1 | ||
| 63 | end | 64 | end |
| 64 | _len_0 = _len_0 + 1 | ||
| 65 | end | 65 | end |
| 66 | x = _accum_0 | 66 | x = _accum_0 |
| 67 | end | 67 | end |
| @@ -132,13 +132,11 @@ do | |||
| 132 | end | 132 | end |
| 133 | do | 133 | do |
| 134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
| 135 | local _len_0 = 1 | ||
| 136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
| 137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
| 138 | local thing = _list_2[_index_0] | 137 | local thing = _list_2[_index_0] |
| 139 | y = "hello" | 138 | y = "hello" |
| 140 | break | 139 | break |
| 141 | _len_0 = _len_0 + 1 | ||
| 142 | end | 140 | end |
| 143 | x = _accum_0 | 141 | x = _accum_0 |
| 144 | end | 142 | end |
| @@ -370,3 +368,131 @@ do | |||
| 370 | end | 368 | end |
| 371 | until false | 369 | until false |
| 372 | end | 370 | end |
| 371 | local _anon_func_0 = function(i, tb) | ||
| 372 | local _accum_0 = { } | ||
| 373 | local _len_0 = 1 | ||
| 374 | while tb[i] do | ||
| 375 | i = i + 1 | ||
| 376 | _accum_0[_len_0] = i - 1 | ||
| 377 | _len_0 = _len_0 + 1 | ||
| 378 | end | ||
| 379 | return _accum_0 | ||
| 380 | end | ||
| 381 | do | ||
| 382 | local index | ||
| 383 | do | ||
| 384 | local _accum_0 | ||
| 385 | for i = 1, #tb do | ||
| 386 | if tb[i] then | ||
| 387 | _accum_0 = i | ||
| 388 | break | ||
| 389 | end | ||
| 390 | end | ||
| 391 | index = _accum_0 | ||
| 392 | end | ||
| 393 | f((function() | ||
| 394 | local _accum_0 | ||
| 395 | for i = 1, #tb do | ||
| 396 | if tb[i] then | ||
| 397 | _accum_0 = i | ||
| 398 | break | ||
| 399 | end | ||
| 400 | end | ||
| 401 | return _accum_0 | ||
| 402 | end)()) | ||
| 403 | f((function() | ||
| 404 | local _accum_0 = { } | ||
| 405 | local _len_0 = 1 | ||
| 406 | for i = 1, #tb do | ||
| 407 | if tb[i] then | ||
| 408 | _accum_0[_len_0] = i | ||
| 409 | _len_0 = _len_0 + 1 | ||
| 410 | end | ||
| 411 | end | ||
| 412 | return _accum_0 | ||
| 413 | end)()) | ||
| 414 | i = 1 | ||
| 415 | local ids | ||
| 416 | do | ||
| 417 | local _accum_0 = { } | ||
| 418 | local _len_0 = 1 | ||
| 419 | while tb[i] do | ||
| 420 | i = i + 1 | ||
| 421 | _accum_0[_len_0] = i - 1 | ||
| 422 | _len_0 = _len_0 + 1 | ||
| 423 | end | ||
| 424 | ids = _accum_0 | ||
| 425 | end | ||
| 426 | i = 1 | ||
| 427 | local idx | ||
| 428 | do | ||
| 429 | local _accum_0 | ||
| 430 | while tb[i] do | ||
| 431 | i = i + 1 | ||
| 432 | _accum_0 = i - 1 | ||
| 433 | break | ||
| 434 | end | ||
| 435 | idx = _accum_0 | ||
| 436 | end | ||
| 437 | local f1 | ||
| 438 | f1 = function() | ||
| 439 | i = 1 | ||
| 440 | return f(_anon_func_0(i, tb)) | ||
| 441 | end | ||
| 442 | i = 1 | ||
| 443 | f((function() | ||
| 444 | local _accum_0 | ||
| 445 | while tb[i] do | ||
| 446 | i = i + 1 | ||
| 447 | _accum_0 = i - 1 | ||
| 448 | break | ||
| 449 | end | ||
| 450 | return _accum_0 | ||
| 451 | end)()) | ||
| 452 | local _accum_0 = { } | ||
| 453 | local _len_0 = 1 | ||
| 454 | local _list_3 = items | ||
| 455 | for _index_0 = 1, #_list_3 do | ||
| 456 | local item = _list_3[_index_0] | ||
| 457 | local _type_0 = type(item) | ||
| 458 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 459 | if _tab_0 then | ||
| 460 | local value = item.value | ||
| 461 | if "A" == item.type and value ~= nil then | ||
| 462 | if value > 5 then | ||
| 463 | _accum_0[_len_0] = item | ||
| 464 | _len_0 = _len_0 + 1 | ||
| 465 | end | ||
| 466 | end | ||
| 467 | end | ||
| 468 | end | ||
| 469 | list = _accum_0 | ||
| 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 4d31574..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 |
| @@ -330,10 +341,8 @@ local _1 | |||
| 330 | _1 = function() | 341 | _1 = function() |
| 331 | print(1) | 342 | print(1) |
| 332 | local _accum_0 = { } | 343 | local _accum_0 = { } |
| 333 | local _len_0 = 1 | ||
| 334 | while false do | 344 | while false do |
| 335 | break | 345 | break |
| 336 | _len_0 = _len_0 + 1 | ||
| 337 | end | 346 | end |
| 338 | return _accum_0 | 347 | return _accum_0 |
| 339 | end | 348 | end |
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 e4dedc9..7c1004b 100644 --- a/spec/outputs/switch.lua +++ b/spec/outputs/switch.lua | |||
| @@ -415,4 +415,366 @@ do | |||
| 415 | end | 415 | end |
| 416 | end | 416 | end |
| 417 | end | 417 | end |
| 418 | do | ||
| 419 | local _exp_0 = tb | ||
| 420 | local _type_0 = type(_exp_0) | ||
| 421 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 422 | local _match_0 = false | ||
| 423 | if _tab_0 then | ||
| 424 | if 1 == _exp_0[1] and 2 == _exp_0[2] and 3 == _exp_0[3] then | ||
| 425 | _match_0 = true | ||
| 426 | print("1, 2, 3") | ||
| 427 | end | ||
| 428 | end | ||
| 429 | if not _match_0 then | ||
| 430 | local _match_1 = false | ||
| 431 | if _tab_0 then | ||
| 432 | local b = _exp_0[2] | ||
| 433 | if 1 == _exp_0[1] and b ~= nil and 3 == _exp_0[3] then | ||
| 434 | _match_1 = true | ||
| 435 | print("1, " .. tostring(b) .. ", 3") | ||
| 436 | end | ||
| 437 | end | ||
| 438 | if not _match_1 then | ||
| 439 | if _tab_0 then | ||
| 440 | local b = _exp_0[3] | ||
| 441 | if b == nil then | ||
| 442 | b = 3 | ||
| 443 | end | ||
| 444 | if 1 == _exp_0[1] and 2 == _exp_0[2] then | ||
| 445 | print("1, 2, " .. tostring(b)) | ||
| 446 | end | ||
| 447 | end | ||
| 448 | end | ||
| 449 | end | ||
| 450 | end | ||
| 451 | do | ||
| 452 | local _exp_0 = tb | ||
| 453 | local _type_0 = type(_exp_0) | ||
| 454 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 455 | local _match_0 = false | ||
| 456 | if _tab_0 then | ||
| 457 | local result = _exp_0.result | ||
| 458 | if true == _exp_0.success and result ~= nil then | ||
| 459 | _match_0 = true | ||
| 460 | print("success", result) | ||
| 461 | end | ||
| 462 | end | ||
| 463 | if not _match_0 then | ||
| 464 | local _match_1 = false | ||
| 465 | if _tab_0 then | ||
| 466 | if false == _exp_0.success then | ||
| 467 | _match_1 = true | ||
| 468 | print("failed", result) | ||
| 469 | end | ||
| 470 | end | ||
| 471 | if not _match_1 then | ||
| 472 | print("invalid") | ||
| 473 | end | ||
| 474 | end | ||
| 475 | end | ||
| 476 | do | ||
| 477 | local _exp_0 = tb | ||
| 478 | local _type_0 = type(_exp_0) | ||
| 479 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 480 | local _match_0 = false | ||
| 481 | if _tab_0 then | ||
| 482 | local content = _exp_0.content | ||
| 483 | if "success" == _exp_0.type and content ~= nil then | ||
| 484 | _match_0 = true | ||
| 485 | print("success", content) | ||
| 486 | end | ||
| 487 | end | ||
| 488 | if not _match_0 then | ||
| 489 | local _match_1 = false | ||
| 490 | if _tab_0 then | ||
| 491 | local content = _exp_0.content | ||
| 492 | if "error" == _exp_0.type and content ~= nil then | ||
| 493 | _match_1 = true | ||
| 494 | print("failed", content) | ||
| 495 | end | ||
| 496 | end | ||
| 497 | if not _match_1 then | ||
| 498 | print("invalid") | ||
| 499 | end | ||
| 500 | end | ||
| 501 | end | ||
| 502 | do | ||
| 503 | do | ||
| 504 | local _exp_0 = tb | ||
| 505 | local _type_0 = type(_exp_0) | ||
| 506 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 507 | if _tab_0 then | ||
| 508 | local fourth = _exp_0[4] | ||
| 509 | local _val_0 | ||
| 510 | do | ||
| 511 | local _obj_0 = _exp_0[1] | ||
| 512 | if _obj_0 ~= nil then | ||
| 513 | _val_0 = _obj_0.a | ||
| 514 | end | ||
| 515 | end | ||
| 516 | local _val_1 | ||
| 517 | do | ||
| 518 | local _obj_0 = _exp_0[1] | ||
| 519 | if _obj_0 ~= nil then | ||
| 520 | _val_1 = _obj_0.b | ||
| 521 | end | ||
| 522 | end | ||
| 523 | local _val_2 | ||
| 524 | do | ||
| 525 | local _obj_0 = _exp_0[2] | ||
| 526 | if _obj_0 ~= nil then | ||
| 527 | _val_2 = _obj_0.a | ||
| 528 | end | ||
| 529 | end | ||
| 530 | local _val_3 | ||
| 531 | do | ||
| 532 | local _obj_0 = _exp_0[2] | ||
| 533 | if _obj_0 ~= nil then | ||
| 534 | _val_3 = _obj_0.b | ||
| 535 | end | ||
| 536 | end | ||
| 537 | local _val_4 | ||
| 538 | do | ||
| 539 | local _obj_0 = _exp_0[3] | ||
| 540 | if _obj_0 ~= nil then | ||
| 541 | _val_4 = _obj_0.a | ||
| 542 | end | ||
| 543 | end | ||
| 544 | local _val_5 | ||
| 545 | do | ||
| 546 | local _obj_0 = _exp_0[3] | ||
| 547 | if _obj_0 ~= nil then | ||
| 548 | _val_5 = _obj_0.b | ||
| 549 | end | ||
| 550 | end | ||
| 551 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and fourth ~= nil then | ||
| 552 | print("matched", fourth) | ||
| 553 | end | ||
| 554 | end | ||
| 555 | end | ||
| 556 | local _exp_0 = tb | ||
| 557 | local _type_0 = type(_exp_0) | ||
| 558 | local _tab_0 = "table" == _type_0 or "userdata" == _type_0 | ||
| 559 | local _match_0 = false | ||
| 560 | if _tab_0 then | ||
| 561 | local _val_0 | ||
| 562 | do | ||
| 563 | local _obj_0 = _exp_0[1] | ||
| 564 | if _obj_0 ~= nil then | ||
| 565 | _val_0 = _obj_0.c | ||
| 566 | end | ||
| 567 | end | ||
| 568 | local _val_1 | ||
| 569 | do | ||
| 570 | local _obj_0 = _exp_0[1] | ||
| 571 | if _obj_0 ~= nil then | ||
| 572 | _val_1 = _obj_0.d | ||
| 573 | end | ||
| 574 | end | ||
| 575 | local _val_2 | ||
| 576 | do | ||
| 577 | local _obj_0 = _exp_0[2] | ||
| 578 | if _obj_0 ~= nil then | ||
| 579 | _val_2 = _obj_0.c | ||
| 580 | end | ||
| 581 | end | ||
| 582 | local _val_3 | ||
| 583 | do | ||
| 584 | local _obj_0 = _exp_0[2] | ||
| 585 | if _obj_0 ~= nil then | ||
| 586 | _val_3 = _obj_0.d | ||
| 587 | end | ||
| 588 | end | ||
| 589 | local _val_4 | ||
| 590 | do | ||
| 591 | local _obj_0 = _exp_0[3] | ||
| 592 | if _obj_0 ~= nil then | ||
| 593 | _val_4 = _obj_0.c | ||
| 594 | end | ||
| 595 | end | ||
| 596 | local _val_5 | ||
| 597 | do | ||
| 598 | local _obj_0 = _exp_0[3] | ||
| 599 | if _obj_0 ~= nil then | ||
| 600 | _val_5 = _obj_0.d | ||
| 601 | end | ||
| 602 | end | ||
| 603 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 then | ||
| 604 | _match_0 = true | ||
| 605 | print("OK") | ||
| 606 | end | ||
| 607 | end | ||
| 608 | if not _match_0 then | ||
| 609 | if _tab_0 then | ||
| 610 | local sixth = _exp_0[6] | ||
| 611 | local _val_0 | ||
| 612 | do | ||
| 613 | local _obj_0 = _exp_0[3] | ||
| 614 | if _obj_0 ~= nil then | ||
| 615 | _val_0 = _obj_0.a | ||
| 616 | end | ||
| 617 | end | ||
| 618 | local _val_1 | ||
| 619 | do | ||
| 620 | local _obj_0 = _exp_0[3] | ||
| 621 | if _obj_0 ~= nil then | ||
| 622 | _val_1 = _obj_0.b | ||
| 623 | end | ||
| 624 | end | ||
| 625 | local _val_2 | ||
| 626 | do | ||
| 627 | local _obj_0 = _exp_0[4] | ||
| 628 | if _obj_0 ~= nil then | ||
| 629 | _val_2 = _obj_0.a | ||
| 630 | end | ||
| 631 | end | ||
| 632 | local _val_3 | ||
| 633 | do | ||
| 634 | local _obj_0 = _exp_0[4] | ||
| 635 | if _obj_0 ~= nil then | ||
| 636 | _val_3 = _obj_0.b | ||
| 637 | end | ||
| 638 | end | ||
| 639 | local _val_4 | ||
| 640 | do | ||
| 641 | local _obj_0 = _exp_0[5] | ||
| 642 | if _obj_0 ~= nil then | ||
| 643 | _val_4 = _obj_0.a | ||
| 644 | end | ||
| 645 | end | ||
| 646 | local _val_5 | ||
| 647 | do | ||
| 648 | local _obj_0 = _exp_0[5] | ||
| 649 | if _obj_0 ~= nil then | ||
| 650 | _val_5 = _obj_0.b | ||
| 651 | end | ||
| 652 | end | ||
| 653 | if 1 == _val_0 and 2 == _val_1 and 3 == _val_2 and 4 == _val_3 and 5 == _val_4 and 6 == _val_5 and sixth ~= nil then | ||
| 654 | print("matched", sixth) | ||
| 655 | end | ||
| 656 | end | ||
| 657 | 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 | ||
| 418 | return nil | 780 | return nil |
diff --git a/spec/outputs/syntax.lua b/spec/outputs/syntax.lua index 040a325..eb4543c 100644 --- a/spec/outputs/syntax.lua +++ b/spec/outputs/syntax.lua | |||
| @@ -5,9 +5,9 @@ func(arg1, arg2, another, arg3) | |||
| 5 | local we | 5 | local we |
| 6 | here, we = function() end, yeah | 6 | here, we = function() end, yeah |
| 7 | local the, different | 7 | local the, different |
| 8 | the, different = function() | 8 | the, different = (function() |
| 9 | return approach | 9 | return approach |
| 10 | end, yeah | 10 | end), yeah |
| 11 | dad() | 11 | dad() |
| 12 | dad(lord) | 12 | dad(lord) |
| 13 | hello(one, two)(); | 13 | hello(one, two)(); |
| @@ -430,4 +430,94 @@ 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 | ||
| 444 | do | ||
| 445 | x = 1 | ||
| 446 | y = 2 | ||
| 447 | i = i + 1 | ||
| 448 | j = j + 1 | ||
| 449 | if condition then | ||
| 450 | setup() | ||
| 451 | run() | ||
| 452 | cleanup() | ||
| 453 | end | ||
| 454 | a = 1 | ||
| 455 | local b = 2 | ||
| 456 | local c = a + b | ||
| 457 | print(a) | ||
| 458 | print(b) | ||
| 459 | print(c) | ||
| 460 | f = function() | ||
| 461 | a = 1 | ||
| 462 | b = 2 | ||
| 463 | return a + b | ||
| 464 | end | ||
| 465 | a = 1 | ||
| 466 | b = 2 | ||
| 467 | local success, result = pcall(function() | ||
| 468 | return func() | ||
| 469 | end) | ||
| 470 | if success then | ||
| 471 | print(result) | ||
| 472 | end | ||
| 473 | local value = "foo" | ||
| 474 | print(value) | ||
| 475 | value = value .. "bar" | ||
| 476 | print(value) | ||
| 477 | do | ||
| 478 | if ok then | ||
| 479 | print("ok!") | ||
| 480 | end | ||
| 481 | return 42 | ||
| 482 | end | ||
| 483 | for i = 1, 3 do | ||
| 484 | print(i) | ||
| 485 | goto _continue_0 | ||
| 486 | ::_continue_0:: | ||
| 487 | end | ||
| 488 | local n = 0 | ||
| 489 | while n < 2 do | ||
| 490 | print("n=", n) | ||
| 491 | n = n + 1 | ||
| 492 | end | ||
| 493 | local obj = { } | ||
| 494 | obj:set(10) | ||
| 495 | obj:get() | ||
| 496 | print("done") | ||
| 497 | do | ||
| 498 | local _with_0 = tbl | ||
| 499 | _with_0:push(1) | ||
| 500 | print("push") | ||
| 501 | end | ||
| 502 | a = 5 | ||
| 503 | if a > 3 then | ||
| 504 | print("big") | ||
| 505 | b = a * 2 | ||
| 506 | print(b) | ||
| 507 | else | ||
| 508 | print("small") | ||
| 509 | b = a | ||
| 510 | end | ||
| 511 | xpcall(function() | ||
| 512 | x = 1 | ||
| 513 | y = 2 | ||
| 514 | return print(x + y) | ||
| 515 | end, function(err) | ||
| 516 | return print("error:", err) | ||
| 517 | end) | ||
| 518 | end | ||
| 519 | local q = 1 | ||
| 520 | local w = 2 | ||
| 521 | local e = 3 | ||
| 522 | print(q, w, e) | ||
| 433 | return nil | 523 | 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/loops.lua b/spec/outputs/unicode/loops.lua index 8379993..27bbe2e 100644 --- a/spec/outputs/unicode/loops.lua +++ b/spec/outputs/unicode/loops.lua | |||
| @@ -60,8 +60,8 @@ do | |||
| 60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] | 60 | local _u53d8_u91cfy = _u4f60_u597d[_index_0] |
| 61 | if _u53d8_u91cfy % 2 == 0 then | 61 | if _u53d8_u91cfy % 2 == 0 then |
| 62 | _accum_0[_len_0] = _u53d8_u91cfy | 62 | _accum_0[_len_0] = _u53d8_u91cfy |
| 63 | _len_0 = _len_0 + 1 | ||
| 63 | end | 64 | end |
| 64 | _len_0 = _len_0 + 1 | ||
| 65 | end | 65 | end |
| 66 | _u53d8_u91cfx = _accum_0 | 66 | _u53d8_u91cfx = _accum_0 |
| 67 | end | 67 | end |
| @@ -132,13 +132,11 @@ do | |||
| 132 | end | 132 | end |
| 133 | do | 133 | do |
| 134 | local _accum_0 = { } | 134 | local _accum_0 = { } |
| 135 | local _len_0 = 1 | ||
| 136 | local _list_2 = 3 | 135 | local _list_2 = 3 |
| 137 | for _index_0 = 1, #_list_2 do | 136 | for _index_0 = 1, #_list_2 do |
| 138 | local _u4e1c_u897f = _list_2[_index_0] | 137 | local _u4e1c_u897f = _list_2[_index_0] |
| 139 | _u53d8_u91cfy = "ä½ å¥½" | 138 | _u53d8_u91cfy = "ä½ å¥½" |
| 140 | break | 139 | break |
| 141 | _len_0 = _len_0 + 1 | ||
| 142 | end | 140 | end |
| 143 | _u53d8_u91cfx = _accum_0 | 141 | _u53d8_u91cfx = _accum_0 |
| 144 | end | 142 | end |
diff --git a/spec/outputs/unicode/macro.lua b/spec/outputs/unicode/macro.lua index b14f571..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() |
| @@ -365,10 +359,8 @@ local _1 | |||
| 365 | _1 = function() | 359 | _1 = function() |
| 366 | _u6253_u5370(1) | 360 | _u6253_u5370(1) |
| 367 | local _accum_0 = { } | 361 | local _accum_0 = { } |
| 368 | local _len_0 = 1 | ||
| 369 | while false do | 362 | while false do |
| 370 | break | 363 | break |
| 371 | _len_0 = _len_0 + 1 | ||
| 372 | end | 364 | end |
| 373 | return _accum_0 | 365 | return _accum_0 |
| 374 | end | 366 | end |
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..f5d5d8a 100644 --- a/spec/outputs/unicode/syntax.lua +++ b/spec/outputs/unicode/syntax.lua | |||
| @@ -5,9 +5,9 @@ _u51fd_u6570(_u53c2_u65701, _u53c2_u65702, _u53e6_u5916, _u53c2_u65703) | |||
| 5 | local _u6211_u4eec | 5 | local _u6211_u4eec |
| 6 | _u8fd9_u91cc, _u6211_u4eec = function() end, _u662f_u7684 | 6 | _u8fd9_u91cc, _u6211_u4eec = function() end, _u662f_u7684 |
| 7 | local _u8fd9_u4e2a, _u4e0d_u540c | 7 | local _u8fd9_u4e2a, _u4e0d_u540c |
| 8 | _u8fd9_u4e2a, _u4e0d_u540c = function() | 8 | _u8fd9_u4e2a, _u4e0d_u540c = (function() |
| 9 | return _u65b9_u6cd5 | 9 | return _u65b9_u6cd5 |
| 10 | end, _u662f_u7684 | 10 | end), _u662f_u7684 |
| 11 | _u7238_u7238() | 11 | _u7238_u7238() |
| 12 | _u7238_u7238(_u4e3b) | 12 | _u7238_u7238(_u4e3b) |
| 13 | _u4f60_u597d(_u4e00, _u4e8c)(); | 13 | _u4f60_u597d(_u4e00, _u4e8c)(); |
| @@ -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/unicode/whitespace.lua b/spec/outputs/unicode/whitespace.lua index d026abb..7a83d9f 100644 --- a/spec/outputs/unicode/whitespace.lua +++ b/spec/outputs/unicode/whitespace.lua | |||
| @@ -82,12 +82,12 @@ v = function() | |||
| 82 | return _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc | 82 | return _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc |
| 83 | end | 83 | end |
| 84 | local v1, v2, v3 | 84 | local v1, v2, v3 |
| 85 | v1, v2, v3 = function() | 85 | v1, v2, v3 = (function() |
| 86 | return _u53d8_u91cfa | 86 | return _u53d8_u91cfa |
| 87 | end, _u53d8_u91cfb, _u53d8_u91cfc | 87 | end), _u53d8_u91cfb, _u53d8_u91cfc |
| 88 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, f2({ | 88 | local _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc, _u53d8_u91cfd, _u53d8_u91cfe, _u53d8_u91cff = 1, (f2({ |
| 89 | abc = abc | 89 | abc = abc |
| 90 | }), 3, 4, _u51fd_u65705(abc), 6 | 90 | })), 3, 4, _u51fd_u65705(abc), 6 |
| 91 | for _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc in pairs(_u5bf9_u8c61tb) do | 91 | for _u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc in pairs(_u5bf9_u8c61tb) do |
| 92 | _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) | 92 | _u6253_u5370(_u53d8_u91cfa, _u53d8_u91cfb, _u53d8_u91cfc) |
| 93 | end | 93 | end |
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/whitespace.lua b/spec/outputs/whitespace.lua index 0251968..864f085 100644 --- a/spec/outputs/whitespace.lua +++ b/spec/outputs/whitespace.lua | |||
| @@ -94,12 +94,12 @@ v = function() | |||
| 94 | return a, b, c | 94 | return a, b, c |
| 95 | end | 95 | end |
| 96 | local v1, v2, v3 | 96 | local v1, v2, v3 |
| 97 | v1, v2, v3 = function() | 97 | v1, v2, v3 = (function() |
| 98 | return a | 98 | return a |
| 99 | end, b, c | 99 | end), b, c |
| 100 | local a, b, c, d, e, f = 1, f2({ | 100 | local a, b, c, d, e, f = 1, (f2({ |
| 101 | abc = abc | 101 | abc = abc |
| 102 | }), 3, 4, f5(abc), 6 | 102 | })), 3, 4, f5(abc), 6 |
| 103 | for a, b, c in pairs(tb) do | 103 | for a, b, c in pairs(tb) do |
| 104 | print(a, b, c) | 104 | print(a, b, c) |
| 105 | end | 105 | end |
diff --git a/spec/outputs/with.lua b/spec/outputs/with.lua index 1a795c1..530915e 100644 --- a/spec/outputs/with.lua +++ b/spec/outputs/with.lua | |||
| @@ -187,4 +187,66 @@ do | |||
| 187 | return _with_0[123] | 187 | return _with_0[123] |
| 188 | end | 188 | end |
| 189 | end | 189 | end |
| 190 | do | ||
| 191 | f((function() | ||
| 192 | local _with_0 = item | ||
| 193 | do | ||
| 194 | local _accum_0 | ||
| 195 | repeat | ||
| 196 | if _with_0.id > 0 then | ||
| 197 | _accum_0 = _with_0.content | ||
| 198 | break | ||
| 199 | end | ||
| 200 | until true | ||
| 201 | _with_0 = _accum_0 | ||
| 202 | end | ||
| 203 | return _with_0 | ||
| 204 | end)()) | ||
| 205 | local a | ||
| 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 | ||
| 220 | local _accum_0 | ||
| 221 | while true do | ||
| 222 | local _with_0 = tb | ||
| 223 | local _accum_1 | ||
| 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 | ||
| 248 | end | ||
| 249 | end | ||
| 250 | a = _accum_0 | ||
| 251 | end | ||
| 190 | 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/efsw/FileWatcherGeneric.cpp b/src/3rdParty/efsw/FileWatcherGeneric.cpp index 3f3c52e..468d27c 100644 --- a/src/3rdParty/efsw/FileWatcherGeneric.cpp +++ b/src/3rdParty/efsw/FileWatcherGeneric.cpp | |||
| @@ -25,7 +25,7 @@ FileWatcherGeneric::~FileWatcherGeneric() { | |||
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, | 27 | WatchID FileWatcherGeneric::addWatch( const std::string& directory, FileWatchListener* watcher, |
| 28 | bool recursive, const std::vector<WatcherOption>& options ) { | 28 | bool recursive, const std::vector<WatcherOption>& /*options*/ ) { |
| 29 | std::string dir( directory ); | 29 | std::string dir( directory ); |
| 30 | 30 | ||
| 31 | FileSystem::dirAddSlashAtEnd( dir ); | 31 | FileSystem::dirAddSlashAtEnd( dir ); |
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..2722c55 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) { |
| @@ -304,7 +341,7 @@ int main(int narg, const char** args) { | |||
| 304 | " -- Read from standard in, print to standard out\n" | 341 | " -- Read from standard in, print to standard out\n" |
| 305 | " (Must be first and only argument)\n\n" | 342 | " (Must be first and only argument)\n\n" |
| 306 | " --target=version Specify the Lua version that codes will be generated to\n" | 343 | " --target=version Specify the Lua version that codes will be generated to\n" |
| 307 | " (version can only be 5.1, 5.2, 5.3 or 5.4)\n" | 344 | " (version can only be 5.1 to 5.5)\n" |
| 308 | " --path=path_str Append an extra Lua search path string to package.path\n\n" | 345 | " --path=path_str Append an extra Lua search path string to package.path\n\n" |
| 309 | " Execute without options to enter REPL, type symbol '$'\n" | 346 | " Execute without options to enter REPL, type symbol '$'\n" |
| 310 | " in a single line to start/stop multi-line mode\n" | 347 | " in a single line to start/stop multi-line mode\n" |
| @@ -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 fe6e726..cfd4cc6 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,12 +174,11 @@ 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* ud) const { | 180 | std::string GlobalOp_t::to_string(void*) const { |
| 174 | auto info = reinterpret_cast<YueFormat*>(ud); | 181 | return "*"s; |
| 175 | return info->convert(this); | ||
| 176 | } | 182 | } |
| 177 | std::string ExportDefault_t::to_string(void*) const { | 183 | std::string ExportDefault_t::to_string(void*) const { |
| 178 | return "default"s; | 184 | return "default"s; |
| @@ -188,22 +194,34 @@ std::string ConstValue_t::to_string(void* ud) const { | |||
| 188 | std::string NotIn_t::to_string(void*) const { | 194 | std::string NotIn_t::to_string(void*) const { |
| 189 | return {}; | 195 | return {}; |
| 190 | } | 196 | } |
| 197 | std::string Break_t::to_string(void*) const { | ||
| 198 | return "break"s; | ||
| 199 | } | ||
| 200 | std::string Continue_t::to_string(void*) const { | ||
| 201 | return "continue"s; | ||
| 202 | } | ||
| 191 | std::string BreakLoop_t::to_string(void* ud) const { | 203 | std::string BreakLoop_t::to_string(void* ud) const { |
| 192 | auto info = reinterpret_cast<YueFormat*>(ud); | 204 | if (value) { |
| 193 | return info->convert(this); | 205 | return type->to_string(ud) + ' ' + value->to_string(ud); |
| 206 | } | ||
| 207 | return type->to_string(ud); | ||
| 194 | } | 208 | } |
| 195 | std::string YueLineComment_t::to_string(void* ud) const { | 209 | std::string YueLineComment_t::to_string(void* ud) const { |
| 196 | auto info = reinterpret_cast<YueFormat*>(ud); | 210 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 197 | return "--"s + info->convert(this); | 211 | return "--"s + info->convert(this); |
| 198 | } | 212 | } |
| 199 | std::string MultilineCommentInner_t::to_string(void* ud) const { | 213 | std::string YueMultilineComment_t::to_string(void* ud) const { |
| 200 | auto info = reinterpret_cast<YueFormat*>(ud); | 214 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 201 | return info->convert(this); | 215 | return "--[["s + info->convert(this) + "]]"s; |
| 202 | } | 216 | } |
| 203 | std::string Variable_t::to_string(void* ud) const { | 217 | std::string YueComment_t::to_string(void* ud) const { |
| 204 | return name->to_string(ud); | 218 | if (comment) { |
| 219 | return comment->to_string(ud); | ||
| 220 | } else { | ||
| 221 | return {}; | ||
| 222 | } | ||
| 205 | } | 223 | } |
| 206 | std::string LabelName_t::to_string(void* ud) const { | 224 | std::string Variable_t::to_string(void* ud) const { |
| 207 | return name->to_string(ud); | 225 | return name->to_string(ud); |
| 208 | } | 226 | } |
| 209 | std::string LuaKeyword_t::to_string(void* ud) const { | 227 | std::string LuaKeyword_t::to_string(void* ud) const { |
| @@ -297,6 +315,20 @@ std::string ImportAs_t::to_string(void* ud) const { | |||
| 297 | } | 315 | } |
| 298 | return join(temp, " "s); | 316 | return join(temp, " "s); |
| 299 | } | 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 | } | ||
| 329 | std::string ImportAllGlobal_t::to_string(void*) const { | ||
| 330 | return "global"s; | ||
| 331 | } | ||
| 300 | std::string Import_t::to_string(void* ud) const { | 332 | std::string Import_t::to_string(void* ud) const { |
| 301 | if (ast_is<FromImport_t>(content)) { | 333 | if (ast_is<FromImport_t>(content)) { |
| 302 | return content->to_string(ud); | 334 | return content->to_string(ud); |
| @@ -324,6 +356,12 @@ std::string Backcall_t::to_string(void* ud) const { | |||
| 324 | temp.emplace_back(value->to_string(ud)); | 356 | temp.emplace_back(value->to_string(ud)); |
| 325 | return join(temp, " "sv); | 357 | return join(temp, " "sv); |
| 326 | } | 358 | } |
| 359 | std::string SubBackcall_t::to_string(void* ud) const { | ||
| 360 | str_list temp; | ||
| 361 | temp.emplace_back(arrow->to_string(ud)); | ||
| 362 | temp.emplace_back(value->to_string(ud)); | ||
| 363 | return join(temp, " "sv); | ||
| 364 | } | ||
| 327 | std::string PipeBody_t::to_string(void* ud) const { | 365 | std::string PipeBody_t::to_string(void* ud) const { |
| 328 | auto info = reinterpret_cast<YueFormat*>(ud); | 366 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 329 | str_list temp; | 367 | str_list temp; |
| @@ -332,13 +370,6 @@ std::string PipeBody_t::to_string(void* ud) const { | |||
| 332 | } | 370 | } |
| 333 | return join(temp, "\n"sv); | 371 | return join(temp, "\n"sv); |
| 334 | } | 372 | } |
| 335 | std::string ExpListLow_t::to_string(void* ud) const { | ||
| 336 | str_list temp; | ||
| 337 | for (auto exp : exprs.objects()) { | ||
| 338 | temp.emplace_back(exp->to_string(ud)); | ||
| 339 | } | ||
| 340 | return join(temp, "; "sv); | ||
| 341 | } | ||
| 342 | std::string ExpList_t::to_string(void* ud) const { | 373 | std::string ExpList_t::to_string(void* ud) const { |
| 343 | str_list temp; | 374 | str_list temp; |
| 344 | for (auto exp : exprs.objects()) { | 375 | for (auto exp : exprs.objects()) { |
| @@ -359,8 +390,8 @@ std::string With_t::to_string(void* ud) const { | |||
| 359 | str_list temp{ | 390 | str_list temp{ |
| 360 | eop ? "with?"s : "with"s, | 391 | eop ? "with?"s : "with"s, |
| 361 | valueList->to_string(ud)}; | 392 | valueList->to_string(ud)}; |
| 362 | if (assigns) { | 393 | if (assign) { |
| 363 | temp.push_back(assigns->to_string(ud)); | 394 | temp.push_back(':' + assign->to_string(ud)); |
| 364 | } | 395 | } |
| 365 | if (body.is<Statement_t>()) { | 396 | if (body.is<Statement_t>()) { |
| 366 | return join(temp, " "sv) + " do "s + body->to_string(ud); | 397 | return join(temp, " "sv) + " do "s + body->to_string(ud); |
| @@ -406,6 +437,9 @@ std::string SwitchCase_t::to_string(void* ud) const { | |||
| 406 | std::string Switch_t::to_string(void* ud) const { | 437 | std::string Switch_t::to_string(void* ud) const { |
| 407 | auto info = reinterpret_cast<YueFormat*>(ud); | 438 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 408 | str_list temp{"switch "s + target->to_string(ud)}; | 439 | str_list temp{"switch "s + target->to_string(ud)}; |
| 440 | if (assignment) { | ||
| 441 | temp.back().append(assignment->to_string(ud)); | ||
| 442 | } | ||
| 409 | info->pushScope(); | 443 | info->pushScope(); |
| 410 | for (auto branch : branches.objects()) { | 444 | for (auto branch : branches.objects()) { |
| 411 | temp.emplace_back(info->ind() + branch->to_string(ud)); | 445 | temp.emplace_back(info->ind() + branch->to_string(ud)); |
| @@ -449,41 +483,75 @@ std::string If_t::to_string(void* ud) const { | |||
| 449 | temp.back() += " then"s; | 483 | temp.back() += " then"s; |
| 450 | } | 484 | } |
| 451 | ++it; | 485 | ++it; |
| 452 | bool condition = true; | 486 | enum class NType { |
| 487 | Cond, | ||
| 488 | Stat, | ||
| 489 | Block | ||
| 490 | }; | ||
| 491 | NType lastType = NType::Cond; | ||
| 453 | for (; it != nodes.objects().end(); ++it) { | 492 | for (; it != nodes.objects().end(); ++it) { |
| 454 | auto node = *it; | 493 | auto node = *it; |
| 455 | switch (node->get_id()) { | 494 | switch (node->get_id()) { |
| 456 | case id<IfCond_t>(): | 495 | case id<IfCond_t>(): |
| 457 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); | 496 | temp.emplace_back(info->ind() + "elseif "s + node->to_string(ud)); |
| 458 | condition = true; | 497 | lastType = NType::Cond; |
| 459 | break; | 498 | break; |
| 460 | case id<Statement_t>(): { | 499 | case id<Statement_t>(): { |
| 461 | if (condition) { | 500 | switch (lastType) { |
| 462 | temp.back() += " then "s + node->to_string(ud); | 501 | case NType::Cond: |
| 463 | } else { | 502 | temp.back() += " then "s + node->to_string(ud); |
| 464 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | 503 | break; |
| 504 | case NType::Stat: | ||
| 505 | if (temp.back().back() == '\n') { | ||
| 506 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
| 507 | } else { | ||
| 508 | temp.back() += " else "s + node->to_string(ud); | ||
| 509 | } | ||
| 510 | break; | ||
| 511 | case NType::Block: | ||
| 512 | temp.emplace_back(info->ind() + "else "s + node->to_string(ud)); | ||
| 513 | break; | ||
| 465 | } | 514 | } |
| 466 | condition = false; | 515 | lastType = NType::Stat; |
| 467 | break; | 516 | break; |
| 468 | } | 517 | } |
| 469 | case id<Block_t>(): { | 518 | case id<Block_t>(): { |
| 470 | if (condition) { | 519 | switch (lastType) { |
| 471 | info->pushScope(); | 520 | case NType::Cond: { |
| 472 | temp.emplace_back(node->to_string(ud)); | 521 | info->pushScope(); |
| 473 | if (temp.back().empty()) { | 522 | temp.emplace_back(node->to_string(ud)); |
| 474 | temp.back() = info->ind() + "--"s; | 523 | if (temp.back().empty()) { |
| 524 | temp.back() = info->ind() + "--"s; | ||
| 525 | } | ||
| 526 | info->popScope(); | ||
| 527 | break; | ||
| 528 | } | ||
| 529 | case NType::Stat: { | ||
| 530 | if (temp.back().back() == '\n') { | ||
| 531 | temp.emplace_back(info->ind() + "else"s); | ||
| 532 | } else { | ||
| 533 | temp.back() += " else"s; | ||
| 534 | } | ||
| 535 | info->pushScope(); | ||
| 536 | temp.emplace_back(node->to_string(ud)); | ||
| 537 | if (temp.back().empty()) { | ||
| 538 | temp.back() = info->ind() + "--"s; | ||
| 539 | } | ||
| 540 | info->popScope(); | ||
| 541 | break; | ||
| 475 | } | 542 | } |
| 476 | info->popScope(); | 543 | case NType::Block: { |
| 477 | } else { | 544 | temp.emplace_back(info->ind() + "else"s); |
| 478 | temp.emplace_back(info->ind() + "else"s); | 545 | info->pushScope(); |
| 479 | info->pushScope(); | 546 | temp.emplace_back(node->to_string(ud)); |
| 480 | temp.emplace_back(node->to_string(ud)); | 547 | if (temp.back().empty()) { |
| 481 | if (temp.back().empty()) { | 548 | temp.back() = info->ind() + "--"s; |
| 482 | temp.back() = info->ind() + "--"s; | 549 | } |
| 550 | info->popScope(); | ||
| 551 | break; | ||
| 483 | } | 552 | } |
| 484 | info->popScope(); | ||
| 485 | } | 553 | } |
| 486 | condition = false; | 554 | lastType = NType::Block; |
| 487 | break; | 555 | break; |
| 488 | } | 556 | } |
| 489 | } | 557 | } |
| @@ -511,10 +579,10 @@ std::string While_t::to_string(void* ud) const { | |||
| 511 | } | 579 | } |
| 512 | std::string Repeat_t::to_string(void* ud) const { | 580 | std::string Repeat_t::to_string(void* ud) const { |
| 513 | auto info = reinterpret_cast<YueFormat*>(ud); | 581 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 514 | str_list temp; | 582 | if (body.is<Statement_t>()) { |
| 515 | if (body->content.is<Statement_t>()) { | 583 | return "repeat "s + body->to_string(ud) + " until "s + condition->to_string(ud); |
| 516 | temp.emplace_back("repeat "s + body->to_string(ud)); | ||
| 517 | } else { | 584 | } else { |
| 585 | str_list temp; | ||
| 518 | temp.emplace_back("repeat"s); | 586 | temp.emplace_back("repeat"s); |
| 519 | info->pushScope(); | 587 | info->pushScope(); |
| 520 | temp.emplace_back(body->to_string(ud)); | 588 | temp.emplace_back(body->to_string(ud)); |
| @@ -522,14 +590,14 @@ std::string Repeat_t::to_string(void* ud) const { | |||
| 522 | temp.back() = info->ind() + "--"s; | 590 | temp.back() = info->ind() + "--"s; |
| 523 | } | 591 | } |
| 524 | info->popScope(); | 592 | info->popScope(); |
| 593 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 594 | return join(temp, "\n"sv); | ||
| 525 | } | 595 | } |
| 526 | temp.emplace_back(info->ind() + "until "s + condition->to_string(ud)); | ||
| 527 | return join(temp, "\n"sv); | ||
| 528 | } | 596 | } |
| 529 | std::string ForStepValue_t::to_string(void* ud) const { | 597 | std::string ForStepValue_t::to_string(void* ud) const { |
| 530 | return value->to_string(ud); | 598 | return value->to_string(ud); |
| 531 | } | 599 | } |
| 532 | std::string For_t::to_string(void* ud) const { | 600 | std::string ForNum_t::to_string(void* ud) const { |
| 533 | auto info = reinterpret_cast<YueFormat*>(ud); | 601 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 534 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); | 602 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); |
| 535 | if (stepValue) { | 603 | if (stepValue) { |
| @@ -568,6 +636,9 @@ std::string ForEach_t::to_string(void* ud) const { | |||
| 568 | return line + '\n' + block; | 636 | return line + '\n' + block; |
| 569 | } | 637 | } |
| 570 | } | 638 | } |
| 639 | std::string For_t::to_string(void* ud) const { | ||
| 640 | return forLoop->to_string(ud); | ||
| 641 | } | ||
| 571 | std::string Do_t::to_string(void* ud) const { | 642 | std::string Do_t::to_string(void* ud) const { |
| 572 | auto info = reinterpret_cast<YueFormat*>(ud); | 643 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 573 | if (body->content.is<Statement_t>()) { | 644 | if (body->content.is<Statement_t>()) { |
| @@ -596,10 +667,13 @@ std::string CatchBlock_t::to_string(void* ud) const { | |||
| 596 | std::string Try_t::to_string(void* ud) const { | 667 | std::string Try_t::to_string(void* ud) const { |
| 597 | auto info = reinterpret_cast<YueFormat*>(ud); | 668 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 598 | str_list temp; | 669 | str_list temp; |
| 670 | temp.emplace_back("try"s); | ||
| 671 | if (eop) { | ||
| 672 | temp.back() += eop->to_string(ud); | ||
| 673 | } | ||
| 599 | if (func.is<Exp_t>()) { | 674 | if (func.is<Exp_t>()) { |
| 600 | temp.emplace_back("try "s + func->to_string(ud)); | 675 | temp.back() += (" "s + func->to_string(ud)); |
| 601 | } else { | 676 | } else { |
| 602 | temp.emplace_back("try"s); | ||
| 603 | info->pushScope(); | 677 | info->pushScope(); |
| 604 | temp.emplace_back(func->to_string(ud)); | 678 | temp.emplace_back(func->to_string(ud)); |
| 605 | if (temp.back().empty()) { | 679 | if (temp.back().empty()) { |
| @@ -716,7 +790,7 @@ static bool isInBlockExp(ast_node* node, bool last = false) { | |||
| 716 | return false; | 790 | return false; |
| 717 | } | 791 | } |
| 718 | std::string Comprehension_t::to_string(void* ud) const { | 792 | std::string Comprehension_t::to_string(void* ud) const { |
| 719 | if (items.size() != 2 || !ast_is<CompInner_t>(items.back())) { | 793 | if (items.size() != 2 || !ast_is<CompFor_t>(items.back())) { |
| 720 | if (items.size() == 1) { | 794 | if (items.size() == 1) { |
| 721 | str_list temp; | 795 | str_list temp; |
| 722 | for (const auto& item : items.objects()) { | 796 | for (const auto& item : items.objects()) { |
| @@ -783,14 +857,14 @@ std::string StarExp_t::to_string(void* ud) const { | |||
| 783 | std::string CompForEach_t::to_string(void* ud) const { | 857 | std::string CompForEach_t::to_string(void* ud) const { |
| 784 | return "for "s + nameList->to_string(ud) + " in "s + loopValue->to_string(ud); | 858 | return "for "s + nameList->to_string(ud) + " in "s + loopValue->to_string(ud); |
| 785 | } | 859 | } |
| 786 | std::string CompFor_t::to_string(void* ud) const { | 860 | std::string CompForNum_t::to_string(void* ud) const { |
| 787 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); | 861 | auto line = "for "s + varName->to_string(ud) + " = "s + startValue->to_string(ud) + ", "s + stopValue->to_string(ud); |
| 788 | if (stepValue) { | 862 | if (stepValue) { |
| 789 | line += stepValue->to_string(ud); | 863 | line += stepValue->to_string(ud); |
| 790 | } | 864 | } |
| 791 | return line; | 865 | return line; |
| 792 | } | 866 | } |
| 793 | std::string CompInner_t::to_string(void* ud) const { | 867 | std::string CompFor_t::to_string(void* ud) const { |
| 794 | str_list temp; | 868 | str_list temp; |
| 795 | for (auto item : items.objects()) { | 869 | for (auto item : items.objects()) { |
| 796 | if (ast_is<Exp_t>(item)) { | 870 | if (ast_is<Exp_t>(item)) { |
| @@ -809,7 +883,7 @@ std::string Assign_t::to_string(void* ud) const { | |||
| 809 | for (auto value : values.objects()) { | 883 | for (auto value : values.objects()) { |
| 810 | temp.emplace_back(value->to_string(ud)); | 884 | temp.emplace_back(value->to_string(ud)); |
| 811 | } | 885 | } |
| 812 | return "= "s + join(temp, "; "sv); | 886 | return "= "s + join(temp, ", "sv); |
| 813 | } | 887 | } |
| 814 | std::string Update_t::to_string(void* ud) const { | 888 | std::string Update_t::to_string(void* ud) const { |
| 815 | return op->to_string(ud) + "= "s + value->to_string(ud); | 889 | return op->to_string(ud) + "= "s + value->to_string(ud); |
| @@ -851,6 +925,12 @@ std::string Exp_t::to_string(void* ud) const { | |||
| 851 | } | 925 | } |
| 852 | return join(temp, " "sv); | 926 | return join(temp, " "sv); |
| 853 | } | 927 | } |
| 928 | std::string ReversedIndex_t::to_string(void* ud) const { | ||
| 929 | if (modifier) { | ||
| 930 | return "[# - "s + modifier->to_string(ud) + ']'; | ||
| 931 | } | ||
| 932 | return "[#]"s; | ||
| 933 | } | ||
| 854 | std::string Callable_t::to_string(void* ud) const { | 934 | std::string Callable_t::to_string(void* ud) const { |
| 855 | return item->to_string(ud); | 935 | return item->to_string(ud); |
| 856 | } | 936 | } |
| @@ -937,6 +1017,51 @@ std::string DoubleString_t::to_string(void* ud) const { | |||
| 937 | } | 1017 | } |
| 938 | return '"' + join(temp) + '"'; | 1018 | return '"' + join(temp) + '"'; |
| 939 | } | 1019 | } |
| 1020 | std::string YAMLIndent_t::to_string(void* ud) const { | ||
| 1021 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1022 | return info->convert(this); | ||
| 1023 | } | ||
| 1024 | std::string YAMLLineInner_t::to_string(void* ud) const { | ||
| 1025 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1026 | return info->convert(this); | ||
| 1027 | } | ||
| 1028 | std::string YAMLLineContent_t::to_string(void* ud) const { | ||
| 1029 | if (content.is<Exp_t>()) { | ||
| 1030 | return "#{"s + content->to_string(ud) + '}'; | ||
| 1031 | } | ||
| 1032 | return content->to_string(ud); | ||
| 1033 | } | ||
| 1034 | std::string YAMLLine_t::to_string(void* ud) const { | ||
| 1035 | str_list temp; | ||
| 1036 | for (auto seg : segments.objects()) { | ||
| 1037 | temp.emplace_back(seg->to_string(ud)); | ||
| 1038 | } | ||
| 1039 | return join(temp); | ||
| 1040 | } | ||
| 1041 | std::string YAMLMultiline_t::to_string(void* ud) const { | ||
| 1042 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1043 | int currentIndent = info->indent; | ||
| 1044 | str_list temp; | ||
| 1045 | int lastIndent = -1; | ||
| 1046 | for (auto line_ : lines.objects()) { | ||
| 1047 | auto line = static_cast<YAMLLine_t*>(line_); | ||
| 1048 | auto indent = line->indent->to_string(ud); | ||
| 1049 | int ind = 0; | ||
| 1050 | for (auto c : indent) { | ||
| 1051 | if (c == ' ') ind++; | ||
| 1052 | if (c == '\t') ind += 4; | ||
| 1053 | } | ||
| 1054 | if (lastIndent < ind) { | ||
| 1055 | info->pushScope(); | ||
| 1056 | } else if (lastIndent > ind) { | ||
| 1057 | info->popScope(); | ||
| 1058 | } | ||
| 1059 | lastIndent = ind; | ||
| 1060 | temp.emplace_back(indent + line->to_string(ud)); | ||
| 1061 | } | ||
| 1062 | info->indent = currentIndent; | ||
| 1063 | return "|\n" + join(temp, "\n"sv) + '\n'; | ||
| 1064 | } | ||
| 940 | std::string String_t::to_string(void* ud) const { | 1065 | std::string String_t::to_string(void* ud) const { |
| 941 | return str->to_string(ud); | 1066 | return str->to_string(ud); |
| 942 | } | 1067 | } |
| @@ -1125,7 +1250,7 @@ std::string ClassDecl_t::to_string(void* ud) const { | |||
| 1125 | return line; | 1250 | return line; |
| 1126 | } | 1251 | } |
| 1127 | std::string GlobalValues_t::to_string(void* ud) const { | 1252 | std::string GlobalValues_t::to_string(void* ud) const { |
| 1128 | auto line = nameList->to_string(ud); | 1253 | std::string line = nameList->to_string(ud); |
| 1129 | if (valueList) { | 1254 | if (valueList) { |
| 1130 | if (valueList.is<TableBlock_t>()) { | 1255 | if (valueList.is<TableBlock_t>()) { |
| 1131 | line += " =\n"s + valueList->to_string(ud); | 1256 | line += " =\n"s + valueList->to_string(ud); |
| @@ -1136,7 +1261,7 @@ std::string GlobalValues_t::to_string(void* ud) const { | |||
| 1136 | return line; | 1261 | return line; |
| 1137 | } | 1262 | } |
| 1138 | std::string Global_t::to_string(void* ud) const { | 1263 | std::string Global_t::to_string(void* ud) const { |
| 1139 | return "global "s + item->to_string(ud); | 1264 | return "global "s + (constAttrib ? "const "s : ""s) + item->to_string(ud); |
| 1140 | } | 1265 | } |
| 1141 | std::string Export_t::to_string(void* ud) const { | 1266 | std::string Export_t::to_string(void* ud) const { |
| 1142 | auto line = "export"s; | 1267 | auto line = "export"s; |
| @@ -1235,6 +1360,9 @@ std::string FnArgDef_t::to_string(void* ud) const { | |||
| 1235 | if (op) { | 1360 | if (op) { |
| 1236 | line += op->to_string(ud); | 1361 | line += op->to_string(ud); |
| 1237 | } | 1362 | } |
| 1363 | if (label) { | ||
| 1364 | line += '`' + label->to_string(ud); | ||
| 1365 | } | ||
| 1238 | if (defaultValue) { | 1366 | if (defaultValue) { |
| 1239 | line += " = "s + defaultValue->to_string(ud); | 1367 | line += " = "s + defaultValue->to_string(ud); |
| 1240 | } | 1368 | } |
| @@ -1257,6 +1385,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
| 1257 | } | 1385 | } |
| 1258 | if (varArg) { | 1386 | if (varArg) { |
| 1259 | temp.emplace_back(info->ind() + varArg->to_string(ud)); | 1387 | temp.emplace_back(info->ind() + varArg->to_string(ud)); |
| 1388 | if (label) { | ||
| 1389 | temp.back().append('`' + label->to_string(ud)); | ||
| 1390 | } | ||
| 1260 | } | 1391 | } |
| 1261 | return join(temp, "\n"sv); | 1392 | return join(temp, "\n"sv); |
| 1262 | } else { | 1393 | } else { |
| @@ -1265,6 +1396,9 @@ std::string FnArgDefList_t::to_string(void* ud) const { | |||
| 1265 | } | 1396 | } |
| 1266 | if (varArg) { | 1397 | if (varArg) { |
| 1267 | temp.emplace_back(varArg->to_string(ud)); | 1398 | temp.emplace_back(varArg->to_string(ud)); |
| 1399 | if (label) { | ||
| 1400 | temp.back().append('`' + label->to_string(ud)); | ||
| 1401 | } | ||
| 1268 | } | 1402 | } |
| 1269 | return join(temp, ", "sv); | 1403 | return join(temp, ", "sv); |
| 1270 | } | 1404 | } |
| @@ -1475,37 +1609,17 @@ std::string StatementAppendix_t::to_string(void* ud) const { | |||
| 1475 | return item->to_string(ud); | 1609 | return item->to_string(ud); |
| 1476 | } | 1610 | } |
| 1477 | std::string Statement_t::to_string(void* ud) const { | 1611 | std::string Statement_t::to_string(void* ud) const { |
| 1478 | std::string line; | 1612 | if (appendix) { |
| 1479 | if (!comments.empty()) { | 1613 | return content->to_string(ud) + ' ' + appendix->to_string(ud); |
| 1480 | auto info = reinterpret_cast<YueFormat*>(ud); | ||
| 1481 | str_list temp; | ||
| 1482 | for (ast_node* comment : comments.objects()) { | ||
| 1483 | if (comment == comments.front()) { | ||
| 1484 | temp.push_back(comment->to_string(ud)); | ||
| 1485 | } else { | ||
| 1486 | temp.push_back(info->ind() + comment->to_string(ud)); | ||
| 1487 | } | ||
| 1488 | } | ||
| 1489 | if (appendix) { | ||
| 1490 | temp.push_back(info->ind() + content->to_string(ud) + ' ' + appendix->to_string(ud)); | ||
| 1491 | return join(temp, "\n"sv); | ||
| 1492 | } else { | ||
| 1493 | temp.push_back(info->ind() + content->to_string(ud)); | ||
| 1494 | return join(temp, "\n"sv); | ||
| 1495 | } | ||
| 1496 | } else { | 1614 | } else { |
| 1497 | if (appendix) { | 1615 | return content->to_string(ud); |
| 1498 | return content->to_string(ud) + ' ' + appendix->to_string(ud); | ||
| 1499 | } else { | ||
| 1500 | return content->to_string(ud); | ||
| 1501 | } | ||
| 1502 | } | 1616 | } |
| 1503 | } | 1617 | } |
| 1504 | std::string StatementSep_t::to_string(void*) const { | 1618 | std::string StatementSep_t::to_string(void*) const { |
| 1505 | return {}; | 1619 | return {}; |
| 1506 | } | 1620 | } |
| 1507 | std::string YueMultilineComment_t::to_string(void* ud) const { | 1621 | std::string EmptyLine_t::to_string(void*) const { |
| 1508 | return "--[["s + inner->to_string(ud) + "]]"s; | 1622 | return {}; |
| 1509 | } | 1623 | } |
| 1510 | std::string ChainAssign_t::to_string(void* ud) const { | 1624 | std::string ChainAssign_t::to_string(void* ud) const { |
| 1511 | str_list temp; | 1625 | str_list temp; |
| @@ -1520,14 +1634,22 @@ std::string Body_t::to_string(void* ud) const { | |||
| 1520 | std::string Block_t::to_string(void* ud) const { | 1634 | std::string Block_t::to_string(void* ud) const { |
| 1521 | auto info = reinterpret_cast<YueFormat*>(ud); | 1635 | auto info = reinterpret_cast<YueFormat*>(ud); |
| 1522 | str_list temp; | 1636 | str_list temp; |
| 1523 | for (auto stmt_ : statements.objects()) { | 1637 | for (auto stmt_ : statementOrComments.objects()) { |
| 1524 | auto stmt = static_cast<Statement_t*>(stmt_); | 1638 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { |
| 1525 | if (stmt->content.is<PipeBody_t>()) { | 1639 | if (stmt->content.is<PipeBody_t>()) { |
| 1526 | info->pushScope(); | 1640 | info->pushScope(); |
| 1527 | temp.emplace_back(stmt->to_string(ud)); | 1641 | temp.emplace_back(stmt->to_string(ud)); |
| 1528 | info->popScope(); | 1642 | info->popScope(); |
| 1529 | } else { | 1643 | } else { |
| 1530 | temp.emplace_back(info->ind() + stmt->to_string(ud)); | 1644 | temp.emplace_back(info->ind() + stmt->to_string(ud)); |
| 1645 | } | ||
| 1646 | } else if (info->reserveComment) { | ||
| 1647 | if (auto comment = ast_cast<YueComment_t>(stmt_)) { | ||
| 1648 | temp.emplace_back(info->ind() + comment->to_string(ud)); | ||
| 1649 | } else { | ||
| 1650 | auto empty = ast_to<EmptyLine_t>(stmt_); | ||
| 1651 | temp.emplace_back(empty->to_string(ud)); | ||
| 1652 | } | ||
| 1531 | } | 1653 | } |
| 1532 | } | 1654 | } |
| 1533 | return join(temp, "\n"sv); | 1655 | return join(temp, "\n"sv); |
| @@ -1546,3 +1668,4 @@ std::string File_t::to_string(void* ud) const { | |||
| 1546 | } // namespace yue | 1668 | } // namespace yue |
| 1547 | 1669 | ||
| 1548 | } // namespace parserlib | 1670 | } // namespace parserlib |
| 1671 | |||
diff --git a/src/yuescript/yue_ast.h b/src/yuescript/yue_ast.h index 5e70645..5043526 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 | ||
| @@ -50,7 +50,7 @@ std::string_view ast_name() { return {}; } | |||
| 50 | // clang-format off | 50 | // clang-format off |
| 51 | 51 | ||
| 52 | namespace yue { | 52 | namespace yue { |
| 53 | class ExpListLow_t; | 53 | class ExpList_t; |
| 54 | class TableBlock_t; | 54 | class TableBlock_t; |
| 55 | class SimpleTable_t; | 55 | class SimpleTable_t; |
| 56 | class TableLit_t; | 56 | class TableLit_t; |
| @@ -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 | ||
| @@ -156,7 +156,7 @@ AST_END(NameList) | |||
| 156 | 156 | ||
| 157 | AST_NODE(LocalValues) | 157 | AST_NODE(LocalValues) |
| 158 | ast_ptr<true, NameList_t> nameList; | 158 | ast_ptr<true, NameList_t> nameList; |
| 159 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; | 159 | ast_sel<false, TableBlock_t, ExpList_t> valueList; |
| 160 | AST_MEMBER(LocalValues, &nameList, &valueList) | 160 | AST_MEMBER(LocalValues, &nameList, &valueList) |
| 161 | AST_END(LocalValues) | 161 | AST_END(LocalValues) |
| 162 | 162 | ||
| @@ -233,18 +233,28 @@ 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_LEAF(ImportAllGlobal) | ||
| 237 | AST_END(ImportAllGlobal) | ||
| 238 | |||
| 239 | AST_NODE(ImportGlobal) | ||
| 240 | ast_ptr<true, Seperator_t> sep; | ||
| 241 | ast_list<true, UnicodeName_t> segs; | ||
| 242 | ast_ptr<false, Variable_t> target; | ||
| 243 | AST_MEMBER(ImportGlobal, &sep, &segs, &target) | ||
| 244 | AST_END(ImportGlobal) | ||
| 245 | |||
| 236 | AST_NODE(Import) | 246 | AST_NODE(Import) |
| 237 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t> content; | 247 | ast_sel<true, ImportAs_t, ImportFrom_t, FromImport_t, ImportGlobal_t, ImportAllGlobal_t> content; |
| 238 | AST_MEMBER(Import, &content) | 248 | AST_MEMBER(Import, &content) |
| 239 | AST_END(Import) | 249 | AST_END(Import) |
| 240 | 250 | ||
| 241 | AST_NODE(Label) | 251 | AST_NODE(Label) |
| 242 | ast_ptr<true, LabelName_t> label; | 252 | ast_ptr<true, UnicodeName_t> label; |
| 243 | AST_MEMBER(Label, &label) | 253 | AST_MEMBER(Label, &label) |
| 244 | AST_END(Label) | 254 | AST_END(Label) |
| 245 | 255 | ||
| 246 | AST_NODE(Goto) | 256 | AST_NODE(Goto) |
| 247 | ast_ptr<true, LabelName_t> label; | 257 | ast_ptr<true, UnicodeName_t> label; |
| 248 | AST_MEMBER(Goto, &label) | 258 | AST_MEMBER(Goto, &label) |
| 249 | AST_END(Goto) | 259 | AST_END(Goto) |
| 250 | 260 | ||
| @@ -263,31 +273,27 @@ AST_NODE(Backcall) | |||
| 263 | AST_MEMBER(Backcall, &argsDef, &arrow, &value) | 273 | AST_MEMBER(Backcall, &argsDef, &arrow, &value) |
| 264 | AST_END(Backcall) | 274 | AST_END(Backcall) |
| 265 | 275 | ||
| 266 | AST_NODE(ExpListLow) | ||
| 267 | ast_ptr<true, Seperator_t> sep; | ||
| 268 | ast_list<true, Exp_t> exprs; | ||
| 269 | AST_MEMBER(ExpListLow, &sep, &exprs) | ||
| 270 | AST_END(ExpListLow) | ||
| 271 | |||
| 272 | AST_NODE(ExpList) | 276 | AST_NODE(ExpList) |
| 273 | ast_ptr<true, Seperator_t> sep; | 277 | ast_ptr<true, Seperator_t> sep; |
| 274 | ast_list<true, Exp_t> exprs; | 278 | ast_list<true, Exp_t> exprs; |
| 275 | AST_MEMBER(ExpList, &sep, &exprs) | 279 | AST_MEMBER(ExpList, &sep, &exprs) |
| 280 | bool followStmtProcessed = false; | ||
| 281 | Statement_t* followStmt = nullptr; | ||
| 276 | AST_END(ExpList) | 282 | AST_END(ExpList) |
| 277 | 283 | ||
| 278 | AST_NODE(Return) | 284 | AST_NODE(Return) |
| 279 | bool allowBlockMacroReturn = false; | 285 | bool allowBlockMacroReturn = false; |
| 280 | bool explicitReturn = true; | 286 | bool explicitReturn = true; |
| 281 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; | 287 | ast_sel<false, TableBlock_t, ExpList_t> valueList; |
| 282 | AST_MEMBER(Return, &valueList) | 288 | AST_MEMBER(Return, &valueList) |
| 283 | AST_END(Return) | 289 | AST_END(Return) |
| 284 | 290 | ||
| 285 | AST_NODE(With) | 291 | AST_NODE(With) |
| 286 | ast_ptr<false, ExistentialOp_t> eop; | 292 | ast_ptr<false, ExistentialOp_t> eop; |
| 287 | ast_ptr<true, ExpList_t> valueList; | 293 | ast_ptr<true, ExpList_t> valueList; |
| 288 | ast_ptr<false, Assign_t> assigns; | 294 | ast_ptr<false, Assign_t> assign; |
| 289 | ast_sel<true, Block_t, Statement_t> body; | 295 | ast_sel<true, Block_t, Statement_t> body; |
| 290 | AST_MEMBER(With, &eop, &valueList, &assigns, &body) | 296 | AST_MEMBER(With, &eop, &valueList, &assign, &body) |
| 291 | AST_END(With) | 297 | AST_END(With) |
| 292 | 298 | ||
| 293 | AST_NODE(SwitchList) | 299 | AST_NODE(SwitchList) |
| @@ -302,20 +308,21 @@ AST_NODE(SwitchCase) | |||
| 302 | AST_MEMBER(SwitchCase, &condition, &body) | 308 | AST_MEMBER(SwitchCase, &condition, &body) |
| 303 | AST_END(SwitchCase) | 309 | AST_END(SwitchCase) |
| 304 | 310 | ||
| 311 | AST_NODE(Assignment) | ||
| 312 | ast_ptr<false, ExpList_t> expList; | ||
| 313 | ast_ptr<true, Assign_t> assign; | ||
| 314 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 315 | AST_END(Assignment) | ||
| 316 | |||
| 305 | AST_NODE(Switch) | 317 | AST_NODE(Switch) |
| 306 | ast_ptr<true, Exp_t> target; | 318 | ast_ptr<true, Exp_t> target; |
| 319 | ast_ptr<false, Assignment_t> assignment; | ||
| 307 | ast_ptr<true, Seperator_t> sep; | 320 | ast_ptr<true, Seperator_t> sep; |
| 308 | ast_list<true, SwitchCase_t> branches; | 321 | ast_list<true, SwitchCase_t> branches; |
| 309 | ast_sel<false, Block_t, Statement_t> lastBranch; | 322 | ast_sel<false, Block_t, Statement_t> lastBranch; |
| 310 | AST_MEMBER(Switch, &target, &sep, &branches, &lastBranch) | 323 | AST_MEMBER(Switch, &target, &assignment, &sep, &branches, &lastBranch) |
| 311 | AST_END(Switch) | 324 | AST_END(Switch) |
| 312 | 325 | ||
| 313 | AST_NODE(Assignment) | ||
| 314 | ast_ptr<false, ExpList_t> expList; | ||
| 315 | ast_ptr<true, Assign_t> assign; | ||
| 316 | AST_MEMBER(Assignment, &expList, &assign) | ||
| 317 | AST_END(Assignment) | ||
| 318 | |||
| 319 | AST_NODE(IfCond) | 326 | AST_NODE(IfCond) |
| 320 | ast_ptr<true, Exp_t> condition; | 327 | ast_ptr<true, Exp_t> condition; |
| 321 | ast_ptr<false, Assignment_t> assignment; | 328 | ast_ptr<false, Assignment_t> assignment; |
| @@ -343,7 +350,7 @@ AST_NODE(While) | |||
| 343 | AST_END(While) | 350 | AST_END(While) |
| 344 | 351 | ||
| 345 | AST_NODE(Repeat) | 352 | AST_NODE(Repeat) |
| 346 | ast_ptr<true, Body_t> body; | 353 | ast_sel<true, Block_t, Statement_t> body; |
| 347 | ast_ptr<true, Exp_t> condition; | 354 | ast_ptr<true, Exp_t> condition; |
| 348 | AST_MEMBER(Repeat, &body, &condition) | 355 | AST_MEMBER(Repeat, &body, &condition) |
| 349 | AST_END(Repeat) | 356 | AST_END(Repeat) |
| @@ -353,14 +360,14 @@ AST_NODE(ForStepValue) | |||
| 353 | AST_MEMBER(ForStepValue, &value) | 360 | AST_MEMBER(ForStepValue, &value) |
| 354 | AST_END(ForStepValue) | 361 | AST_END(ForStepValue) |
| 355 | 362 | ||
| 356 | AST_NODE(For) | 363 | AST_NODE(ForNum) |
| 357 | ast_ptr<true, Variable_t> varName; | 364 | ast_ptr<true, Variable_t> varName; |
| 358 | ast_ptr<true, Exp_t> startValue; | 365 | ast_ptr<true, Exp_t> startValue; |
| 359 | ast_ptr<true, Exp_t> stopValue; | 366 | ast_ptr<true, Exp_t> stopValue; |
| 360 | ast_ptr<false, ForStepValue_t> stepValue; | 367 | ast_ptr<false, ForStepValue_t> stepValue; |
| 361 | ast_sel<true, Block_t, Statement_t> body; | 368 | ast_sel<true, Block_t, Statement_t> body; |
| 362 | AST_MEMBER(For, &varName, &startValue, &stopValue, &stepValue, &body) | 369 | AST_MEMBER(ForNum, &varName, &startValue, &stopValue, &stepValue, &body) |
| 363 | AST_END(For) | 370 | AST_END(ForNum) |
| 364 | 371 | ||
| 365 | AST_NODE(ForEach) | 372 | AST_NODE(ForEach) |
| 366 | ast_ptr<true, AssignableNameList_t> nameList; | 373 | ast_ptr<true, AssignableNameList_t> nameList; |
| @@ -369,6 +376,11 @@ AST_NODE(ForEach) | |||
| 369 | AST_MEMBER(ForEach, &nameList, &loopValue, &body) | 376 | AST_MEMBER(ForEach, &nameList, &loopValue, &body) |
| 370 | AST_END(ForEach) | 377 | AST_END(ForEach) |
| 371 | 378 | ||
| 379 | AST_NODE(For) | ||
| 380 | ast_sel<true, ForEach_t, ForNum_t> forLoop; | ||
| 381 | AST_MEMBER(For, &forLoop) | ||
| 382 | AST_END(For) | ||
| 383 | |||
| 372 | AST_NODE(Do) | 384 | AST_NODE(Do) |
| 373 | ast_ptr<true, Body_t> body; | 385 | ast_ptr<true, Body_t> body; |
| 374 | AST_MEMBER(Do, &body) | 386 | AST_MEMBER(Do, &body) |
| @@ -381,14 +393,15 @@ AST_NODE(CatchBlock) | |||
| 381 | AST_END(CatchBlock) | 393 | AST_END(CatchBlock) |
| 382 | 394 | ||
| 383 | AST_NODE(Try) | 395 | AST_NODE(Try) |
| 396 | ast_ptr<false, ExistentialOp_t> eop; | ||
| 384 | ast_sel<true, Block_t, Exp_t> func; | 397 | ast_sel<true, Block_t, Exp_t> func; |
| 385 | ast_ptr<false, CatchBlock_t> catchBlock; | 398 | ast_ptr<false, CatchBlock_t> catchBlock; |
| 386 | AST_MEMBER(Try, &func, &catchBlock) | 399 | AST_MEMBER(Try, &eop, &func, &catchBlock) |
| 387 | AST_END(Try) | 400 | AST_END(Try) |
| 388 | 401 | ||
| 389 | AST_NODE(Comprehension) | 402 | AST_NODE(Comprehension) |
| 390 | ast_ptr<true, Seperator_t> sep; | 403 | ast_ptr<true, Seperator_t> sep; |
| 391 | ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompInner_t, | 404 | ast_sel_list<false, NormalDef_t, SpreadListExp_t, CompFor_t, |
| 392 | /*non-syntax-rule*/ Statement_t> items; | 405 | /*non-syntax-rule*/ Statement_t> items; |
| 393 | AST_MEMBER(Comprehension, &sep, &items) | 406 | AST_MEMBER(Comprehension, &sep, &items) |
| 394 | AST_END(Comprehension) | 407 | AST_END(Comprehension) |
| @@ -401,7 +414,7 @@ AST_END(CompValue) | |||
| 401 | AST_NODE(TblComprehension) | 414 | AST_NODE(TblComprehension) |
| 402 | ast_ptr<true, Exp_t> key; | 415 | ast_ptr<true, Exp_t> key; |
| 403 | ast_ptr<false, CompValue_t> value; | 416 | ast_ptr<false, CompValue_t> value; |
| 404 | ast_ptr<true, CompInner_t> forLoop; | 417 | ast_ptr<true, CompFor_t> forLoop; |
| 405 | AST_MEMBER(TblComprehension, &key, &value, &forLoop) | 418 | AST_MEMBER(TblComprehension, &key, &value, &forLoop) |
| 406 | AST_END(TblComprehension) | 419 | AST_END(TblComprehension) |
| 407 | 420 | ||
| @@ -416,23 +429,23 @@ AST_NODE(CompForEach) | |||
| 416 | AST_MEMBER(CompForEach, &nameList, &loopValue) | 429 | AST_MEMBER(CompForEach, &nameList, &loopValue) |
| 417 | AST_END(CompForEach) | 430 | AST_END(CompForEach) |
| 418 | 431 | ||
| 419 | AST_NODE(CompFor) | 432 | AST_NODE(CompForNum) |
| 420 | ast_ptr<true, Variable_t> varName; | 433 | ast_ptr<true, Variable_t> varName; |
| 421 | ast_ptr<true, Exp_t> startValue; | 434 | ast_ptr<true, Exp_t> startValue; |
| 422 | ast_ptr<true, Exp_t> stopValue; | 435 | ast_ptr<true, Exp_t> stopValue; |
| 423 | ast_ptr<false, ForStepValue_t> stepValue; | 436 | ast_ptr<false, ForStepValue_t> stepValue; |
| 424 | AST_MEMBER(CompFor, &varName, &startValue, &stopValue, &stepValue) | 437 | AST_MEMBER(CompForNum, &varName, &startValue, &stopValue, &stepValue) |
| 425 | AST_END(CompFor) | 438 | AST_END(CompForNum) |
| 426 | 439 | ||
| 427 | AST_NODE(CompInner) | 440 | AST_NODE(CompFor) |
| 428 | ast_ptr<true, Seperator_t> sep; | 441 | ast_ptr<true, Seperator_t> sep; |
| 429 | ast_sel_list<true, CompFor_t, CompForEach_t, Exp_t> items; | 442 | ast_sel_list<true, CompForNum_t, CompForEach_t, Exp_t> items; |
| 430 | AST_MEMBER(CompInner, &sep, &items) | 443 | AST_MEMBER(CompFor, &sep, &items) |
| 431 | AST_END(CompInner) | 444 | AST_END(CompFor) |
| 432 | 445 | ||
| 433 | AST_NODE(Assign) | 446 | AST_NODE(Assign) |
| 434 | ast_ptr<true, Seperator_t> sep; | 447 | ast_ptr<true, Seperator_t> sep; |
| 435 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t> values; | 448 | ast_sel_list<true, With_t, If_t, Switch_t, TableBlock_t, Exp_t, SpreadListExp_t> values; |
| 436 | AST_MEMBER(Assign, &sep, &values) | 449 | AST_MEMBER(Assign, &sep, &values) |
| 437 | AST_END(Assign) | 450 | AST_END(Assign) |
| 438 | 451 | ||
| @@ -547,8 +560,8 @@ AST_NODE(SimpleValue) | |||
| 547 | ast_sel<true, | 560 | ast_sel<true, |
| 548 | TableLit_t, ConstValue_t, | 561 | TableLit_t, ConstValue_t, |
| 549 | If_t, Switch_t, With_t, ClassDecl_t, | 562 | If_t, Switch_t, With_t, ClassDecl_t, |
| 550 | ForEach_t, For_t, While_t, Do_t, Try_t, | 563 | For_t, While_t, Repeat_t, |
| 551 | UnaryValue_t, | 564 | Do_t, Try_t, UnaryValue_t, |
| 552 | TblComprehension_t, Comprehension_t, | 565 | TblComprehension_t, Comprehension_t, |
| 553 | FunLit_t, Num_t, VarArg_t> value; | 566 | FunLit_t, Num_t, VarArg_t> value; |
| 554 | AST_MEMBER(SimpleValue, &value) | 567 | AST_MEMBER(SimpleValue, &value) |
| @@ -587,8 +600,31 @@ AST_NODE(DoubleString) | |||
| 587 | AST_MEMBER(DoubleString, &sep, &segments) | 600 | AST_MEMBER(DoubleString, &sep, &segments) |
| 588 | AST_END(DoubleString) | 601 | AST_END(DoubleString) |
| 589 | 602 | ||
| 603 | AST_LEAF(YAMLIndent) | ||
| 604 | AST_END(YAMLIndent) | ||
| 605 | |||
| 606 | AST_LEAF(YAMLLineInner) | ||
| 607 | AST_END(YAMLLineInner) | ||
| 608 | |||
| 609 | AST_NODE(YAMLLineContent) | ||
| 610 | ast_sel<true, YAMLLineInner_t, Exp_t> content; | ||
| 611 | AST_MEMBER(YAMLLineContent, &content) | ||
| 612 | AST_END(YAMLLineContent) | ||
| 613 | |||
| 614 | AST_NODE(YAMLLine) | ||
| 615 | ast_ptr<true, YAMLIndent_t> indent; | ||
| 616 | ast_list<true, YAMLLineContent_t> segments; | ||
| 617 | AST_MEMBER(YAMLLine, &indent, &segments) | ||
| 618 | AST_END(YAMLLine) | ||
| 619 | |||
| 620 | AST_NODE(YAMLMultiline) | ||
| 621 | ast_ptr<true, Seperator_t> sep; | ||
| 622 | ast_list<true, YAMLLine_t> lines; | ||
| 623 | AST_MEMBER(YAMLMultiline, &sep, &lines) | ||
| 624 | AST_END(YAMLMultiline) | ||
| 625 | |||
| 590 | AST_NODE(String) | 626 | AST_NODE(String) |
| 591 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t> str; | 627 | ast_sel<true, DoubleString_t, SingleString_t, LuaString_t, YAMLMultiline_t> str; |
| 592 | AST_MEMBER(String, &str) | 628 | AST_MEMBER(String, &str) |
| 593 | AST_END(String) | 629 | AST_END(String) |
| 594 | 630 | ||
| @@ -639,9 +675,14 @@ AST_END(TableAppendingOp) | |||
| 639 | AST_LEAF(PlainItem) | 675 | AST_LEAF(PlainItem) |
| 640 | AST_END(PlainItem) | 676 | AST_END(PlainItem) |
| 641 | 677 | ||
| 678 | AST_NODE(ReversedIndex) | ||
| 679 | ast_ptr<false, Exp_t> modifier; | ||
| 680 | AST_MEMBER(ReversedIndex, &modifier) | ||
| 681 | AST_END(ReversedIndex) | ||
| 682 | |||
| 642 | AST_NODE(ChainValue) | 683 | AST_NODE(ChainValue) |
| 643 | ast_ptr<true, Seperator_t> sep; | 684 | ast_ptr<true, Seperator_t> sep; |
| 644 | ast_sel_list<true, Callable_t, Invoke_t, DotChainItem_t, ColonChainItem_t, Slice_t, Exp_t, String_t, InvokeArgs_t, ExistentialOp_t, TableAppendingOp_t, | 685 | 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, |
| 645 | /*non-syntax-rule*/ PlainItem_t> items; | 686 | /*non-syntax-rule*/ PlainItem_t> items; |
| 646 | AST_MEMBER(ChainValue, &sep, &items) | 687 | AST_MEMBER(ChainValue, &sep, &items) |
| 647 | AST_END(ChainValue) | 688 | AST_END(ChainValue) |
| @@ -717,7 +758,7 @@ AST_END(ClassDecl) | |||
| 717 | 758 | ||
| 718 | AST_NODE(GlobalValues) | 759 | AST_NODE(GlobalValues) |
| 719 | ast_ptr<true, NameList_t> nameList; | 760 | ast_ptr<true, NameList_t> nameList; |
| 720 | ast_sel<false, TableBlock_t, ExpListLow_t> valueList; | 761 | ast_sel<false, TableBlock_t, ExpList_t> valueList; |
| 721 | AST_MEMBER(GlobalValues, &nameList, &valueList) | 762 | AST_MEMBER(GlobalValues, &nameList, &valueList) |
| 722 | AST_END(GlobalValues) | 763 | AST_END(GlobalValues) |
| 723 | 764 | ||
| @@ -725,8 +766,9 @@ AST_LEAF(GlobalOp) | |||
| 725 | AST_END(GlobalOp) | 766 | AST_END(GlobalOp) |
| 726 | 767 | ||
| 727 | AST_NODE(Global) | 768 | AST_NODE(Global) |
| 769 | ast_ptr<false, ConstAttrib_t> constAttrib; | ||
| 728 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; | 770 | ast_sel<true, ClassDecl_t, GlobalOp_t, GlobalValues_t> item; |
| 729 | AST_MEMBER(Global, &item) | 771 | AST_MEMBER(Global, &constAttrib, &item) |
| 730 | AST_END(Global) | 772 | AST_END(Global) |
| 731 | 773 | ||
| 732 | AST_LEAF(ExportDefault) | 774 | AST_LEAF(ExportDefault) |
| @@ -740,17 +782,19 @@ AST_NODE(Export) | |||
| 740 | AST_END(Export) | 782 | AST_END(Export) |
| 741 | 783 | ||
| 742 | AST_NODE(FnArgDef) | 784 | AST_NODE(FnArgDef) |
| 743 | ast_sel<true, Variable_t, SelfItem_t> name; | 785 | ast_sel<true, Variable_t, SelfItem_t, SimpleTable_t, TableLit_t> name; |
| 744 | ast_ptr<false, ExistentialOp_t> op; | 786 | ast_ptr<false, ExistentialOp_t> op; |
| 787 | ast_ptr<false, Name_t> label; | ||
| 745 | ast_ptr<false, Exp_t> defaultValue; | 788 | ast_ptr<false, Exp_t> defaultValue; |
| 746 | AST_MEMBER(FnArgDef, &name, &op, &defaultValue) | 789 | AST_MEMBER(FnArgDef, &name, &op, &label, &defaultValue) |
| 747 | AST_END(FnArgDef) | 790 | AST_END(FnArgDef) |
| 748 | 791 | ||
| 749 | AST_NODE(FnArgDefList) | 792 | AST_NODE(FnArgDefList) |
| 750 | ast_ptr<true, Seperator_t> sep; | 793 | ast_ptr<true, Seperator_t> sep; |
| 751 | ast_list<false, FnArgDef_t> definitions; | 794 | ast_list<false, FnArgDef_t> definitions; |
| 752 | ast_ptr<false, VarArg_t> varArg; | 795 | ast_ptr<false, VarArgDef_t> varArg; |
| 753 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg) | 796 | ast_ptr<false, Name_t> label; |
| 797 | AST_MEMBER(FnArgDefList, &sep, &definitions, &varArg, &label) | ||
| 754 | AST_END(FnArgDefList) | 798 | AST_END(FnArgDefList) |
| 755 | 799 | ||
| 756 | AST_NODE(OuterVarShadow) | 800 | AST_NODE(OuterVarShadow) |
| @@ -769,7 +813,7 @@ AST_END(FnArrow) | |||
| 769 | 813 | ||
| 770 | AST_NODE(FunLit) | 814 | AST_NODE(FunLit) |
| 771 | ast_ptr<false, FnArgsDef_t> argsDef; | 815 | ast_ptr<false, FnArgsDef_t> argsDef; |
| 772 | ast_sel<false, ExpListLow_t, DefaultValue_t> defaultReturn; | 816 | ast_sel<false, ExpList_t, DefaultValue_t> defaultReturn; |
| 773 | ast_ptr<true, FnArrow_t> arrow; | 817 | ast_ptr<true, FnArrow_t> arrow; |
| 774 | ast_ptr<false, Body_t> body; | 818 | ast_ptr<false, Body_t> body; |
| 775 | bool noRecursion = false; | 819 | bool noRecursion = false; |
| @@ -806,7 +850,7 @@ AST_NODE(Macro) | |||
| 806 | AST_END(Macro) | 850 | AST_END(Macro) |
| 807 | 851 | ||
| 808 | AST_NODE(NameOrDestructure) | 852 | AST_NODE(NameOrDestructure) |
| 809 | ast_sel<true, Variable_t, TableLit_t, Comprehension_t> item; | 853 | ast_sel<true, Variable_t, SimpleTable_t, TableLit_t, Comprehension_t> item; |
| 810 | AST_MEMBER(NameOrDestructure, &item) | 854 | AST_MEMBER(NameOrDestructure, &item) |
| 811 | AST_END(NameOrDestructure) | 855 | AST_END(NameOrDestructure) |
| 812 | 856 | ||
| @@ -838,9 +882,15 @@ AST_NODE(UnaryExp) | |||
| 838 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) | 882 | AST_MEMBER(UnaryExp, &ops, &expos, &inExp) |
| 839 | AST_END(UnaryExp) | 883 | AST_END(UnaryExp) |
| 840 | 884 | ||
| 885 | AST_NODE(SubBackcall) | ||
| 886 | ast_ptr<true, FnArrowBack_t> arrow; | ||
| 887 | ast_ptr<true, ChainValue_t> value; | ||
| 888 | AST_MEMBER(SubBackcall, &arrow, &value) | ||
| 889 | AST_END(SubBackcall) | ||
| 890 | |||
| 841 | AST_NODE(ExpListAssign) | 891 | AST_NODE(ExpListAssign) |
| 842 | ast_ptr<true, ExpList_t> expList; | 892 | ast_ptr<true, ExpList_t> expList; |
| 843 | ast_sel<false, Update_t, Assign_t> action; | 893 | ast_sel<false, Update_t, Assign_t, SubBackcall_t> action; |
| 844 | AST_MEMBER(ExpListAssign, &expList, &action) | 894 | AST_MEMBER(ExpListAssign, &expList, &action) |
| 845 | AST_END(ExpListAssign) | 895 | AST_END(ExpListAssign) |
| 846 | 896 | ||
| @@ -856,7 +906,17 @@ AST_NODE(WhileLine) | |||
| 856 | AST_MEMBER(WhileLine, &type, &condition) | 906 | AST_MEMBER(WhileLine, &type, &condition) |
| 857 | AST_END(WhileLine) | 907 | AST_END(WhileLine) |
| 858 | 908 | ||
| 859 | AST_LEAF(BreakLoop) | 909 | AST_LEAF(Break) |
| 910 | AST_END(Break) | ||
| 911 | |||
| 912 | AST_LEAF(Continue) | ||
| 913 | AST_END(Continue) | ||
| 914 | |||
| 915 | AST_NODE(BreakLoop) | ||
| 916 | ast_sel<true, Break_t, Continue_t> type; | ||
| 917 | ast_ptr<false, Exp_t> value; | ||
| 918 | AST_MEMBER(BreakLoop, &type, &value) | ||
| 919 | std::string varBWV; | ||
| 860 | AST_END(BreakLoop) | 920 | AST_END(BreakLoop) |
| 861 | 921 | ||
| 862 | AST_NODE(PipeBody) | 922 | AST_NODE(PipeBody) |
| @@ -866,7 +926,7 @@ AST_NODE(PipeBody) | |||
| 866 | AST_END(PipeBody) | 926 | AST_END(PipeBody) |
| 867 | 927 | ||
| 868 | AST_NODE(StatementAppendix) | 928 | AST_NODE(StatementAppendix) |
| 869 | ast_sel<true, IfLine_t, WhileLine_t, CompInner_t> item; | 929 | ast_sel<true, IfLine_t, WhileLine_t, CompFor_t> item; |
| 870 | AST_MEMBER(StatementAppendix, &item) | 930 | AST_MEMBER(StatementAppendix, &item) |
| 871 | AST_END(StatementAppendix) | 931 | AST_END(StatementAppendix) |
| 872 | 932 | ||
| @@ -876,14 +936,17 @@ AST_END(StatementSep) | |||
| 876 | AST_LEAF(YueLineComment) | 936 | AST_LEAF(YueLineComment) |
| 877 | AST_END(YueLineComment) | 937 | AST_END(YueLineComment) |
| 878 | 938 | ||
| 879 | AST_LEAF(MultilineCommentInner) | 939 | AST_LEAF(YueMultilineComment) |
| 880 | AST_END(MultilineCommentInner) | ||
| 881 | |||
| 882 | AST_NODE(YueMultilineComment) | ||
| 883 | ast_ptr<true, MultilineCommentInner_t> inner; | ||
| 884 | AST_MEMBER(YueMultilineComment, &inner) | ||
| 885 | AST_END(YueMultilineComment) | 940 | AST_END(YueMultilineComment) |
| 886 | 941 | ||
| 942 | AST_NODE(YueComment) | ||
| 943 | ast_sel<true, YueLineComment_t, YueMultilineComment_t> comment; | ||
| 944 | AST_MEMBER(YueComment, &comment) | ||
| 945 | AST_END(YueComment) | ||
| 946 | |||
| 947 | AST_LEAF(EmptyLine) | ||
| 948 | AST_END(EmptyLine) | ||
| 949 | |||
| 887 | AST_NODE(ChainAssign) | 950 | AST_NODE(ChainAssign) |
| 888 | ast_ptr<true, Seperator_t> sep; | 951 | ast_ptr<true, Seperator_t> sep; |
| 889 | ast_list<true, Exp_t> exprs; | 952 | ast_list<true, Exp_t> exprs; |
| @@ -892,16 +955,14 @@ AST_NODE(ChainAssign) | |||
| 892 | AST_END(ChainAssign) | 955 | AST_END(ChainAssign) |
| 893 | 956 | ||
| 894 | AST_NODE(Statement) | 957 | AST_NODE(Statement) |
| 895 | ast_ptr<true, Seperator_t> sep; | ||
| 896 | ast_sel_list<false, YueLineComment_t, YueMultilineComment_t> comments; | ||
| 897 | ast_sel<true, | 958 | ast_sel<true, |
| 898 | Import_t, While_t, Repeat_t, For_t, ForEach_t, | 959 | Import_t, While_t, Repeat_t, For_t, |
| 899 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, | 960 | Return_t, Local_t, Global_t, Export_t, Macro_t, MacroInPlace_t, |
| 900 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, | 961 | BreakLoop_t, Label_t, Goto_t, ShortTabAppending_t, |
| 901 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t | 962 | Backcall_t, LocalAttrib_t, PipeBody_t, ExpListAssign_t, ChainAssign_t |
| 902 | > content; | 963 | > content; |
| 903 | ast_ptr<false, StatementAppendix_t> appendix; | 964 | ast_ptr<false, StatementAppendix_t> appendix; |
| 904 | AST_MEMBER(Statement, &sep, &comments, &content, &appendix) | 965 | AST_MEMBER(Statement, &content, &appendix) |
| 905 | AST_END(Statement) | 966 | AST_END(Statement) |
| 906 | 967 | ||
| 907 | AST_NODE(Body) | 968 | AST_NODE(Body) |
| @@ -911,8 +972,8 @@ AST_END(Body) | |||
| 911 | 972 | ||
| 912 | AST_NODE(Block) | 973 | AST_NODE(Block) |
| 913 | ast_ptr<true, Seperator_t> sep; | 974 | ast_ptr<true, Seperator_t> sep; |
| 914 | ast_list<false, Statement_t> statements; | 975 | ast_sel_list<false, Statement_t, YueComment_t, EmptyLine_t> statementOrComments; |
| 915 | AST_MEMBER(Block, &sep, &statements) | 976 | AST_MEMBER(Block, &sep, &statementOrComments) |
| 916 | AST_END(Block) | 977 | AST_END(Block) |
| 917 | 978 | ||
| 918 | AST_NODE(BlockEnd) | 979 | AST_NODE(BlockEnd) |
| @@ -931,9 +992,9 @@ struct YueFormat { | |||
| 931 | int indent = 0; | 992 | int indent = 0; |
| 932 | bool spaceOverTab = false; | 993 | bool spaceOverTab = false; |
| 933 | int tabSpaces = 4; | 994 | int tabSpaces = 4; |
| 995 | bool reserveComment = true; | ||
| 934 | std::string toString(ast_node* node); | 996 | std::string toString(ast_node* node); |
| 935 | 997 | ||
| 936 | Converter converter{}; | ||
| 937 | void pushScope(); | 998 | void pushScope(); |
| 938 | void popScope(); | 999 | void popScope(); |
| 939 | std::string convert(const ast_node* node); | 1000 | std::string convert(const ast_node* node); |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 590c502..f9b4f18 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.27.5"sv; | 81 | const std::string_view version = "0.32.1"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"; |
| @@ -429,8 +430,18 @@ private: | |||
| 429 | }; | 430 | }; |
| 430 | enum class VarType { | 431 | enum class VarType { |
| 431 | Local = 0, | 432 | Local = 0, |
| 432 | Const = 1, | 433 | LocalConst = 1, |
| 433 | Global = 2 | 434 | Global = 2, |
| 435 | GlobalConst = 3 | ||
| 436 | }; | ||
| 437 | struct Scope; | ||
| 438 | struct ImportedGlobal { | ||
| 439 | std::string* globalCodeLine = nullptr; | ||
| 440 | std::unordered_map<std::string, VarType>* vars = nullptr; | ||
| 441 | std::string indent; | ||
| 442 | std::string nl; | ||
| 443 | std::unordered_set<std::string_view> globals; | ||
| 444 | str_list globalList; | ||
| 434 | }; | 445 | }; |
| 435 | struct Scope { | 446 | struct Scope { |
| 436 | GlobalMode mode = GlobalMode::None; | 447 | GlobalMode mode = GlobalMode::None; |
| @@ -440,8 +451,10 @@ private: | |||
| 440 | #endif | 451 | #endif |
| 441 | std::unique_ptr<std::unordered_map<std::string, VarType>> vars; | 452 | std::unique_ptr<std::unordered_map<std::string, VarType>> vars; |
| 442 | std::unique_ptr<std::unordered_set<std::string>> allows; | 453 | std::unique_ptr<std::unordered_set<std::string>> allows; |
| 454 | std::unique_ptr<ImportedGlobal> importedGlobal; | ||
| 443 | }; | 455 | }; |
| 444 | std::list<Scope> _scopes; | 456 | std::list<Scope> _scopes; |
| 457 | ImportedGlobal* _importedGlobal = nullptr; | ||
| 445 | static const std::string Empty; | 458 | static const std::string Empty; |
| 446 | 459 | ||
| 447 | enum class MemType { | 460 | enum class MemType { |
| @@ -558,7 +571,7 @@ private: | |||
| 558 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | 571 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { |
| 559 | auto vars = it->vars.get(); | 572 | auto vars = it->vars.get(); |
| 560 | auto vit = vars->find(name); | 573 | auto vit = vars->find(name); |
| 561 | if (vit != vars->end() && vit->second != VarType::Global) { | 574 | if (vit != vars->end() && (vit->second == VarType::Local || vit->second == VarType::LocalConst)) { |
| 562 | local = true; | 575 | local = true; |
| 563 | break; | 576 | break; |
| 564 | } | 577 | } |
| @@ -571,7 +584,7 @@ private: | |||
| 571 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { | 584 | for (auto it = _scopes.rbegin(); it != _scopes.rend(); ++it) { |
| 572 | auto vars = it->vars.get(); | 585 | auto vars = it->vars.get(); |
| 573 | auto vit = vars->find(name); | 586 | auto vit = vars->find(name); |
| 574 | if (vit != vars->end() && vit->second == VarType::Global) { | 587 | if (vit != vars->end() && (vit->second == VarType::Global || vit->second == VarType::GlobalConst)) { |
| 575 | global = true; | 588 | global = true; |
| 576 | break; | 589 | break; |
| 577 | } | 590 | } |
| @@ -593,7 +606,7 @@ private: | |||
| 593 | auto vars = it->vars.get(); | 606 | auto vars = it->vars.get(); |
| 594 | auto vit = vars->find(name); | 607 | auto vit = vars->find(name); |
| 595 | if (vit != vars->end()) { | 608 | if (vit != vars->end()) { |
| 596 | isConst = (vit->second == VarType::Const); | 609 | isConst = (vit->second == VarType::LocalConst || vit->second == VarType::GlobalConst); |
| 597 | break; | 610 | break; |
| 598 | } | 611 | } |
| 599 | if (checkShadowScopeOnly && it->allows) break; | 612 | if (checkShadowScopeOnly && it->allows) break; |
| @@ -874,9 +887,13 @@ private: | |||
| 874 | return false; | 887 | return false; |
| 875 | } | 888 | } |
| 876 | 889 | ||
| 877 | void markVarConst(const std::string& name) { | 890 | bool isListComp(Comprehension_t* comp) const { |
| 891 | return comp->items.size() == 2 && ast_is<CompFor_t>(comp->items.back()); | ||
| 892 | } | ||
| 893 | |||
| 894 | void markVarLocalConst(const std::string& name) { | ||
| 878 | auto& scope = _scopes.back(); | 895 | auto& scope = _scopes.back(); |
| 879 | scope.vars->insert_or_assign(name, VarType::Const); | 896 | scope.vars->insert_or_assign(name, VarType::LocalConst); |
| 880 | } | 897 | } |
| 881 | 898 | ||
| 882 | void markVarShadowed() { | 899 | void markVarShadowed() { |
| @@ -895,6 +912,11 @@ private: | |||
| 895 | scope.vars->insert_or_assign(name, VarType::Global); | 912 | scope.vars->insert_or_assign(name, VarType::Global); |
| 896 | } | 913 | } |
| 897 | 914 | ||
| 915 | void markVarGlobalConst(const std::string& name) { | ||
| 916 | auto& scope = _scopes.back(); | ||
| 917 | scope.vars->insert_or_assign(name, VarType::GlobalConst); | ||
| 918 | } | ||
| 919 | |||
| 898 | void addToAllowList(const std::string& name) { | 920 | void addToAllowList(const std::string& name) { |
| 899 | auto& scope = _scopes.back(); | 921 | auto& scope = _scopes.back(); |
| 900 | scope.allows->insert(name); | 922 | scope.allows->insert(name); |
| @@ -961,7 +983,7 @@ private: | |||
| 961 | } | 983 | } |
| 962 | } | 984 | } |
| 963 | 985 | ||
| 964 | const std::string nll(ast_node* node) const { | 986 | const std::string nl(ast_node* node) const { |
| 965 | if (_config.reserveLineNumber) { | 987 | if (_config.reserveLineNumber) { |
| 966 | return " -- "s + std::to_string(node->m_begin.m_line + _config.lineOffset) + _newLine; | 988 | return " -- "s + std::to_string(node->m_begin.m_line + _config.lineOffset) + _newLine; |
| 967 | } else { | 989 | } else { |
| @@ -969,14 +991,6 @@ private: | |||
| 969 | } | 991 | } |
| 970 | } | 992 | } |
| 971 | 993 | ||
| 972 | const std::string nlr(ast_node* node) const { | ||
| 973 | if (_config.reserveLineNumber) { | ||
| 974 | return " -- "s + std::to_string(node->m_end.m_line + _config.lineOffset) + _newLine; | ||
| 975 | } else { | ||
| 976 | return _newLine; | ||
| 977 | } | ||
| 978 | } | ||
| 979 | |||
| 980 | void incIndentOffset() { | 994 | void incIndentOffset() { |
| 981 | _indentOffset++; | 995 | _indentOffset++; |
| 982 | } | 996 | } |
| @@ -1043,13 +1057,6 @@ private: | |||
| 1043 | } | 1057 | } |
| 1044 | break; | 1058 | break; |
| 1045 | } | 1059 | } |
| 1046 | case id<ExpListLow_t>(): { | ||
| 1047 | auto expList = static_cast<ExpListLow_t*>(item); | ||
| 1048 | if (expList->exprs.size() == 1) { | ||
| 1049 | exp = static_cast<Exp_t*>(expList->exprs.front()); | ||
| 1050 | } | ||
| 1051 | break; | ||
| 1052 | } | ||
| 1053 | case id<SwitchList_t>(): { | 1060 | case id<SwitchList_t>(): { |
| 1054 | auto expList = static_cast<SwitchList_t*>(item); | 1061 | auto expList = static_cast<SwitchList_t*>(item); |
| 1055 | if (expList->exprs.size() == 1) { | 1062 | if (expList->exprs.size() == 1) { |
| @@ -1078,12 +1085,12 @@ private: | |||
| 1078 | return nullptr; | 1085 | return nullptr; |
| 1079 | } | 1086 | } |
| 1080 | 1087 | ||
| 1081 | Value_t* singleValueFrom(ast_node* item) const { | 1088 | Value_t* singleValueFrom(ast_node* item, bool forceUnparened = false) const { |
| 1082 | if (auto unary = singleUnaryExpFrom(item)) { | 1089 | if (auto unary = singleUnaryExpFrom(item)) { |
| 1083 | if (unary->ops.empty()) { | 1090 | if (unary->ops.empty()) { |
| 1084 | Value_t* value = static_cast<Value_t*>(unary->expos.back()); | 1091 | Value_t* value = static_cast<Value_t*>(unary->expos.back()); |
| 1085 | if (auto chain = ast_cast<ChainValue_t>(value->item); chain && chain->items.size() == 1) { | 1092 | if (auto chain = ast_cast<ChainValue_t>(value->item); chain && chain->items.size() == 1) { |
| 1086 | if (auto parens = chain->get_by_path<Callable_t, Parens_t>(); parens && parens->extra) { | 1093 | if (auto parens = chain->get_by_path<Callable_t, Parens_t>(); parens && (forceUnparened || parens->extra)) { |
| 1087 | if (auto insideValue = singleValueFrom(parens->expr)) { | 1094 | if (auto insideValue = singleValueFrom(parens->expr)) { |
| 1088 | return insideValue; | 1095 | return insideValue; |
| 1089 | } | 1096 | } |
| @@ -1143,6 +1150,22 @@ private: | |||
| 1143 | return exp; | 1150 | return exp; |
| 1144 | } | 1151 | } |
| 1145 | 1152 | ||
| 1153 | ast_ptr<false, Return_t> newReturn(Exp_t* value) { | ||
| 1154 | auto returnNode = value->new_ptr<Return_t>(); | ||
| 1155 | returnNode->explicitReturn = false; | ||
| 1156 | auto expList = value->new_ptr<ExpList_t>(); | ||
| 1157 | expList->exprs.push_back(value); | ||
| 1158 | returnNode->valueList.set(expList); | ||
| 1159 | return returnNode; | ||
| 1160 | } | ||
| 1161 | |||
| 1162 | ast_ptr<false, Return_t> newReturn(ExpList_t* valueList) { | ||
| 1163 | auto returnNode = valueList->new_ptr<Return_t>(); | ||
| 1164 | returnNode->explicitReturn = false; | ||
| 1165 | returnNode->valueList.set(valueList); | ||
| 1166 | return returnNode; | ||
| 1167 | } | ||
| 1168 | |||
| 1146 | SimpleValue_t* simpleSingleValueFrom(ast_node* node) const { | 1169 | SimpleValue_t* simpleSingleValueFrom(ast_node* node) const { |
| 1147 | auto value = singleValueFrom(node); | 1170 | auto value = singleValueFrom(node); |
| 1148 | if (value && value->item.is<SimpleValue_t>()) { | 1171 | if (value && value->item.is<SimpleValue_t>()) { |
| @@ -1163,14 +1186,22 @@ private: | |||
| 1163 | return nullptr; | 1186 | return nullptr; |
| 1164 | } | 1187 | } |
| 1165 | 1188 | ||
| 1166 | Statement_t* lastStatementFrom(const node_container& stmts) const { | 1189 | Statement_t* lastStatementFrom(const node_container& statementOrComments) const { |
| 1167 | if (!stmts.empty()) { | 1190 | if (!statementOrComments.empty()) { |
| 1168 | auto it = stmts.end(); | 1191 | for (auto it = statementOrComments.rbegin(); it != statementOrComments.rend(); ++it) { |
| 1169 | --it; | 1192 | if (auto stmt = ast_cast<Statement_t>(*it)) { |
| 1170 | while (!static_cast<Statement_t*>(*it)->content && it != stmts.begin()) { | 1193 | return stmt; |
| 1171 | --it; | 1194 | } |
| 1195 | } | ||
| 1196 | } | ||
| 1197 | return nullptr; | ||
| 1198 | } | ||
| 1199 | |||
| 1200 | Statement_t* firstStatementFrom(Block_t* block) const { | ||
| 1201 | for (auto stmt_ : block->statementOrComments.objects()) { | ||
| 1202 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { | ||
| 1203 | return stmt; | ||
| 1172 | } | 1204 | } |
| 1173 | return static_cast<Statement_t*>(*it); | ||
| 1174 | } | 1205 | } |
| 1175 | return nullptr; | 1206 | return nullptr; |
| 1176 | } | 1207 | } |
| @@ -1179,16 +1210,26 @@ private: | |||
| 1179 | if (auto stmt = body->content.as<Statement_t>()) { | 1210 | if (auto stmt = body->content.as<Statement_t>()) { |
| 1180 | return stmt; | 1211 | return stmt; |
| 1181 | } else { | 1212 | } else { |
| 1182 | const auto& stmts = body->content.to<Block_t>()->statements.objects(); | 1213 | const auto& stmts = body->content.to<Block_t>()->statementOrComments.objects(); |
| 1183 | return lastStatementFrom(stmts); | 1214 | return lastStatementFrom(stmts); |
| 1184 | } | 1215 | } |
| 1185 | } | 1216 | } |
| 1186 | 1217 | ||
| 1187 | Statement_t* lastStatementFrom(Block_t* block) const { | 1218 | Statement_t* lastStatementFrom(Block_t* block) const { |
| 1188 | const auto& stmts = block->statements.objects(); | 1219 | const auto& stmts = block->statementOrComments.objects(); |
| 1189 | return lastStatementFrom(stmts); | 1220 | return lastStatementFrom(stmts); |
| 1190 | } | 1221 | } |
| 1191 | 1222 | ||
| 1223 | int countStatementFrom(Block_t* block) const { | ||
| 1224 | int count = 0; | ||
| 1225 | for (auto stmt_ : block->statementOrComments.objects()) { | ||
| 1226 | if (ast_is<Statement_t>(stmt_)) { | ||
| 1227 | count++; | ||
| 1228 | } | ||
| 1229 | } | ||
| 1230 | return count; | ||
| 1231 | } | ||
| 1232 | |||
| 1192 | Exp_t* lastExpFromAssign(ast_node* action) { | 1233 | Exp_t* lastExpFromAssign(ast_node* action) { |
| 1193 | switch (action->get_id()) { | 1234 | switch (action->get_id()) { |
| 1194 | case id<Update_t>(): { | 1235 | case id<Update_t>(): { |
| @@ -1232,7 +1273,7 @@ private: | |||
| 1232 | } | 1273 | } |
| 1233 | case id<Local_t>(): { | 1274 | case id<Local_t>(): { |
| 1234 | if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<LocalValues_t>()) { | 1275 | if (auto localValues = static_cast<Local_t*>(stmt->content.get())->item.as<LocalValues_t>()) { |
| 1235 | if (auto expList = localValues->valueList.as<ExpListLow_t>()) { | 1276 | if (auto expList = localValues->valueList.as<ExpList_t>()) { |
| 1236 | return static_cast<Exp_t*>(expList->exprs.back()); | 1277 | return static_cast<Exp_t*>(expList->exprs.back()); |
| 1237 | } | 1278 | } |
| 1238 | } | 1279 | } |
| @@ -1240,7 +1281,7 @@ private: | |||
| 1240 | } | 1281 | } |
| 1241 | case id<Global_t>(): { | 1282 | case id<Global_t>(): { |
| 1242 | if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<GlobalValues_t>()) { | 1283 | if (auto globalValues = static_cast<Global_t*>(stmt->content.get())->item.as<GlobalValues_t>()) { |
| 1243 | if (auto expList = globalValues->valueList.as<ExpListLow_t>()) { | 1284 | if (auto expList = globalValues->valueList.as<ExpList_t>()) { |
| 1244 | return static_cast<Exp_t*>(expList->exprs.back()); | 1285 | return static_cast<Exp_t*>(expList->exprs.back()); |
| 1245 | } | 1286 | } |
| 1246 | } | 1287 | } |
| @@ -1252,7 +1293,7 @@ private: | |||
| 1252 | 1293 | ||
| 1253 | template <class T> | 1294 | template <class T> |
| 1254 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { | 1295 | ast_ptr<false, T> toAst(std::string_view codes, ast_node* parent) { |
| 1255 | auto res = _parser.parse<T>(std::string(codes)); | 1296 | auto res = _parser.parse<T>(std::string(codes), false); |
| 1256 | if (res.error) { | 1297 | if (res.error) { |
| 1257 | throw CompileError(res.error.value().msg, parent); | 1298 | throw CompileError(res.error.value().msg, parent); |
| 1258 | } | 1299 | } |
| @@ -1275,6 +1316,8 @@ private: | |||
| 1275 | Common, | 1316 | Common, |
| 1276 | EndWithColon, | 1317 | EndWithColon, |
| 1277 | EndWithEOP, | 1318 | EndWithEOP, |
| 1319 | EndWithSlice, | ||
| 1320 | HasRIndex, | ||
| 1278 | HasEOP, | 1321 | HasEOP, |
| 1279 | HasKeyword, | 1322 | HasKeyword, |
| 1280 | HasUnicode, | 1323 | HasUnicode, |
| @@ -1293,6 +1336,9 @@ private: | |||
| 1293 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { | 1336 | if (ast_is<ExistentialOp_t>(chainValue->items.back())) { |
| 1294 | return ChainType::EndWithEOP; | 1337 | return ChainType::EndWithEOP; |
| 1295 | } | 1338 | } |
| 1339 | if (ast_is<Slice_t>(chainValue->items.back())) { | ||
| 1340 | return ChainType::EndWithSlice; | ||
| 1341 | } | ||
| 1296 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 1342 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { |
| 1297 | if (dot->name.is<Metatable_t>()) { | 1343 | if (dot->name.is<Metatable_t>()) { |
| 1298 | return ChainType::Metatable; | 1344 | return ChainType::Metatable; |
| @@ -1318,6 +1364,8 @@ private: | |||
| 1318 | } | 1364 | } |
| 1319 | } else if (ast_is<ExistentialOp_t>(item)) { | 1365 | } else if (ast_is<ExistentialOp_t>(item)) { |
| 1320 | return ChainType::HasEOP; | 1366 | return ChainType::HasEOP; |
| 1367 | } else if (ast_is<ReversedIndex_t>(item)) { | ||
| 1368 | return ChainType::HasRIndex; | ||
| 1321 | } | 1369 | } |
| 1322 | } | 1370 | } |
| 1323 | return type; | 1371 | return type; |
| @@ -1347,10 +1395,10 @@ private: | |||
| 1347 | std::ostringstream buf; | 1395 | std::ostringstream buf; |
| 1348 | for (auto it = uname->m_begin.m_it; it != uname->m_end.m_it; ++it) { | 1396 | for (auto it = uname->m_begin.m_it; it != uname->m_end.m_it; ++it) { |
| 1349 | auto ch = *it; | 1397 | auto ch = *it; |
| 1350 | if (ch > 255) { | 1398 | if (ch <= 0x7F && ((ch == '_') || ((ch | 0x20) >= 'a' && (ch | 0x20) <= 'z') || (ch >= '0' && ch <= '9'))) { |
| 1351 | buf << "_u"sv << std::hex << static_cast<int>(ch); | ||
| 1352 | } else { | ||
| 1353 | buf << static_cast<char>(ch); | 1399 | buf << static_cast<char>(ch); |
| 1400 | } else { | ||
| 1401 | buf << "_u"sv << std::hex << static_cast<uint32_t>(ch); | ||
| 1354 | } | 1402 | } |
| 1355 | } | 1403 | } |
| 1356 | return buf.str(); | 1404 | return buf.str(); |
| @@ -1432,6 +1480,7 @@ private: | |||
| 1432 | case id<DotChainItem_t>(): | 1480 | case id<DotChainItem_t>(): |
| 1433 | case id<Exp_t>(): | 1481 | case id<Exp_t>(): |
| 1434 | case id<TableAppendingOp_t>(): | 1482 | case id<TableAppendingOp_t>(): |
| 1483 | case id<ReversedIndex_t>(): | ||
| 1435 | return true; | 1484 | return true; |
| 1436 | } | 1485 | } |
| 1437 | } | 1486 | } |
| @@ -1449,7 +1498,7 @@ private: | |||
| 1449 | if (simpleValue->value.is<TableLit_t>()) { | 1498 | if (simpleValue->value.is<TableLit_t>()) { |
| 1450 | return true; | 1499 | return true; |
| 1451 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { | 1500 | } else if (auto comp = simpleValue->value.as<Comprehension_t>()) { |
| 1452 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 1501 | if (!isListComp(comp)) { |
| 1453 | return true; | 1502 | return true; |
| 1454 | } | 1503 | } |
| 1455 | } | 1504 | } |
| @@ -1581,16 +1630,26 @@ private: | |||
| 1581 | return !_varArgs.empty() && _varArgs.top().usedVar ? "end)(...)"s : "end)()"s; | 1630 | return !_varArgs.empty() && _varArgs.top().usedVar ? "end)(...)"s : "end)()"s; |
| 1582 | } | 1631 | } |
| 1583 | 1632 | ||
| 1633 | void markGlobalImported(const std::string& name) { | ||
| 1634 | if (_importedGlobal->globals.find(name) == _importedGlobal->globals.end() && !isSolidDefined(name)) { | ||
| 1635 | const auto& global = _importedGlobal->globalList.emplace_back(name); | ||
| 1636 | _importedGlobal->globals.insert(global); | ||
| 1637 | _importedGlobal->vars->insert_or_assign(name, VarType::LocalConst); | ||
| 1638 | } | ||
| 1639 | } | ||
| 1640 | |||
| 1584 | std::string globalVar(std::string_view var, ast_node* x, AccessType accessType) { | 1641 | std::string globalVar(std::string_view var, ast_node* x, AccessType accessType) { |
| 1585 | std::string str(var); | 1642 | std::string str(var); |
| 1586 | if (_config.lintGlobalVariable) { | 1643 | if (_importedGlobal) { |
| 1644 | markGlobalImported(str); | ||
| 1645 | } else if (_config.lintGlobalVariable) { | ||
| 1587 | if (!isLocal(str)) { | 1646 | if (!isLocal(str)) { |
| 1588 | auto key = str + ':' + std::to_string(x->m_begin.m_line) + ':' + std::to_string(x->m_begin.m_col); | 1647 | auto key = str + ':' + std::to_string(x->m_begin.m_line) + ':' + std::to_string(x->m_begin.m_col); |
| 1589 | if (_globals.find(key) == _globals.end()) { | 1648 | if (_globals.find(key) == _globals.end()) { |
| 1590 | if (accessType == AccessType::Read && _funcLevel > 1) { | 1649 | if (accessType == AccessType::Read && _funcLevel > 1) { |
| 1591 | accessType = AccessType::Capture; | 1650 | accessType = AccessType::Capture; |
| 1592 | } | 1651 | } |
| 1593 | _globals[key] = {str, x->m_begin.m_line, x->m_begin.m_col, accessType}; | 1652 | _globals[key] = {str, x->m_begin.m_line, x->m_begin.m_col, accessType, isSolidDefined(str)}; |
| 1594 | } | 1653 | } |
| 1595 | } | 1654 | } |
| 1596 | } | 1655 | } |
| @@ -1632,24 +1691,31 @@ private: | |||
| 1632 | return; | 1691 | return; |
| 1633 | } | 1692 | } |
| 1634 | 1693 | ||
| 1635 | void transformStatement(Statement_t* statement, str_list& out) { | 1694 | void transformComment(YueComment_t* comment, str_list& out) { |
| 1636 | auto x = statement; | 1695 | if (!_config.reserveComment) { |
| 1637 | if (_config.reserveComment && !x->comments.empty()) { | 1696 | return; |
| 1638 | for (ast_node* node : x->comments.objects()) { | 1697 | } |
| 1639 | switch (node->get_id()) { | 1698 | auto node = comment->comment.get(); |
| 1640 | case id<YueLineComment_t>(): { | 1699 | if (!node) { |
| 1641 | auto comment = ast_cast<YueLineComment_t>(node); | 1700 | out.push_back("\n"s); |
| 1642 | out.push_back(indent() + "--"s + _parser.toString(comment) + '\n'); | 1701 | return; |
| 1643 | break; | 1702 | } |
| 1644 | } | 1703 | switch (node->get_id()) { |
| 1645 | case id<YueMultilineComment_t>(): { | 1704 | case id<YueLineComment_t>(): { |
| 1646 | auto comment = ast_cast<YueMultilineComment_t>(node); | 1705 | auto content = static_cast<YueLineComment_t*>(node); |
| 1647 | out.push_back(indent() + _parser.toString(comment) + '\n'); | 1706 | out.push_back(indent() + "--"s + _parser.toString(content) + '\n'); |
| 1648 | break; | 1707 | break; |
| 1649 | } | 1708 | } |
| 1650 | } | 1709 | case id<YueMultilineComment_t>(): { |
| 1710 | auto content = static_cast<YueMultilineComment_t*>(node); | ||
| 1711 | out.push_back(indent() + "--[["s + _parser.toString(content) + "]]\n"s); | ||
| 1712 | break; | ||
| 1651 | } | 1713 | } |
| 1652 | } | 1714 | } |
| 1715 | } | ||
| 1716 | |||
| 1717 | void transformStatement(Statement_t* statement, str_list& out) { | ||
| 1718 | auto x = statement; | ||
| 1653 | if (statement->appendix) { | 1719 | if (statement->appendix) { |
| 1654 | if (auto assignment = assignmentFrom(statement)) { | 1720 | if (auto assignment = assignmentFrom(statement)) { |
| 1655 | auto preDefine = getPreDefineLine(assignment); | 1721 | auto preDefine = getPreDefineLine(assignment); |
| @@ -1713,7 +1779,7 @@ private: | |||
| 1713 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); | 1779 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); |
| 1714 | break; | 1780 | break; |
| 1715 | } | 1781 | } |
| 1716 | case id<CompInner_t>(): { | 1782 | case id<CompFor_t>(): { |
| 1717 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); | 1783 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); |
| 1718 | break; | 1784 | break; |
| 1719 | } | 1785 | } |
| @@ -1774,8 +1840,8 @@ private: | |||
| 1774 | statement->content.set(expListAssign); | 1840 | statement->content.set(expListAssign); |
| 1775 | break; | 1841 | break; |
| 1776 | } | 1842 | } |
| 1777 | case id<CompInner_t>(): { | 1843 | case id<CompFor_t>(): { |
| 1778 | auto compInner = appendix->item.to<CompInner_t>(); | 1844 | auto compInner = appendix->item.to<CompFor_t>(); |
| 1779 | auto comp = x->new_ptr<Comprehension_t>(); | 1845 | auto comp = x->new_ptr<Comprehension_t>(); |
| 1780 | auto stmt = x->new_ptr<Statement_t>(); | 1846 | auto stmt = x->new_ptr<Statement_t>(); |
| 1781 | stmt->content.set(statement->content); | 1847 | stmt->content.set(statement->content); |
| @@ -1840,11 +1906,12 @@ private: | |||
| 1840 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; | 1906 | case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(value), out); break; |
| 1841 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; | 1907 | case id<For_t>(): transformFor(static_cast<For_t*>(value), out); break; |
| 1842 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; | 1908 | case id<While_t>(): transformWhile(static_cast<While_t*>(value), out); break; |
| 1909 | case id<Repeat_t>(): transformRepeat(static_cast<Repeat_t*>(value), out); break; | ||
| 1843 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; | 1910 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Common); break; |
| 1844 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; | 1911 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Common); break; |
| 1845 | case id<Comprehension_t>(): { | 1912 | case id<Comprehension_t>(): { |
| 1846 | auto comp = static_cast<Comprehension_t*>(value); | 1913 | auto comp = static_cast<Comprehension_t*>(value); |
| 1847 | if (comp->items.size() == 2 && ast_is<CompInner_t>(comp->items.back())) { | 1914 | if (isListComp(comp)) { |
| 1848 | transformCompCommon(comp, out); | 1915 | transformCompCommon(comp, out); |
| 1849 | } else { | 1916 | } else { |
| 1850 | specialSingleValue = false; | 1917 | specialSingleValue = false; |
| @@ -1968,7 +2035,7 @@ private: | |||
| 1968 | return indent() + "local "s + join(defs, ", "sv); | 2035 | return indent() + "local "s + join(defs, ", "sv); |
| 1969 | } | 2036 | } |
| 1970 | 2037 | ||
| 1971 | std::string getDestrucureDefine(ExpListAssign_t* assignment) { | 2038 | std::string getDestructureDefine(ExpListAssign_t* assignment) { |
| 1972 | auto info = extractDestructureInfo(assignment, true, false); | 2039 | auto info = extractDestructureInfo(assignment, true, false); |
| 1973 | if (!info.destructures.empty()) { | 2040 | if (!info.destructures.empty()) { |
| 1974 | str_list defs; | 2041 | str_list defs; |
| @@ -1999,8 +2066,31 @@ private: | |||
| 1999 | return clearBuf(); | 2066 | return clearBuf(); |
| 2000 | } | 2067 | } |
| 2001 | 2068 | ||
| 2069 | str_list getArgDestructureList(ExpListAssign_t* assignment) { | ||
| 2070 | str_list defs; | ||
| 2071 | auto info = extractDestructureInfo(assignment, true, false); | ||
| 2072 | if (!info.destructures.empty()) { | ||
| 2073 | for (const auto& des : info.destructures) { | ||
| 2074 | if (std::holds_alternative<Destructure>(des)) { | ||
| 2075 | const auto& destruct = std::get<Destructure>(des); | ||
| 2076 | for (const auto& item : destruct.items) { | ||
| 2077 | if (item.targetVar.empty()) { | ||
| 2078 | throw CompileError("can only destruct argument to variable"sv, item.target); | ||
| 2079 | } else { | ||
| 2080 | defs.push_back(item.targetVar); | ||
| 2081 | } | ||
| 2082 | } | ||
| 2083 | } else { | ||
| 2084 | const auto& assignment = std::get<AssignmentPtr>(des); | ||
| 2085 | YUEE("AST node mismatch", assignment.ptr); | ||
| 2086 | } | ||
| 2087 | } | ||
| 2088 | } | ||
| 2089 | return defs; | ||
| 2090 | } | ||
| 2091 | |||
| 2002 | std::string getPreDefine(ExpListAssign_t* assignment) { | 2092 | std::string getPreDefine(ExpListAssign_t* assignment) { |
| 2003 | auto preDefine = getDestrucureDefine(assignment); | 2093 | auto preDefine = getDestructureDefine(assignment); |
| 2004 | if (preDefine.empty()) { | 2094 | if (preDefine.empty()) { |
| 2005 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); | 2095 | preDefine = toLocalDecl(transformAssignDefs(assignment->expList, DefOp::Mark)); |
| 2006 | } | 2096 | } |
| @@ -2009,7 +2099,7 @@ private: | |||
| 2009 | 2099 | ||
| 2010 | std::string getPreDefineLine(ExpListAssign_t* assignment) { | 2100 | std::string getPreDefineLine(ExpListAssign_t* assignment) { |
| 2011 | auto preDefine = getPreDefine(assignment); | 2101 | auto preDefine = getPreDefine(assignment); |
| 2012 | if (!preDefine.empty()) preDefine += nll(assignment); | 2102 | if (!preDefine.empty()) preDefine += nl(assignment); |
| 2013 | return preDefine; | 2103 | return preDefine; |
| 2014 | } | 2104 | } |
| 2015 | 2105 | ||
| @@ -2051,13 +2141,16 @@ private: | |||
| 2051 | if (item.targetVar.empty()) { | 2141 | if (item.targetVar.empty()) { |
| 2052 | throw CompileError("can only declare variable as const"sv, item.target); | 2142 | throw CompileError("can only declare variable as const"sv, item.target); |
| 2053 | } | 2143 | } |
| 2054 | markVarConst(item.targetVar); | 2144 | markVarLocalConst(item.targetVar); |
| 2055 | } | 2145 | } |
| 2056 | } | 2146 | } |
| 2057 | } | 2147 | } |
| 2058 | } | 2148 | } |
| 2059 | 2149 | ||
| 2060 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { | 2150 | bool transformAssignment(ExpListAssign_t* assignment, str_list& out, bool optionalDestruct = false) { |
| 2151 | if (assignment->action.is<SubBackcall_t>()) { | ||
| 2152 | YUEE("AST node mismatch", assignment->action); | ||
| 2153 | } | ||
| 2061 | checkAssignable(assignment->expList); | 2154 | checkAssignable(assignment->expList); |
| 2062 | BLOCK_START | 2155 | BLOCK_START |
| 2063 | auto assign = ast_cast<Assign_t>(assignment->action); | 2156 | auto assign = ast_cast<Assign_t>(assignment->action); |
| @@ -2162,14 +2255,14 @@ private: | |||
| 2162 | temp.push_back(getPreDefineLine(assignment)); | 2255 | temp.push_back(getPreDefineLine(assignment)); |
| 2163 | bool needScope = !currentScope().lastStatement; | 2256 | bool needScope = !currentScope().lastStatement; |
| 2164 | if (needScope) { | 2257 | if (needScope) { |
| 2165 | temp.push_back(indent() + "do"s + nll(assignment)); | 2258 | temp.push_back(indent() + "do"s + nl(assignment)); |
| 2166 | pushScope(); | 2259 | pushScope(); |
| 2167 | } | 2260 | } |
| 2168 | transformAssignment(preAssignment, temp); | 2261 | transformAssignment(preAssignment, temp); |
| 2169 | transformAssignment(assignment, temp); | 2262 | transformAssignment(assignment, temp); |
| 2170 | if (needScope) { | 2263 | if (needScope) { |
| 2171 | popScope(); | 2264 | popScope(); |
| 2172 | temp.push_back(indent() + "end"s + nll(assignment)); | 2265 | temp.push_back(indent() + "end"s + nl(assignment)); |
| 2173 | } | 2266 | } |
| 2174 | out.push_back(join(temp)); | 2267 | out.push_back(join(temp)); |
| 2175 | return false; | 2268 | return false; |
| @@ -2214,7 +2307,8 @@ private: | |||
| 2214 | BREAK_IF(!value); | 2307 | BREAK_IF(!value); |
| 2215 | auto chainValue = value->item.as<ChainValue_t>(); | 2308 | auto chainValue = value->item.as<ChainValue_t>(); |
| 2216 | BREAK_IF(!chainValue); | 2309 | BREAK_IF(!chainValue); |
| 2217 | if (auto dot = ast_cast<DotChainItem_t>(chainValue->items.back())) { | 2310 | auto last = chainValue->items.back(); |
| 2311 | if (auto dot = ast_cast<DotChainItem_t>(last)) { | ||
| 2218 | BREAK_IF(!dot->name.is<Metatable_t>()); | 2312 | BREAK_IF(!dot->name.is<Metatable_t>()); |
| 2219 | str_list temp; | 2313 | str_list temp; |
| 2220 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | 2314 | auto [beforeAssignment, afterAssignment] = splitAssignment(); |
| @@ -2238,14 +2332,14 @@ private: | |||
| 2238 | throw CompileError("right value missing"sv, values.front()); | 2332 | throw CompileError("right value missing"sv, values.front()); |
| 2239 | } | 2333 | } |
| 2240 | transformAssignItem(*vit, args); | 2334 | transformAssignItem(*vit, args); |
| 2241 | _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nll(x); | 2335 | _buf << indent() << globalVar("setmetatable"sv, x, AccessType::Read) << '(' << join(args, ", "sv) << ')' << nl(x); |
| 2242 | temp.push_back(clearBuf()); | 2336 | temp.push_back(clearBuf()); |
| 2243 | if (!afterAssignment->expList->exprs.empty()) { | 2337 | if (!afterAssignment->expList->exprs.empty()) { |
| 2244 | transformAssignment(afterAssignment, temp); | 2338 | transformAssignment(afterAssignment, temp); |
| 2245 | } | 2339 | } |
| 2246 | out.push_back(join(temp)); | 2340 | out.push_back(join(temp)); |
| 2247 | return false; | 2341 | return false; |
| 2248 | } else if (ast_is<TableAppendingOp_t>(chainValue->items.back())) { | 2342 | } else if (ast_is<TableAppendingOp_t>(last)) { |
| 2249 | str_list temp; | 2343 | str_list temp; |
| 2250 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | 2344 | auto [beforeAssignment, afterAssignment] = splitAssignment(); |
| 2251 | if (!beforeAssignment->expList->exprs.empty()) { | 2345 | if (!beforeAssignment->expList->exprs.empty()) { |
| @@ -2267,7 +2361,7 @@ private: | |||
| 2267 | if (varName.empty() || !isLocal(varName)) { | 2361 | if (varName.empty() || !isLocal(varName)) { |
| 2268 | if (needScope) { | 2362 | if (needScope) { |
| 2269 | extraScoped = true; | 2363 | extraScoped = true; |
| 2270 | temp.push_back(indent() + "do"s + nll(x)); | 2364 | temp.push_back(indent() + "do"s + nl(x)); |
| 2271 | pushScope(); | 2365 | pushScope(); |
| 2272 | } | 2366 | } |
| 2273 | auto objVar = getUnusedName("_obj_"sv); | 2367 | auto objVar = getUnusedName("_obj_"sv); |
| @@ -2279,24 +2373,74 @@ private: | |||
| 2279 | transformAssignment(newAssignment, temp); | 2373 | transformAssignment(newAssignment, temp); |
| 2280 | varName = objVar; | 2374 | varName = objVar; |
| 2281 | } | 2375 | } |
| 2282 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 2376 | if (auto spread = ast_cast<SpreadListExp_t>(*vit)) { |
| 2283 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | 2377 | auto lenVar = getUnusedName("_len_"sv); |
| 2284 | auto assign = x->new_ptr<Assign_t>(); | 2378 | forceAddToScope(lenVar); |
| 2285 | if (vit == values.end()) { | 2379 | temp.push_back(indent() + "local "s + lenVar + " = #"s + varName + " + 1"s + nl(spread)); |
| 2286 | throw CompileError("right value missing"sv, values.front()); | 2380 | auto elmVar = getUnusedName("_elm_"sv); |
| 2381 | _buf << varName << '[' << lenVar << "],"s << lenVar << "="s << elmVar << ',' << lenVar << "+1 for "s << elmVar << " in *nil"s; | ||
| 2382 | auto stmt = toAst<Statement_t>(clearBuf(), spread); | ||
| 2383 | auto comp = stmt->appendix->item.to<CompFor_t>(); | ||
| 2384 | ast_to<CompForEach_t>(comp->items.front())->loopValue.to<StarExp_t>()->value.set(spread->exp); | ||
| 2385 | transformStatement(stmt, temp); | ||
| 2386 | } else { | ||
| 2387 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | ||
| 2388 | newAssignment->expList.set(toAst<ExpList_t>(varName + "[#"s + varName + "+1]"s, x)); | ||
| 2389 | auto assign = x->new_ptr<Assign_t>(); | ||
| 2390 | if (vit == values.end()) { | ||
| 2391 | throw CompileError("right value missing"sv, values.front()); | ||
| 2392 | } | ||
| 2393 | assign->values.push_back(*vit); | ||
| 2394 | newAssignment->action.set(assign); | ||
| 2395 | transformAssignment(newAssignment, temp); | ||
| 2287 | } | 2396 | } |
| 2288 | assign->values.push_back(*vit); | ||
| 2289 | newAssignment->action.set(assign); | ||
| 2290 | transformAssignment(newAssignment, temp); | ||
| 2291 | if (extraScoped) { | 2397 | if (extraScoped) { |
| 2292 | popScope(); | 2398 | popScope(); |
| 2293 | temp.push_back(indent() + "end"s + nlr(x)); | 2399 | temp.push_back(indent() + "end"s + nl(x)); |
| 2294 | } | 2400 | } |
| 2295 | if (!afterAssignment->expList->exprs.empty()) { | 2401 | if (!afterAssignment->expList->exprs.empty()) { |
| 2296 | transformAssignment(afterAssignment, temp); | 2402 | transformAssignment(afterAssignment, temp); |
| 2297 | } | 2403 | } |
| 2298 | out.push_back(join(temp)); | 2404 | out.push_back(join(temp)); |
| 2299 | return false; | 2405 | return false; |
| 2406 | } else if (ast_is<ReversedIndex_t>(last)) { | ||
| 2407 | if (chainValue->items.size() == 1) { | ||
| 2408 | if (_withVars.empty()) { | ||
| 2409 | throw CompileError("short dot/colon syntax must be called within a with block"sv, x); | ||
| 2410 | } else { | ||
| 2411 | break; | ||
| 2412 | } | ||
| 2413 | } | ||
| 2414 | auto tmpChain = chainValue->new_ptr<ChainValue_t>(); | ||
| 2415 | tmpChain->items.dup(chainValue->items); | ||
| 2416 | tmpChain->items.pop_back(); | ||
| 2417 | auto tmpLeft = newExp(tmpChain, tmpChain); | ||
| 2418 | auto leftVar = singleVariableFrom(tmpLeft, AccessType::Read); | ||
| 2419 | if (!leftVar.empty() && isLocal(leftVar)) { | ||
| 2420 | break; | ||
| 2421 | } | ||
| 2422 | leftVar = getUnusedName("_obj_"sv); | ||
| 2423 | auto tmpAsmt = assignmentFrom(toAst<Exp_t>(leftVar, tmpLeft), tmpLeft, tmpLeft); | ||
| 2424 | str_list temp; | ||
| 2425 | transformAssignment(tmpAsmt, temp); | ||
| 2426 | auto [beforeAssignment, afterAssignment] = splitAssignment(); | ||
| 2427 | if (!beforeAssignment->expList->exprs.empty()) { | ||
| 2428 | transformAssignment(beforeAssignment, temp); | ||
| 2429 | } | ||
| 2430 | if (vit == values.end()) { | ||
| 2431 | throw CompileError("right value missing"sv, values.front()); | ||
| 2432 | } | ||
| 2433 | auto newChain = chainValue->new_ptr<ChainValue_t>(); | ||
| 2434 | newChain->items.push_back(toAst<Callable_t>(leftVar, newChain)); | ||
| 2435 | newChain->items.push_back(chainValue->items.back()); | ||
| 2436 | auto newLeft = newExp(newChain, newChain); | ||
| 2437 | auto newAsmt = assignmentFrom(newLeft, *vit, newLeft); | ||
| 2438 | transformAssignment(newAsmt, temp); | ||
| 2439 | if (!afterAssignment->expList->exprs.empty()) { | ||
| 2440 | transformAssignment(afterAssignment, temp); | ||
| 2441 | } | ||
| 2442 | out.push_back(join(temp)); | ||
| 2443 | return false; | ||
| 2300 | } else { | 2444 | } else { |
| 2301 | break; | 2445 | break; |
| 2302 | } | 2446 | } |
| @@ -2320,6 +2464,17 @@ private: | |||
| 2320 | out.back().insert(0, preDefine); | 2464 | out.back().insert(0, preDefine); |
| 2321 | return false; | 2465 | return false; |
| 2322 | } | 2466 | } |
| 2467 | case id<Try_t>(): { | ||
| 2468 | auto tryNode = static_cast<Try_t*>(value); | ||
| 2469 | if (tryNode->eop) { | ||
| 2470 | auto assignList = assignment->expList.get(); | ||
| 2471 | std::string preDefine = getPreDefineLine(assignment); | ||
| 2472 | transformTry(tryNode, out, ExpUsage::Assignment, assignList); | ||
| 2473 | out.back().insert(0, preDefine); | ||
| 2474 | return false; | ||
| 2475 | } | ||
| 2476 | break; | ||
| 2477 | } | ||
| 2323 | case id<Switch_t>(): { | 2478 | case id<Switch_t>(): { |
| 2324 | auto switchNode = static_cast<Switch_t*>(value); | 2479 | auto switchNode = static_cast<Switch_t*>(value); |
| 2325 | auto assignList = assignment->expList.get(); | 2480 | auto assignList = assignment->expList.get(); |
| @@ -2347,7 +2502,7 @@ private: | |||
| 2347 | case id<Comprehension_t>(): { | 2502 | case id<Comprehension_t>(): { |
| 2348 | auto comp = static_cast<Comprehension_t*>(value); | 2503 | auto comp = static_cast<Comprehension_t*>(value); |
| 2349 | auto expList = assignment->expList.get(); | 2504 | auto expList = assignment->expList.get(); |
| 2350 | if (comp->items.size() == 2 && ast_is<CompInner_t>(comp->items.back())) { | 2505 | if (isListComp(comp)) { |
| 2351 | std::string preDefine = getPreDefineLine(assignment); | 2506 | std::string preDefine = getPreDefineLine(assignment); |
| 2352 | transformComprehension(comp, out, ExpUsage::Assignment, expList); | 2507 | transformComprehension(comp, out, ExpUsage::Assignment, expList); |
| 2353 | out.back().insert(0, preDefine); | 2508 | out.back().insert(0, preDefine); |
| @@ -2391,6 +2546,13 @@ private: | |||
| 2391 | out.back().insert(0, preDefine); | 2546 | out.back().insert(0, preDefine); |
| 2392 | return false; | 2547 | return false; |
| 2393 | } | 2548 | } |
| 2549 | case id<Repeat_t>(): { | ||
| 2550 | auto expList = assignment->expList.get(); | ||
| 2551 | std::string preDefine = getPreDefineLine(assignment); | ||
| 2552 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out, expList); | ||
| 2553 | out.back().insert(0, preDefine); | ||
| 2554 | return false; | ||
| 2555 | } | ||
| 2394 | case id<TableLit_t>(): { | 2556 | case id<TableLit_t>(): { |
| 2395 | auto tableLit = static_cast<TableLit_t*>(value); | 2557 | auto tableLit = static_cast<TableLit_t*>(value); |
| 2396 | if (hasSpreadExp(tableLit->values.objects())) { | 2558 | if (hasSpreadExp(tableLit->values.objects())) { |
| @@ -2443,12 +2605,14 @@ private: | |||
| 2443 | switch (type) { | 2605 | switch (type) { |
| 2444 | case ChainType::HasEOP: | 2606 | case ChainType::HasEOP: |
| 2445 | case ChainType::EndWithColon: | 2607 | case ChainType::EndWithColon: |
| 2608 | case ChainType::EndWithSlice: | ||
| 2446 | case ChainType::MetaFieldInvocation: { | 2609 | case ChainType::MetaFieldInvocation: { |
| 2447 | std::string preDefine = getPreDefineLine(assignment); | 2610 | std::string preDefine = getPreDefineLine(assignment); |
| 2448 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); | 2611 | transformChainValue(chainValue, out, ExpUsage::Assignment, expList, false, optionalDestruct); |
| 2449 | out.back().insert(0, preDefine); | 2612 | out.back().insert(0, preDefine); |
| 2450 | return false; | 2613 | return false; |
| 2451 | } | 2614 | } |
| 2615 | case ChainType::HasRIndex: | ||
| 2452 | case ChainType::HasKeyword: | 2616 | case ChainType::HasKeyword: |
| 2453 | case ChainType::HasUnicode: | 2617 | case ChainType::HasUnicode: |
| 2454 | case ChainType::Macro: | 2618 | case ChainType::Macro: |
| @@ -2464,6 +2628,10 @@ private: | |||
| 2464 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); | 2628 | auto info = extractDestructureInfo(assignment, false, optionalDestruct); |
| 2465 | if (info.destructures.empty()) { | 2629 | if (info.destructures.empty()) { |
| 2466 | transformAssignmentCommon(assignment, out); | 2630 | transformAssignmentCommon(assignment, out); |
| 2631 | if (assignment->expList->followStmt) { | ||
| 2632 | transformStatement(assignment->expList->followStmt, out); | ||
| 2633 | assignment->expList->followStmtProcessed = true; | ||
| 2634 | } | ||
| 2467 | return true; | 2635 | return true; |
| 2468 | } else { | 2636 | } else { |
| 2469 | auto x = assignment; | 2637 | auto x = assignment; |
| @@ -2499,11 +2667,11 @@ private: | |||
| 2499 | checkConst(def, x); | 2667 | checkConst(def, x); |
| 2500 | addToScope(def); | 2668 | addToScope(def); |
| 2501 | } | 2669 | } |
| 2502 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2670 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2503 | } | 2671 | } |
| 2504 | if (needScope) { | 2672 | if (needScope) { |
| 2505 | extraScope = true; | 2673 | extraScope = true; |
| 2506 | temp.push_back(indent() + "do"s + nll(x)); | 2674 | temp.push_back(indent() + "do"s + nl(x)); |
| 2507 | pushScope(); | 2675 | pushScope(); |
| 2508 | } | 2676 | } |
| 2509 | } | 2677 | } |
| @@ -2555,13 +2723,13 @@ private: | |||
| 2555 | continue; | 2723 | continue; |
| 2556 | } | 2724 | } |
| 2557 | if (extraScope) { | 2725 | if (extraScope) { |
| 2558 | temp.push_back(indent() + "do"s + nll(x)); | 2726 | temp.push_back(indent() + "do"s + nl(x)); |
| 2559 | pushScope(); | 2727 | pushScope(); |
| 2560 | } | 2728 | } |
| 2561 | if (!pair.targetVar.empty()) { | 2729 | if (!pair.targetVar.empty()) { |
| 2562 | checkConst(pair.targetVar, x); | 2730 | checkConst(pair.targetVar, x); |
| 2563 | if (addToScope(pair.targetVar)) { | 2731 | if (addToScope(pair.targetVar)) { |
| 2564 | _buf << indent() << "local "sv << pair.targetVar << nll(x); | 2732 | _buf << indent() << "local "sv << pair.targetVar << nl(x); |
| 2565 | temp.push_back(clearBuf()); | 2733 | temp.push_back(clearBuf()); |
| 2566 | } | 2734 | } |
| 2567 | } | 2735 | } |
| @@ -2571,7 +2739,7 @@ private: | |||
| 2571 | objVar = destruct.valueVar; | 2739 | objVar = destruct.valueVar; |
| 2572 | } else { | 2740 | } else { |
| 2573 | if (needScope) { | 2741 | if (needScope) { |
| 2574 | temp.push_back(indent() + "do"s + nll(x)); | 2742 | temp.push_back(indent() + "do"s + nl(x)); |
| 2575 | pushScope(); | 2743 | pushScope(); |
| 2576 | } | 2744 | } |
| 2577 | objVar = getUnusedName("_obj_"sv); | 2745 | objVar = getUnusedName("_obj_"sv); |
| @@ -2587,7 +2755,7 @@ private: | |||
| 2587 | if (!isLocalValue) { | 2755 | if (!isLocalValue) { |
| 2588 | if (needScope) { | 2756 | if (needScope) { |
| 2589 | popScope(); | 2757 | popScope(); |
| 2590 | _buf << indent() << "end"sv << nlr(x); | 2758 | _buf << indent() << "end"sv << nl(x); |
| 2591 | temp.push_back(clearBuf()); | 2759 | temp.push_back(clearBuf()); |
| 2592 | } | 2760 | } |
| 2593 | } | 2761 | } |
| @@ -2625,9 +2793,9 @@ private: | |||
| 2625 | checkConst(def, x); | 2793 | checkConst(def, x); |
| 2626 | addToScope(def); | 2794 | addToScope(def); |
| 2627 | } | 2795 | } |
| 2628 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2796 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2629 | } | 2797 | } |
| 2630 | temp.push_back(indent() + "do"s + nll(x)); | 2798 | temp.push_back(indent() + "do"s + nl(x)); |
| 2631 | pushScope(); | 2799 | pushScope(); |
| 2632 | } | 2800 | } |
| 2633 | } else { | 2801 | } else { |
| @@ -2636,11 +2804,11 @@ private: | |||
| 2636 | checkConst(def, x); | 2804 | checkConst(def, x); |
| 2637 | addToScope(def); | 2805 | addToScope(def); |
| 2638 | } | 2806 | } |
| 2639 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nll(x)); | 2807 | temp.push_back(indent() + "local "s + join(defs, ", "sv) + nl(x)); |
| 2640 | } | 2808 | } |
| 2641 | if (needScope) { | 2809 | if (needScope) { |
| 2642 | extraScope = true; | 2810 | extraScope = true; |
| 2643 | temp.push_back(indent() + "do"s + nll(x)); | 2811 | temp.push_back(indent() + "do"s + nl(x)); |
| 2644 | pushScope(); | 2812 | pushScope(); |
| 2645 | } | 2813 | } |
| 2646 | auto valVar = getUnusedName("_obj_"sv); | 2814 | auto valVar = getUnusedName("_obj_"sv); |
| @@ -2655,7 +2823,7 @@ private: | |||
| 2655 | if (destruct.inlineAssignment) { | 2823 | if (destruct.inlineAssignment) { |
| 2656 | if (needScope && !extraScope) { | 2824 | if (needScope && !extraScope) { |
| 2657 | extraScope = true; | 2825 | extraScope = true; |
| 2658 | temp.push_back(indent() + "do"s + nll(x)); | 2826 | temp.push_back(indent() + "do"s + nl(x)); |
| 2659 | pushScope(); | 2827 | pushScope(); |
| 2660 | } | 2828 | } |
| 2661 | transformAssignment(destruct.inlineAssignment, temp); | 2829 | transformAssignment(destruct.inlineAssignment, temp); |
| @@ -2720,17 +2888,21 @@ private: | |||
| 2720 | } | 2888 | } |
| 2721 | if (extraScope) { | 2889 | if (extraScope) { |
| 2722 | popScope(); | 2890 | popScope(); |
| 2723 | _buf << indent() << "end"sv << nlr(x); | 2891 | _buf << indent() << "end"sv << nl(x); |
| 2724 | temp.push_back(clearBuf()); | 2892 | temp.push_back(clearBuf()); |
| 2725 | } | 2893 | } |
| 2726 | } | 2894 | } |
| 2727 | if (extraScope) { | 2895 | if (extraScope) { |
| 2728 | popScope(); | 2896 | popScope(); |
| 2729 | temp.push_back(indent() + "end"s + nlr(x)); | 2897 | temp.push_back(indent() + "end"s + nl(x)); |
| 2730 | } | 2898 | } |
| 2731 | out.push_back(join(temp)); | 2899 | out.push_back(join(temp)); |
| 2900 | if (assignment->expList->followStmt) { | ||
| 2901 | transformStatement(assignment->expList->followStmt, out); | ||
| 2902 | assignment->expList->followStmtProcessed = true; | ||
| 2903 | } | ||
| 2904 | return false; | ||
| 2732 | } | 2905 | } |
| 2733 | return false; | ||
| 2734 | } | 2906 | } |
| 2735 | 2907 | ||
| 2736 | void transformAssignItem(ast_node* value, str_list& out) { | 2908 | void transformAssignItem(ast_node* value, str_list& out) { |
| @@ -2740,6 +2912,7 @@ private: | |||
| 2740 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; | 2912 | case id<Switch_t>(): transformSwitch(static_cast<Switch_t*>(value), out, ExpUsage::Closure); break; |
| 2741 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; | 2913 | case id<TableBlock_t>(): transformTableBlock(static_cast<TableBlock_t*>(value), out); break; |
| 2742 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; | 2914 | case id<Exp_t>(): transformExp(static_cast<Exp_t*>(value), out, ExpUsage::Closure); break; |
| 2915 | case id<SpreadListExp_t>(): throw CompileError("can only be used for ranged table append assignments"sv, value); break; | ||
| 2743 | default: YUEE("AST node mismatch", value); break; | 2916 | default: YUEE("AST node mismatch", value); break; |
| 2744 | } | 2917 | } |
| 2745 | } | 2918 | } |
| @@ -2754,7 +2927,7 @@ private: | |||
| 2754 | if (auto tbA = item->get_by_path<TableLit_t>()) { | 2927 | if (auto tbA = item->get_by_path<TableLit_t>()) { |
| 2755 | tableItems = &tbA->values.objects(); | 2928 | tableItems = &tbA->values.objects(); |
| 2756 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { | 2929 | } else if (auto tbB = item->get_by_path<Comprehension_t>()) { |
| 2757 | if (tbB->items.size() == 2 && ast_is<CompInner_t>(tbB->items.back())) { | 2930 | if (isListComp(tbB)) { |
| 2758 | throw CompileError("invalid destructure value"sv, tbB); | 2931 | throw CompileError("invalid destructure value"sv, tbB); |
| 2759 | } | 2932 | } |
| 2760 | tableItems = &tbB->items.objects(); | 2933 | tableItems = &tbB->items.objects(); |
| @@ -2785,7 +2958,7 @@ private: | |||
| 2785 | } | 2958 | } |
| 2786 | case id<Comprehension_t>(): { | 2959 | case id<Comprehension_t>(): { |
| 2787 | auto table = static_cast<Comprehension_t*>(node); | 2960 | auto table = static_cast<Comprehension_t*>(node); |
| 2788 | if (table->items.size() == 2 && ast_is<CompInner_t>(table->items.back())) { | 2961 | if (isListComp(table)) { |
| 2789 | throw CompileError("invalid destructure value"sv, table); | 2962 | throw CompileError("invalid destructure value"sv, table); |
| 2790 | } | 2963 | } |
| 2791 | tableItems = &table->items.objects(); | 2964 | tableItems = &table->items.objects(); |
| @@ -2796,20 +2969,46 @@ private: | |||
| 2796 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); | 2969 | if (!tableItems) throw CompileError("invalid destructure value"sv, node); |
| 2797 | std::list<DestructItem> pairs; | 2970 | std::list<DestructItem> pairs; |
| 2798 | int index = 0; | 2971 | int index = 0; |
| 2972 | int count = 0; | ||
| 2973 | bool hasSpread = false; | ||
| 2799 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); | 2974 | auto subMetaDestruct = node->new_ptr<TableLit_t>(); |
| 2800 | for (auto pair : *tableItems) { | 2975 | for (auto pair : *tableItems) { |
| 2801 | switch (pair->get_id()) { | 2976 | switch (pair->get_id()) { |
| 2802 | case id<Exp_t>(): | 2977 | case id<Exp_t>(): |
| 2803 | case id<NormalDef_t>(): { | 2978 | case id<NormalDef_t>(): { |
| 2979 | ++index; | ||
| 2804 | Exp_t* defVal = nullptr; | 2980 | Exp_t* defVal = nullptr; |
| 2805 | if (auto nd = ast_cast<NormalDef_t>(pair)) { | 2981 | if (auto nd = ast_cast<NormalDef_t>(pair)) { |
| 2806 | pair = nd->item.get(); | 2982 | pair = nd->item.get(); |
| 2807 | defVal = nd->defVal.get(); | 2983 | defVal = nd->defVal.get(); |
| 2808 | } | 2984 | } |
| 2809 | ++index; | 2985 | bool assignable = false; |
| 2810 | if (!varDefOnly && !isAssignable(static_cast<Exp_t*>(pair))) { | 2986 | try { |
| 2987 | assignable = isAssignable(static_cast<Exp_t*>(pair)); | ||
| 2988 | } catch (const CompileError& e) { | ||
| 2989 | if (!varDefOnly) throw e; | ||
| 2990 | } | ||
| 2991 | if (!assignable && !varDefOnly) { | ||
| 2992 | if (optional) break; | ||
| 2811 | throw CompileError("can't destructure value"sv, pair); | 2993 | throw CompileError("can't destructure value"sv, pair); |
| 2812 | } | 2994 | } |
| 2995 | ast_ptr<true, ast_node> indexItem; | ||
| 2996 | if (hasSpread) { | ||
| 2997 | int rIndex = count - index; | ||
| 2998 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), pair)); | ||
| 2999 | } else { | ||
| 3000 | indexItem.set(toAst<Exp_t>(std::to_string(index), pair)); | ||
| 3001 | } | ||
| 3002 | if (optional && varDefOnly && !assignable) { | ||
| 3003 | if (defVal) { | ||
| 3004 | throw CompileError("default value is not supported here"sv, defVal); | ||
| 3005 | } | ||
| 3006 | auto exp = static_cast<Exp_t*>(pair); | ||
| 3007 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
| 3008 | chain->items.push_back(indexItem); | ||
| 3009 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
| 3010 | break; | ||
| 3011 | } | ||
| 2813 | auto value = singleValueFrom(pair); | 3012 | auto value = singleValueFrom(pair); |
| 2814 | auto item = value->item.get(); | 3013 | auto item = value->item.get(); |
| 2815 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 3014 | ast_node* subExp = ast_cast<SimpleTable_t>(item); |
| @@ -2820,7 +3019,6 @@ private: | |||
| 2820 | throw CompileError("default value is not supported here"sv, defVal); | 3019 | throw CompileError("default value is not supported here"sv, defVal); |
| 2821 | } | 3020 | } |
| 2822 | } | 3021 | } |
| 2823 | auto indexItem = toAst<Exp_t>(std::to_string(index), value); | ||
| 2824 | for (auto& p : subPairs) { | 3022 | for (auto& p : subPairs) { |
| 2825 | if (sep) p.structure->items.push_front(sep); | 3023 | if (sep) p.structure->items.push_front(sep); |
| 2826 | p.structure->items.push_front(indexItem); | 3024 | p.structure->items.push_front(indexItem); |
| @@ -2831,7 +3029,6 @@ private: | |||
| 2831 | auto varName = singleVariableFrom(exp, AccessType::None); | 3029 | auto varName = singleVariableFrom(exp, AccessType::None); |
| 2832 | if (varName == "_"sv) break; | 3030 | if (varName == "_"sv) break; |
| 2833 | auto chain = exp->new_ptr<ChainValue_t>(); | 3031 | auto chain = exp->new_ptr<ChainValue_t>(); |
| 2834 | auto indexItem = toAst<Exp_t>(std::to_string(index), exp); | ||
| 2835 | chain->items.push_back(indexItem); | 3032 | chain->items.push_back(indexItem); |
| 2836 | pairs.push_back({exp, | 3033 | pairs.push_back({exp, |
| 2837 | varName, | 3034 | varName, |
| @@ -2889,7 +3086,25 @@ private: | |||
| 2889 | } | 3086 | } |
| 2890 | } | 3087 | } |
| 2891 | if (auto exp = np->value.as<Exp_t>()) { | 3088 | if (auto exp = np->value.as<Exp_t>()) { |
| 2892 | if (!varDefOnly && !isAssignable(exp)) throw CompileError("can't do destructure value"sv, exp); | 3089 | bool assignable = false; |
| 3090 | try { | ||
| 3091 | assignable = isAssignable(exp); | ||
| 3092 | } catch (const CompileError& e) { | ||
| 3093 | if (!varDefOnly) throw e; | ||
| 3094 | } | ||
| 3095 | if (!assignable && !varDefOnly) { | ||
| 3096 | if (optional) break; | ||
| 3097 | throw CompileError("can't destructure value"sv, pair); | ||
| 3098 | } | ||
| 3099 | if (optional && varDefOnly && !assignable) { | ||
| 3100 | if (defVal) { | ||
| 3101 | throw CompileError("default value is not supported here"sv, defVal); | ||
| 3102 | } | ||
| 3103 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
| 3104 | if (keyIndex) chain->items.push_back(keyIndex); | ||
| 3105 | pairs.push_back({exp, Empty, chain, nullptr}); | ||
| 3106 | break; | ||
| 3107 | } | ||
| 2893 | auto item = singleValueFrom(exp)->item.get(); | 3108 | auto item = singleValueFrom(exp)->item.get(); |
| 2894 | ast_node* subExp = ast_cast<SimpleTable_t>(item); | 3109 | ast_node* subExp = ast_cast<SimpleTable_t>(item); |
| 2895 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { | 3110 | if (subExp || (subExp = item->get_by_path<TableLit_t>()) || (subExp = item->get_by_path<Comprehension_t>())) { |
| @@ -2938,7 +3153,13 @@ private: | |||
| 2938 | auto tb = static_cast<TableBlockIndent_t*>(pair); | 3153 | auto tb = static_cast<TableBlockIndent_t*>(pair); |
| 2939 | ++index; | 3154 | ++index; |
| 2940 | auto subPairs = destructFromExp(tb, varDefOnly, optional); | 3155 | auto subPairs = destructFromExp(tb, varDefOnly, optional); |
| 2941 | auto indexItem = toAst<Exp_t>(std::to_string(index), tb); | 3156 | ast_ptr<true, ast_node> indexItem; |
| 3157 | if (hasSpread) { | ||
| 3158 | int rIndex = count - index; | ||
| 3159 | indexItem.set(toAst<ReversedIndex_t>('#' + (rIndex == 0 ? Empty : "-"s + std::to_string(rIndex)), tb)); | ||
| 3160 | } else { | ||
| 3161 | indexItem.set(toAst<Exp_t>(std::to_string(index), tb)); | ||
| 3162 | } | ||
| 2942 | for (auto& p : subPairs) { | 3163 | for (auto& p : subPairs) { |
| 2943 | if (sep) p.structure->items.push_front(sep); | 3164 | if (sep) p.structure->items.push_front(sep); |
| 2944 | p.structure->items.push_front(indexItem); | 3165 | p.structure->items.push_front(indexItem); |
| @@ -2995,6 +3216,42 @@ private: | |||
| 2995 | subMetaDestruct->values.push_back(newPairDef); | 3216 | subMetaDestruct->values.push_back(newPairDef); |
| 2996 | break; | 3217 | break; |
| 2997 | } | 3218 | } |
| 3219 | case id<SpreadListExp_t>(): | ||
| 3220 | case id<SpreadExp_t>(): { | ||
| 3221 | ++index; | ||
| 3222 | if (hasSpread) { | ||
| 3223 | throw CompileError("duplicated spread expression"sv, pair); | ||
| 3224 | } | ||
| 3225 | hasSpread = true; | ||
| 3226 | for (auto item : *tableItems) { | ||
| 3227 | if (ast_is< | ||
| 3228 | SpreadListExp_t, SpreadExp_t, | ||
| 3229 | TableBlockIndent_t, | ||
| 3230 | Exp_t, NormalDef_t>(item)) { | ||
| 3231 | count++; | ||
| 3232 | } | ||
| 3233 | } | ||
| 3234 | Exp_t* exp = nullptr; | ||
| 3235 | if (auto se = ast_cast<SpreadExp_t>(pair)) { | ||
| 3236 | exp = se->exp.get(); | ||
| 3237 | } else { | ||
| 3238 | exp = ast_to<SpreadListExp_t>(pair)->exp.get(); | ||
| 3239 | } | ||
| 3240 | auto varName = singleVariableFrom(exp, AccessType::None); | ||
| 3241 | if (varName == "_"sv) break; | ||
| 3242 | int start = index; | ||
| 3243 | int stop = index - count - 1; | ||
| 3244 | auto chain = exp->new_ptr<ChainValue_t>(); | ||
| 3245 | auto slice = toAst<Slice_t>( | ||
| 3246 | '[' + (start == 1 ? Empty : std::to_string(start)) + ',' + (stop == -1 ? Empty : std::to_string(stop)) + ']', exp); | ||
| 3247 | chain->items.push_back(slice); | ||
| 3248 | auto nil = toAst<Exp_t>("nil"sv, slice); | ||
| 3249 | pairs.push_back({exp, | ||
| 3250 | varName, | ||
| 3251 | chain, | ||
| 3252 | nil.get()}); | ||
| 3253 | break; | ||
| 3254 | } | ||
| 2998 | default: YUEE("AST node mismatch", pair); break; | 3255 | default: YUEE("AST node mismatch", pair); break; |
| 2999 | } | 3256 | } |
| 3000 | } | 3257 | } |
| @@ -3072,7 +3329,7 @@ private: | |||
| 3072 | if (auto tab = sVal->value.as<TableLit_t>()) { | 3329 | if (auto tab = sVal->value.as<TableLit_t>()) { |
| 3073 | destructNode = tab; | 3330 | destructNode = tab; |
| 3074 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { | 3331 | } else if (auto comp = sVal->value.as<Comprehension_t>()) { |
| 3075 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 3332 | if (!isListComp(comp)) { |
| 3076 | destructNode = comp; | 3333 | destructNode = comp; |
| 3077 | } | 3334 | } |
| 3078 | } | 3335 | } |
| @@ -3111,7 +3368,11 @@ private: | |||
| 3111 | break; | 3368 | break; |
| 3112 | default: YUEE("AST node mismatch", destructNode); break; | 3369 | default: YUEE("AST node mismatch", destructNode); break; |
| 3113 | } | 3370 | } |
| 3114 | if (dlist->empty()) throw CompileError("expect items to be destructured"sv, destructNode); | 3371 | if (dlist->empty()) { |
| 3372 | if (!optional) { | ||
| 3373 | throw CompileError("expect items to be destructured"sv, destructNode); | ||
| 3374 | } | ||
| 3375 | } | ||
| 3115 | for (auto item : *dlist) { | 3376 | for (auto item : *dlist) { |
| 3116 | switch (item->get_id()) { | 3377 | switch (item->get_id()) { |
| 3117 | case id<MetaVariablePairDef_t>(): { | 3378 | case id<MetaVariablePairDef_t>(): { |
| @@ -3247,7 +3508,9 @@ private: | |||
| 3247 | simpleValue->value.set(tab); | 3508 | simpleValue->value.set(tab); |
| 3248 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); | 3509 | auto pairs = destructFromExp(newExp(simpleValue, expr), varDefOnly, optional); |
| 3249 | if (pairs.empty()) { | 3510 | if (pairs.empty()) { |
| 3250 | throw CompileError("expect items to be destructured"sv, tab); | 3511 | if (!optional) { |
| 3512 | throw CompileError("expect items to be destructured"sv, tab); | ||
| 3513 | } | ||
| 3251 | } | 3514 | } |
| 3252 | destruct.items = std::move(pairs); | 3515 | destruct.items = std::move(pairs); |
| 3253 | if (!varDefOnly) { | 3516 | if (!varDefOnly) { |
| @@ -3286,7 +3549,7 @@ private: | |||
| 3286 | destruct.valueVar.clear(); | 3549 | destruct.valueVar.clear(); |
| 3287 | } | 3550 | } |
| 3288 | } | 3551 | } |
| 3289 | destructs.push_back(destruct); | 3552 | destructs.push_back(std::move(destruct)); |
| 3290 | } | 3553 | } |
| 3291 | } | 3554 | } |
| 3292 | } else { | 3555 | } else { |
| @@ -3453,7 +3716,7 @@ private: | |||
| 3453 | _buf << defs; | 3716 | _buf << defs; |
| 3454 | else | 3717 | else |
| 3455 | _buf << indent() << left; | 3718 | _buf << indent() << left; |
| 3456 | _buf << " = "sv << left << ' ' << op << ' ' << right << nll(assignment); | 3719 | _buf << " = "sv << left << ' ' << op << ' ' << right << nl(assignment); |
| 3457 | out.push_back(clearBuf()); | 3720 | out.push_back(clearBuf()); |
| 3458 | break; | 3721 | break; |
| 3459 | } | 3722 | } |
| @@ -3463,7 +3726,7 @@ private: | |||
| 3463 | bool oneLined = defs.size() == expList->exprs.objects().size(); | 3726 | bool oneLined = defs.size() == expList->exprs.objects().size(); |
| 3464 | bool nonRecursionFunLit = false; | 3727 | bool nonRecursionFunLit = false; |
| 3465 | for (auto val : assign->values.objects()) { | 3728 | for (auto val : assign->values.objects()) { |
| 3466 | if (auto value = singleValueFrom(val)) { | 3729 | if (auto value = singleValueFrom(val, true)) { |
| 3467 | if (auto spValue = value->item.as<SimpleValue_t>()) { | 3730 | if (auto spValue = value->item.as<SimpleValue_t>()) { |
| 3468 | if (auto funLit = spValue->value.as<FunLit_t>()) { | 3731 | if (auto funLit = spValue->value.as<FunLit_t>()) { |
| 3469 | if (funLit->noRecursion) { | 3732 | if (funLit->noRecursion) { |
| @@ -3500,9 +3763,9 @@ private: | |||
| 3500 | transformExpList(expList, temp); | 3763 | transformExpList(expList, temp); |
| 3501 | std::string left = std::move(temp.back()); | 3764 | std::string left = std::move(temp.back()); |
| 3502 | temp.pop_back(); | 3765 | temp.pop_back(); |
| 3503 | out.push_back(indent() + left + " = "s + join(temp, ", "sv) + nll(assignment)); | 3766 | out.push_back(indent() + left + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3504 | } else { | 3767 | } else { |
| 3505 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nll(assignment)); | 3768 | out.push_back(preDefine + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3506 | } | 3769 | } |
| 3507 | } else { | 3770 | } else { |
| 3508 | std::string preDefine = toLocalDecl(defs); | 3771 | std::string preDefine = toLocalDecl(defs); |
| @@ -3518,7 +3781,7 @@ private: | |||
| 3518 | for (auto value : assign->values.objects()) { | 3781 | for (auto value : assign->values.objects()) { |
| 3519 | transformAssignItem(value, temp); | 3782 | transformAssignItem(value, temp); |
| 3520 | } | 3783 | } |
| 3521 | out.push_back((preDefine.empty() ? Empty : preDefine + nll(assignment)) + indent() + left + " = "s + join(temp, ", "sv) + nll(assignment)); | 3784 | out.push_back((preDefine.empty() ? Empty : preDefine + nl(assignment)) + indent() + left + " = "s + join(temp, ", "sv) + nl(assignment)); |
| 3522 | } | 3785 | } |
| 3523 | break; | 3786 | break; |
| 3524 | } | 3787 | } |
| @@ -3619,7 +3882,7 @@ private: | |||
| 3619 | if (usage != ExpUsage::Closure) { | 3882 | if (usage != ExpUsage::Closure) { |
| 3620 | if (!currentScope().lastStatement) { | 3883 | if (!currentScope().lastStatement) { |
| 3621 | extraScope = true; | 3884 | extraScope = true; |
| 3622 | temp.push_back(indent() + "do"s + nll(asmt)); | 3885 | temp.push_back(indent() + "do"s + nl(asmt)); |
| 3623 | pushScope(); | 3886 | pushScope(); |
| 3624 | } | 3887 | } |
| 3625 | } | 3888 | } |
| @@ -3652,7 +3915,7 @@ private: | |||
| 3652 | if (usage != ExpUsage::Closure) { | 3915 | if (usage != ExpUsage::Closure) { |
| 3653 | if (!currentScope().lastStatement) { | 3916 | if (!currentScope().lastStatement) { |
| 3654 | extraScope = true; | 3917 | extraScope = true; |
| 3655 | temp.push_back(indent() + "do"s + nll(asmt)); | 3918 | temp.push_back(indent() + "do"s + nl(asmt)); |
| 3656 | pushScope(); | 3919 | pushScope(); |
| 3657 | } | 3920 | } |
| 3658 | } | 3921 | } |
| @@ -3681,12 +3944,12 @@ private: | |||
| 3681 | if (pair != ifCondPairs.front()) { | 3944 | if (pair != ifCondPairs.front()) { |
| 3682 | _buf << "else"sv; | 3945 | _buf << "else"sv; |
| 3683 | } | 3946 | } |
| 3684 | _buf << "if "sv << condStr << " then"sv << nll(condition); | 3947 | _buf << "if "sv << condStr << " then"sv << nl(condition); |
| 3685 | temp.push_back(clearBuf()); | 3948 | temp.push_back(clearBuf()); |
| 3686 | } | 3949 | } |
| 3687 | if (pair.second) { | 3950 | if (pair.second) { |
| 3688 | if (!pair.first) { | 3951 | if (!pair.first) { |
| 3689 | temp.push_back(indent() + "else"s + nll(pair.second)); | 3952 | temp.push_back(indent() + "else"s + nl(pair.second)); |
| 3690 | } | 3953 | } |
| 3691 | pushScope(); | 3954 | pushScope(); |
| 3692 | if (pair == ifCondPairs.front() && extraAssignment) { | 3955 | if (pair == ifCondPairs.front() && extraAssignment) { |
| @@ -3696,17 +3959,17 @@ private: | |||
| 3696 | popScope(); | 3959 | popScope(); |
| 3697 | } | 3960 | } |
| 3698 | if (!pair.first) { | 3961 | if (!pair.first) { |
| 3699 | temp.push_back(indent() + "end"s + nll(nodes.front())); | 3962 | temp.push_back(indent() + "end"s + nl(nodes.front())); |
| 3700 | break; | 3963 | break; |
| 3701 | } | 3964 | } |
| 3702 | } | 3965 | } |
| 3703 | if (extraScope) { | 3966 | if (extraScope) { |
| 3704 | popScope(); | 3967 | popScope(); |
| 3705 | temp.push_back(indent() + "end"s + nlr(nodes.front())); | 3968 | temp.push_back(indent() + "end"s + nl(nodes.front())); |
| 3706 | } | 3969 | } |
| 3707 | if (usage == ExpUsage::Closure) { | 3970 | if (usage == ExpUsage::Closure) { |
| 3708 | popScope(); | 3971 | popScope(); |
| 3709 | *funcStart = anonFuncStart() + nll(nodes.front()); | 3972 | *funcStart = anonFuncStart() + nl(nodes.front()); |
| 3710 | temp.push_back(indent() + anonFuncEnd()); | 3973 | temp.push_back(indent() + anonFuncEnd()); |
| 3711 | popAnonVarArg(); | 3974 | popAnonVarArg(); |
| 3712 | popFunctionScope(); | 3975 | popFunctionScope(); |
| @@ -3727,14 +3990,6 @@ private: | |||
| 3727 | out.push_back(join(temp, ", "sv)); | 3990 | out.push_back(join(temp, ", "sv)); |
| 3728 | } | 3991 | } |
| 3729 | 3992 | ||
| 3730 | void transformExpListLow(ExpListLow_t* expListLow, str_list& out) { | ||
| 3731 | str_list temp; | ||
| 3732 | for (auto exp : expListLow->exprs.objects()) { | ||
| 3733 | transformExp(static_cast<Exp_t*>(exp), temp, ExpUsage::Closure); | ||
| 3734 | } | ||
| 3735 | out.push_back(join(temp, ", "sv)); | ||
| 3736 | } | ||
| 3737 | |||
| 3738 | void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 3993 | void transform_pipe_exp(const node_container& values, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 3739 | if (values.size() == 1 && usage == ExpUsage::Closure) { | 3994 | if (values.size() == 1 && usage == ExpUsage::Closure) { |
| 3740 | transformUnaryExp(static_cast<UnaryExp_t*>(values.front()), out, ExpUsage::Closure); | 3995 | transformUnaryExp(static_cast<UnaryExp_t*>(values.front()), out, ExpUsage::Closure); |
| @@ -3801,16 +4056,12 @@ private: | |||
| 3801 | } else { | 4056 | } else { |
| 3802 | transformExp(arg, out, ExpUsage::Closure); | 4057 | transformExp(arg, out, ExpUsage::Closure); |
| 3803 | out.back().insert(0, indent()); | 4058 | out.back().insert(0, indent()); |
| 3804 | out.back().append(nlr(x)); | 4059 | out.back().append(nl(x)); |
| 3805 | } | 4060 | } |
| 3806 | return; | 4061 | return; |
| 3807 | } | 4062 | } |
| 3808 | case ExpUsage::Return: { | 4063 | case ExpUsage::Return: { |
| 3809 | auto ret = x->new_ptr<Return_t>(); | 4064 | auto ret = newReturn(arg); |
| 3810 | ret->explicitReturn = false; | ||
| 3811 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
| 3812 | expListLow->exprs.push_back(arg); | ||
| 3813 | ret->valueList.set(expListLow); | ||
| 3814 | transformReturn(ret, out); | 4065 | transformReturn(ret, out); |
| 3815 | return; | 4066 | return; |
| 3816 | } | 4067 | } |
| @@ -3925,7 +4176,7 @@ private: | |||
| 3925 | auto stmt = exp->new_ptr<Statement_t>(); | 4176 | auto stmt = exp->new_ptr<Statement_t>(); |
| 3926 | stmt->content.set(preDefine); | 4177 | stmt->content.set(preDefine); |
| 3927 | preDefine.set(nullptr); | 4178 | preDefine.set(nullptr); |
| 3928 | block->statements.push_back(stmt); | 4179 | block->statementOrComments.push_back(stmt); |
| 3929 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | 4180 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); |
| 3930 | simpleValue->value.set(ifNode); | 4181 | simpleValue->value.set(ifNode); |
| 3931 | auto explist = exp->new_ptr<ExpList_t>(); | 4182 | auto explist = exp->new_ptr<ExpList_t>(); |
| @@ -3934,7 +4185,7 @@ private: | |||
| 3934 | expListAssign->expList.set(explist); | 4185 | expListAssign->expList.set(explist); |
| 3935 | stmt = exp->new_ptr<Statement_t>(); | 4186 | stmt = exp->new_ptr<Statement_t>(); |
| 3936 | stmt->content.set(expListAssign); | 4187 | stmt->content.set(expListAssign); |
| 3937 | block->statements.push_back(stmt); | 4188 | block->statementOrComments.push_back(stmt); |
| 3938 | nodes->push_back(block); | 4189 | nodes->push_back(block); |
| 3939 | nodes = &ifNode->nodes; | 4190 | nodes = &ifNode->nodes; |
| 3940 | } else { | 4191 | } else { |
| @@ -3942,7 +4193,7 @@ private: | |||
| 3942 | auto stmt = exp->new_ptr<Statement_t>(); | 4193 | auto stmt = exp->new_ptr<Statement_t>(); |
| 3943 | stmt->content.set(preDefine); | 4194 | stmt->content.set(preDefine); |
| 3944 | preDefine.set(nullptr); | 4195 | preDefine.set(nullptr); |
| 3945 | block->statements.push_back(stmt); | 4196 | block->statementOrComments.push_back(stmt); |
| 3946 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); | 4197 | auto simpleValue = exp->new_ptr<SimpleValue_t>(); |
| 3947 | simpleValue->value.set(ifNode); | 4198 | simpleValue->value.set(ifNode); |
| 3948 | auto explist = exp->new_ptr<ExpList_t>(); | 4199 | auto explist = exp->new_ptr<ExpList_t>(); |
| @@ -3951,7 +4202,7 @@ private: | |||
| 3951 | expListAssign->expList.set(explist); | 4202 | expListAssign->expList.set(explist); |
| 3952 | stmt = exp->new_ptr<Statement_t>(); | 4203 | stmt = exp->new_ptr<Statement_t>(); |
| 3953 | stmt->content.set(expListAssign); | 4204 | stmt->content.set(expListAssign); |
| 3954 | block->statements.push_back(stmt); | 4205 | block->statementOrComments.push_back(stmt); |
| 3955 | auto body = exp->new_ptr<Body_t>(); | 4206 | auto body = exp->new_ptr<Body_t>(); |
| 3956 | body->content.set(block); | 4207 | body->content.set(block); |
| 3957 | auto doNode = exp->new_ptr<Do_t>(); | 4208 | auto doNode = exp->new_ptr<Do_t>(); |
| @@ -4035,11 +4286,7 @@ private: | |||
| 4035 | break; | 4286 | break; |
| 4036 | } | 4287 | } |
| 4037 | case ExpUsage::Return: { | 4288 | case ExpUsage::Return: { |
| 4038 | auto expListLow = exp->new_ptr<ExpListLow_t>(); | 4289 | auto returnNode = newReturn(e); |
| 4039 | expListLow->exprs.push_back(e); | ||
| 4040 | auto returnNode = exp->new_ptr<Return_t>(); | ||
| 4041 | returnNode->explicitReturn = false; | ||
| 4042 | returnNode->valueList.set(expListLow); | ||
| 4043 | transformReturn(returnNode, out); | 4290 | transformReturn(returnNode, out); |
| 4044 | break; | 4291 | break; |
| 4045 | } | 4292 | } |
| @@ -4113,7 +4360,7 @@ private: | |||
| 4113 | auto stmt = x->new_ptr<Statement_t>(); | 4360 | auto stmt = x->new_ptr<Statement_t>(); |
| 4114 | stmt->content.set(expListAssign); | 4361 | stmt->content.set(expListAssign); |
| 4115 | auto blk = x->new_ptr<Block_t>(); | 4362 | auto blk = x->new_ptr<Block_t>(); |
| 4116 | blk->statements.push_back(stmt); | 4363 | blk->statementOrComments.push_back(stmt); |
| 4117 | newBlock.set(blk); | 4364 | newBlock.set(blk); |
| 4118 | } | 4365 | } |
| 4119 | if (!globals.empty()) { | 4366 | if (!globals.empty()) { |
| @@ -4205,15 +4452,21 @@ private: | |||
| 4205 | 4452 | ||
| 4206 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { | 4453 | std::optional<std::pair<std::string, str_list>> upValueFuncFromExp(Exp_t* exp, str_list* ensureArgListInTheEnd, bool blockRewrite) { |
| 4207 | if (checkUpValueFuncAvailable(exp)) { | 4454 | if (checkUpValueFuncAvailable(exp)) { |
| 4208 | auto returnNode = exp->new_ptr<Return_t>(); | ||
| 4209 | returnNode->explicitReturn = false; | ||
| 4210 | auto returnList = exp->new_ptr<ExpListLow_t>(); | ||
| 4211 | returnList->exprs.push_back(exp); | ||
| 4212 | returnNode->valueList.set(returnList); | ||
| 4213 | auto block = exp->new_ptr<Block_t>(); | 4455 | auto block = exp->new_ptr<Block_t>(); |
| 4456 | if (auto sVal = simpleSingleValueFrom(exp)) { | ||
| 4457 | if (auto doNode = sVal->value.as<Do_t>()) { | ||
| 4458 | if (auto blk = doNode->body->content.as<Block_t>()) { | ||
| 4459 | block->statementOrComments.dup(blk->statementOrComments); | ||
| 4460 | } else { | ||
| 4461 | block->statementOrComments.push_back(doNode->body->content.to<Statement_t>()); | ||
| 4462 | } | ||
| 4463 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | ||
| 4464 | } | ||
| 4465 | } | ||
| 4466 | auto returnNode = newReturn(exp); | ||
| 4214 | auto stmt = exp->new_ptr<Statement_t>(); | 4467 | auto stmt = exp->new_ptr<Statement_t>(); |
| 4215 | stmt->content.set(returnNode); | 4468 | stmt->content.set(returnNode); |
| 4216 | block->statements.push_back(stmt); | 4469 | block->statementOrComments.push_back(stmt); |
| 4217 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); | 4470 | return getUpValueFuncFromBlock(block, ensureArgListInTheEnd, false, blockRewrite); |
| 4218 | } | 4471 | } |
| 4219 | return std::nullopt; | 4472 | return std::nullopt; |
| @@ -4270,7 +4523,7 @@ private: | |||
| 4270 | bool extraScope = !currentScope().lastStatement; | 4523 | bool extraScope = !currentScope().lastStatement; |
| 4271 | if (forAssignment) { | 4524 | if (forAssignment) { |
| 4272 | if (extraScope) { | 4525 | if (extraScope) { |
| 4273 | temp.push_back(indent() + "do"s + nll(x)); | 4526 | temp.push_back(indent() + "do"s + nl(x)); |
| 4274 | pushScope(); | 4527 | pushScope(); |
| 4275 | } | 4528 | } |
| 4276 | } | 4529 | } |
| @@ -4287,26 +4540,24 @@ private: | |||
| 4287 | return false; | 4540 | return false; |
| 4288 | }; | 4541 | }; |
| 4289 | switch (usage) { | 4542 | switch (usage) { |
| 4290 | case ExpUsage::Common: YUEE("AST node mismatch", x); return; | 4543 | case ExpUsage::Common: |
| 4544 | YUEE("AST node mismatch", x); | ||
| 4545 | return; | ||
| 4291 | case ExpUsage::Return: | 4546 | case ExpUsage::Return: |
| 4292 | case ExpUsage::Closure: { | 4547 | case ExpUsage::Closure: { |
| 4293 | prepareValue(); | 4548 | prepareValue(); |
| 4294 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 4549 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 4295 | _buf << indent(1) << "return "s << objVar << nll(x); | 4550 | _buf << indent(1) << "return "s << objVar << nl(x); |
| 4296 | _buf << indent() << "else"s << nll(x); | 4551 | _buf << indent() << "else"s << nl(x); |
| 4297 | temp.push_back(clearBuf()); | 4552 | temp.push_back(clearBuf()); |
| 4298 | auto ret = x->new_ptr<Return_t>(); | ||
| 4299 | ret->explicitReturn = false; | ||
| 4300 | auto retList = x->new_ptr<ExpListLow_t>(); | ||
| 4301 | retList->exprs.push_back(exp->nilCoalesed); | ||
| 4302 | ret->valueList.set(retList); | ||
| 4303 | incIndentOffset(); | 4553 | incIndentOffset(); |
| 4554 | auto ret = newReturn(exp->nilCoalesed); | ||
| 4304 | transformReturn(ret, temp); | 4555 | transformReturn(ret, temp); |
| 4305 | decIndentOffset(); | 4556 | decIndentOffset(); |
| 4306 | temp.push_back(indent() + "end"s + nll(x)); | 4557 | temp.push_back(indent() + "end"s + nl(x)); |
| 4307 | if (usage == ExpUsage::Closure) { | 4558 | if (usage == ExpUsage::Closure) { |
| 4308 | popScope(); | 4559 | popScope(); |
| 4309 | *funcStart = anonFuncStart() + nll(x); | 4560 | *funcStart = anonFuncStart() + nl(x); |
| 4310 | temp.push_back(indent() + anonFuncEnd()); | 4561 | temp.push_back(indent() + anonFuncEnd()); |
| 4311 | popAnonVarArg(); | 4562 | popAnonVarArg(); |
| 4312 | popFunctionScope(); | 4563 | popFunctionScope(); |
| @@ -4323,14 +4574,14 @@ private: | |||
| 4323 | assign->values.push_back(exp); | 4574 | assign->values.push_back(exp); |
| 4324 | temp.push_back(getPreDefineLine(assignment)); | 4575 | temp.push_back(getPreDefineLine(assignment)); |
| 4325 | extraScope = prepareValue(true); | 4576 | extraScope = prepareValue(true); |
| 4326 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 4577 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 4327 | temp.push_back(clearBuf()); | 4578 | temp.push_back(clearBuf()); |
| 4328 | pushScope(); | 4579 | pushScope(); |
| 4329 | assign->values.clear(); | 4580 | assign->values.clear(); |
| 4330 | assign->values.push_back(toAst<Exp_t>(objVar, x)); | 4581 | assign->values.push_back(toAst<Exp_t>(objVar, x)); |
| 4331 | transformAssignment(assignment, temp); | 4582 | transformAssignment(assignment, temp); |
| 4332 | popScope(); | 4583 | popScope(); |
| 4333 | temp.push_back(indent() + "else"s + nll(x)); | 4584 | temp.push_back(indent() + "else"s + nl(x)); |
| 4334 | assign->values.clear(); | 4585 | assign->values.clear(); |
| 4335 | assign->values.push_back(exp->nilCoalesed); | 4586 | assign->values.push_back(exp->nilCoalesed); |
| 4336 | } else { | 4587 | } else { |
| @@ -4338,17 +4589,17 @@ private: | |||
| 4338 | assign->values.push_back(exp->nilCoalesed); | 4589 | assign->values.push_back(exp->nilCoalesed); |
| 4339 | temp.push_back(getPreDefineLine(assignment)); | 4590 | temp.push_back(getPreDefineLine(assignment)); |
| 4340 | transformExp(left, temp, ExpUsage::Closure); | 4591 | transformExp(left, temp, ExpUsage::Closure); |
| 4341 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nll(x); | 4592 | _buf << indent() << "if "sv << temp.back() << " == nil then"sv << nl(x); |
| 4342 | temp.pop_back(); | 4593 | temp.pop_back(); |
| 4343 | temp.push_back(clearBuf()); | 4594 | temp.push_back(clearBuf()); |
| 4344 | } | 4595 | } |
| 4345 | pushScope(); | 4596 | pushScope(); |
| 4346 | transformAssignment(assignment, temp); | 4597 | transformAssignment(assignment, temp); |
| 4347 | popScope(); | 4598 | popScope(); |
| 4348 | temp.push_back(indent() + "end"s + nlr(x)); | 4599 | temp.push_back(indent() + "end"s + nl(x)); |
| 4349 | if (extraScope) { | 4600 | if (extraScope) { |
| 4350 | popScope(); | 4601 | popScope(); |
| 4351 | temp.push_back(indent() + "end"s + nlr(x)); | 4602 | temp.push_back(indent() + "end"s + nl(x)); |
| 4352 | } | 4603 | } |
| 4353 | break; | 4604 | break; |
| 4354 | } | 4605 | } |
| @@ -4372,13 +4623,17 @@ private: | |||
| 4372 | switch (item->get_id()) { | 4623 | switch (item->get_id()) { |
| 4373 | case id<Variable_t>(): { | 4624 | case id<Variable_t>(): { |
| 4374 | transformVariable(static_cast<Variable_t*>(item), out); | 4625 | transformVariable(static_cast<Variable_t*>(item), out); |
| 4375 | if (_config.lintGlobalVariable && accessType != AccessType::None && !isLocal(out.back())) { | 4626 | if (accessType != AccessType::None) { |
| 4376 | auto key = out.back() + ':' + std::to_string(item->m_begin.m_line) + ':' + std::to_string(item->m_begin.m_col); | 4627 | if (_importedGlobal) { |
| 4377 | if (_globals.find(key) == _globals.end()) { | 4628 | markGlobalImported(out.back()); |
| 4378 | if (accessType == AccessType::Read && _funcLevel > 1) { | 4629 | } else if (_config.lintGlobalVariable && !isLocal(out.back())) { |
| 4379 | accessType = AccessType::Capture; | 4630 | auto key = out.back() + ':' + std::to_string(item->m_begin.m_line) + ':' + std::to_string(item->m_begin.m_col); |
| 4631 | if (_globals.find(key) == _globals.end()) { | ||
| 4632 | if (accessType == AccessType::Read && _funcLevel > 1) { | ||
| 4633 | accessType = AccessType::Capture; | ||
| 4634 | } | ||
| 4635 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType, isSolidDefined(out.back())}; | ||
| 4380 | } | 4636 | } |
| 4381 | _globals[key] = {out.back(), item->m_begin.m_line, item->m_begin.m_col, accessType}; | ||
| 4382 | } | 4637 | } |
| 4383 | } | 4638 | } |
| 4384 | break; | 4639 | break; |
| @@ -4410,6 +4665,7 @@ private: | |||
| 4410 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; | 4665 | case id<ForEach_t>(): transformForEachClosure(static_cast<ForEach_t*>(value), out); break; |
| 4411 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; | 4666 | case id<For_t>(): transformForClosure(static_cast<For_t*>(value), out); break; |
| 4412 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; | 4667 | case id<While_t>(): transformWhileClosure(static_cast<While_t*>(value), out); break; |
| 4668 | case id<Repeat_t>(): transformRepeatClosure(static_cast<Repeat_t*>(value), out); break; | ||
| 4413 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; | 4669 | case id<Do_t>(): transformDo(static_cast<Do_t*>(value), out, ExpUsage::Closure); break; |
| 4414 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; | 4670 | case id<Try_t>(): transformTry(static_cast<Try_t*>(value), out, ExpUsage::Closure); break; |
| 4415 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; | 4671 | case id<UnaryValue_t>(): transformUnaryValue(static_cast<UnaryValue_t*>(value), out); break; |
| @@ -4446,23 +4702,21 @@ private: | |||
| 4446 | switch (content->get_id()) { | 4702 | switch (content->get_id()) { |
| 4447 | case id<Block_t>(): { | 4703 | case id<Block_t>(): { |
| 4448 | auto block = static_cast<Block_t*>(content); | 4704 | auto block = static_cast<Block_t*>(content); |
| 4449 | newBlock->statements.dup(block->statements); | 4705 | newBlock->statementOrComments.dup(block->statementOrComments); |
| 4450 | break; | 4706 | break; |
| 4451 | } | 4707 | } |
| 4452 | case id<Statement_t>(): { | 4708 | case id<Statement_t>(): { |
| 4453 | newBlock->statements.push_back(content); | 4709 | newBlock->statementOrComments.push_back(content); |
| 4454 | break; | 4710 | break; |
| 4455 | } | 4711 | } |
| 4456 | default: YUEE("AST node mismatch", content); break; | 4712 | default: YUEE("AST node mismatch", content); break; |
| 4457 | } | 4713 | } |
| 4458 | } | 4714 | } |
| 4459 | if (funLit->defaultReturn.is<ExpListLow_t>()) { | 4715 | if (auto defaultReturn = funLit->defaultReturn.as<ExpList_t>()) { |
| 4460 | auto returnNode = newBlock->new_ptr<Return_t>(); | 4716 | auto returnNode = newReturn(defaultReturn); |
| 4461 | returnNode->explicitReturn = false; | ||
| 4462 | returnNode->valueList.set(funLit->defaultReturn); | ||
| 4463 | auto stmt = newBlock->new_ptr<Statement_t>(); | 4717 | auto stmt = newBlock->new_ptr<Statement_t>(); |
| 4464 | stmt->content.set(returnNode); | 4718 | stmt->content.set(returnNode); |
| 4465 | newBlock->statements.push_back(stmt); | 4719 | newBlock->statementOrComments.push_back(stmt); |
| 4466 | } | 4720 | } |
| 4467 | transformBlock(newBlock, temp, ExpUsage::Common); | 4721 | transformBlock(newBlock, temp, ExpUsage::Common); |
| 4468 | } else { | 4722 | } else { |
| @@ -4484,7 +4738,7 @@ private: | |||
| 4484 | } | 4738 | } |
| 4485 | _buf << args << ')'; | 4739 | _buf << args << ')'; |
| 4486 | if (!initArgs.empty() || !bodyCodes.empty()) { | 4740 | if (!initArgs.empty() || !bodyCodes.empty()) { |
| 4487 | _buf << nlr(argsDef) << initArgs << bodyCodes; | 4741 | _buf << nl(argsDef) << initArgs << bodyCodes; |
| 4488 | popScope(); | 4742 | popScope(); |
| 4489 | _buf << indent() << "end"sv; | 4743 | _buf << indent() << "end"sv; |
| 4490 | } else { | 4744 | } else { |
| @@ -4495,7 +4749,7 @@ private: | |||
| 4495 | auto& bodyCodes = temp.back(); | 4749 | auto& bodyCodes = temp.back(); |
| 4496 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; | 4750 | _buf << "function("sv << (isFatArrow ? "self"s : Empty) << ')'; |
| 4497 | if (!bodyCodes.empty()) { | 4751 | if (!bodyCodes.empty()) { |
| 4498 | _buf << nll(funLit) << bodyCodes; | 4752 | _buf << nl(funLit) << bodyCodes; |
| 4499 | popScope(); | 4753 | popScope(); |
| 4500 | _buf << indent() << "end"sv; | 4754 | _buf << indent() << "end"sv; |
| 4501 | } else { | 4755 | } else { |
| @@ -4512,7 +4766,7 @@ private: | |||
| 4512 | auto x = body; | 4766 | auto x = body; |
| 4513 | if (auto stmt = body->content.as<Statement_t>()) { | 4767 | if (auto stmt = body->content.as<Statement_t>()) { |
| 4514 | auto block = x->new_ptr<Block_t>(); | 4768 | auto block = x->new_ptr<Block_t>(); |
| 4515 | block->statements.push_back(stmt); | 4769 | block->statementOrComments.push_back(stmt); |
| 4516 | transformBlock(block, out, usage, assignList); | 4770 | transformBlock(block, out, usage, assignList); |
| 4517 | } else { | 4771 | } else { |
| 4518 | transformBlock(body->content.to<Block_t>(), out, usage, assignList); | 4772 | transformBlock(body->content.to<Block_t>(), out, usage, assignList); |
| @@ -4524,13 +4778,15 @@ private: | |||
| 4524 | out.push_back(Empty); | 4778 | out.push_back(Empty); |
| 4525 | return; | 4779 | return; |
| 4526 | } | 4780 | } |
| 4527 | const auto& nodes = block->statements.objects(); | 4781 | const auto& nodes = block->statementOrComments.objects(); |
| 4782 | auto lastStmt = lastStatementFrom(nodes); | ||
| 4528 | LocalMode mode = LocalMode::None; | 4783 | LocalMode mode = LocalMode::None; |
| 4529 | Local_t *any = nullptr, *capital = nullptr; | 4784 | Local_t *any = nullptr, *capital = nullptr; |
| 4530 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { | 4785 | for (auto it = nodes.begin(); it != nodes.end(); ++it) { |
| 4531 | auto node = *it; | 4786 | auto node = *it; |
| 4532 | auto stmt = static_cast<Statement_t*>(node); | 4787 | auto stmt = ast_cast<Statement_t>(node); |
| 4533 | if (!stmt->appendix && stmt->content.is<Return_t>() && stmt != nodes.back()) { | 4788 | if (!stmt) continue; |
| 4789 | if (!stmt->appendix && stmt->content.is<Return_t>() && stmt != lastStmt) { | ||
| 4534 | throw CompileError("'return' statement must be the last line in the block"sv, stmt->content); | 4790 | throw CompileError("'return' statement must be the last line in the block"sv, stmt->content); |
| 4535 | } else if (auto pipeBody = stmt->content.as<PipeBody_t>()) { | 4791 | } else if (auto pipeBody = stmt->content.as<PipeBody_t>()) { |
| 4536 | auto x = stmt; | 4792 | auto x = stmt; |
| @@ -4539,6 +4795,16 @@ private: | |||
| 4539 | BREAK_IF(it == nodes.begin()); | 4795 | BREAK_IF(it == nodes.begin()); |
| 4540 | auto last = it; | 4796 | auto last = it; |
| 4541 | --last; | 4797 | --last; |
| 4798 | bool found = true; | ||
| 4799 | while (!ast_is<Statement_t>(*last)) { | ||
| 4800 | if (last == nodes.begin()) { | ||
| 4801 | found = false; | ||
| 4802 | break; | ||
| 4803 | } else { | ||
| 4804 | --last; | ||
| 4805 | } | ||
| 4806 | } | ||
| 4807 | BREAK_IF(!found); | ||
| 4542 | auto lst = static_cast<Statement_t*>(*last); | 4808 | auto lst = static_cast<Statement_t*>(*last); |
| 4543 | if (lst->appendix) { | 4809 | if (lst->appendix) { |
| 4544 | throw CompileError("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()); | 4810 | throw CompileError("statement decorator must be placed at the end of pipe chain"sv, lst->appendix.get()); |
| @@ -4556,9 +4822,17 @@ private: | |||
| 4556 | stmt->content.set(nullptr); | 4822 | stmt->content.set(nullptr); |
| 4557 | auto next = it; | 4823 | auto next = it; |
| 4558 | ++next; | 4824 | ++next; |
| 4825 | Statement_t* nextStmt = nullptr; | ||
| 4826 | while (next != nodes.end()) { | ||
| 4827 | nextStmt = ast_cast<Statement_t>(*next); | ||
| 4828 | if (nextStmt) { | ||
| 4829 | break; | ||
| 4830 | } | ||
| 4831 | ++next; | ||
| 4832 | } | ||
| 4559 | BLOCK_START | 4833 | BLOCK_START |
| 4560 | BREAK_IF(next == nodes.end()); | 4834 | BREAK_IF(!nextStmt); |
| 4561 | BREAK_IF(!static_cast<Statement_t*>(*next)->content.as<PipeBody_t>()); | 4835 | BREAK_IF(!nextStmt->content.as<PipeBody_t>()); |
| 4562 | throw CompileError("indent mismatch in pipe chain"sv, *next); | 4836 | throw CompileError("indent mismatch in pipe chain"sv, *next); |
| 4563 | BLOCK_END | 4837 | BLOCK_END |
| 4564 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { | 4838 | } else if (auto backcall = stmt->content.as<Backcall_t>()) { |
| @@ -4566,7 +4840,7 @@ private: | |||
| 4566 | auto newBlock = x->new_ptr<Block_t>(); | 4840 | auto newBlock = x->new_ptr<Block_t>(); |
| 4567 | if (it != nodes.begin()) { | 4841 | if (it != nodes.begin()) { |
| 4568 | for (auto i = nodes.begin(); i != it; ++i) { | 4842 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4569 | newBlock->statements.push_back(*i); | 4843 | newBlock->statementOrComments.push_back(*i); |
| 4570 | } | 4844 | } |
| 4571 | } | 4845 | } |
| 4572 | x = backcall; | 4846 | x = backcall; |
| @@ -4577,7 +4851,7 @@ private: | |||
| 4577 | ++next; | 4851 | ++next; |
| 4578 | if (next != nodes.end()) { | 4852 | if (next != nodes.end()) { |
| 4579 | for (auto i = next; i != nodes.end(); ++i) { | 4853 | for (auto i = next; i != nodes.end(); ++i) { |
| 4580 | block->statements.push_back(*i); | 4854 | block->statementOrComments.push_back(*i); |
| 4581 | } | 4855 | } |
| 4582 | } | 4856 | } |
| 4583 | auto body = x->new_ptr<Body_t>(); | 4857 | auto body = x->new_ptr<Body_t>(); |
| @@ -4629,7 +4903,7 @@ private: | |||
| 4629 | expListAssign->expList.set(expList); | 4903 | expListAssign->expList.set(expList); |
| 4630 | newStmt->content.set(expListAssign); | 4904 | newStmt->content.set(expListAssign); |
| 4631 | newStmt->appendix.set(stmt->appendix); | 4905 | newStmt->appendix.set(stmt->appendix); |
| 4632 | newBlock->statements.push_back(newStmt); | 4906 | newBlock->statementOrComments.push_back(newStmt); |
| 4633 | } | 4907 | } |
| 4634 | transformBlock(newBlock, out, usage, assignList, isRoot); | 4908 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4635 | return; | 4909 | return; |
| @@ -4656,7 +4930,7 @@ private: | |||
| 4656 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); | 4930 | throw CompileError("while-loop line decorator is not supported here"sv, appendix->item.get()); |
| 4657 | break; | 4931 | break; |
| 4658 | } | 4932 | } |
| 4659 | case id<CompInner_t>(): { | 4933 | case id<CompFor_t>(): { |
| 4660 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); | 4934 | throw CompileError("for-loop line decorator is not supported here"sv, appendix->item.get()); |
| 4661 | break; | 4935 | break; |
| 4662 | } | 4936 | } |
| @@ -4685,7 +4959,7 @@ private: | |||
| 4685 | auto newBlock = x->new_ptr<Block_t>(); | 4959 | auto newBlock = x->new_ptr<Block_t>(); |
| 4686 | if (it != nodes.begin()) { | 4960 | if (it != nodes.begin()) { |
| 4687 | for (auto i = nodes.begin(); i != it; ++i) { | 4961 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4688 | newBlock->statements.push_back(*i); | 4962 | newBlock->statementOrComments.push_back(*i); |
| 4689 | } | 4963 | } |
| 4690 | } | 4964 | } |
| 4691 | x = expListAssign; | 4965 | x = expListAssign; |
| @@ -4695,7 +4969,7 @@ private: | |||
| 4695 | ++next; | 4969 | ++next; |
| 4696 | if (next != nodes.end()) { | 4970 | if (next != nodes.end()) { |
| 4697 | for (auto i = next; i != nodes.end(); ++i) { | 4971 | for (auto i = next; i != nodes.end(); ++i) { |
| 4698 | followingBlock->statements.push_back(*i); | 4972 | followingBlock->statementOrComments.push_back(*i); |
| 4699 | } | 4973 | } |
| 4700 | } | 4974 | } |
| 4701 | } | 4975 | } |
| @@ -4723,17 +4997,13 @@ private: | |||
| 4723 | newAssignment->action.set(newAssign); | 4997 | newAssignment->action.set(newAssign); |
| 4724 | auto newStatement = x->new_ptr<Statement_t>(); | 4998 | auto newStatement = x->new_ptr<Statement_t>(); |
| 4725 | newStatement->content.set(newAssignment); | 4999 | newStatement->content.set(newAssignment); |
| 4726 | followingBlock->statements.push_front(newStatement); | 5000 | followingBlock->statementOrComments.push_front(newStatement); |
| 4727 | } | 5001 | } |
| 4728 | argNames.push_back("..."s); | 5002 | argNames.push_back("..."s); |
| 4729 | auto newBody = x->new_ptr<Body_t>(); | 5003 | auto newBody = x->new_ptr<Body_t>(); |
| 4730 | newBody->content.set(followingBlock); | 5004 | newBody->content.set(followingBlock); |
| 4731 | { | 5005 | { |
| 4732 | auto doNode = x->new_ptr<Do_t>(); | 5006 | if (auto result = upValueFuncFromBlock(followingBlock.get(), &argNames, false, true)) { |
| 4733 | doNode->body.set(newBody); | ||
| 4734 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 4735 | simpleValue->value.set(doNode); | ||
| 4736 | if (auto result = upValueFuncFromExp(newExp(simpleValue, x), &argNames, true)) { | ||
| 4737 | auto [funcName, args] = std::move(*result); | 5007 | auto [funcName, args] = std::move(*result); |
| 4738 | str_list finalArgs; | 5008 | str_list finalArgs; |
| 4739 | for (const auto& arg : args) { | 5009 | for (const auto& arg : args) { |
| @@ -4741,9 +5011,14 @@ private: | |||
| 4741 | finalArgs.push_back(arg); | 5011 | finalArgs.push_back(arg); |
| 4742 | } | 5012 | } |
| 4743 | } | 5013 | } |
| 4744 | newBlock->statements.push_back(toAst<Statement_t>(funcName + ' ' + join(finalArgs, ","sv), x)); | 5014 | auto lastNewStmt = toAst<Statement_t>(funcName + ' ' + (finalArgs.empty() ? "nil"s : join(finalArgs, ","sv)), x); |
| 4745 | auto sVal = singleValueFrom(static_cast<Statement_t*>(newBlock->statements.back())->content.to<ExpListAssign_t>()->expList); | 5015 | newBlock->statementOrComments.push_back(lastNewStmt); |
| 4746 | ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back())->args.dup(newInvoke->args); | 5016 | auto sVal = singleValueFrom(lastNewStmt->content.to<ExpListAssign_t>()->expList); |
| 5017 | auto invokArgs = ast_to<InvokeArgs_t>(sVal->item.to<ChainValue_t>()->items.back()); | ||
| 5018 | if (finalArgs.empty()) { | ||
| 5019 | invokArgs->args.clear(); | ||
| 5020 | } | ||
| 5021 | invokArgs->args.dup(newInvoke->args); | ||
| 4747 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5022 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4748 | return; | 5023 | return; |
| 4749 | } | 5024 | } |
| @@ -4768,7 +5043,7 @@ private: | |||
| 4768 | newItemListAssign->expList.set(newItemList); | 5043 | newItemListAssign->expList.set(newItemList); |
| 4769 | auto newItemStatement = x->new_ptr<Statement_t>(); | 5044 | auto newItemStatement = x->new_ptr<Statement_t>(); |
| 4770 | newItemStatement->content.set(newItemListAssign); | 5045 | newItemStatement->content.set(newItemListAssign); |
| 4771 | newBlock->statements.push_back(newItemStatement); | 5046 | newBlock->statementOrComments.push_back(newItemStatement); |
| 4772 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5047 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4773 | return; | 5048 | return; |
| 4774 | BLOCK_END | 5049 | BLOCK_END |
| @@ -4777,11 +5052,11 @@ private: | |||
| 4777 | auto newBlock = x->new_ptr<Block_t>(); | 5052 | auto newBlock = x->new_ptr<Block_t>(); |
| 4778 | if (it != nodes.begin()) { | 5053 | if (it != nodes.begin()) { |
| 4779 | for (auto i = nodes.begin(); i != it; ++i) { | 5054 | for (auto i = nodes.begin(); i != it; ++i) { |
| 4780 | newBlock->statements.push_back(*i); | 5055 | newBlock->statementOrComments.push_back(*i); |
| 4781 | } | 5056 | } |
| 4782 | } | 5057 | } |
| 4783 | localAttrib->attrib.set(localAttrib->new_ptr<ConstAttrib_t>()); | 5058 | localAttrib->attrib.set(localAttrib->new_ptr<ConstAttrib_t>()); |
| 4784 | newBlock->statements.push_back(*it); | 5059 | newBlock->statementOrComments.push_back(*it); |
| 4785 | x = localAttrib; | 5060 | x = localAttrib; |
| 4786 | auto followingBlock = x->new_ptr<Block_t>(); | 5061 | auto followingBlock = x->new_ptr<Block_t>(); |
| 4787 | { | 5062 | { |
| @@ -4789,7 +5064,7 @@ private: | |||
| 4789 | ++next; | 5064 | ++next; |
| 4790 | if (next != nodes.end()) { | 5065 | if (next != nodes.end()) { |
| 4791 | for (auto i = next; i != nodes.end(); ++i) { | 5066 | for (auto i = next; i != nodes.end(); ++i) { |
| 4792 | followingBlock->statements.push_back(*i); | 5067 | followingBlock->statementOrComments.push_back(*i); |
| 4793 | } | 5068 | } |
| 4794 | } | 5069 | } |
| 4795 | } | 5070 | } |
| @@ -4811,13 +5086,44 @@ private: | |||
| 4811 | auto value = singleValueFrom(pCallExp); | 5086 | auto value = singleValueFrom(pCallExp); |
| 4812 | value->item.to<SimpleValue_t>()->value.to<Try_t>()->func.set(followingBlock); | 5087 | value->item.to<SimpleValue_t>()->value.to<Try_t>()->func.set(followingBlock); |
| 4813 | for (const auto& stmt : getCloses) { | 5088 | for (const auto& stmt : getCloses) { |
| 4814 | newBlock->statements.push_back(toAst<Statement_t>(stmt, x)); | 5089 | newBlock->statementOrComments.push_back(toAst<Statement_t>(stmt, x)); |
| 4815 | } | 5090 | } |
| 4816 | newBlock->statements.push_back(pCallStmt); | 5091 | newBlock->statementOrComments.push_back(pCallStmt); |
| 4817 | for (const auto& stmt : doCloses) { | 5092 | for (const auto& stmt : doCloses) { |
| 4818 | newBlock->statements.push_back(toAst<Statement_t>(stmt, x)); | 5093 | newBlock->statementOrComments.push_back(toAst<Statement_t>(stmt, x)); |
| 5094 | } | ||
| 5095 | newBlock->statementOrComments.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); | ||
| 5096 | transformBlock(newBlock, out, usage, assignList, isRoot); | ||
| 5097 | return; | ||
| 5098 | } else if (auto expListAssign = stmt->content.as<ExpListAssign_t>(); | ||
| 5099 | expListAssign && expListAssign->action && expListAssign->action.is<SubBackcall_t>()) { | ||
| 5100 | auto x = *nodes.begin(); | ||
| 5101 | auto newBlock = x->new_ptr<Block_t>(); | ||
| 5102 | if (it != nodes.begin()) { | ||
| 5103 | for (auto i = nodes.begin(); i != it; ++i) { | ||
| 5104 | newBlock->statementOrComments.push_back(*i); | ||
| 5105 | } | ||
| 5106 | } | ||
| 5107 | auto doBackcall = static_cast<SubBackcall_t*>(expListAssign->action.get()); | ||
| 5108 | auto backcall = expListAssign->new_ptr<Backcall_t>(); | ||
| 5109 | auto argsDef = backcall->new_ptr<FnArgsDef_t>(); | ||
| 5110 | try { | ||
| 5111 | auto defList = toAst<FnArgDefList_t>(YueFormat{}.toString(expListAssign->expList), expListAssign->expList); | ||
| 5112 | argsDef->defList.set(defList); | ||
| 5113 | } catch (const std::exception&) { | ||
| 5114 | throw CompileError("backcall syntax error", backcall); | ||
| 5115 | } | ||
| 5116 | backcall->argsDef.set(argsDef); | ||
| 5117 | backcall->arrow.set(doBackcall->arrow); | ||
| 5118 | backcall->value.set(doBackcall->value); | ||
| 5119 | auto newStmt = backcall->new_ptr<Statement_t>(); | ||
| 5120 | newStmt->content.set(backcall); | ||
| 5121 | newStmt->appendix.set(stmt->appendix); | ||
| 5122 | newBlock->statementOrComments.push_back(newStmt); | ||
| 5123 | auto ait = it; | ||
| 5124 | for (auto i = ++ait; i != nodes.end(); ++i) { | ||
| 5125 | newBlock->statementOrComments.push_back(*i); | ||
| 4819 | } | 5126 | } |
| 4820 | newBlock->statements.push_back(toAst<Statement_t>("if "s + okVar + " then return ... else error ..."s, x)); | ||
| 4821 | transformBlock(newBlock, out, usage, assignList, isRoot); | 5127 | transformBlock(newBlock, out, usage, assignList, isRoot); |
| 4822 | return; | 5128 | return; |
| 4823 | } | 5129 | } |
| @@ -4928,7 +5234,7 @@ private: | |||
| 4928 | } | 5234 | } |
| 4929 | } | 5235 | } |
| 4930 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { | 5236 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 4931 | block->statements.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : (_info.exportMetatable ? "=<>:{}"s : "={}"s)), block)); | 5237 | block->statementOrComments.push_front(toAst<Statement_t>(_info.moduleName + (_info.exportDefault ? "=nil"s : (_info.exportMetatable ? "=<>:{}"s : "={}"s)), block)); |
| 4932 | } | 5238 | } |
| 4933 | switch (usage) { | 5239 | switch (usage) { |
| 4934 | case ExpUsage::Closure: | 5240 | case ExpUsage::Closure: |
| @@ -4941,11 +5247,9 @@ private: | |||
| 4941 | auto expList = expListFrom(last); | 5247 | auto expList = expListFrom(last); |
| 4942 | BREAK_IF(!expList); | 5248 | BREAK_IF(!expList); |
| 4943 | BREAK_IF(last->appendix && !last->appendix->item.is<IfLine_t>()); | 5249 | BREAK_IF(last->appendix && !last->appendix->item.is<IfLine_t>()); |
| 4944 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
| 4945 | expListLow->exprs.dup(expList->exprs); | ||
| 4946 | auto returnNode = x->new_ptr<Return_t>(); | 5250 | auto returnNode = x->new_ptr<Return_t>(); |
| 4947 | returnNode->explicitReturn = false; | 5251 | returnNode->explicitReturn = false; |
| 4948 | returnNode->valueList.set(expListLow); | 5252 | returnNode->valueList.set(expList); |
| 4949 | returnNode->allowBlockMacroReturn = true; | 5253 | returnNode->allowBlockMacroReturn = true; |
| 4950 | last->content.set(returnNode); | 5254 | last->content.set(returnNode); |
| 4951 | BLOCK_END | 5255 | BLOCK_END |
| @@ -4965,7 +5269,7 @@ private: | |||
| 4965 | break; | 5269 | break; |
| 4966 | } | 5270 | } |
| 4967 | } | 5271 | } |
| 4968 | bool lastAssignable = (expListFrom(last) || ast_is<For_t, ForEach_t, While_t>(last->content)); | 5272 | bool lastAssignable = (expListFrom(last) || ast_is<For_t, While_t>(last->content)); |
| 4969 | if (lastAssignable) { | 5273 | if (lastAssignable) { |
| 4970 | auto x = last; | 5274 | auto x = last; |
| 4971 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); | 5275 | auto newAssignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -4990,45 +5294,88 @@ private: | |||
| 4990 | } | 5294 | } |
| 4991 | if (!nodes.empty()) { | 5295 | if (!nodes.empty()) { |
| 4992 | str_list temp; | 5296 | str_list temp; |
| 5297 | auto lastStmt = lastStatementFrom(nodes); | ||
| 4993 | for (auto node : nodes) { | 5298 | for (auto node : nodes) { |
| 4994 | currentScope().lastStatement = (node == nodes.back()) && currentScope().mode == GlobalMode::None; | 5299 | if (auto comment = ast_cast<YueComment_t>(node)) { |
| 4995 | transformStatement(static_cast<Statement_t*>(node), temp); | 5300 | transformComment(comment, temp); |
| 4996 | if (isRoot && !_rootDefs.empty()) { | 5301 | continue; |
| 4997 | auto last = std::move(temp.back()); | 5302 | } |
| 4998 | temp.pop_back(); | 5303 | if (!ast_is<Statement_t>(node)) { |
| 4999 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); | 5304 | continue; |
| 5000 | _rootDefs.clear(); | 5305 | } |
| 5001 | temp.push_back(std::move(last)); | 5306 | auto transformNode = [&]() { |
| 5002 | } | 5307 | currentScope().lastStatement = (node == lastStmt) && currentScope().mode == GlobalMode::None; |
| 5003 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | 5308 | auto stmt = static_cast<Statement_t*>(node); |
| 5004 | auto rit = ++temp.rbegin(); | 5309 | if (auto importNode = stmt->content.as<Import_t>(); |
| 5005 | if (rit != temp.rend() && !rit->empty()) { | 5310 | importNode && importNode->content.is<ImportAllGlobal_t>()) { |
| 5006 | auto index = std::string::npos; | 5311 | if (_importedGlobal) { |
| 5007 | if (_config.reserveLineNumber) { | 5312 | throw CompileError("import global redeclared in same scope"sv, importNode); |
| 5008 | index = rit->rfind(" -- "sv); | ||
| 5009 | } else { | 5313 | } else { |
| 5010 | index = rit->find_last_not_of('\n'); | 5314 | auto& scope = currentScope(); |
| 5011 | if (index != std::string::npos) index++; | 5315 | scope.importedGlobal = std::make_unique<ImportedGlobal>(); |
| 5012 | } | 5316 | _importedGlobal = scope.importedGlobal.get(); |
| 5013 | if (index != std::string::npos) { | 5317 | _importedGlobal->vars = scope.vars.get(); |
| 5014 | auto ending = rit->substr(0, index); | 5318 | _importedGlobal->indent = indent(); |
| 5015 | auto ind = ending.find_last_of(" \t\n"sv); | 5319 | _importedGlobal->nl = nl(stmt); |
| 5016 | if (ind != std::string::npos) { | 5320 | _importedGlobal->globalCodeLine = &temp.emplace_back(); |
| 5017 | ending = ending.substr(ind + 1); | 5321 | } |
| 5322 | } else { | ||
| 5323 | transformStatement(stmt, temp); | ||
| 5324 | } | ||
| 5325 | if (isRoot && !_rootDefs.empty()) { | ||
| 5326 | auto last = std::move(temp.back()); | ||
| 5327 | temp.pop_back(); | ||
| 5328 | temp.insert(temp.end(), _rootDefs.begin(), _rootDefs.end()); | ||
| 5329 | _rootDefs.clear(); | ||
| 5330 | temp.push_back(std::move(last)); | ||
| 5331 | } | ||
| 5332 | if (!temp.empty() && _parser.startWith<StatementSep_t>(temp.back())) { | ||
| 5333 | auto rit = ++temp.rbegin(); | ||
| 5334 | if (rit != temp.rend() && !rit->empty()) { | ||
| 5335 | auto index = std::string::npos; | ||
| 5336 | if (_config.reserveLineNumber) { | ||
| 5337 | index = rit->rfind(" -- "sv); | ||
| 5338 | } else { | ||
| 5339 | index = rit->find_last_not_of('\n'); | ||
| 5340 | if (index != std::string::npos) index++; | ||
| 5018 | } | 5341 | } |
| 5019 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | 5342 | if (index != std::string::npos) { |
| 5020 | rit->insert(index, ";"sv); | 5343 | auto ending = rit->substr(0, index); |
| 5344 | auto ind = ending.find_last_of(" \t\n"sv); | ||
| 5345 | if (ind != std::string::npos) { | ||
| 5346 | ending = ending.substr(ind + 1); | ||
| 5347 | } | ||
| 5348 | if (LuaKeywords.find(ending) == LuaKeywords.end()) { | ||
| 5349 | rit->insert(index, ";"sv); | ||
| 5350 | } | ||
| 5021 | } | 5351 | } |
| 5022 | } | 5352 | } |
| 5023 | } | 5353 | } |
| 5354 | }; | ||
| 5355 | if (_config.lax) { | ||
| 5356 | try { | ||
| 5357 | transformNode(); | ||
| 5358 | } catch (const CompileError&) { } | ||
| 5359 | } else { | ||
| 5360 | transformNode(); | ||
| 5024 | } | 5361 | } |
| 5025 | } | 5362 | } |
| 5363 | if (auto importedGlobal = currentScope().importedGlobal.get()) { | ||
| 5364 | int target = getLuaTarget(block); | ||
| 5365 | auto attrib = target >= 504 ? " <const>"s : Empty; | ||
| 5366 | str_list globalCodes; | ||
| 5367 | for (const auto& global : importedGlobal->globalList) { | ||
| 5368 | globalCodes.emplace_back(importedGlobal->indent + "local "s + global + attrib + " = "s + global + importedGlobal->nl); | ||
| 5369 | } | ||
| 5370 | *importedGlobal->globalCodeLine = join(globalCodes); | ||
| 5371 | _importedGlobal = nullptr; | ||
| 5372 | } | ||
| 5026 | out.push_back(join(temp)); | 5373 | out.push_back(join(temp)); |
| 5027 | } else { | 5374 | } else { |
| 5028 | out.push_back(Empty); | 5375 | out.push_back(Empty); |
| 5029 | } | 5376 | } |
| 5030 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { | 5377 | if (isRoot && !_info.moduleName.empty() && !_info.exportMacro) { |
| 5031 | out.back().append(indent() + "return "s + _info.moduleName + nlr(block)); | 5378 | out.back().append(indent() + "return "s + _info.moduleName + nl(block)); |
| 5032 | } | 5379 | } |
| 5033 | } | 5380 | } |
| 5034 | 5381 | ||
| @@ -5229,18 +5576,29 @@ private: | |||
| 5229 | auto macroLit = macro->decl.to<MacroLit_t>(); | 5576 | auto macroLit = macro->decl.to<MacroLit_t>(); |
| 5230 | auto argsDef = macroLit->argsDef.get(); | 5577 | auto argsDef = macroLit->argsDef.get(); |
| 5231 | str_list newArgs; | 5578 | str_list newArgs; |
| 5579 | str_list argChecks; | ||
| 5580 | bool hasCheck = false; | ||
| 5232 | if (argsDef) { | 5581 | if (argsDef) { |
| 5233 | for (auto def_ : argsDef->definitions.objects()) { | 5582 | for (auto def_ : argsDef->definitions.objects()) { |
| 5234 | auto def = static_cast<FnArgDef_t*>(def_); | 5583 | auto def = static_cast<FnArgDef_t*>(def_); |
| 5235 | if (def->name.is<SelfItem_t>()) { | 5584 | if (def->name.is<SelfItem_t>()) { |
| 5236 | throw CompileError("self name is not supported for macro function argument"sv, def->name); | 5585 | throw CompileError("self name is not supported for macro function argument"sv, def->name); |
| 5237 | } else { | 5586 | } else { |
| 5587 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5588 | if (def->label) { | ||
| 5589 | hasCheck = true; | ||
| 5590 | const auto& astName = argChecks.emplace_back(_parser.toString(def->label)); | ||
| 5591 | if (!_parser.hasAST(astName)) { | ||
| 5592 | throw CompileError("invalid AST name"sv, def->label); | ||
| 5593 | } | ||
| 5594 | } else { | ||
| 5595 | argChecks.emplace_back(); | ||
| 5596 | } | ||
| 5238 | std::string defVal; | 5597 | std::string defVal; |
| 5239 | if (def->defaultValue) { | 5598 | if (def->defaultValue) { |
| 5240 | defVal = _parser.toString(def->defaultValue); | 5599 | defVal = _parser.toString(def->defaultValue); |
| 5241 | Utils::trim(defVal); | 5600 | Utils::trim(defVal); |
| 5242 | defVal.insert(0, "=[==========["sv); | 5601 | defVal = '=' + Utils::toLuaDoubleString(defVal); |
| 5243 | defVal.append("]==========]"sv); | ||
| 5244 | } | 5602 | } |
| 5245 | newArgs.emplace_back(_parser.toString(def->name) + defVal); | 5603 | newArgs.emplace_back(_parser.toString(def->name) + defVal); |
| 5246 | } | 5604 | } |
| @@ -5248,6 +5606,14 @@ private: | |||
| 5248 | if (argsDef->varArg) { | 5606 | if (argsDef->varArg) { |
| 5249 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); | 5607 | newArgs.emplace_back(_parser.toString(argsDef->varArg)); |
| 5250 | } | 5608 | } |
| 5609 | if (argsDef->label) { | ||
| 5610 | hasCheck = true; | ||
| 5611 | const auto& astName = _parser.toString(argsDef->label); | ||
| 5612 | if (!_parser.hasAST(astName)) { | ||
| 5613 | throw CompileError("invalid AST name"sv, argsDef->label); | ||
| 5614 | } | ||
| 5615 | argChecks.emplace_back("..."s + astName); | ||
| 5616 | } | ||
| 5251 | } | 5617 | } |
| 5252 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); | 5618 | std::string macroCodes = "_ENV=require('yue').macro_env\n("s + join(newArgs, ","sv) + ")->"s + _parser.toString(macroLit->body); |
| 5253 | auto chunkName = "=(macro "s + macroName + ')'; | 5619 | auto chunkName = "=(macro "s + macroName + ')'; |
| @@ -5278,6 +5644,24 @@ private: | |||
| 5278 | throw CompileError("failed to generate macro function\n"s + err, macroLit); | 5644 | throw CompileError("failed to generate macro function\n"s + err, macroLit); |
| 5279 | } // cur true macro | 5645 | } // cur true macro |
| 5280 | lua_remove(L, -2); // cur macro | 5646 | lua_remove(L, -2); // cur macro |
| 5647 | if (hasCheck) { | ||
| 5648 | lua_createtable(L, 0, 0); // cur macro checks | ||
| 5649 | int i = 1; | ||
| 5650 | for (const auto& check : argChecks) { | ||
| 5651 | if (check.empty()) { | ||
| 5652 | lua_pushboolean(L, 0); | ||
| 5653 | lua_rawseti(L, -2, i); | ||
| 5654 | } else { | ||
| 5655 | lua_pushlstring(L, check.c_str(), check.size()); | ||
| 5656 | lua_rawseti(L, -2, i); | ||
| 5657 | } | ||
| 5658 | i++; | ||
| 5659 | } | ||
| 5660 | lua_createtable(L, 2, 0); // cur macro checks macrotab | ||
| 5661 | lua_insert(L, -3); // cur macrotab macro checks | ||
| 5662 | lua_rawseti(L, -3, 1); // macrotab[1] = checks, cur macrotab macro | ||
| 5663 | lua_rawseti(L, -2, 2); // macrotab[2] = macro, cur macrotab | ||
| 5664 | } // cur macro | ||
| 5281 | if (exporting && _config.exporting && !_config.module.empty()) { | 5665 | if (exporting && _config.exporting && !_config.module.empty()) { |
| 5282 | pushModuleTable(_config.module); // cur macro module | 5666 | pushModuleTable(_config.module); // cur macro module |
| 5283 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name | 5667 | lua_pushlstring(L, macroName.c_str(), macroName.size()); // cur macro module name |
| @@ -5310,7 +5694,7 @@ private: | |||
| 5310 | if (!target) target = returnNode; | 5694 | if (!target) target = returnNode; |
| 5311 | throw CompileError("explicit return statement is not allowed in this context"sv, target); | 5695 | throw CompileError("explicit return statement is not allowed in this context"sv, target); |
| 5312 | } | 5696 | } |
| 5313 | if (auto valueList = returnNode->valueList.as<ExpListLow_t>()) { | 5697 | if (auto valueList = returnNode->valueList.as<ExpList_t>()) { |
| 5314 | if (valueList->exprs.size() == 1) { | 5698 | if (valueList->exprs.size() == 1) { |
| 5315 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); | 5699 | auto exp = static_cast<Exp_t*>(valueList->exprs.back()); |
| 5316 | if (isPurePipeChain(exp)) { | 5700 | if (isPurePipeChain(exp)) { |
| @@ -5352,11 +5736,11 @@ private: | |||
| 5352 | case id<While_t>(): | 5736 | case id<While_t>(): |
| 5353 | transformWhileInPlace(static_cast<While_t*>(value), out); | 5737 | transformWhileInPlace(static_cast<While_t*>(value), out); |
| 5354 | return; | 5738 | return; |
| 5355 | case id<For_t>(): | 5739 | case id<Repeat_t>(): |
| 5356 | transformForInPlace(static_cast<For_t*>(value), out); | 5740 | transformRepeatInPlace(static_cast<Repeat_t*>(value), out); |
| 5357 | return; | 5741 | return; |
| 5358 | case id<ForEach_t>(): | 5742 | case id<For_t>(): |
| 5359 | transformForEachInPlace(static_cast<ForEach_t*>(value), out); | 5743 | transformForInPlace(static_cast<For_t*>(value), out, nullptr); |
| 5360 | return; | 5744 | return; |
| 5361 | case id<If_t>(): | 5745 | case id<If_t>(): |
| 5362 | transformIf(static_cast<If_t*>(value), out, ExpUsage::Return); | 5746 | transformIf(static_cast<If_t*>(value), out, ExpUsage::Return); |
| @@ -5376,12 +5760,12 @@ private: | |||
| 5376 | } | 5760 | } |
| 5377 | } | 5761 | } |
| 5378 | transformValue(singleValue, out); | 5762 | transformValue(singleValue, out); |
| 5379 | out.back() = indent() + "return "s + out.back() + nlr(returnNode); | 5763 | out.back() = indent() + "return "s + out.back() + nl(returnNode); |
| 5380 | return; | 5764 | return; |
| 5381 | } else { | 5765 | } else { |
| 5382 | str_list temp; | 5766 | str_list temp; |
| 5383 | transformExpListLow(valueList, temp); | 5767 | transformExpList(valueList, temp); |
| 5384 | out.push_back(indent() + "return "s + temp.back() + nlr(returnNode)); | 5768 | out.push_back(indent() + "return "s + temp.back() + nl(returnNode)); |
| 5385 | } | 5769 | } |
| 5386 | } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { | 5770 | } else if (auto tableBlock = returnNode->valueList.as<TableBlock_t>()) { |
| 5387 | const auto& values = tableBlock->values.objects(); | 5771 | const auto& values = tableBlock->values.objects(); |
| @@ -5389,10 +5773,10 @@ private: | |||
| 5389 | transformSpreadTable(values, out, ExpUsage::Return, nullptr, false); | 5773 | transformSpreadTable(values, out, ExpUsage::Return, nullptr, false); |
| 5390 | } else { | 5774 | } else { |
| 5391 | transformTable(values, out); | 5775 | transformTable(values, out); |
| 5392 | out.back() = indent() + "return "s + out.back() + nlr(returnNode); | 5776 | out.back() = indent() + "return "s + out.back() + nl(returnNode); |
| 5393 | } | 5777 | } |
| 5394 | } else { | 5778 | } else { |
| 5395 | out.push_back(indent() + "return"s + nll(returnNode)); | 5779 | out.push_back(indent() + "return"s + nl(returnNode)); |
| 5396 | } | 5780 | } |
| 5397 | } | 5781 | } |
| 5398 | 5782 | ||
| @@ -5423,6 +5807,7 @@ private: | |||
| 5423 | bool checkExistence = false; | 5807 | bool checkExistence = false; |
| 5424 | std::string name; | 5808 | std::string name; |
| 5425 | std::string assignSelf; | 5809 | std::string assignSelf; |
| 5810 | ast_ptr<false, ExpListAssign_t> assignment; | ||
| 5426 | }; | 5811 | }; |
| 5427 | std::list<ArgItem> argItems; | 5812 | std::list<ArgItem> argItems; |
| 5428 | str_list temp; | 5813 | str_list temp; |
| @@ -5432,7 +5817,11 @@ private: | |||
| 5432 | auto def = static_cast<FnArgDef_t*>(_def); | 5817 | auto def = static_cast<FnArgDef_t*>(_def); |
| 5433 | auto& arg = argItems.emplace_back(); | 5818 | auto& arg = argItems.emplace_back(); |
| 5434 | switch (def->name->get_id()) { | 5819 | switch (def->name->get_id()) { |
| 5435 | case id<Variable_t>(): arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); break; | 5820 | case id<Variable_t>(): { |
| 5821 | if (def->op) throw CompileError("invalid existence checking"sv, def->op); | ||
| 5822 | arg.name = variableToString(static_cast<Variable_t*>(def->name.get())); | ||
| 5823 | break; | ||
| 5824 | } | ||
| 5436 | case id<SelfItem_t>(): { | 5825 | case id<SelfItem_t>(): { |
| 5437 | assignSelf = true; | 5826 | assignSelf = true; |
| 5438 | if (def->op) { | 5827 | if (def->op) { |
| @@ -5473,6 +5862,22 @@ private: | |||
| 5473 | } | 5862 | } |
| 5474 | break; | 5863 | break; |
| 5475 | } | 5864 | } |
| 5865 | case id<TableLit_t>(): { | ||
| 5866 | arg.name = getUnusedName("_arg_"sv); | ||
| 5867 | auto simpleValue = def->new_ptr<SimpleValue_t>(); | ||
| 5868 | simpleValue->value.set(def->name); | ||
| 5869 | auto asmt = assignmentFrom(newExp(simpleValue, def), toAst<Exp_t>(arg.name, def), def); | ||
| 5870 | arg.assignment = asmt; | ||
| 5871 | break; | ||
| 5872 | } | ||
| 5873 | case id<SimpleTable_t>(): { | ||
| 5874 | arg.name = getUnusedName("_arg_"sv); | ||
| 5875 | auto value = def->new_ptr<Value_t>(); | ||
| 5876 | value->item.set(def->name); | ||
| 5877 | auto asmt = assignmentFrom(newExp(value, def), toAst<Exp_t>(arg.name, def), def); | ||
| 5878 | arg.assignment = asmt; | ||
| 5879 | break; | ||
| 5880 | } | ||
| 5476 | default: YUEE("AST node mismatch", def->name.get()); break; | 5881 | default: YUEE("AST node mismatch", def->name.get()); break; |
| 5477 | } | 5882 | } |
| 5478 | forceAddToScope(arg.name); | 5883 | forceAddToScope(arg.name); |
| @@ -5486,23 +5891,46 @@ private: | |||
| 5486 | assignment->action.set(assign); | 5891 | assignment->action.set(assign); |
| 5487 | transformAssignment(assignment, temp); | 5892 | transformAssignment(assignment, temp); |
| 5488 | popScope(); | 5893 | popScope(); |
| 5489 | _buf << indent() << "if "sv << arg.name << " == nil then"sv << nll(def); | 5894 | _buf << indent() << "if "sv << arg.name << " == nil then"sv << nl(def); |
| 5490 | _buf << temp.back(); | 5895 | _buf << temp.back(); |
| 5491 | _buf << indent() << "end"sv << nll(def); | 5896 | _buf << indent() << "end"sv << nl(def); |
| 5492 | temp.back() = clearBuf(); | 5897 | temp.back() = clearBuf(); |
| 5493 | } | 5898 | } |
| 5494 | if (varNames.empty()) | 5899 | if (arg.assignment) { |
| 5900 | auto names = getArgDestructureList(arg.assignment); | ||
| 5901 | for (const auto& name : names) { | ||
| 5902 | forceAddToScope(name); | ||
| 5903 | } | ||
| 5904 | temp.emplace_back(indent() + "local "s + join(names, ", "sv) + nl(def)); | ||
| 5905 | transformAssignment(arg.assignment, temp); | ||
| 5906 | } | ||
| 5907 | if (varNames.empty()) { | ||
| 5495 | varNames = arg.name; | 5908 | varNames = arg.name; |
| 5496 | else | 5909 | } else { |
| 5497 | varNames.append(", "s + arg.name); | 5910 | varNames.append(", "s + arg.name); |
| 5911 | } | ||
| 5498 | } | 5912 | } |
| 5499 | if (argDefList->varArg) { | 5913 | if (argDefList->varArg) { |
| 5914 | std::string varStr; | ||
| 5915 | if (auto varName = argDefList->varArg->name.get()) { | ||
| 5916 | varStr = variableToString(varName); | ||
| 5917 | int target = getLuaTarget(varName); | ||
| 5918 | forceAddToScope(varStr); | ||
| 5919 | if (target < 505) { | ||
| 5920 | temp.push_back(indent() + "local "s + varStr + " = {"s + nl(varName)); | ||
| 5921 | temp.push_back(indent(1) + "n = "s + globalVar("select", varName, AccessType::Read) + "(\"#\", ...),"s + nl(varName)); | ||
| 5922 | temp.push_back(indent(1) + "..."s + nl(varName)); | ||
| 5923 | temp.push_back(indent() + '}' + nl(varName)); | ||
| 5924 | varStr.clear(); | ||
| 5925 | } | ||
| 5926 | } | ||
| 5500 | auto& arg = argItems.emplace_back(); | 5927 | auto& arg = argItems.emplace_back(); |
| 5501 | arg.name = "..."sv; | 5928 | arg.name = "..."sv; |
| 5502 | if (varNames.empty()) | 5929 | if (varNames.empty()) { |
| 5503 | varNames = arg.name; | 5930 | varNames = arg.name + varStr; |
| 5504 | else | 5931 | } else { |
| 5505 | varNames.append(", "s + arg.name); | 5932 | varNames.append(", "s + arg.name + varStr); |
| 5933 | } | ||
| 5506 | _varArgs.top().hasVar = true; | 5934 | _varArgs.top().hasVar = true; |
| 5507 | } | 5935 | } |
| 5508 | if (assignSelf) { | 5936 | if (assignSelf) { |
| @@ -5571,6 +5999,45 @@ private: | |||
| 5571 | } | 5999 | } |
| 5572 | } | 6000 | } |
| 5573 | 6001 | ||
| 6002 | bool transformChainEndWithSlice(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | ||
| 6003 | auto x = chainList.front(); | ||
| 6004 | if (ast_is<Slice_t>(chainList.back())) { | ||
| 6005 | auto comp = x->new_ptr<Comprehension_t>(); | ||
| 6006 | { | ||
| 6007 | auto chainValue = x->new_ptr<ChainValue_t>(); | ||
| 6008 | for (auto item : chainList) { | ||
| 6009 | chainValue->items.push_back(item); | ||
| 6010 | } | ||
| 6011 | auto itemVar = getUnusedName("_item_"sv); | ||
| 6012 | auto expCode = YueFormat{}.toString(chainValue); | ||
| 6013 | auto compCode = '[' + itemVar + " for "s + itemVar + " in *"s + expCode + ']'; | ||
| 6014 | comp.set(toAst<Comprehension_t>(compCode, x)); | ||
| 6015 | } | ||
| 6016 | switch (usage) { | ||
| 6017 | case ExpUsage::Assignment: { | ||
| 6018 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 6019 | simpleValue->value.set(comp); | ||
| 6020 | auto exp = newExp(simpleValue, x); | ||
| 6021 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6022 | assignment->expList.set(assignList); | ||
| 6023 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6024 | assign->values.push_back(exp); | ||
| 6025 | assignment->action.set(assign); | ||
| 6026 | transformAssignment(assignment, out); | ||
| 6027 | break; | ||
| 6028 | } | ||
| 6029 | case ExpUsage::Return: | ||
| 6030 | transformComprehension(comp, out, ExpUsage::Return); | ||
| 6031 | break; | ||
| 6032 | default: | ||
| 6033 | transformComprehension(comp, out, ExpUsage::Closure); | ||
| 6034 | break; | ||
| 6035 | } | ||
| 6036 | return true; | ||
| 6037 | } | ||
| 6038 | return false; | ||
| 6039 | } | ||
| 6040 | |||
| 5574 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { | 6041 | bool transformChainEndWithEOP(const node_container& chainList, str_list& out, ExpUsage usage, ExpList_t* assignList) { |
| 5575 | auto x = chainList.front(); | 6042 | auto x = chainList.front(); |
| 5576 | if (ast_is<ExistentialOp_t>(chainList.back())) { | 6043 | if (ast_is<ExistentialOp_t>(chainList.back())) { |
| @@ -5605,7 +6072,7 @@ private: | |||
| 5605 | case ExpUsage::Return: | 6072 | case ExpUsage::Return: |
| 5606 | transformParens(parens, out); | 6073 | transformParens(parens, out); |
| 5607 | out.back().insert(0, indent() + "return "s); | 6074 | out.back().insert(0, indent() + "return "s); |
| 5608 | out.back().append(nlr(x)); | 6075 | out.back().append(nl(x)); |
| 5609 | break; | 6076 | break; |
| 5610 | default: | 6077 | default: |
| 5611 | transformParens(parens, out); | 6078 | transformParens(parens, out); |
| @@ -5676,7 +6143,7 @@ private: | |||
| 5676 | } | 6143 | } |
| 5677 | } | 6144 | } |
| 5678 | if (isScoped) { | 6145 | if (isScoped) { |
| 5679 | temp.push_back(indent() + "do"s + nll(x)); | 6146 | temp.push_back(indent() + "do"s + nl(x)); |
| 5680 | pushScope(); | 6147 | pushScope(); |
| 5681 | } | 6148 | } |
| 5682 | objVar = getUnusedName("_obj_"sv); | 6149 | objVar = getUnusedName("_obj_"sv); |
| @@ -5736,9 +6203,9 @@ private: | |||
| 5736 | _buf << typeVar << "=type "sv << objVar; | 6203 | _buf << typeVar << "=type "sv << objVar; |
| 5737 | auto typeAssign = toAst<ExpListAssign_t>(clearBuf(), partOne); | 6204 | auto typeAssign = toAst<ExpListAssign_t>(clearBuf(), partOne); |
| 5738 | transformAssignment(typeAssign, temp); | 6205 | transformAssignment(typeAssign, temp); |
| 5739 | _buf << indent() << "if \"table\" == " << typeVar << " or \"userdata\" == "sv << typeVar << " then"sv << nll(x); | 6206 | _buf << indent() << "if \"table\" == " << typeVar << " or \"userdata\" == "sv << typeVar << " then"sv << nl(x); |
| 5740 | } else { | 6207 | } else { |
| 5741 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nll(x); | 6208 | _buf << indent() << "if "sv << objVar << " ~= nil then"sv << nl(x); |
| 5742 | } | 6209 | } |
| 5743 | temp.push_back(clearBuf()); | 6210 | temp.push_back(clearBuf()); |
| 5744 | pushScope(); | 6211 | pushScope(); |
| @@ -5764,25 +6231,21 @@ private: | |||
| 5764 | case ExpUsage::Return: | 6231 | case ExpUsage::Return: |
| 5765 | case ExpUsage::Closure: { | 6232 | case ExpUsage::Closure: { |
| 5766 | auto exp = newExp(partTwo, x); | 6233 | auto exp = newExp(partTwo, x); |
| 5767 | auto ret = x->new_ptr<Return_t>(); | 6234 | auto ret = newReturn(exp); |
| 5768 | ret->explicitReturn = false; | ||
| 5769 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
| 5770 | expListLow->exprs.push_back(exp); | ||
| 5771 | ret->valueList.set(expListLow); | ||
| 5772 | transformReturn(ret, temp); | 6235 | transformReturn(ret, temp); |
| 5773 | break; | 6236 | break; |
| 5774 | } | 6237 | } |
| 5775 | } | 6238 | } |
| 5776 | popScope(); | 6239 | popScope(); |
| 5777 | temp.push_back(indent() + "end"s + nlr(x)); | 6240 | temp.push_back(indent() + "end"s + nl(x)); |
| 5778 | switch (usage) { | 6241 | switch (usage) { |
| 5779 | case ExpUsage::Return: | 6242 | case ExpUsage::Return: |
| 5780 | temp.push_back(indent() + "return nil"s + nlr(x)); | 6243 | temp.push_back(indent() + "return nil"s + nl(x)); |
| 5781 | break; | 6244 | break; |
| 5782 | case ExpUsage::Closure: | 6245 | case ExpUsage::Closure: |
| 5783 | temp.push_back(indent() + "return nil"s + nlr(x)); | 6246 | temp.push_back(indent() + "return nil"s + nl(x)); |
| 5784 | popScope(); | 6247 | popScope(); |
| 5785 | *funcStart = anonFuncStart() + nll(x); | 6248 | *funcStart = anonFuncStart() + nl(x); |
| 5786 | temp.push_back(indent() + anonFuncEnd()); | 6249 | temp.push_back(indent() + anonFuncEnd()); |
| 5787 | popAnonVarArg(); | 6250 | popAnonVarArg(); |
| 5788 | popFunctionScope(); | 6251 | popFunctionScope(); |
| @@ -5792,7 +6255,7 @@ private: | |||
| 5792 | } | 6255 | } |
| 5793 | if (isScoped) { | 6256 | if (isScoped) { |
| 5794 | popScope(); | 6257 | popScope(); |
| 5795 | temp.push_back(indent() + "end"s + nlr(x)); | 6258 | temp.push_back(indent() + "end"s + nl(x)); |
| 5796 | } | 6259 | } |
| 5797 | out.push_back(join(temp)); | 6260 | out.push_back(join(temp)); |
| 5798 | return true; | 6261 | return true; |
| @@ -5809,7 +6272,7 @@ private: | |||
| 5809 | switch (usage) { | 6272 | switch (usage) { |
| 5810 | case ExpUsage::Assignment: | 6273 | case ExpUsage::Assignment: |
| 5811 | if (isScoped) { | 6274 | if (isScoped) { |
| 5812 | temp.push_back(indent() + "do"s + nll(x)); | 6275 | temp.push_back(indent() + "do"s + nl(x)); |
| 5813 | pushScope(); | 6276 | pushScope(); |
| 5814 | } | 6277 | } |
| 5815 | break; | 6278 | break; |
| @@ -5863,11 +6326,7 @@ private: | |||
| 5863 | switch (usage) { | 6326 | switch (usage) { |
| 5864 | case ExpUsage::Closure: | 6327 | case ExpUsage::Closure: |
| 5865 | case ExpUsage::Return: { | 6328 | case ExpUsage::Return: { |
| 5866 | auto returnNode = x->new_ptr<Return_t>(); | 6329 | auto returnNode = newReturn(funLit); |
| 5867 | returnNode->explicitReturn = false; | ||
| 5868 | auto expListLow = x->new_ptr<ExpListLow_t>(); | ||
| 5869 | expListLow->exprs.push_back(funLit); | ||
| 5870 | returnNode->valueList.set(expListLow); | ||
| 5871 | transformReturn(returnNode, temp); | 6330 | transformReturn(returnNode, temp); |
| 5872 | break; | 6331 | break; |
| 5873 | } | 6332 | } |
| @@ -5887,12 +6346,12 @@ private: | |||
| 5887 | case ExpUsage::Assignment: | 6346 | case ExpUsage::Assignment: |
| 5888 | if (isScoped) { | 6347 | if (isScoped) { |
| 5889 | popScope(); | 6348 | popScope(); |
| 5890 | temp.push_back(indent() + "end"s + nlr(x)); | 6349 | temp.push_back(indent() + "end"s + nl(x)); |
| 5891 | } | 6350 | } |
| 5892 | break; | 6351 | break; |
| 5893 | case ExpUsage::Closure: | 6352 | case ExpUsage::Closure: |
| 5894 | popScope(); | 6353 | popScope(); |
| 5895 | *funcStart = anonFuncStart() + nll(x); | 6354 | *funcStart = anonFuncStart() + nl(x); |
| 5896 | temp.push_back(indent() + anonFuncEnd()); | 6355 | temp.push_back(indent() + anonFuncEnd()); |
| 5897 | popAnonVarArg(); | 6356 | popAnonVarArg(); |
| 5898 | popFunctionScope(); | 6357 | popFunctionScope(); |
| @@ -5968,7 +6427,7 @@ private: | |||
| 5968 | pushScope(); | 6427 | pushScope(); |
| 5969 | } else if (usage != ExpUsage::Return) { | 6428 | } else if (usage != ExpUsage::Return) { |
| 5970 | if (isScoped) { | 6429 | if (isScoped) { |
| 5971 | temp.push_back(indent() + "do"s + nll(x)); | 6430 | temp.push_back(indent() + "do"s + nl(x)); |
| 5972 | pushScope(); | 6431 | pushScope(); |
| 5973 | } | 6432 | } |
| 5974 | } | 6433 | } |
| @@ -5998,25 +6457,17 @@ private: | |||
| 5998 | } | 6457 | } |
| 5999 | switch (usage) { | 6458 | switch (usage) { |
| 6000 | case ExpUsage::Closure: { | 6459 | case ExpUsage::Closure: { |
| 6001 | auto returnNode = x->new_ptr<Return_t>(); | 6460 | auto returnNode = newReturn(newChainExp); |
| 6002 | returnNode->explicitReturn = false; | ||
| 6003 | auto values = x->new_ptr<ExpListLow_t>(); | ||
| 6004 | values->exprs.push_back(newChainExp); | ||
| 6005 | returnNode->valueList.set(values); | ||
| 6006 | transformReturn(returnNode, temp); | 6461 | transformReturn(returnNode, temp); |
| 6007 | popScope(); | 6462 | popScope(); |
| 6008 | *funcStart = anonFuncStart() + nll(x); | 6463 | *funcStart = anonFuncStart() + nl(x); |
| 6009 | temp.push_back(indent() + anonFuncEnd()); | 6464 | temp.push_back(indent() + anonFuncEnd()); |
| 6010 | popAnonVarArg(); | 6465 | popAnonVarArg(); |
| 6011 | popFunctionScope(); | 6466 | popFunctionScope(); |
| 6012 | break; | 6467 | break; |
| 6013 | } | 6468 | } |
| 6014 | case ExpUsage::Return: { | 6469 | case ExpUsage::Return: { |
| 6015 | auto returnNode = x->new_ptr<Return_t>(); | 6470 | auto returnNode = newReturn(newChainExp); |
| 6016 | returnNode->explicitReturn = false; | ||
| 6017 | auto values = x->new_ptr<ExpListLow_t>(); | ||
| 6018 | values->exprs.push_back(newChainExp); | ||
| 6019 | returnNode->valueList.set(values); | ||
| 6020 | transformReturn(returnNode, temp); | 6471 | transformReturn(returnNode, temp); |
| 6021 | break; | 6472 | break; |
| 6022 | } | 6473 | } |
| @@ -6029,7 +6480,7 @@ private: | |||
| 6029 | transformAssignment(assignment, temp); | 6480 | transformAssignment(assignment, temp); |
| 6030 | if (isScoped) { | 6481 | if (isScoped) { |
| 6031 | popScope(); | 6482 | popScope(); |
| 6032 | temp.push_back(indent() + "end"s + nlr(x)); | 6483 | temp.push_back(indent() + "end"s + nl(x)); |
| 6033 | } | 6484 | } |
| 6034 | break; | 6485 | break; |
| 6035 | } | 6486 | } |
| @@ -6037,7 +6488,7 @@ private: | |||
| 6037 | transformExp(newChainExp, temp, usage); | 6488 | transformExp(newChainExp, temp, usage); |
| 6038 | if (isScoped) { | 6489 | if (isScoped) { |
| 6039 | popScope(); | 6490 | popScope(); |
| 6040 | temp.push_back(indent() + "end"s + nlr(x)); | 6491 | temp.push_back(indent() + "end"s + nl(x)); |
| 6041 | } | 6492 | } |
| 6042 | break; | 6493 | break; |
| 6043 | } | 6494 | } |
| @@ -6088,7 +6539,7 @@ private: | |||
| 6088 | case id<ColonChainItem_t>(): | 6539 | case id<ColonChainItem_t>(): |
| 6089 | case id<Exp_t>(): | 6540 | case id<Exp_t>(): |
| 6090 | if (_withVars.empty()) { | 6541 | if (_withVars.empty()) { |
| 6091 | throw CompileError("short dot/colon and indexing syntax must be called within a with block"sv, x); | 6542 | throw CompileError("short dot/colon/indexing syntax must be called within a with block"sv, x); |
| 6092 | } else { | 6543 | } else { |
| 6093 | temp.push_back(_withVars.top()); | 6544 | temp.push_back(_withVars.top()); |
| 6094 | } | 6545 | } |
| @@ -6142,7 +6593,7 @@ private: | |||
| 6142 | assignment->action.set(assign); | 6593 | assignment->action.set(assign); |
| 6143 | auto stmt = x->new_ptr<Statement_t>(); | 6594 | auto stmt = x->new_ptr<Statement_t>(); |
| 6144 | stmt->content.set(assignment); | 6595 | stmt->content.set(assignment); |
| 6145 | block->statements.push_back(stmt); | 6596 | block->statementOrComments.push_back(stmt); |
| 6146 | } | 6597 | } |
| 6147 | } | 6598 | } |
| 6148 | ast_ptr<false, Exp_t> nexp; | 6599 | ast_ptr<false, Exp_t> nexp; |
| @@ -6188,7 +6639,7 @@ private: | |||
| 6188 | expListAssign->expList.set(expList); | 6639 | expListAssign->expList.set(expList); |
| 6189 | auto stmt = x->new_ptr<Statement_t>(); | 6640 | auto stmt = x->new_ptr<Statement_t>(); |
| 6190 | stmt->content.set(expListAssign); | 6641 | stmt->content.set(expListAssign); |
| 6191 | block->statements.push_back(stmt); | 6642 | block->statementOrComments.push_back(stmt); |
| 6192 | } | 6643 | } |
| 6193 | switch (usage) { | 6644 | switch (usage) { |
| 6194 | case ExpUsage::Common: | 6645 | case ExpUsage::Common: |
| @@ -6202,7 +6653,7 @@ private: | |||
| 6202 | default: | 6653 | default: |
| 6203 | break; | 6654 | break; |
| 6204 | } | 6655 | } |
| 6205 | if (block->statements.size() == 1) { | 6656 | if (block->statementOrComments.size() == 1) { |
| 6206 | transformExp(nexp, out, usage, assignList); | 6657 | transformExp(nexp, out, usage, assignList); |
| 6207 | } else { | 6658 | } else { |
| 6208 | auto body = x->new_ptr<Body_t>(); | 6659 | auto body = x->new_ptr<Body_t>(); |
| @@ -6234,6 +6685,120 @@ private: | |||
| 6234 | } | 6685 | } |
| 6235 | return; | 6686 | return; |
| 6236 | } | 6687 | } |
| 6688 | break; | ||
| 6689 | } | ||
| 6690 | case id<ReversedIndex_t>(): { | ||
| 6691 | auto rIndex = static_cast<ReversedIndex_t*>(*it); | ||
| 6692 | auto current = it; | ||
| 6693 | auto prevChain = x->new_ptr<ChainValue_t>(); | ||
| 6694 | for (auto i = chainList.begin(); i != current; ++i) { | ||
| 6695 | prevChain->items.push_back(*i); | ||
| 6696 | } | ||
| 6697 | auto var = singleVariableFrom(prevChain, AccessType::None); | ||
| 6698 | if (!var.empty() && isLocal(var)) { | ||
| 6699 | auto indexNode = toAst<Exp_t>('#' + var, rIndex); | ||
| 6700 | if (rIndex->modifier) { | ||
| 6701 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6702 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6703 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6704 | indexNode->opValues.push_back(opValue); | ||
| 6705 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6706 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6707 | } | ||
| 6708 | prevChain->items.push_back(indexNode); | ||
| 6709 | auto next = current; | ||
| 6710 | ++next; | ||
| 6711 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6712 | prevChain->items.push_back(*i); | ||
| 6713 | } | ||
| 6714 | if (usage == ExpUsage::Assignment) { | ||
| 6715 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6716 | assignment->expList.set(assignList); | ||
| 6717 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6718 | assign->values.push_back(newExp(prevChain, x)); | ||
| 6719 | assignment->action.set(assign); | ||
| 6720 | transformAssignment(assignment, out); | ||
| 6721 | return; | ||
| 6722 | } | ||
| 6723 | transformChainValue(prevChain, out, usage, assignList); | ||
| 6724 | return; | ||
| 6725 | } else { | ||
| 6726 | auto itemVar = getUnusedName("_item_"sv); | ||
| 6727 | auto asmt = assignmentFrom(toAst<Exp_t>(itemVar, x), newExp(prevChain, x), x); | ||
| 6728 | auto stmt1 = x->new_ptr<Statement_t>(); | ||
| 6729 | stmt1->content.set(asmt); | ||
| 6730 | auto newChain = x->new_ptr<ChainValue_t>(); | ||
| 6731 | newChain->items.push_back(toAst<Callable_t>(itemVar, x)); | ||
| 6732 | auto indexNode = toAst<Exp_t>('#' + itemVar, rIndex); | ||
| 6733 | if (rIndex->modifier) { | ||
| 6734 | auto opValue = rIndex->new_ptr<ExpOpValue_t>(); | ||
| 6735 | opValue->op.set(toAst<BinaryOperator_t>("-"sv, rIndex)); | ||
| 6736 | opValue->pipeExprs.dup(rIndex->modifier->pipeExprs); | ||
| 6737 | indexNode->opValues.push_back(opValue); | ||
| 6738 | indexNode->opValues.dup(rIndex->modifier->opValues); | ||
| 6739 | indexNode->nilCoalesed.set(rIndex->modifier->nilCoalesed); | ||
| 6740 | } | ||
| 6741 | newChain->items.push_back(indexNode); | ||
| 6742 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 6743 | expList->exprs.push_back(newExp(newChain, x)); | ||
| 6744 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
| 6745 | expListAssign->expList.set(expList); | ||
| 6746 | auto stmt2 = x->new_ptr<Statement_t>(); | ||
| 6747 | stmt2->content.set(expListAssign); | ||
| 6748 | auto block = x->new_ptr<Block_t>(); | ||
| 6749 | block->statementOrComments.push_back(stmt1); | ||
| 6750 | block->statementOrComments.push_back(stmt2); | ||
| 6751 | auto body = x->new_ptr<Body_t>(); | ||
| 6752 | body->content.set(block); | ||
| 6753 | auto doNode = x->new_ptr<Do_t>(); | ||
| 6754 | doNode->body.set(body); | ||
| 6755 | if (usage == ExpUsage::Assignment) { | ||
| 6756 | auto next = current; | ||
| 6757 | ++next; | ||
| 6758 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6759 | newChain->items.push_back(*i); | ||
| 6760 | } | ||
| 6761 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 6762 | assignment->expList.set(assignList); | ||
| 6763 | auto assign = x->new_ptr<Assign_t>(); | ||
| 6764 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 6765 | sVal->value.set(doNode); | ||
| 6766 | assign->values.push_back(newExp(sVal, x)); | ||
| 6767 | assignment->action.set(assign); | ||
| 6768 | transformAssignment(assignment, out); | ||
| 6769 | return; | ||
| 6770 | } | ||
| 6771 | if (usage == ExpUsage::Closure) { | ||
| 6772 | auto next = current; | ||
| 6773 | ++next; | ||
| 6774 | if (next != chainList.end()) { | ||
| 6775 | doNode->new_ptr<ChainValue_t>(); | ||
| 6776 | auto dVal = doNode->new_ptr<SimpleValue_t>(); | ||
| 6777 | dVal->value.set(doNode); | ||
| 6778 | auto dExp = newExp(dVal, dVal); | ||
| 6779 | auto dParen = dExp->new_ptr<Parens_t>(); | ||
| 6780 | dParen->extra = true; | ||
| 6781 | dParen->expr.set(dExp); | ||
| 6782 | auto dCallable = dExp->new_ptr<Callable_t>(); | ||
| 6783 | dCallable->item.set(dParen); | ||
| 6784 | auto dChain = doNode->new_ptr<ChainValue_t>(); | ||
| 6785 | dChain->items.push_back(dCallable); | ||
| 6786 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6787 | dChain->items.push_back(*i); | ||
| 6788 | } | ||
| 6789 | transformExp(newExp(dChain, dExp), out, usage); | ||
| 6790 | return; | ||
| 6791 | } | ||
| 6792 | } | ||
| 6793 | auto next = current; | ||
| 6794 | ++next; | ||
| 6795 | for (auto i = next; i != chainList.end(); ++i) { | ||
| 6796 | newChain->items.push_back(*i); | ||
| 6797 | } | ||
| 6798 | transformDo(doNode, out, usage); | ||
| 6799 | return; | ||
| 6800 | } | ||
| 6801 | break; | ||
| 6237 | } | 6802 | } |
| 6238 | } | 6803 | } |
| 6239 | } | 6804 | } |
| @@ -6283,10 +6848,10 @@ private: | |||
| 6283 | } | 6848 | } |
| 6284 | switch (usage) { | 6849 | switch (usage) { |
| 6285 | case ExpUsage::Common: | 6850 | case ExpUsage::Common: |
| 6286 | out.push_back(indent() + join(temp) + nll(x)); | 6851 | out.push_back(indent() + join(temp) + nl(x)); |
| 6287 | break; | 6852 | break; |
| 6288 | case ExpUsage::Return: | 6853 | case ExpUsage::Return: |
| 6289 | out.push_back(indent() + "return "s + join(temp) + nll(x)); | 6854 | out.push_back(indent() + "return "s + join(temp) + nl(x)); |
| 6290 | break; | 6855 | break; |
| 6291 | case ExpUsage::Assignment: YUEE("invalid expression usage", x); break; | 6856 | case ExpUsage::Assignment: YUEE("invalid expression usage", x); break; |
| 6292 | default: | 6857 | default: |
| @@ -6418,7 +6983,7 @@ private: | |||
| 6418 | } | 6983 | } |
| 6419 | } | 6984 | } |
| 6420 | } | 6985 | } |
| 6421 | int len = lua_objlen(L, -1); | 6986 | int len = static_cast<int>(lua_objlen(L, -1)); |
| 6422 | lua_pushnil(L); // cur nil | 6987 | lua_pushnil(L); // cur nil |
| 6423 | for (int i = len; i >= 1; i--) { | 6988 | for (int i = len; i >= 1; i--) { |
| 6424 | lua_pop(L, 1); // cur | 6989 | lua_pop(L, 1); // cur |
| @@ -6430,7 +6995,25 @@ private: | |||
| 6430 | break; | 6995 | break; |
| 6431 | } | 6996 | } |
| 6432 | } | 6997 | } |
| 6433 | if (!lua_isfunction(L, -1)) { | 6998 | str_list checks; |
| 6999 | if (lua_istable(L, -1)) { | ||
| 7000 | lua_rawgeti(L, -1, 1); // cur macrotab checks | ||
| 7001 | int len = static_cast<int>(lua_objlen(L, -1)); | ||
| 7002 | for (int i = 1; i <= len; i++) { | ||
| 7003 | lua_rawgeti(L, -1, i); | ||
| 7004 | if (lua_toboolean(L, -1) == 0) { | ||
| 7005 | checks.emplace_back(); | ||
| 7006 | } else { | ||
| 7007 | size_t str_len = 0; | ||
| 7008 | auto str = lua_tolstring(L, -1, &str_len); | ||
| 7009 | checks.emplace_back(std::string{str, str_len}); | ||
| 7010 | } | ||
| 7011 | lua_pop(L, 1); | ||
| 7012 | } | ||
| 7013 | lua_pop(L, 1); | ||
| 7014 | lua_rawgeti(L, -1, 2); // cur macrotab macroFunc | ||
| 7015 | lua_remove(L, -2); // cur macroFunc | ||
| 7016 | } else if (!lua_isfunction(L, -1)) { | ||
| 6434 | auto code = expandBuiltinMacro(macroName, x); | 7017 | auto code = expandBuiltinMacro(macroName, x); |
| 6435 | if (!code.empty()) return code; | 7018 | if (!code.empty()) return code; |
| 6436 | if (macroName == "is_ast"sv) { | 7019 | if (macroName == "is_ast"sv) { |
| @@ -6475,11 +7058,34 @@ private: | |||
| 6475 | } // cur macroFunc | 7058 | } // cur macroFunc |
| 6476 | pushYue("pcall"sv); // cur macroFunc pcall | 7059 | pushYue("pcall"sv); // cur macroFunc pcall |
| 6477 | lua_insert(L, -2); // cur pcall macroFunc | 7060 | lua_insert(L, -2); // cur pcall macroFunc |
| 6478 | if (!lua_checkstack(L, argStrs.size())) { | 7061 | if (!lua_checkstack(L, static_cast<int>(argStrs.size()))) { |
| 6479 | throw CompileError("too much macro params"s, x); | 7062 | throw CompileError("too much macro params"s, x); |
| 6480 | } | 7063 | } |
| 7064 | auto checkIt = checks.begin(); | ||
| 7065 | node_container::const_iterator argIt; | ||
| 7066 | if (args) { | ||
| 7067 | argIt = args->begin(); | ||
| 7068 | } | ||
| 6481 | for (const auto& arg : argStrs) { | 7069 | for (const auto& arg : argStrs) { |
| 7070 | if (checkIt != checks.end()) { | ||
| 7071 | if (checkIt->empty()) { | ||
| 7072 | ++checkIt; | ||
| 7073 | } else { | ||
| 7074 | if ((*checkIt)[0] == '.') { | ||
| 7075 | auto astName = checkIt->substr(3); | ||
| 7076 | if (!_parser.match(astName, arg)) { | ||
| 7077 | throw CompileError("expecting \""s + astName + "\", AST mismatch"s, *argIt); | ||
| 7078 | } | ||
| 7079 | } else { | ||
| 7080 | if (!_parser.match(*checkIt, arg)) { | ||
| 7081 | throw CompileError("expecting \""s + *checkIt + "\", AST mismatch"s, *argIt); | ||
| 7082 | } | ||
| 7083 | ++checkIt; | ||
| 7084 | } | ||
| 7085 | } | ||
| 7086 | } | ||
| 6482 | lua_pushlstring(L, arg.c_str(), arg.size()); | 7087 | lua_pushlstring(L, arg.c_str(), arg.size()); |
| 7088 | ++argIt; | ||
| 6483 | } // cur pcall macroFunc args... | 7089 | } // cur pcall macroFunc args... |
| 6484 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; | 7090 | bool success = lua_pcall(L, static_cast<int>(argStrs.size()), 1, 0) == 0; |
| 6485 | if (!success) { // cur err | 7091 | if (!success) { // cur err |
| @@ -6571,8 +7177,8 @@ private: | |||
| 6571 | throw CompileError("lua macro is not expanding to valid block\n"s + err, x); | 7177 | throw CompileError("lua macro is not expanding to valid block\n"s + err, x); |
| 6572 | } | 7178 | } |
| 6573 | if (!codes.empty()) { | 7179 | if (!codes.empty()) { |
| 6574 | codes.insert(0, indent() + "do"s + nll(chainValue)); | 7180 | codes.insert(0, indent() + "do"s + nl(chainValue)); |
| 6575 | codes.append(_newLine + indent() + "end"s + nlr(chainValue)); | 7181 | codes.append(_newLine + indent() + "end"s + nl(chainValue)); |
| 6576 | } | 7182 | } |
| 6577 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; | 7183 | return {nullptr, nullptr, std::move(codes), std::move(localVars)}; |
| 6578 | } else { | 7184 | } else { |
| @@ -6609,14 +7215,14 @@ private: | |||
| 6609 | } else { | 7215 | } else { |
| 6610 | if (!codes.empty()) { | 7216 | if (!codes.empty()) { |
| 6611 | if (isBlock) { | 7217 | if (isBlock) { |
| 6612 | info = _parser.parse<BlockEnd_t>(codes); | 7218 | info = _parser.parse<BlockEnd_t>(codes, false); |
| 6613 | if (info.error) { | 7219 | if (info.error) { |
| 6614 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); | 7220 | throw CompileError("failed to expand macro as block: "s + info.error.value().msg, x); |
| 6615 | } | 7221 | } |
| 6616 | } else { | 7222 | } else { |
| 6617 | info = _parser.parse<Exp_t>(codes); | 7223 | info = _parser.parse<Exp_t>(codes, false); |
| 6618 | if (!info.node && allowBlockMacroReturn) { | 7224 | if (!info.node && allowBlockMacroReturn) { |
| 6619 | info = _parser.parse<BlockEnd_t>(codes); | 7225 | info = _parser.parse<BlockEnd_t>(codes, false); |
| 6620 | if (info.error) { | 7226 | if (info.error) { |
| 6621 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); | 7227 | throw CompileError("failed to expand macro as expr or block: "s + info.error.value().msg, x); |
| 6622 | } | 7228 | } |
| @@ -6661,7 +7267,7 @@ private: | |||
| 6661 | auto stmt = x->new_ptr<Statement_t>(); | 7267 | auto stmt = x->new_ptr<Statement_t>(); |
| 6662 | stmt->content.set(exps); | 7268 | stmt->content.set(exps); |
| 6663 | auto block = x->new_ptr<Block_t>(); | 7269 | auto block = x->new_ptr<Block_t>(); |
| 6664 | block->statements.push_back(stmt); | 7270 | block->statementOrComments.push_back(stmt); |
| 6665 | info.node.set(block); | 7271 | info.node.set(block); |
| 6666 | } else { | 7272 | } else { |
| 6667 | info.node.set(exp); | 7273 | info.node.set(exp); |
| @@ -6698,7 +7304,7 @@ private: | |||
| 6698 | return; | 7304 | return; |
| 6699 | } | 7305 | } |
| 6700 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { | 7306 | if (usage == ExpUsage::Common || (usage == ExpUsage::Return && node.is<Block_t>())) { |
| 6701 | if (node.to<Block_t>()->statements.empty()) { | 7307 | if (node.to<Block_t>()->statementOrComments.empty()) { |
| 6702 | out.push_back(Empty); | 7308 | out.push_back(Empty); |
| 6703 | } else { | 7309 | } else { |
| 6704 | auto doBody = node->new_ptr<Body_t>(); | 7310 | auto doBody = node->new_ptr<Body_t>(); |
| @@ -6720,11 +7326,7 @@ private: | |||
| 6720 | break; | 7326 | break; |
| 6721 | } | 7327 | } |
| 6722 | case ExpUsage::Return: { | 7328 | case ExpUsage::Return: { |
| 6723 | auto expListLow = x->new_ptr<ExpListLow_t>(); | 7329 | auto returnNode = newReturn(node.to<Exp_t>()); |
| 6724 | expListLow->exprs.push_back(node); | ||
| 6725 | auto returnNode = x->new_ptr<Return_t>(); | ||
| 6726 | returnNode->explicitReturn = false; | ||
| 6727 | returnNode->valueList.set(expListLow); | ||
| 6728 | transformReturn(returnNode, out); | 7330 | transformReturn(returnNode, out); |
| 6729 | break; | 7331 | break; |
| 6730 | } | 7332 | } |
| @@ -6752,6 +7354,9 @@ private: | |||
| 6752 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { | 7354 | if (transformChainEndWithColonItem(chainList, out, usage, assignList)) { |
| 6753 | return; | 7355 | return; |
| 6754 | } | 7356 | } |
| 7357 | if (transformChainEndWithSlice(chainList, out, usage, assignList)) { | ||
| 7358 | return; | ||
| 7359 | } | ||
| 6755 | transformChainList(chainList, out, usage, assignList); | 7360 | transformChainList(chainList, out, usage, assignList); |
| 6756 | } | 7361 | } |
| 6757 | 7362 | ||
| @@ -6848,7 +7453,7 @@ private: | |||
| 6848 | } | 7453 | } |
| 6849 | } | 7454 | } |
| 6850 | } else if (auto comp = sval->value.as<Comprehension_t>()) { | 7455 | } else if (auto comp = sval->value.as<Comprehension_t>()) { |
| 6851 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 7456 | if (!isListComp(comp)) { |
| 6852 | discrete = inExp->new_ptr<ExpList_t>(); | 7457 | discrete = inExp->new_ptr<ExpList_t>(); |
| 6853 | for (ast_node* val : comp->items.objects()) { | 7458 | for (ast_node* val : comp->items.objects()) { |
| 6854 | if (auto def = ast_cast<NormalDef_t>(val)) { | 7459 | if (auto def = ast_cast<NormalDef_t>(val)) { |
| @@ -6877,7 +7482,7 @@ private: | |||
| 6877 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); | 7482 | auto assignment = assignmentFrom(toAst<Exp_t>(checkVar, inExp), newExp(inExp, inExp), inExp); |
| 6878 | auto stmt = x->new_ptr<Statement_t>(); | 7483 | auto stmt = x->new_ptr<Statement_t>(); |
| 6879 | stmt->content.set(assignment); | 7484 | stmt->content.set(assignment); |
| 6880 | block->statements.push_back(stmt); | 7485 | block->statementOrComments.push_back(stmt); |
| 6881 | } | 7486 | } |
| 6882 | if (varName.empty()) { | 7487 | if (varName.empty()) { |
| 6883 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); | 7488 | auto newUnaryExp = x->new_ptr<UnaryExp_t>(); |
| @@ -6889,7 +7494,7 @@ private: | |||
| 6889 | auto assignment = assignmentFrom(assignExp, exp, x); | 7494 | auto assignment = assignmentFrom(assignExp, exp, x); |
| 6890 | auto stmt = x->new_ptr<Statement_t>(); | 7495 | auto stmt = x->new_ptr<Statement_t>(); |
| 6891 | stmt->content.set(assignment); | 7496 | stmt->content.set(assignment); |
| 6892 | block->statements.push_back(stmt); | 7497 | block->statementOrComments.push_back(stmt); |
| 6893 | } | 7498 | } |
| 6894 | auto findVar = getUnusedName("_find_"); | 7499 | auto findVar = getUnusedName("_find_"); |
| 6895 | auto itemVar = getUnusedName("_item_"); | 7500 | auto itemVar = getUnusedName("_item_"); |
| @@ -6905,7 +7510,7 @@ private: | |||
| 6905 | } | 7510 | } |
| 6906 | auto blockStr = clearBuf(); | 7511 | auto blockStr = clearBuf(); |
| 6907 | auto checkBlock = toAst<Block_t>(blockStr, inExp); | 7512 | auto checkBlock = toAst<Block_t>(blockStr, inExp); |
| 6908 | block->statements.dup(checkBlock->statements); | 7513 | block->statementOrComments.dup(checkBlock->statementOrComments); |
| 6909 | auto body = x->new_ptr<Body_t>(); | 7514 | auto body = x->new_ptr<Body_t>(); |
| 6910 | body->content.set(block); | 7515 | body->content.set(block); |
| 6911 | auto doNode = x->new_ptr<Do_t>(); | 7516 | auto doNode = x->new_ptr<Do_t>(); |
| @@ -6925,16 +7530,16 @@ private: | |||
| 6925 | } else { | 7530 | } else { |
| 6926 | auto arrayCheck = [&](bool exist) { | 7531 | auto arrayCheck = [&](bool exist) { |
| 6927 | auto indexVar = getUnusedName("_index_"); | 7532 | auto indexVar = getUnusedName("_index_"); |
| 6928 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nll(x); | 7533 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << checkVar << " do"sv << nl(x); |
| 6929 | incIndentOffset(); | 7534 | incIndentOffset(); |
| 6930 | _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nll(x); | 7535 | _buf << indent() << "if "sv << checkVar << '[' << indexVar << "] == "sv << varName << " then"sv << nl(x); |
| 6931 | incIndentOffset(); | 7536 | incIndentOffset(); |
| 6932 | _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nll(x); | 7537 | _buf << indent() << "return "sv << (exist ? "true"sv : "false"sv) << nl(x); |
| 6933 | decIndentOffset(); | 7538 | decIndentOffset(); |
| 6934 | _buf << indent() << "end"sv << nll(x); | 7539 | _buf << indent() << "end"sv << nl(x); |
| 6935 | decIndentOffset(); | 7540 | decIndentOffset(); |
| 6936 | _buf << indent() << "end"sv << nll(x); | 7541 | _buf << indent() << "end"sv << nl(x); |
| 6937 | _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nll(x); | 7542 | _buf << indent() << "return "sv << (exist ? "false"sv : "true"sv) << nl(x); |
| 6938 | temp.push_back(clearBuf()); | 7543 | temp.push_back(clearBuf()); |
| 6939 | }; | 7544 | }; |
| 6940 | bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); | 7545 | bool useShortCheck = (usage == ExpUsage::Closure) && !varName.empty() && !checkVar.empty() && isLocal(checkVar); |
| @@ -6950,7 +7555,7 @@ private: | |||
| 6950 | pushAnonVarArg(); | 7555 | pushAnonVarArg(); |
| 6951 | pushScope(); | 7556 | pushScope(); |
| 6952 | arrayCheck(true); | 7557 | arrayCheck(true); |
| 6953 | temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nll(x)); | 7558 | temp.push_front("(#"s + checkVar + " > 0 and "s + anonFuncStart() + nl(x)); |
| 6954 | popScope(); | 7559 | popScope(); |
| 6955 | temp.push_back(indent() + anonFuncEnd() + ')'); | 7560 | temp.push_back(indent() + anonFuncEnd() + ')'); |
| 6956 | if (unary_exp->inExp->not_) { | 7561 | if (unary_exp->inExp->not_) { |
| @@ -6987,7 +7592,7 @@ private: | |||
| 6987 | arrayCheck(!unary_exp->inExp->not_); | 7592 | arrayCheck(!unary_exp->inExp->not_); |
| 6988 | } else { | 7593 | } else { |
| 6989 | arrayCheck(!unary_exp->inExp->not_); | 7594 | arrayCheck(!unary_exp->inExp->not_); |
| 6990 | temp.push_front(anonFuncStart() + nll(x)); | 7595 | temp.push_front(anonFuncStart() + nl(x)); |
| 6991 | popScope(); | 7596 | popScope(); |
| 6992 | temp.push_back(indent() + anonFuncEnd()); | 7597 | temp.push_back(indent() + anonFuncEnd()); |
| 6993 | popAnonVarArg(); | 7598 | popAnonVarArg(); |
| @@ -7027,7 +7632,7 @@ private: | |||
| 7027 | pushScope(); | 7632 | pushScope(); |
| 7028 | } else if (usage == ExpUsage::Assignment) { | 7633 | } else if (usage == ExpUsage::Assignment) { |
| 7029 | if (isScoped) { | 7634 | if (isScoped) { |
| 7030 | temp.push_back(indent() + "do"s + nll(x)); | 7635 | temp.push_back(indent() + "do"s + nl(x)); |
| 7031 | pushScope(); | 7636 | pushScope(); |
| 7032 | } | 7637 | } |
| 7033 | } | 7638 | } |
| @@ -7067,10 +7672,10 @@ private: | |||
| 7067 | if (unary_exp->inExp->not_) { | 7672 | if (unary_exp->inExp->not_) { |
| 7068 | _buf << ")"sv; | 7673 | _buf << ")"sv; |
| 7069 | } | 7674 | } |
| 7070 | _buf << nll(x); | 7675 | _buf << nl(x); |
| 7071 | temp.push_back(clearBuf()); | 7676 | temp.push_back(clearBuf()); |
| 7072 | if (usage == ExpUsage::Closure) { | 7677 | if (usage == ExpUsage::Closure) { |
| 7073 | temp.push_front(anonFuncStart() + nll(x)); | 7678 | temp.push_front(anonFuncStart() + nl(x)); |
| 7074 | popScope(); | 7679 | popScope(); |
| 7075 | temp.push_back(indent() + anonFuncEnd()); | 7680 | temp.push_back(indent() + anonFuncEnd()); |
| 7076 | out.push_back(join(temp)); | 7681 | out.push_back(join(temp)); |
| @@ -7079,7 +7684,7 @@ private: | |||
| 7079 | } else if (usage == ExpUsage::Assignment) { | 7684 | } else if (usage == ExpUsage::Assignment) { |
| 7080 | if (isScoped) { | 7685 | if (isScoped) { |
| 7081 | popScope(); | 7686 | popScope(); |
| 7082 | temp.push_back(indent() + "end"s + nll(x)); | 7687 | temp.push_back(indent() + "end"s + nl(x)); |
| 7083 | } | 7688 | } |
| 7084 | out.push_back(join(temp)); | 7689 | out.push_back(join(temp)); |
| 7085 | } else { | 7690 | } else { |
| @@ -7113,7 +7718,7 @@ private: | |||
| 7113 | } | 7718 | } |
| 7114 | _buf << ')'; | 7719 | _buf << ')'; |
| 7115 | if (usage == ExpUsage::Assignment || usage == ExpUsage::Return) { | 7720 | if (usage == ExpUsage::Assignment || usage == ExpUsage::Return) { |
| 7116 | _buf << nll(discrete); | 7721 | _buf << nl(discrete); |
| 7117 | } | 7722 | } |
| 7118 | out.push_back(clearBuf()); | 7723 | out.push_back(clearBuf()); |
| 7119 | } | 7724 | } |
| @@ -7153,7 +7758,7 @@ private: | |||
| 7153 | try { | 7758 | try { |
| 7154 | unsigned long long value = std::stoull(binaryPart, nullptr, 2); | 7759 | unsigned long long value = std::stoull(binaryPart, nullptr, 2); |
| 7155 | numStr = std::to_string(value); | 7760 | numStr = std::to_string(value); |
| 7156 | } catch (const std::exception& e) { | 7761 | } catch (const std::exception&) { |
| 7157 | throw CompileError("invalid binary literal"sv, num); | 7762 | throw CompileError("invalid binary literal"sv, num); |
| 7158 | } | 7763 | } |
| 7159 | } else if (getLuaTarget(num) < 502) { | 7764 | } else if (getLuaTarget(num) < 502) { |
| @@ -7233,7 +7838,7 @@ private: | |||
| 7233 | forceAddToScope(tableVar); | 7838 | forceAddToScope(tableVar); |
| 7234 | auto it = values.begin(); | 7839 | auto it = values.begin(); |
| 7235 | if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 7840 | if (ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { |
| 7236 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nll(x)); | 7841 | temp.push_back(indent() + "local "s + tableVar + " = { }"s + nl(x)); |
| 7237 | } else { | 7842 | } else { |
| 7238 | auto initialTab = x->new_ptr<TableLit_t>(); | 7843 | auto initialTab = x->new_ptr<TableLit_t>(); |
| 7239 | while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { | 7844 | while (it != values.end() && !ast_is<SpreadExp_t, SpreadListExp_t>(*it)) { |
| @@ -7241,7 +7846,7 @@ private: | |||
| 7241 | ++it; | 7846 | ++it; |
| 7242 | } | 7847 | } |
| 7243 | transformTable(initialTab->values.objects(), temp); | 7848 | transformTable(initialTab->values.objects(), temp); |
| 7244 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nll(*it); | 7849 | temp.back() = indent() + "local "s + tableVar + " = "s + temp.back() + nl(*it); |
| 7245 | } | 7850 | } |
| 7246 | for (; it != values.end(); ++it) { | 7851 | for (; it != values.end(); ++it) { |
| 7247 | auto item = *it; | 7852 | auto item = *it; |
| @@ -7261,14 +7866,14 @@ private: | |||
| 7261 | transformAssignment(assignment, temp); | 7866 | transformAssignment(assignment, temp); |
| 7262 | } | 7867 | } |
| 7263 | forceAddToScope(indexVar); | 7868 | forceAddToScope(indexVar); |
| 7264 | temp.push_back(indent() + "local "s + indexVar + " = 1"s + nll(item)); | 7869 | temp.push_back(indent() + "local "s + indexVar + " = 1"s + nl(item)); |
| 7265 | _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar | 7870 | _buf << "for "sv << keyVar << ',' << valueVar << " in pairs "sv << objVar |
| 7266 | << "\n\tif "sv << indexVar << "=="sv << keyVar | 7871 | << "\n\tif "sv << indexVar << "=="sv << keyVar |
| 7267 | << "\n\t\t"sv << tableVar << "[]="sv << valueVar | 7872 | << "\n\t\t"sv << tableVar << "[]="sv << valueVar |
| 7268 | << "\n\t\t"sv << indexVar << "+=1"sv | 7873 | << "\n\t\t"sv << indexVar << "+=1"sv |
| 7269 | << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; | 7874 | << "\n\telse "sv << tableVar << '[' << keyVar << "]="sv << valueVar; |
| 7270 | auto forEach = toAst<ForEach_t>(clearBuf(), item); | 7875 | auto forNode = toAst<For_t>(clearBuf(), item); |
| 7271 | transformForEach(forEach, temp); | 7876 | transformFor(forNode, temp); |
| 7272 | break; | 7877 | break; |
| 7273 | } | 7878 | } |
| 7274 | case id<SpreadListExp_t>(): { | 7879 | case id<SpreadListExp_t>(): { |
| @@ -7285,12 +7890,12 @@ private: | |||
| 7285 | transformAssignment(assignment, temp); | 7890 | transformAssignment(assignment, temp); |
| 7286 | } | 7891 | } |
| 7287 | forceAddToScope(indexVar); | 7892 | forceAddToScope(indexVar); |
| 7288 | temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nll(item)); | 7893 | temp.push_back(indent() + "local "s + indexVar + " = #"s + tableVar + " + 1"s + nl(item)); |
| 7289 | _buf << "for "sv << valueVar << " in *"sv << objVar | 7894 | _buf << "for "sv << valueVar << " in *"sv << objVar |
| 7290 | << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar | 7895 | << "\n\t"sv << tableVar << '[' << indexVar << "]="sv << valueVar |
| 7291 | << "\n\t"sv << indexVar << "+=1"sv; | 7896 | << "\n\t"sv << indexVar << "+=1"sv; |
| 7292 | auto forEach = toAst<ForEach_t>(clearBuf(), item); | 7897 | auto forNode = toAst<For_t>(clearBuf(), item); |
| 7293 | transformForEach(forEach, temp); | 7898 | transformFor(forNode, temp); |
| 7294 | break; | 7899 | break; |
| 7295 | } | 7900 | } |
| 7296 | case id<VariablePair_t>(): | 7901 | case id<VariablePair_t>(): |
| @@ -7468,9 +8073,9 @@ private: | |||
| 7468 | break; | 8073 | break; |
| 7469 | case ExpUsage::Closure: { | 8074 | case ExpUsage::Closure: { |
| 7470 | out.push_back(join(temp)); | 8075 | out.push_back(join(temp)); |
| 7471 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 8076 | out.back().append(indent() + "return "s + tableVar + nl(x)); |
| 7472 | popScope(); | 8077 | popScope(); |
| 7473 | out.back().insert(0, anonFuncStart() + nll(x)); | 8078 | out.back().insert(0, anonFuncStart() + nl(x)); |
| 7474 | out.back().append(indent() + anonFuncEnd()); | 8079 | out.back().append(indent() + anonFuncEnd()); |
| 7475 | popAnonVarArg(); | 8080 | popAnonVarArg(); |
| 7476 | popFunctionScope(); | 8081 | popFunctionScope(); |
| @@ -7486,13 +8091,13 @@ private: | |||
| 7486 | if (extraScope) popScope(); | 8091 | if (extraScope) popScope(); |
| 7487 | out.push_back(join(temp)); | 8092 | out.push_back(join(temp)); |
| 7488 | if (extraScope) { | 8093 | if (extraScope) { |
| 7489 | out.back() = indent() + "do"s + nll(x) + out.back() + indent() + "end"s + nlr(x); | 8094 | out.back() = indent() + "do"s + nl(x) + out.back() + indent() + "end"s + nl(x); |
| 7490 | } | 8095 | } |
| 7491 | break; | 8096 | break; |
| 7492 | } | 8097 | } |
| 7493 | case ExpUsage::Return: | 8098 | case ExpUsage::Return: |
| 7494 | out.push_back(join(temp)); | 8099 | out.push_back(join(temp)); |
| 7495 | out.back().append(indent() + "return "s + tableVar + nlr(x)); | 8100 | out.back().append(indent() + "return "s + tableVar + nl(x)); |
| 7496 | break; | 8101 | break; |
| 7497 | default: | 8102 | default: |
| 7498 | break; | 8103 | break; |
| @@ -7613,11 +8218,11 @@ private: | |||
| 7613 | default: YUEE("AST node mismatch", item); break; | 8218 | default: YUEE("AST node mismatch", item); break; |
| 7614 | } | 8219 | } |
| 7615 | if (!isMetamethod) { | 8220 | if (!isMetamethod) { |
| 7616 | temp.back() = indent() + (value == values.back() ? temp.back() : temp.back() + ',') + nll(value); | 8221 | temp.back() = indent() + (value == values.back() ? temp.back() : temp.back() + ',') + nl(value); |
| 7617 | } | 8222 | } |
| 7618 | } | 8223 | } |
| 7619 | if (metatable->pairs.empty() && !metatableItem) { | 8224 | if (metatable->pairs.empty() && !metatableItem) { |
| 7620 | out.push_back('{' + nll(x) + join(temp)); | 8225 | out.push_back('{' + nl(x) + join(temp)); |
| 7621 | decIndentOffset(); | 8226 | decIndentOffset(); |
| 7622 | out.back() += (indent() + '}'); | 8227 | out.back() += (indent() + '}'); |
| 7623 | } else { | 8228 | } else { |
| @@ -7627,7 +8232,7 @@ private: | |||
| 7627 | decIndentOffset(); | 8232 | decIndentOffset(); |
| 7628 | tabStr += "{ }"sv; | 8233 | tabStr += "{ }"sv; |
| 7629 | } else { | 8234 | } else { |
| 7630 | tabStr += ('{' + nll(x) + join(temp)); | 8235 | tabStr += ('{' + nl(x) + join(temp)); |
| 7631 | decIndentOffset(); | 8236 | decIndentOffset(); |
| 7632 | tabStr += (indent() + '}'); | 8237 | tabStr += (indent() + '}'); |
| 7633 | } | 8238 | } |
| @@ -7671,18 +8276,18 @@ private: | |||
| 7671 | void transformCompCommon(Comprehension_t* comp, str_list& out) { | 8276 | void transformCompCommon(Comprehension_t* comp, str_list& out) { |
| 7672 | str_list temp; | 8277 | str_list temp; |
| 7673 | auto x = comp; | 8278 | auto x = comp; |
| 7674 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | 8279 | auto compFor = static_cast<CompFor_t*>(comp->items.back()); |
| 7675 | for (auto item : compInner->items.objects()) { | 8280 | for (auto item : compFor->items.objects()) { |
| 7676 | switch (item->get_id()) { | 8281 | switch (item->get_id()) { |
| 7677 | case id<CompForEach_t>(): | 8282 | case id<CompForEach_t>(): |
| 7678 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 8283 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 7679 | break; | 8284 | break; |
| 7680 | case id<CompFor_t>(): | 8285 | case id<CompForNum_t>(): |
| 7681 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 8286 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 7682 | break; | 8287 | break; |
| 7683 | case id<Exp_t>(): | 8288 | case id<Exp_t>(): |
| 7684 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 8289 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 7685 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 8290 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 7686 | pushScope(); | 8291 | pushScope(); |
| 7687 | break; | 8292 | break; |
| 7688 | default: YUEE("AST node mismatch", item); break; | 8293 | default: YUEE("AST node mismatch", item); break; |
| @@ -7702,16 +8307,16 @@ private: | |||
| 7702 | auto value = std::move(temp.back()); | 8307 | auto value = std::move(temp.back()); |
| 7703 | temp.pop_back(); | 8308 | temp.pop_back(); |
| 7704 | _buf << join(temp) << value; | 8309 | _buf << join(temp) << value; |
| 7705 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 8310 | for (size_t i = 0; i < compFor->items.objects().size(); ++i) { |
| 7706 | popScope(); | 8311 | popScope(); |
| 7707 | _buf << indent() << "end"sv << nll(comp); | 8312 | _buf << indent() << "end"sv << nl(comp); |
| 7708 | } | 8313 | } |
| 7709 | out.push_back(clearBuf()); | 8314 | out.push_back(clearBuf()); |
| 7710 | } | 8315 | } |
| 7711 | 8316 | ||
| 7712 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8317 | void transformComprehension(Comprehension_t* comp, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 7713 | auto x = comp; | 8318 | auto x = comp; |
| 7714 | if (comp->items.size() != 2 || !ast_is<CompInner_t>(comp->items.back())) { | 8319 | if (!isListComp(comp)) { |
| 7715 | switch (usage) { | 8320 | switch (usage) { |
| 7716 | case ExpUsage::Assignment: { | 8321 | case ExpUsage::Assignment: { |
| 7717 | auto tableLit = x->new_ptr<TableLit_t>(); | 8322 | auto tableLit = x->new_ptr<TableLit_t>(); |
| @@ -7733,11 +8338,7 @@ private: | |||
| 7733 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | 8338 | auto simpleValue = x->new_ptr<SimpleValue_t>(); |
| 7734 | simpleValue->value.set(tableLit); | 8339 | simpleValue->value.set(tableLit); |
| 7735 | auto exp = newExp(simpleValue, x); | 8340 | auto exp = newExp(simpleValue, x); |
| 7736 | auto returnNode = x->new_ptr<Return_t>(); | 8341 | auto returnNode = newReturn(exp); |
| 7737 | returnNode->explicitReturn = false; | ||
| 7738 | auto expList = x->new_ptr<ExpListLow_t>(); | ||
| 7739 | expList->exprs.push_back(exp); | ||
| 7740 | returnNode->valueList.set(expList); | ||
| 7741 | transformReturn(returnNode, out); | 8342 | transformReturn(returnNode, out); |
| 7742 | break; | 8343 | break; |
| 7743 | } | 8344 | } |
| @@ -7750,9 +8351,16 @@ private: | |||
| 7750 | } | 8351 | } |
| 7751 | return; | 8352 | return; |
| 7752 | } | 8353 | } |
| 7753 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | 8354 | ast_node* value = nullptr; |
| 7754 | if (!def || def->defVal) { | 8355 | bool isSpread = ast_is<SpreadListExp_t>(comp->items.front()); |
| 7755 | throw CompileError("invalid comprehension expression", comp->items.front()); | 8356 | if (isSpread) { |
| 8357 | value = comp->items.front(); | ||
| 8358 | } else { | ||
| 8359 | auto def = ast_cast<NormalDef_t>(comp->items.front()); | ||
| 8360 | if (!def || def->defVal) { | ||
| 8361 | throw CompileError("invalid comprehension expression", comp->items.front()); | ||
| 8362 | } | ||
| 8363 | value = def->item.get(); | ||
| 7756 | } | 8364 | } |
| 7757 | bool extraScope = false; | 8365 | bool extraScope = false; |
| 7758 | switch (usage) { | 8366 | switch (usage) { |
| @@ -7776,31 +8384,33 @@ private: | |||
| 7776 | default: | 8384 | default: |
| 7777 | break; | 8385 | break; |
| 7778 | } | 8386 | } |
| 7779 | auto value = def->item.get(); | 8387 | auto compFor = static_cast<CompFor_t*>(comp->items.back()); |
| 7780 | auto compInner = static_cast<CompInner_t*>(comp->items.back()); | ||
| 7781 | str_list temp; | 8388 | str_list temp; |
| 7782 | std::string accumVar = getUnusedName("_accum_"sv); | 8389 | std::string accumVar = getUnusedName("_accum_"sv); |
| 7783 | std::string lenVar = getUnusedName("_len_"sv); | ||
| 7784 | addToScope(accumVar); | 8390 | addToScope(accumVar); |
| 7785 | addToScope(lenVar); | 8391 | std::string lenVar; |
| 7786 | for (auto item : compInner->items.objects()) { | 8392 | if (!isSpread) { |
| 8393 | lenVar = getUnusedName("_len_"sv); | ||
| 8394 | addToScope(lenVar); | ||
| 8395 | } | ||
| 8396 | for (auto item : compFor->items.objects()) { | ||
| 7787 | switch (item->get_id()) { | 8397 | switch (item->get_id()) { |
| 7788 | case id<CompForEach_t>(): | 8398 | case id<CompForEach_t>(): |
| 7789 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 8399 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 7790 | break; | 8400 | break; |
| 7791 | case id<CompFor_t>(): | 8401 | case id<CompForNum_t>(): |
| 7792 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 8402 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 7793 | break; | 8403 | break; |
| 7794 | case id<Exp_t>(): | 8404 | case id<Exp_t>(): |
| 7795 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 8405 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 7796 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 8406 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 7797 | pushScope(); | 8407 | pushScope(); |
| 7798 | break; | 8408 | break; |
| 7799 | default: YUEE("AST node mismatch", item); break; | 8409 | default: YUEE("AST node mismatch", item); break; |
| 7800 | } | 8410 | } |
| 7801 | } | 8411 | } |
| 7802 | { | 8412 | { |
| 7803 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 8413 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + (isSpread ? "]"s : lenVar + ']'), x); |
| 7804 | auto assign = x->new_ptr<Assign_t>(); | 8414 | auto assign = x->new_ptr<Assign_t>(); |
| 7805 | assign->values.push_back(value); | 8415 | assign->values.push_back(value); |
| 7806 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8416 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -7810,25 +8420,30 @@ private: | |||
| 7810 | } | 8420 | } |
| 7811 | auto assignStr = std::move(temp.back()); | 8421 | auto assignStr = std::move(temp.back()); |
| 7812 | temp.pop_back(); | 8422 | temp.pop_back(); |
| 7813 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 8423 | for (size_t i = 0; i < compFor->items.objects().size(); ++i) { |
| 7814 | popScope(); | 8424 | popScope(); |
| 7815 | } | 8425 | } |
| 7816 | _buf << indent() << "local "sv << accumVar << " = { }"sv << nll(comp); | 8426 | _buf << indent() << "local "sv << accumVar << " = { }"sv << nl(comp); |
| 7817 | _buf << indent() << "local "sv << lenVar << " = 1"sv << nll(comp); | 8427 | if (isSpread) { |
| 7818 | _buf << join(temp); | 8428 | _buf << join(temp); |
| 7819 | _buf << assignStr; | 8429 | _buf << assignStr; |
| 7820 | _buf << indent(int(temp.size())) << lenVar << " = "sv << lenVar << " + 1"sv << nll(comp); | 8430 | } else { |
| 8431 | _buf << indent() << "local "sv << lenVar << " = 1"sv << nl(comp); | ||
| 8432 | _buf << join(temp); | ||
| 8433 | _buf << assignStr; | ||
| 8434 | _buf << indent(int(temp.size())) << lenVar << " = "sv << lenVar << " + 1"sv << nl(comp); | ||
| 8435 | } | ||
| 7821 | for (int ind = int(temp.size()) - 1; ind > -1; --ind) { | 8436 | for (int ind = int(temp.size()) - 1; ind > -1; --ind) { |
| 7822 | _buf << indent(ind) << "end"sv << nll(comp); | 8437 | _buf << indent(ind) << "end"sv << nl(comp); |
| 7823 | } | 8438 | } |
| 7824 | switch (usage) { | 8439 | switch (usage) { |
| 7825 | case ExpUsage::Common: | 8440 | case ExpUsage::Common: |
| 7826 | break; | 8441 | break; |
| 7827 | case ExpUsage::Closure: { | 8442 | case ExpUsage::Closure: { |
| 7828 | out.push_back(clearBuf()); | 8443 | out.push_back(clearBuf()); |
| 7829 | out.back().append(indent() + "return "s + accumVar + nlr(comp)); | 8444 | out.back().append(indent() + "return "s + accumVar + nl(comp)); |
| 7830 | popScope(); | 8445 | popScope(); |
| 7831 | out.back().insert(0, anonFuncStart() + nll(comp)); | 8446 | out.back().insert(0, anonFuncStart() + nl(comp)); |
| 7832 | out.back().append(indent() + anonFuncEnd()); | 8447 | out.back().append(indent() + anonFuncEnd()); |
| 7833 | popAnonVarArg(); | 8448 | popAnonVarArg(); |
| 7834 | popFunctionScope(); | 8449 | popFunctionScope(); |
| @@ -7845,13 +8460,13 @@ private: | |||
| 7845 | out.back().append(temp.back()); | 8460 | out.back().append(temp.back()); |
| 7846 | if (extraScope) { | 8461 | if (extraScope) { |
| 7847 | popScope(); | 8462 | popScope(); |
| 7848 | out.back() = indent() + "do"s + nll(comp) + out.back() + indent() + "end"s + nlr(comp); | 8463 | out.back() = indent() + "do"s + nl(comp) + out.back() + indent() + "end"s + nl(comp); |
| 7849 | } | 8464 | } |
| 7850 | break; | 8465 | break; |
| 7851 | } | 8466 | } |
| 7852 | case ExpUsage::Return: | 8467 | case ExpUsage::Return: |
| 7853 | out.push_back(clearBuf()); | 8468 | out.push_back(clearBuf()); |
| 7854 | out.back().append(indent() + "return "s + accumVar + nlr(comp)); | 8469 | out.back().append(indent() + "return "s + accumVar + nl(comp)); |
| 7855 | break; | 8470 | break; |
| 7856 | default: | 8471 | default: |
| 7857 | break; | 8472 | break; |
| @@ -7859,6 +8474,11 @@ private: | |||
| 7859 | } | 8474 | } |
| 7860 | 8475 | ||
| 7861 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { | 8476 | bool transformForEachHead(AssignableNameList_t* nameList, ast_node* loopTarget, str_list& out, bool inClosure) { |
| 8477 | enum class NumState { | ||
| 8478 | Unknown, | ||
| 8479 | Positive, | ||
| 8480 | Negtive | ||
| 8481 | }; | ||
| 7862 | auto x = nameList; | 8482 | auto x = nameList; |
| 7863 | str_list temp; | 8483 | str_list temp; |
| 7864 | str_list vars; | 8484 | str_list vars; |
| @@ -7877,13 +8497,8 @@ private: | |||
| 7877 | varConstAfter = vars.back(); | 8497 | varConstAfter = vars.back(); |
| 7878 | } | 8498 | } |
| 7879 | break; | 8499 | break; |
| 7880 | case id<TableLit_t>(): { | 8500 | case id<SimpleTable_t>(): |
| 7881 | auto desVar = getUnusedName("_des_"sv); | 8501 | case id<TableLit_t>(): |
| 7882 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); | ||
| 7883 | vars.push_back(desVar); | ||
| 7884 | varAfter.push_back(desVar); | ||
| 7885 | break; | ||
| 7886 | } | ||
| 7887 | case id<Comprehension_t>(): { | 8502 | case id<Comprehension_t>(): { |
| 7888 | auto desVar = getUnusedName("_des_"sv); | 8503 | auto desVar = getUnusedName("_des_"sv); |
| 7889 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); | 8504 | destructPairs.emplace_back(item, toAst<Exp_t>(desVar, x)); |
| @@ -7925,15 +8540,35 @@ private: | |||
| 7925 | for (auto item : chainList) { | 8540 | for (auto item : chainList) { |
| 7926 | chain->items.push_back(item); | 8541 | chain->items.push_back(item); |
| 7927 | } | 8542 | } |
| 7928 | std::string startValue("1"sv); | 8543 | std::string startValue; |
| 8544 | NumState startStatus = NumState::Unknown; | ||
| 7929 | if (auto exp = slice->startValue.as<Exp_t>()) { | 8545 | if (auto exp = slice->startValue.as<Exp_t>()) { |
| 7930 | transformExp(exp, temp, ExpUsage::Closure); | 8546 | transformExp(exp, temp, ExpUsage::Closure); |
| 8547 | if (temp.back().at(0) == '-') { | ||
| 8548 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
| 8549 | startStatus = NumState::Negtive; | ||
| 8550 | } | ||
| 8551 | } else { | ||
| 8552 | if (_parser.match<Num_t>(temp.back())) { | ||
| 8553 | startStatus = NumState::Positive; | ||
| 8554 | } | ||
| 8555 | } | ||
| 7931 | startValue = std::move(temp.back()); | 8556 | startValue = std::move(temp.back()); |
| 7932 | temp.pop_back(); | 8557 | temp.pop_back(); |
| 7933 | } | 8558 | } |
| 7934 | std::string stopValue; | 8559 | std::string stopValue; |
| 8560 | NumState stopStatus = NumState::Unknown; | ||
| 7935 | if (auto exp = slice->stopValue.as<Exp_t>()) { | 8561 | if (auto exp = slice->stopValue.as<Exp_t>()) { |
| 7936 | transformExp(exp, temp, ExpUsage::Closure); | 8562 | transformExp(exp, temp, ExpUsage::Closure); |
| 8563 | if (temp.back().at(0) == '-') { | ||
| 8564 | if (_parser.match<Num_t>(temp.back().substr(1))) { | ||
| 8565 | stopStatus = NumState::Negtive; | ||
| 8566 | } | ||
| 8567 | } else { | ||
| 8568 | if (_parser.match<Num_t>(temp.back())) { | ||
| 8569 | stopStatus = NumState::Positive; | ||
| 8570 | } | ||
| 8571 | } | ||
| 7937 | stopValue = std::move(temp.back()); | 8572 | stopValue = std::move(temp.back()); |
| 7938 | temp.pop_back(); | 8573 | temp.pop_back(); |
| 7939 | } | 8574 | } |
| @@ -7947,38 +8582,94 @@ private: | |||
| 7947 | std::string prefix; | 8582 | std::string prefix; |
| 7948 | if (!inClosure && needScope) { | 8583 | if (!inClosure && needScope) { |
| 7949 | extraScope = true; | 8584 | extraScope = true; |
| 7950 | prefix = indent() + "do"s + nll(x); | 8585 | prefix = indent() + "do"s + nl(x); |
| 7951 | pushScope(); | 8586 | pushScope(); |
| 7952 | } | 8587 | } |
| 7953 | listVar = getUnusedName("_list_"sv); | 8588 | listVar = getUnusedName("_list_"sv); |
| 7954 | varBefore.push_back(listVar); | 8589 | varBefore.push_back(listVar); |
| 7955 | transformChainValue(chain, temp, ExpUsage::Closure); | 8590 | transformChainValue(chain, temp, ExpUsage::Closure); |
| 7956 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8591 | _buf << prefix << indent() << "local "sv << listVar << " = "sv << temp.back() << nl(nameList); |
| 8592 | } | ||
| 8593 | if (startValue.empty()) { | ||
| 8594 | startValue = "1"s; | ||
| 8595 | startStatus = NumState::Positive; | ||
| 8596 | } | ||
| 8597 | std::string minVar; | ||
| 8598 | if (startStatus != NumState::Positive) { | ||
| 8599 | std::string prefix; | ||
| 8600 | if (!extraScope && !inClosure && needScope) { | ||
| 8601 | extraScope = true; | ||
| 8602 | prefix = indent() + "do"s + nl(x); | ||
| 8603 | pushScope(); | ||
| 8604 | } | ||
| 8605 | minVar = getUnusedName("_min_"sv); | ||
| 8606 | varBefore.push_back(minVar); | ||
| 8607 | if (startStatus == NumState::Negtive) { | ||
| 8608 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << "#"sv << listVar << " + "sv << startValue << " + 1"sv << nl(nameList); | ||
| 8609 | } else { | ||
| 8610 | _buf << prefix << indent() << "local "sv << minVar << " = "sv << startValue << nl(nameList); | ||
| 8611 | } | ||
| 8612 | } | ||
| 8613 | bool defaultStop = false; | ||
| 8614 | if (stopValue.empty()) { | ||
| 8615 | stopValue = "#"s + listVar; | ||
| 8616 | defaultStop = true; | ||
| 7957 | } | 8617 | } |
| 7958 | std::string maxVar; | 8618 | std::string maxVar; |
| 7959 | if (!stopValue.empty()) { | 8619 | if (stopStatus != NumState::Positive) { |
| 7960 | std::string prefix; | 8620 | std::string prefix; |
| 7961 | if (!extraScope && !inClosure && needScope) { | 8621 | if (!extraScope && !inClosure && needScope) { |
| 7962 | extraScope = true; | 8622 | extraScope = true; |
| 7963 | prefix = indent() + "do"s + nll(x); | 8623 | prefix = indent() + "do"s + nl(x); |
| 7964 | pushScope(); | 8624 | pushScope(); |
| 7965 | } | 8625 | } |
| 7966 | maxVar = getUnusedName("_max_"sv); | 8626 | maxVar = getUnusedName("_max_"sv); |
| 7967 | varBefore.push_back(maxVar); | 8627 | varBefore.push_back(maxVar); |
| 7968 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nll(nameList); | 8628 | if (stopStatus == NumState::Negtive) { |
| 8629 | _buf << indent() << "local "sv << maxVar << " = "sv << "#"sv << listVar << " + "sv << stopValue << " + 1"sv << nl(nameList); | ||
| 8630 | } else { | ||
| 8631 | _buf << prefix << indent() << "local "sv << maxVar << " = "sv << stopValue << nl(nameList); | ||
| 8632 | } | ||
| 8633 | } | ||
| 8634 | if (startStatus == NumState::Unknown) { | ||
| 8635 | _buf << indent() << minVar << " = "sv << minVar << " < 0 and #"sv << listVar << " + "sv << minVar << " + 1 or "sv << minVar << nl(nameList); | ||
| 8636 | } | ||
| 8637 | if (!defaultStop && stopStatus == NumState::Unknown) { | ||
| 8638 | _buf << indent() << maxVar << " = "sv << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " + 1 or "sv << maxVar << nl(nameList); | ||
| 7969 | } | 8639 | } |
| 7970 | _buf << indent() << "for "sv << indexVar << " = "sv; | 8640 | _buf << indent() << "for "sv << indexVar << " = "sv; |
| 7971 | _buf << startValue << ", "sv; | 8641 | if (startValue.empty()) { |
| 8642 | _buf << "1"sv; | ||
| 8643 | } else { | ||
| 8644 | switch (startStatus) { | ||
| 8645 | case NumState::Unknown: | ||
| 8646 | case NumState::Negtive: | ||
| 8647 | _buf << minVar; | ||
| 8648 | break; | ||
| 8649 | case NumState::Positive: | ||
| 8650 | _buf << startValue; | ||
| 8651 | break; | ||
| 8652 | } | ||
| 8653 | } | ||
| 8654 | _buf << ", "sv; | ||
| 7972 | if (stopValue.empty()) { | 8655 | if (stopValue.empty()) { |
| 7973 | _buf << "#"sv << listVar; | 8656 | _buf << "#"sv << listVar; |
| 7974 | } else { | 8657 | } else { |
| 7975 | _buf << maxVar << " < 0 and #"sv << listVar << " + "sv << maxVar << " or "sv << maxVar; | 8658 | switch (stopStatus) { |
| 8659 | case NumState::Unknown: | ||
| 8660 | case NumState::Negtive: | ||
| 8661 | _buf << maxVar; | ||
| 8662 | break; | ||
| 8663 | case NumState::Positive: | ||
| 8664 | _buf << stopValue; | ||
| 8665 | break; | ||
| 8666 | } | ||
| 7976 | } | 8667 | } |
| 7977 | if (!stepValue.empty()) { | 8668 | if (!stepValue.empty()) { |
| 7978 | _buf << ", "sv << stepValue; | 8669 | _buf << ", "sv << stepValue; |
| 7979 | } | 8670 | } |
| 7980 | _buf << " do"sv << nlr(loopTarget); | 8671 | _buf << " do"sv << nl(loopTarget); |
| 7981 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); | 8672 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nl(nameList); |
| 7982 | out.push_back(clearBuf()); | 8673 | out.push_back(clearBuf()); |
| 7983 | BLOCK_END | 8674 | BLOCK_END |
| 7984 | bool newListVal = false; | 8675 | bool newListVal = false; |
| @@ -7989,21 +8680,21 @@ private: | |||
| 7989 | } | 8680 | } |
| 7990 | if (!endWithSlice) { | 8681 | if (!endWithSlice) { |
| 7991 | transformExp(star_exp->value, temp, ExpUsage::Closure); | 8682 | transformExp(star_exp->value, temp, ExpUsage::Closure); |
| 7992 | if (newListVal) _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nll(nameList); | 8683 | if (newListVal) _buf << indent() << "local "sv << listVar << " = "sv << temp.back() << nl(nameList); |
| 7993 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << listVar << " do"sv << nlr(loopTarget); | 8684 | _buf << indent() << "for "sv << indexVar << " = 1, #"sv << listVar << " do"sv << nl(loopTarget); |
| 7994 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nll(nameList); | 8685 | _buf << indent(1) << "local "sv << join(vars, ", "sv) << " = "sv << listVar << "["sv << indexVar << "]"sv << nl(nameList); |
| 7995 | out.push_back(clearBuf()); | 8686 | out.push_back(clearBuf()); |
| 7996 | } | 8687 | } |
| 7997 | break; | 8688 | break; |
| 7998 | } | 8689 | } |
| 7999 | case id<Exp_t>(): | 8690 | case id<Exp_t>(): |
| 8000 | transformExp(static_cast<Exp_t*>(loopTarget), temp, ExpUsage::Closure); | 8691 | transformExp(static_cast<Exp_t*>(loopTarget), temp, ExpUsage::Closure); |
| 8001 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); | 8692 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nl(loopTarget); |
| 8002 | out.push_back(clearBuf()); | 8693 | out.push_back(clearBuf()); |
| 8003 | break; | 8694 | break; |
| 8004 | case id<ExpList_t>(): | 8695 | case id<ExpList_t>(): |
| 8005 | transformExpList(static_cast<ExpList_t*>(loopTarget), temp); | 8696 | transformExpList(static_cast<ExpList_t*>(loopTarget), temp); |
| 8006 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nlr(loopTarget); | 8697 | _buf << indent() << "for "sv << join(vars, ", "sv) << " in "sv << temp.back() << " do"sv << nl(loopTarget); |
| 8007 | out.push_back(clearBuf()); | 8698 | out.push_back(clearBuf()); |
| 8008 | break; | 8699 | break; |
| 8009 | default: YUEE("AST node mismatch", loopTarget); break; | 8700 | default: YUEE("AST node mismatch", loopTarget); break; |
| @@ -8012,15 +8703,22 @@ private: | |||
| 8012 | pushScope(); | 8703 | pushScope(); |
| 8013 | for (const auto& var : vars) forceAddToScope(var); | 8704 | for (const auto& var : vars) forceAddToScope(var); |
| 8014 | for (const auto& var : varAfter) addToScope(var); | 8705 | for (const auto& var : varAfter) addToScope(var); |
| 8015 | if (!varConstAfter.empty()) markVarConst(varConstAfter); | 8706 | if (!varConstAfter.empty()) markVarLocalConst(varConstAfter); |
| 8016 | if (!destructPairs.empty()) { | 8707 | if (!destructPairs.empty()) { |
| 8017 | temp.clear(); | 8708 | temp.clear(); |
| 8018 | for (auto& pair : destructPairs) { | 8709 | for (auto& pair : destructPairs) { |
| 8019 | auto sValue = x->new_ptr<SimpleValue_t>(); | ||
| 8020 | sValue->value.set(pair.first); | ||
| 8021 | auto exp = newExp(sValue, x); | ||
| 8022 | auto expList = x->new_ptr<ExpList_t>(); | 8710 | auto expList = x->new_ptr<ExpList_t>(); |
| 8023 | expList->exprs.push_back(exp); | 8711 | if (ast_is<SimpleTable_t>(pair.first)) { |
| 8712 | auto value = x->new_ptr<Value_t>(); | ||
| 8713 | value->item.set(pair.first); | ||
| 8714 | auto exp = newExp(value, x); | ||
| 8715 | expList->exprs.push_back(exp); | ||
| 8716 | } else { | ||
| 8717 | auto sValue = x->new_ptr<SimpleValue_t>(); | ||
| 8718 | sValue->value.set(pair.first); | ||
| 8719 | auto exp = newExp(sValue, x); | ||
| 8720 | expList->exprs.push_back(exp); | ||
| 8721 | } | ||
| 8024 | auto assign = x->new_ptr<Assign_t>(); | 8722 | auto assign = x->new_ptr<Assign_t>(); |
| 8025 | assign->values.push_back(pair.second); | 8723 | assign->values.push_back(pair.second); |
| 8026 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 8724 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -8080,7 +8778,7 @@ private: | |||
| 8080 | out.push_back('(' + join(temp, ", "sv) + ')'); | 8778 | out.push_back('(' + join(temp, ", "sv) + ')'); |
| 8081 | } | 8779 | } |
| 8082 | 8780 | ||
| 8083 | void transformForHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { | 8781 | void transformForNumHead(Variable_t* var, Exp_t* startVal, Exp_t* stopVal, ForStepValue_t* stepVal, str_list& out) { |
| 8084 | str_list temp; | 8782 | str_list temp; |
| 8085 | std::string varName = variableToString(var); | 8783 | std::string varName = variableToString(var); |
| 8086 | transformExp(startVal, temp, ExpUsage::Closure); | 8784 | transformExp(startVal, temp, ExpUsage::Closure); |
| @@ -8094,37 +8792,70 @@ private: | |||
| 8094 | const auto& start = *it; | 8792 | const auto& start = *it; |
| 8095 | const auto& stop = *(++it); | 8793 | const auto& stop = *(++it); |
| 8096 | const auto& step = *(++it); | 8794 | const auto& step = *(++it); |
| 8097 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nll(var); | 8795 | _buf << indent() << "for "sv << varName << " = "sv << start << ", "sv << stop << (step.empty() ? Empty : ", "s + step) << " do"sv << nl(var); |
| 8098 | pushScope(); | 8796 | pushScope(); |
| 8099 | forceAddToScope(varName); | 8797 | forceAddToScope(varName); |
| 8100 | markVarConst(varName); | 8798 | markVarLocalConst(varName); |
| 8101 | out.push_back(clearBuf()); | 8799 | out.push_back(clearBuf()); |
| 8102 | } | 8800 | } |
| 8103 | 8801 | ||
| 8104 | void transformForHead(For_t* forNode, str_list& out) { | 8802 | void transformForNumHead(ForNum_t* forNum, str_list& out) { |
| 8105 | transformForHead(forNode->varName, forNode->startValue, forNode->stopValue, forNode->stepValue, out); | 8803 | transformForNumHead(forNum->varName, forNum->startValue, forNum->stopValue, forNum->stepValue, out); |
| 8106 | } | 8804 | } |
| 8107 | 8805 | ||
| 8108 | void transform_plain_body(ast_node* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8806 | void transform_plain_body(ast_node* bodyOrStmt, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 8109 | switch (body->get_id()) { | 8807 | switch (bodyOrStmt->get_id()) { |
| 8110 | case id<Block_t>(): | 8808 | case id<Block_t>(): |
| 8111 | transformBlock(static_cast<Block_t*>(body), out, usage, assignList); | 8809 | transformBlock(static_cast<Block_t*>(bodyOrStmt), out, usage, assignList); |
| 8112 | break; | 8810 | break; |
| 8113 | case id<Statement_t>(): { | 8811 | case id<Statement_t>(): { |
| 8114 | auto newBlock = body->new_ptr<Block_t>(); | 8812 | auto newBlock = bodyOrStmt->new_ptr<Block_t>(); |
| 8115 | newBlock->statements.push_back(body); | 8813 | newBlock->statementOrComments.push_back(bodyOrStmt); |
| 8116 | transformBlock(newBlock, out, usage, assignList); | 8814 | transformBlock(newBlock, out, usage, assignList); |
| 8117 | break; | 8815 | break; |
| 8118 | } | 8816 | } |
| 8119 | default: YUEE("AST node mismatch", body); break; | 8817 | default: YUEE("AST node mismatch", bodyOrStmt); break; |
| 8120 | } | 8818 | } |
| 8121 | } | 8819 | } |
| 8122 | 8820 | ||
| 8123 | bool hasContinueStatement(ast_node* body) { | 8821 | enum class BreakLoopType { |
| 8124 | return traversal::Stop == body->traverse([&](ast_node* node) { | 8822 | None = 0, |
| 8823 | Break = 1, | ||
| 8824 | BreakWithValue = 1 << 1, | ||
| 8825 | Continue = 1 << 2 | ||
| 8826 | }; | ||
| 8827 | |||
| 8828 | bool hasBreak(uint32_t breakLoopType) const { | ||
| 8829 | return (breakLoopType & int(BreakLoopType::Break)) != 0; | ||
| 8830 | } | ||
| 8831 | |||
| 8832 | bool hasBreakWithValue(uint32_t breakLoopType) const { | ||
| 8833 | return (breakLoopType & int(BreakLoopType::BreakWithValue)) != 0; | ||
| 8834 | } | ||
| 8835 | |||
| 8836 | bool hasContinue(uint32_t breakLoopType) const { | ||
| 8837 | return (breakLoopType & int(BreakLoopType::Continue)) != 0; | ||
| 8838 | } | ||
| 8839 | |||
| 8840 | uint32_t getBreakLoopType(ast_node* body, const std::string& varBWV) { | ||
| 8841 | uint32_t type = 0; | ||
| 8842 | body->traverse([&](ast_node* node) { | ||
| 8125 | if (auto stmt = ast_cast<Statement_t>(node)) { | 8843 | if (auto stmt = ast_cast<Statement_t>(node)) { |
| 8126 | if (stmt->content.is<BreakLoop_t>()) { | 8844 | if (auto breakLoop = stmt->content.as<BreakLoop_t>()) { |
| 8127 | return _parser.toString(stmt->content) == "continue"sv ? traversal::Stop : traversal::Return; | 8845 | if (breakLoop->type.is<Continue_t>()) { |
| 8846 | type |= int(BreakLoopType::Continue); | ||
| 8847 | return traversal::Return; | ||
| 8848 | } else { | ||
| 8849 | if (breakLoop->value) { | ||
| 8850 | if (varBWV.empty()) { | ||
| 8851 | throw CompileError("break with a value is not allowed here"sv, breakLoop->value); | ||
| 8852 | } | ||
| 8853 | type |= int(BreakLoopType::BreakWithValue); | ||
| 8854 | breakLoop->varBWV = varBWV; | ||
| 8855 | } else { | ||
| 8856 | type |= int(BreakLoopType::Break); | ||
| 8857 | } | ||
| 8858 | } | ||
| 8128 | } else if (auto expList = expListFrom(stmt)) { | 8859 | } else if (auto expList = expListFrom(stmt)) { |
| 8129 | BLOCK_START | 8860 | BLOCK_START |
| 8130 | auto value = singleValueFrom(expList); | 8861 | auto value = singleValueFrom(expList); |
| @@ -8135,40 +8866,30 @@ private: | |||
| 8135 | switch (sVal->get_id()) { | 8866 | switch (sVal->get_id()) { |
| 8136 | case id<With_t>(): { | 8867 | case id<With_t>(): { |
| 8137 | auto withNode = static_cast<With_t*>(sVal); | 8868 | auto withNode = static_cast<With_t*>(sVal); |
| 8138 | if (hasContinueStatement(withNode->body)) { | 8869 | type |= getBreakLoopType(withNode->body, varBWV); |
| 8139 | return traversal::Stop; | 8870 | return traversal::Return; |
| 8140 | } | ||
| 8141 | break; | ||
| 8142 | } | 8871 | } |
| 8143 | case id<Do_t>(): { | 8872 | case id<Do_t>(): { |
| 8144 | auto doNode = static_cast<Do_t*>(sVal); | 8873 | auto doNode = static_cast<Do_t*>(sVal); |
| 8145 | if (hasContinueStatement(doNode->body)) { | 8874 | type |= getBreakLoopType(doNode->body, varBWV); |
| 8146 | return traversal::Stop; | 8875 | return traversal::Return; |
| 8147 | } | ||
| 8148 | break; | ||
| 8149 | } | 8876 | } |
| 8150 | case id<If_t>(): { | 8877 | case id<If_t>(): { |
| 8151 | auto ifNode = static_cast<If_t*>(sVal); | 8878 | auto ifNode = static_cast<If_t*>(sVal); |
| 8152 | for (auto n : ifNode->nodes.objects()) { | 8879 | for (auto n : ifNode->nodes.objects()) { |
| 8153 | if (hasContinueStatement(n)) { | 8880 | type |= getBreakLoopType(n, varBWV); |
| 8154 | return traversal::Stop; | ||
| 8155 | } | ||
| 8156 | } | 8881 | } |
| 8157 | break; | 8882 | return traversal::Return; |
| 8158 | } | 8883 | } |
| 8159 | case id<Switch_t>(): { | 8884 | case id<Switch_t>(): { |
| 8160 | auto switchNode = static_cast<Switch_t*>(sVal); | 8885 | auto switchNode = static_cast<Switch_t*>(sVal); |
| 8161 | for (auto branch : switchNode->branches.objects()) { | 8886 | for (auto branch : switchNode->branches.objects()) { |
| 8162 | if (hasContinueStatement(static_cast<SwitchCase_t*>(branch)->body)) { | 8887 | type |= getBreakLoopType(static_cast<SwitchCase_t*>(branch)->body, varBWV); |
| 8163 | return traversal::Stop; | ||
| 8164 | } | ||
| 8165 | } | 8888 | } |
| 8166 | if (switchNode->lastBranch) { | 8889 | if (switchNode->lastBranch) { |
| 8167 | if (hasContinueStatement(switchNode->lastBranch)) { | 8890 | type |= getBreakLoopType(switchNode->lastBranch, varBWV); |
| 8168 | return traversal::Stop; | ||
| 8169 | } | ||
| 8170 | } | 8891 | } |
| 8171 | break; | 8892 | return traversal::Return; |
| 8172 | } | 8893 | } |
| 8173 | } | 8894 | } |
| 8174 | BLOCK_END | 8895 | BLOCK_END |
| @@ -8182,12 +8903,13 @@ private: | |||
| 8182 | } | 8903 | } |
| 8183 | return traversal::Return; | 8904 | return traversal::Return; |
| 8184 | }); | 8905 | }); |
| 8906 | return type; | ||
| 8185 | } | 8907 | } |
| 8186 | 8908 | ||
| 8187 | void addDoToLastLineReturn(ast_node* body) { | 8909 | void addDoToLastLineReturn(ast_node* body) { |
| 8188 | if (auto block = ast_cast<Block_t>(body); block && !block->statements.empty()) { | 8910 | if (auto block = ast_cast<Block_t>(body); block && !block->statementOrComments.empty()) { |
| 8189 | auto last = static_cast<Statement_t*>(block->statements.back()); | 8911 | auto last = lastStatementFrom(block); |
| 8190 | if (last->content.is<Return_t>()) { | 8912 | if (last && last->content.is<Return_t>()) { |
| 8191 | auto doNode = last->new_ptr<Do_t>(); | 8913 | auto doNode = last->new_ptr<Do_t>(); |
| 8192 | auto newBody = last->new_ptr<Body_t>(); | 8914 | auto newBody = last->new_ptr<Body_t>(); |
| 8193 | auto newStmt = last->new_ptr<Statement_t>(); | 8915 | auto newStmt = last->new_ptr<Statement_t>(); |
| @@ -8205,30 +8927,30 @@ private: | |||
| 8205 | } | 8927 | } |
| 8206 | } | 8928 | } |
| 8207 | 8929 | ||
| 8208 | void transformLoopBody(ast_node* body, str_list& out, const std::string& appendContent, ExpUsage usage, ExpList_t* assignList = nullptr) { | 8930 | void transformLoopBody(ast_node* body, str_list& out, uint32_t breakLoopType, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 8209 | str_list temp; | 8931 | str_list temp; |
| 8210 | bool extraDo = false; | 8932 | bool extraDo = false; |
| 8211 | bool withContinue = hasContinueStatement(body); | 8933 | bool withContinue = hasContinue(breakLoopType); |
| 8212 | int target = getLuaTarget(body); | 8934 | int target = getLuaTarget(body); |
| 8213 | std::string extraLabel; | 8935 | std::string extraLabel; |
| 8214 | if (withContinue) { | 8936 | if (withContinue) { |
| 8215 | if (target < 502) { | 8937 | if (target < 502) { |
| 8216 | if (auto block = ast_cast<Block_t>(body)) { | 8938 | if (auto block = ast_cast<Block_t>(body)) { |
| 8217 | if (!block->statements.empty()) { | 8939 | if (!block->statementOrComments.empty()) { |
| 8218 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 8940 | auto stmt = lastStatementFrom(block); |
| 8219 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 8941 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
| 8220 | extraDo = _parser.toString(breakLoop) == "break"sv; | 8942 | extraDo = breakLoop->type.is<Break_t>(); |
| 8221 | } | 8943 | } |
| 8222 | } | 8944 | } |
| 8223 | } | 8945 | } |
| 8224 | auto continueVar = getUnusedName("_continue_"sv); | 8946 | auto continueVar = getUnusedName("_continue_"sv); |
| 8225 | addToScope(continueVar); | 8947 | addToScope(continueVar); |
| 8226 | _continueVars.push({continueVar, nullptr}); | 8948 | _continueVars.push({continueVar, nullptr}); |
| 8227 | _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); | 8949 | _buf << indent() << "local "sv << continueVar << " = false"sv << nl(body); |
| 8228 | _buf << indent() << "repeat"sv << nll(body); | 8950 | _buf << indent() << "repeat"sv << nl(body); |
| 8229 | pushScope(); | 8951 | pushScope(); |
| 8230 | if (extraDo) { | 8952 | if (extraDo) { |
| 8231 | _buf << indent() << "do"sv << nll(body); | 8953 | _buf << indent() << "do"sv << nl(body); |
| 8232 | pushScope(); | 8954 | pushScope(); |
| 8233 | } | 8955 | } |
| 8234 | temp.push_back(clearBuf()); | 8956 | temp.push_back(clearBuf()); |
| @@ -8248,28 +8970,20 @@ private: | |||
| 8248 | if (target < 502) { | 8970 | if (target < 502) { |
| 8249 | if (extraDo) { | 8971 | if (extraDo) { |
| 8250 | popScope(); | 8972 | popScope(); |
| 8251 | _buf << indent() << "end"sv << nll(body); | 8973 | _buf << indent() << "end"sv << nl(body); |
| 8252 | } | ||
| 8253 | if (!appendContent.empty()) { | ||
| 8254 | _buf << indent() << appendContent; | ||
| 8255 | } | 8974 | } |
| 8256 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 8975 | _buf << indent() << _continueVars.top().var << " = true"sv << nl(body); |
| 8257 | popScope(); | 8976 | popScope(); |
| 8258 | _buf << indent() << "until true"sv << nlr(body); | 8977 | _buf << indent() << "until true"sv << nl(body); |
| 8259 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body); | 8978 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nl(body); |
| 8260 | _buf << indent(1) << "break"sv << nlr(body); | 8979 | _buf << indent(1) << "break"sv << nl(body); |
| 8261 | _buf << indent() << "end"sv << nlr(body); | 8980 | _buf << indent() << "end"sv << nl(body); |
| 8262 | temp.push_back(clearBuf()); | 8981 | temp.push_back(clearBuf()); |
| 8263 | _continueVars.pop(); | 8982 | _continueVars.pop(); |
| 8264 | } else { | 8983 | } else { |
| 8265 | if (!appendContent.empty()) { | ||
| 8266 | temp.push_back(indent() + appendContent); | ||
| 8267 | } | ||
| 8268 | temp.push_back(extraLabel); | 8984 | temp.push_back(extraLabel); |
| 8269 | _continueVars.pop(); | 8985 | _continueVars.pop(); |
| 8270 | } | 8986 | } |
| 8271 | } else if (!appendContent.empty()) { | ||
| 8272 | temp.back().append(indent() + appendContent); | ||
| 8273 | } | 8987 | } |
| 8274 | out.push_back(join(temp)); | 8988 | out.push_back(join(temp)); |
| 8275 | } | 8989 | } |
| @@ -8277,8 +8991,9 @@ private: | |||
| 8277 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { | 8991 | std::string transformRepeatBody(Repeat_t* repeatNode, str_list& out) { |
| 8278 | str_list temp; | 8992 | str_list temp; |
| 8279 | bool extraDo = false; | 8993 | bool extraDo = false; |
| 8280 | auto body = repeatNode->body->content.get(); | 8994 | auto body = repeatNode->body.get(); |
| 8281 | bool withContinue = hasContinueStatement(body); | 8995 | auto breakLoopType = getBreakLoopType(body, Empty); |
| 8996 | bool withContinue = hasContinue(breakLoopType); | ||
| 8282 | std::string conditionVar; | 8997 | std::string conditionVar; |
| 8283 | std::string extraLabel; | 8998 | std::string extraLabel; |
| 8284 | ast_ptr<false, ExpListAssign_t> condAssign; | 8999 | ast_ptr<false, ExpListAssign_t> condAssign; |
| @@ -8286,10 +9001,10 @@ private: | |||
| 8286 | if (withContinue) { | 9001 | if (withContinue) { |
| 8287 | if (target < 502) { | 9002 | if (target < 502) { |
| 8288 | if (auto block = ast_cast<Block_t>(body)) { | 9003 | if (auto block = ast_cast<Block_t>(body)) { |
| 8289 | if (!block->statements.empty()) { | 9004 | if (!block->statementOrComments.empty()) { |
| 8290 | auto stmt = static_cast<Statement_t*>(block->statements.back()); | 9005 | auto stmt = lastStatementFrom(block); |
| 8291 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { | 9006 | if (auto breakLoop = ast_cast<BreakLoop_t>(stmt->content)) { |
| 8292 | extraDo = _parser.toString(breakLoop) == "break"sv; | 9007 | extraDo = breakLoop->type.is<Break_t>(); |
| 8293 | } | 9008 | } |
| 8294 | } | 9009 | } |
| 8295 | } | 9010 | } |
| @@ -8304,12 +9019,12 @@ private: | |||
| 8304 | assign->values.push_back(repeatNode->condition); | 9019 | assign->values.push_back(repeatNode->condition); |
| 8305 | _continueVars.push({continueVar, assignment.get()}); | 9020 | _continueVars.push({continueVar, assignment.get()}); |
| 8306 | } | 9021 | } |
| 8307 | _buf << indent() << "local "sv << conditionVar << " = false"sv << nll(body); | 9022 | _buf << indent() << "local "sv << conditionVar << " = false"sv << nl(body); |
| 8308 | _buf << indent() << "local "sv << continueVar << " = false"sv << nll(body); | 9023 | _buf << indent() << "local "sv << continueVar << " = false"sv << nl(body); |
| 8309 | _buf << indent() << "repeat"sv << nll(body); | 9024 | _buf << indent() << "repeat"sv << nl(body); |
| 8310 | pushScope(); | 9025 | pushScope(); |
| 8311 | if (extraDo) { | 9026 | if (extraDo) { |
| 8312 | _buf << indent() << "do"sv << nll(body); | 9027 | _buf << indent() << "do"sv << nl(body); |
| 8313 | pushScope(); | 9028 | pushScope(); |
| 8314 | } | 9029 | } |
| 8315 | temp.push_back(clearBuf()); | 9030 | temp.push_back(clearBuf()); |
| @@ -8330,14 +9045,14 @@ private: | |||
| 8330 | transformAssignment(_continueVars.top().condAssign, temp); | 9045 | transformAssignment(_continueVars.top().condAssign, temp); |
| 8331 | if (extraDo) { | 9046 | if (extraDo) { |
| 8332 | popScope(); | 9047 | popScope(); |
| 8333 | _buf << indent() << "end"sv << nll(body); | 9048 | _buf << indent() << "end"sv << nl(body); |
| 8334 | } | 9049 | } |
| 8335 | _buf << indent() << _continueVars.top().var << " = true"sv << nll(body); | 9050 | _buf << indent() << _continueVars.top().var << " = true"sv << nl(body); |
| 8336 | popScope(); | 9051 | popScope(); |
| 8337 | _buf << indent() << "until true"sv << nlr(body); | 9052 | _buf << indent() << "until true"sv << nl(body); |
| 8338 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nlr(body); | 9053 | _buf << indent() << "if not "sv << _continueVars.top().var << " then"sv << nl(body); |
| 8339 | _buf << indent(1) << "break"sv << nlr(body); | 9054 | _buf << indent(1) << "break"sv << nl(body); |
| 8340 | _buf << indent() << "end"sv << nlr(body); | 9055 | _buf << indent() << "end"sv << nl(body); |
| 8341 | temp.push_back(clearBuf()); | 9056 | temp.push_back(clearBuf()); |
| 8342 | _continueVars.pop(); | 9057 | _continueVars.pop(); |
| 8343 | } else { | 9058 | } else { |
| @@ -8349,34 +9064,48 @@ private: | |||
| 8349 | return conditionVar; | 9064 | return conditionVar; |
| 8350 | } | 9065 | } |
| 8351 | 9066 | ||
| 8352 | void transformFor(For_t* forNode, str_list& out) { | 9067 | void transformForNum(ForNum_t* forNum, str_list& out) { |
| 8353 | str_list temp; | 9068 | str_list temp; |
| 8354 | transformForHead(forNode, temp); | 9069 | transformForNumHead(forNum, temp); |
| 8355 | transformLoopBody(forNode->body, temp, Empty, ExpUsage::Common); | 9070 | auto breakLoopType = getBreakLoopType(forNum->body, Empty); |
| 9071 | transformLoopBody(forNum->body, temp, breakLoopType, ExpUsage::Common); | ||
| 8356 | popScope(); | 9072 | popScope(); |
| 8357 | out.push_back(join(temp) + indent() + "end"s + nlr(forNode)); | 9073 | out.push_back(join(temp) + indent() + "end"s + nl(forNum)); |
| 8358 | } | 9074 | } |
| 8359 | 9075 | ||
| 8360 | std::string transformForInner(For_t* forNode, str_list& out) { | 9076 | std::string transformForNumInner(ForNum_t* forNum, str_list& out) { |
| 8361 | auto x = forNode; | 9077 | auto x = forNum; |
| 8362 | std::string accum = getUnusedName("_accum_"sv); | 9078 | std::string accum = getUnusedName("_accum_"sv); |
| 8363 | addToScope(accum); | 9079 | addToScope(accum); |
| 8364 | std::string len = getUnusedName("_len_"sv); | 9080 | std::string len = getUnusedName("_len_"sv); |
| 8365 | addToScope(len); | 9081 | addToScope(len); |
| 8366 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forNode); | 9082 | auto breakLoopType = getBreakLoopType(forNum->body, accum); |
| 8367 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forNode); | 9083 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forNum); |
| 8368 | out.push_back(clearBuf()); | 9084 | out.emplace_back(clearBuf()); |
| 8369 | transformForHead(forNode, out); | 9085 | _buf << indent() << "local "sv << len << " = 1"sv << nl(forNum); |
| 8370 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 9086 | auto& lenAssign = out.emplace_back(clearBuf()); |
| 8371 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forNode->body); | 9087 | transformForNumHead(forNum, out); |
| 8372 | transformLoopBody(forNode->body, out, lenLine, ExpUsage::Assignment, expList); | 9088 | if (hasBreakWithValue(breakLoopType)) { |
| 9089 | lenAssign.clear(); | ||
| 9090 | transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Common); | ||
| 9091 | } else { | ||
| 9092 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
| 9093 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forNum->body); | ||
| 9094 | expList->followStmt = followStmt.get(); | ||
| 9095 | transformLoopBody(forNum->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 9096 | if (!expList->followStmtProcessed) { | ||
| 9097 | lenAssign.clear(); | ||
| 9098 | } | ||
| 9099 | } | ||
| 8373 | popScope(); | 9100 | popScope(); |
| 8374 | out.push_back(indent() + "end"s + nlr(forNode)); | 9101 | out.push_back(indent() + "end"s + nl(forNum)); |
| 8375 | return accum; | 9102 | return accum; |
| 8376 | } | 9103 | } |
| 8377 | 9104 | ||
| 8378 | void transformForClosure(For_t* forNode, str_list& out) { | 9105 | void transformForNumClosure(ForNum_t* forNum, str_list& out) { |
| 8379 | auto simpleValue = forNode->new_ptr<SimpleValue_t>(); | 9106 | auto forNode = forNum->new_ptr<For_t>(); |
| 9107 | forNode->forLoop.set(forNum); | ||
| 9108 | auto simpleValue = forNum->new_ptr<SimpleValue_t>(); | ||
| 8380 | simpleValue->value.set(forNode); | 9109 | simpleValue->value.set(forNode); |
| 8381 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { | 9110 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { |
| 8382 | return; | 9111 | return; |
| @@ -8386,26 +9115,26 @@ private: | |||
| 8386 | pushAnonVarArg(); | 9115 | pushAnonVarArg(); |
| 8387 | std::string& funcStart = temp.emplace_back(); | 9116 | std::string& funcStart = temp.emplace_back(); |
| 8388 | pushScope(); | 9117 | pushScope(); |
| 8389 | auto accum = transformForInner(forNode, temp); | 9118 | auto accum = transformForNumInner(forNum, temp); |
| 8390 | temp.push_back(indent() + "return "s + accum + nlr(forNode)); | 9119 | temp.push_back(indent() + "return "s + accum + nl(forNum)); |
| 8391 | popScope(); | 9120 | popScope(); |
| 8392 | funcStart = anonFuncStart() + nll(forNode); | 9121 | funcStart = anonFuncStart() + nl(forNum); |
| 8393 | temp.push_back(indent() + anonFuncEnd()); | 9122 | temp.push_back(indent() + anonFuncEnd()); |
| 8394 | popAnonVarArg(); | 9123 | popAnonVarArg(); |
| 8395 | popFunctionScope(); | 9124 | popFunctionScope(); |
| 8396 | out.push_back(join(temp)); | 9125 | out.push_back(join(temp)); |
| 8397 | } | 9126 | } |
| 8398 | 9127 | ||
| 8399 | void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList = nullptr) { | 9128 | void transformForNumInPlace(ForNum_t* forNum, str_list& out, ExpList_t* assignExpList) { |
| 8400 | auto x = forNode; | 9129 | auto x = forNum; |
| 8401 | str_list temp; | 9130 | str_list temp; |
| 8402 | bool isScoped = !currentScope().lastStatement; | 9131 | bool isScoped = !currentScope().lastStatement; |
| 8403 | if (assignExpList) { | 9132 | if (assignExpList) { |
| 8404 | if (isScoped) { | 9133 | if (isScoped) { |
| 8405 | _buf << indent() << "do"sv << nll(forNode); | 9134 | _buf << indent() << "do"sv << nl(forNum); |
| 8406 | pushScope(); | 9135 | pushScope(); |
| 8407 | } | 9136 | } |
| 8408 | auto accum = transformForInner(forNode, temp); | 9137 | auto accum = transformForNumInner(forNum, temp); |
| 8409 | auto assign = x->new_ptr<Assign_t>(); | 9138 | auto assign = x->new_ptr<Assign_t>(); |
| 8410 | assign->values.push_back(toAst<Exp_t>(accum, x)); | 9139 | assign->values.push_back(toAst<Exp_t>(accum, x)); |
| 8411 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 9140 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| @@ -8414,14 +9143,11 @@ private: | |||
| 8414 | transformAssignment(assignment, temp); | 9143 | transformAssignment(assignment, temp); |
| 8415 | if (isScoped) { | 9144 | if (isScoped) { |
| 8416 | popScope(); | 9145 | popScope(); |
| 8417 | temp.push_back(indent() + "end"s + nlr(forNode)); | 9146 | temp.push_back(indent() + "end"s + nl(forNum)); |
| 8418 | } | 9147 | } |
| 8419 | } else { | 9148 | } else { |
| 8420 | auto accum = transformForInner(forNode, temp); | 9149 | auto accum = transformForNumInner(forNum, temp); |
| 8421 | auto returnNode = x->new_ptr<Return_t>(); | 9150 | auto returnNode = newReturn(toAst<Exp_t>(accum, forNum)); |
| 8422 | returnNode->explicitReturn = false; | ||
| 8423 | auto expListLow = toAst<ExpListLow_t>(accum, x); | ||
| 8424 | returnNode->valueList.set(expListLow); | ||
| 8425 | transformReturn(returnNode, temp); | 9151 | transformReturn(returnNode, temp); |
| 8426 | } | 9152 | } |
| 8427 | out.push_back(join(temp)); | 9153 | out.push_back(join(temp)); |
| @@ -8448,12 +9174,13 @@ private: | |||
| 8448 | void transformForEach(ForEach_t* forEach, str_list& out) { | 9174 | void transformForEach(ForEach_t* forEach, str_list& out) { |
| 8449 | str_list temp; | 9175 | str_list temp; |
| 8450 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); | 9176 | bool extraScoped = transformForEachHead(forEach->nameList, forEach->loopValue, temp, false); |
| 8451 | transformLoopBody(forEach->body, temp, Empty, ExpUsage::Common); | 9177 | auto breakLoopType = getBreakLoopType(forEach->body, Empty); |
| 9178 | transformLoopBody(forEach->body, temp, breakLoopType, ExpUsage::Common); | ||
| 8452 | popScope(); | 9179 | popScope(); |
| 8453 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nlr(forEach)); | 9180 | out.push_back(temp.front() + temp.back() + indent() + "end"s + nl(forEach)); |
| 8454 | if (extraScoped) { | 9181 | if (extraScoped) { |
| 8455 | popScope(); | 9182 | popScope(); |
| 8456 | out.back().append(indent() + "end"s + nlr(forEach)); | 9183 | out.back().append(indent() + "end"s + nl(forEach)); |
| 8457 | } | 9184 | } |
| 8458 | } | 9185 | } |
| 8459 | 9186 | ||
| @@ -8463,22 +9190,35 @@ private: | |||
| 8463 | addToScope(accum); | 9190 | addToScope(accum); |
| 8464 | std::string len = getUnusedName("_len_"sv); | 9191 | std::string len = getUnusedName("_len_"sv); |
| 8465 | addToScope(len); | 9192 | addToScope(len); |
| 8466 | _buf << indent() << "local "sv << accum << " = { }"sv << nll(forEach); | 9193 | auto breakLoopType = getBreakLoopType(forEach->body, accum); |
| 8467 | _buf << indent() << "local "sv << len << " = 1"sv << nll(forEach); | 9194 | _buf << indent() << "local "sv << accum << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(forEach); |
| 8468 | out.push_back(clearBuf()); | 9195 | out.emplace_back(clearBuf()); |
| 9196 | _buf << indent() << "local "sv << len << " = 1"sv << nl(forEach); | ||
| 9197 | auto& lenAssign = out.emplace_back(clearBuf()); | ||
| 8469 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); | 9198 | transformForEachHead(forEach->nameList, forEach->loopValue, out, true); |
| 8470 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | 9199 | if (hasBreakWithValue(breakLoopType)) { |
| 8471 | auto lenLine = len + " = "s + len + " + 1"s + nlr(forEach->body); | 9200 | lenAssign.clear(); |
| 8472 | transformLoopBody(forEach->body, out, lenLine, ExpUsage::Assignment, expList); | 9201 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Common); |
| 9202 | } else { | ||
| 9203 | auto expList = toAst<ExpList_t>(accum + '[' + len + ']', x); | ||
| 9204 | auto followStmt = toAst<Statement_t>(len + "+=1"s, forEach->body); | ||
| 9205 | expList->followStmt = followStmt.get(); | ||
| 9206 | transformLoopBody(forEach->body, out, breakLoopType, ExpUsage::Assignment, expList); | ||
| 9207 | if (!expList->followStmtProcessed) { | ||
| 9208 | lenAssign.clear(); | ||
| 9209 | } | ||
| 9210 | } | ||
| 8473 | popScope(); | 9211 | popScope(); |
| 8474 | out.push_back(indent() + "end"s + nlr(forEach)); | 9212 | out.push_back(indent() + "end"s + nl(forEach)); |
| 8475 | return accum; | 9213 | return accum; |
| 8476 | } | 9214 | } |
| 8477 | 9215 | ||
| 8478 | void transformForEachClosure(ForEach_t* forEach, str_list& out) { | 9216 | void transformForEachClosure(ForEach_t* forEach, str_list& out) { |
| 9217 | auto forNode = forEach->new_ptr<For_t>(); | ||
| 9218 | forNode->forLoop.set(forEach); | ||
| 8479 | auto simpleValue = forEach->new_ptr<SimpleValue_t>(); | 9219 | auto simpleValue = forEach->new_ptr<SimpleValue_t>(); |
| 8480 | simpleValue->value.set(forEach); | 9220 | simpleValue->value.set(forNode); |
| 8481 | if (transformAsUpValueFunc(newExp(simpleValue, forEach), out)) { | 9221 | if (transformAsUpValueFunc(newExp(simpleValue, forNode), out)) { |
| 8482 | return; | 9222 | return; |
| 8483 | } | 9223 | } |
| 8484 | str_list temp; | 9224 | str_list temp; |
| @@ -8487,22 +9227,22 @@ private: | |||
| 8487 | std::string& funcStart = temp.emplace_back(); | 9227 | std::string& funcStart = temp.emplace_back(); |
| 8488 | pushScope(); | 9228 | pushScope(); |
| 8489 | auto accum = transformForEachInner(forEach, temp); | 9229 | auto accum = transformForEachInner(forEach, temp); |
| 8490 | temp.push_back(indent() + "return "s + accum + nlr(forEach)); | 9230 | temp.push_back(indent() + "return "s + accum + nl(forEach)); |
| 8491 | popScope(); | 9231 | popScope(); |
| 8492 | funcStart = anonFuncStart() + nll(forEach); | 9232 | funcStart = anonFuncStart() + nl(forEach); |
| 8493 | temp.push_back(indent() + anonFuncEnd()); | 9233 | temp.push_back(indent() + anonFuncEnd()); |
| 8494 | popAnonVarArg(); | 9234 | popAnonVarArg(); |
| 8495 | popFunctionScope(); | 9235 | popFunctionScope(); |
| 8496 | out.push_back(join(temp)); | 9236 | out.push_back(join(temp)); |
| 8497 | } | 9237 | } |
| 8498 | 9238 | ||
| 8499 | void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList = nullptr) { | 9239 | void transformForEachInPlace(ForEach_t* forEach, str_list& out, ExpList_t* assignExpList) { |
| 8500 | auto x = forEach; | 9240 | auto x = forEach; |
| 8501 | str_list temp; | 9241 | str_list temp; |
| 8502 | bool isScoped = !currentScope().lastStatement; | 9242 | bool isScoped = !currentScope().lastStatement; |
| 8503 | if (assignExpList) { | 9243 | if (assignExpList) { |
| 8504 | if (isScoped) { | 9244 | if (isScoped) { |
| 8505 | _buf << indent() << "do"sv << nll(forEach); | 9245 | _buf << indent() << "do"sv << nl(forEach); |
| 8506 | pushScope(); | 9246 | pushScope(); |
| 8507 | } | 9247 | } |
| 8508 | auto accum = transformForEachInner(forEach, temp); | 9248 | auto accum = transformForEachInner(forEach, temp); |
| @@ -8514,19 +9254,58 @@ private: | |||
| 8514 | transformAssignment(assignment, temp); | 9254 | transformAssignment(assignment, temp); |
| 8515 | if (isScoped) { | 9255 | if (isScoped) { |
| 8516 | popScope(); | 9256 | popScope(); |
| 8517 | temp.push_back(indent() + "end"s + nlr(forEach)); | 9257 | temp.push_back(indent() + "end"s + nl(forEach)); |
| 8518 | } | 9258 | } |
| 8519 | } else { | 9259 | } else { |
| 8520 | auto accum = transformForEachInner(forEach, temp); | 9260 | auto accum = transformForEachInner(forEach, temp); |
| 8521 | auto returnNode = x->new_ptr<Return_t>(); | 9261 | auto returnNode = newReturn(toAst<Exp_t>(accum, forEach)); |
| 8522 | returnNode->explicitReturn = false; | ||
| 8523 | auto expListLow = toAst<ExpListLow_t>(accum, x); | ||
| 8524 | returnNode->valueList.set(expListLow); | ||
| 8525 | transformReturn(returnNode, temp); | 9262 | transformReturn(returnNode, temp); |
| 8526 | } | 9263 | } |
| 8527 | out.push_back(join(temp)); | 9264 | out.push_back(join(temp)); |
| 8528 | } | 9265 | } |
| 8529 | 9266 | ||
| 9267 | void transformFor(For_t* forNode, str_list& out) { | ||
| 9268 | switch (forNode->forLoop->get_id()) { | ||
| 9269 | case id<ForNum_t>(): | ||
| 9270 | transformForNum(static_cast<ForNum_t*>(forNode->forLoop.get()), out); | ||
| 9271 | break; | ||
| 9272 | case id<ForEach_t>(): | ||
| 9273 | transformForEach(static_cast<ForEach_t*>(forNode->forLoop.get()), out); | ||
| 9274 | break; | ||
| 9275 | default: | ||
| 9276 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9277 | break; | ||
| 9278 | } | ||
| 9279 | } | ||
| 9280 | |||
| 9281 | void transformForClosure(For_t* forNode, str_list& out) { | ||
| 9282 | switch (forNode->forLoop->get_id()) { | ||
| 9283 | case id<ForNum_t>(): | ||
| 9284 | transformForNumClosure(static_cast<ForNum_t*>(forNode->forLoop.get()), out); | ||
| 9285 | break; | ||
| 9286 | case id<ForEach_t>(): | ||
| 9287 | transformForEachClosure(static_cast<ForEach_t*>(forNode->forLoop.get()), out); | ||
| 9288 | break; | ||
| 9289 | default: | ||
| 9290 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9291 | break; | ||
| 9292 | } | ||
| 9293 | } | ||
| 9294 | |||
| 9295 | void transformForInPlace(For_t* forNode, str_list& out, ExpList_t* assignExpList) { | ||
| 9296 | switch (forNode->forLoop->get_id()) { | ||
| 9297 | case id<ForNum_t>(): | ||
| 9298 | transformForNumInPlace(static_cast<ForNum_t*>(forNode->forLoop.get()), out, assignExpList); | ||
| 9299 | break; | ||
| 9300 | case id<ForEach_t>(): | ||
| 9301 | transformForEachInPlace(static_cast<ForEach_t*>(forNode->forLoop.get()), out, assignExpList); | ||
| 9302 | break; | ||
| 9303 | default: | ||
| 9304 | YUEE("AST node mismatch", forNode->forLoop.get()); | ||
| 9305 | break; | ||
| 9306 | } | ||
| 9307 | } | ||
| 9308 | |||
| 8530 | void transform_variable_pair(VariablePair_t* pair, str_list& out) { | 9309 | void transform_variable_pair(VariablePair_t* pair, str_list& out) { |
| 8531 | auto name = _parser.toString(pair->name); | 9310 | auto name = _parser.toString(pair->name); |
| 8532 | if (pair->name->name.is<UnicodeName_t>()) { | 9311 | if (pair->name->name.is<UnicodeName_t>()) { |
| @@ -8536,10 +9315,12 @@ private: | |||
| 8536 | } else { | 9315 | } else { |
| 8537 | out.push_back(name + " = "s + name); | 9316 | out.push_back(name + " = "s + name); |
| 8538 | } | 9317 | } |
| 8539 | if (_config.lintGlobalVariable && !isLocal(name)) { | 9318 | if (_importedGlobal) { |
| 9319 | markGlobalImported(name); | ||
| 9320 | } else if (_config.lintGlobalVariable && !isLocal(name)) { | ||
| 8540 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); | 9321 | auto key = name + ':' + std::to_string(pair->name->m_begin.m_line) + ':' + std::to_string(pair->name->m_begin.m_col); |
| 8541 | if (_globals.find(key) != _globals.end()) { | 9322 | if (_globals.find(key) == _globals.end()) { |
| 8542 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read}; | 9323 | _globals[key] = {name, pair->name->m_begin.m_line, pair->name->m_begin.m_col, _funcLevel > 1 ? AccessType::Capture : AccessType::Read, isSolidDefined(name)}; |
| 8543 | } | 9324 | } |
| 8544 | } | 9325 | } |
| 8545 | } | 9326 | } |
| @@ -8653,12 +9434,64 @@ private: | |||
| 8653 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); | 9434 | out.push_back(temp.empty() ? "\"\""s : join(temp, " .. "sv)); |
| 8654 | } | 9435 | } |
| 8655 | 9436 | ||
| 9437 | void transformYAMLMultiline(YAMLMultiline_t* multiline, str_list& out) { | ||
| 9438 | std::optional<std::string> indent; | ||
| 9439 | str_list temp; | ||
| 9440 | for (auto line_ : multiline->lines.objects()) { | ||
| 9441 | auto line = static_cast<YAMLLine_t*>(line_); | ||
| 9442 | auto indentStr = _parser.toString(line->indent); | ||
| 9443 | if (!indent) { | ||
| 9444 | indent = indentStr; | ||
| 9445 | } | ||
| 9446 | if (std::string_view{indentStr.c_str(), indent.value().size()} != indent.value()) { | ||
| 9447 | throw CompileError("inconsistent indent"sv, line); | ||
| 9448 | } | ||
| 9449 | indentStr = indentStr.substr(indent.value().size()); | ||
| 9450 | str_list segs; | ||
| 9451 | bool firstSeg = true; | ||
| 9452 | for (auto seg_ : line->segments.objects()) { | ||
| 9453 | auto content = static_cast<YAMLLineContent_t*>(seg_)->content.get(); | ||
| 9454 | switch (content->get_id()) { | ||
| 9455 | case id<YAMLLineInner_t>(): { | ||
| 9456 | auto seqStr = _parser.toString(content); | ||
| 9457 | Utils::replace(seqStr, "\\#"sv, "#"sv); | ||
| 9458 | if (firstSeg) { | ||
| 9459 | firstSeg = false; | ||
| 9460 | seqStr.insert(0, indentStr); | ||
| 9461 | } | ||
| 9462 | segs.push_back(Utils::toLuaDoubleString(seqStr)); | ||
| 9463 | break; | ||
| 9464 | } | ||
| 9465 | case id<Exp_t>(): { | ||
| 9466 | if (firstSeg) { | ||
| 9467 | firstSeg = false; | ||
| 9468 | if (!indentStr.empty()) { | ||
| 9469 | segs.push_back(Utils::toLuaDoubleString(indentStr)); | ||
| 9470 | } | ||
| 9471 | } | ||
| 9472 | transformExp(static_cast<Exp_t*>(content), segs, ExpUsage::Closure); | ||
| 9473 | segs.back() = globalVar("tostring"sv, content, AccessType::Read) + '(' + segs.back() + ')'; | ||
| 9474 | break; | ||
| 9475 | } | ||
| 9476 | default: YUEE("AST node mismatch", content); break; | ||
| 9477 | } | ||
| 9478 | } | ||
| 9479 | temp.push_back(join(segs, " .. "sv)); | ||
| 9480 | } | ||
| 9481 | auto str = join(temp, " .. '\\n' .. "sv); | ||
| 9482 | Utils::replace(str, "\" .. '\\n' .. \""sv, "\\n"sv); | ||
| 9483 | Utils::replace(str, "\" .. '\\n'"sv, "\\n\""sv); | ||
| 9484 | Utils::replace(str, "'\\n' .. \""sv, "\"\\n"sv); | ||
| 9485 | out.push_back(str); | ||
| 9486 | } | ||
| 9487 | |||
| 8656 | void transformString(String_t* string, str_list& out) { | 9488 | void transformString(String_t* string, str_list& out) { |
| 8657 | auto str = string->str.get(); | 9489 | auto str = string->str.get(); |
| 8658 | switch (str->get_id()) { | 9490 | switch (str->get_id()) { |
| 8659 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; | 9491 | case id<SingleString_t>(): transformSingleString(static_cast<SingleString_t*>(str), out); break; |
| 8660 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; | 9492 | case id<DoubleString_t>(): transformDoubleString(static_cast<DoubleString_t*>(str), out); break; |
| 8661 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; | 9493 | case id<LuaString_t>(): transformLuaString(static_cast<LuaString_t*>(str), out); break; |
| 9494 | case id<YAMLMultiline_t>(): transformYAMLMultiline(static_cast<YAMLMultiline_t*>(str), out); break; | ||
| 8662 | default: YUEE("AST node mismatch", str); break; | 9495 | default: YUEE("AST node mismatch", str); break; |
| 8663 | } | 9496 | } |
| 8664 | } | 9497 | } |
| @@ -8689,7 +9522,7 @@ private: | |||
| 8689 | pushScope(); | 9522 | pushScope(); |
| 8690 | transformClassDecl(classDecl, temp, ExpUsage::Return); | 9523 | transformClassDecl(classDecl, temp, ExpUsage::Return); |
| 8691 | popScope(); | 9524 | popScope(); |
| 8692 | funcStart = anonFuncStart() + nll(classDecl); | 9525 | funcStart = anonFuncStart() + nl(classDecl); |
| 8693 | temp.push_back(indent() + anonFuncEnd()); | 9526 | temp.push_back(indent() + anonFuncEnd()); |
| 8694 | popAnonVarArg(); | 9527 | popAnonVarArg(); |
| 8695 | popFunctionScope(); | 9528 | popFunctionScope(); |
| @@ -8713,7 +9546,7 @@ private: | |||
| 8713 | bool newDefined = false; | 9546 | bool newDefined = false; |
| 8714 | std::tie(className, newDefined, classTextName) = defineClassVariable(assignable); | 9547 | std::tie(className, newDefined, classTextName) = defineClassVariable(assignable); |
| 8715 | if (newDefined) { | 9548 | if (newDefined) { |
| 8716 | temp.push_back(indent() + "local "s + className + nll(classDecl)); | 9549 | temp.push_back(indent() + "local "s + className + nl(classDecl)); |
| 8717 | } | 9550 | } |
| 8718 | if (classTextName.empty()) { | 9551 | if (classTextName.empty()) { |
| 8719 | if (auto chain = ast_cast<AssignableChain_t>(assignable->item)) { | 9552 | if (auto chain = ast_cast<AssignableChain_t>(assignable->item)) { |
| @@ -8750,12 +9583,12 @@ private: | |||
| 8750 | } | 9583 | } |
| 8751 | } | 9584 | } |
| 8752 | if (isScoped) { | 9585 | if (isScoped) { |
| 8753 | temp.push_back(indent() + "do"s + nll(classDecl)); | 9586 | temp.push_back(indent() + "do"s + nl(classDecl)); |
| 8754 | pushScope(); | 9587 | pushScope(); |
| 8755 | } | 9588 | } |
| 8756 | auto classVar = getUnusedName("_class_"sv); | 9589 | auto classVar = getUnusedName("_class_"sv); |
| 8757 | addToScope(classVar); | 9590 | addToScope(classVar); |
| 8758 | temp.push_back(indent() + "local "s + classVar + nll(classDecl)); | 9591 | temp.push_back(indent() + "local "s + classVar + nl(classDecl)); |
| 8759 | auto block = classDecl->new_ptr<Block_t>(); | 9592 | auto block = classDecl->new_ptr<Block_t>(); |
| 8760 | str_list classConstVars; | 9593 | str_list classConstVars; |
| 8761 | if (body) { | 9594 | if (body) { |
| @@ -8764,7 +9597,7 @@ private: | |||
| 8764 | if (auto statement = ast_cast<Statement_t>(item)) { | 9597 | if (auto statement = ast_cast<Statement_t>(item)) { |
| 8765 | ClassDecl_t* clsDecl = nullptr; | 9598 | ClassDecl_t* clsDecl = nullptr; |
| 8766 | if (auto assignment = assignmentFrom(statement)) { | 9599 | if (auto assignment = assignmentFrom(statement)) { |
| 8767 | block->statements.push_back(statement); | 9600 | block->statementOrComments.push_back(statement); |
| 8768 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); | 9601 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Mark); |
| 8769 | for (const auto& name : names) { | 9602 | for (const auto& name : names) { |
| 8770 | varDefs.push_back(name.first); | 9603 | varDefs.push_back(name.first); |
| @@ -8794,12 +9627,12 @@ private: | |||
| 8794 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); | 9627 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); |
| 8795 | BLOCK_END | 9628 | BLOCK_END |
| 8796 | } else if (auto expList = expListFrom(statement)) { | 9629 | } else if (auto expList = expListFrom(statement)) { |
| 8797 | block->statements.push_back(statement); | 9630 | block->statementOrComments.push_back(statement); |
| 8798 | if (auto value = singleValueFrom(expList)) { | 9631 | if (auto value = singleValueFrom(expList)) { |
| 8799 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); | 9632 | clsDecl = value->get_by_path<SimpleValue_t, ClassDecl_t>(); |
| 8800 | } | 9633 | } |
| 8801 | } else if (auto local = statement->content.as<Local_t>()) { | 9634 | } else if (auto local = statement->content.as<Local_t>()) { |
| 8802 | block->statements.push_back(statement); | 9635 | block->statementOrComments.push_back(statement); |
| 8803 | if (auto values = local->item.as<LocalValues_t>()) { | 9636 | if (auto values = local->item.as<LocalValues_t>()) { |
| 8804 | for (auto name : values->nameList->names.objects()) { | 9637 | for (auto name : values->nameList->names.objects()) { |
| 8805 | auto varName = variableToString(static_cast<Variable_t*>(name)); | 9638 | auto varName = variableToString(static_cast<Variable_t*>(name)); |
| @@ -8840,7 +9673,7 @@ private: | |||
| 8840 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); | 9673 | auto names = transformAssignDefs(assignment->expList.get(), DefOp::Get); |
| 8841 | for (const auto& name : names) { | 9674 | for (const auto& name : names) { |
| 8842 | forceAddToScope(name.first); | 9675 | forceAddToScope(name.first); |
| 8843 | markVarConst(name.first); | 9676 | markVarLocalConst(name.first); |
| 8844 | varDefs.push_back(name.first); | 9677 | varDefs.push_back(name.first); |
| 8845 | classConstVars.push_back(name.first); | 9678 | classConstVars.push_back(name.first); |
| 8846 | } | 9679 | } |
| @@ -8854,7 +9687,7 @@ private: | |||
| 8854 | for (const auto& item : destruct.items) { | 9687 | for (const auto& item : destruct.items) { |
| 8855 | if (!item.targetVar.empty()) { | 9688 | if (!item.targetVar.empty()) { |
| 8856 | forceAddToScope(item.targetVar); | 9689 | forceAddToScope(item.targetVar); |
| 8857 | markVarConst(item.targetVar); | 9690 | markVarLocalConst(item.targetVar); |
| 8858 | varDefs.push_back(item.targetVar); | 9691 | varDefs.push_back(item.targetVar); |
| 8859 | classConstVars.push_back(item.targetVar); | 9692 | classConstVars.push_back(item.targetVar); |
| 8860 | } | 9693 | } |
| @@ -8862,7 +9695,6 @@ private: | |||
| 8862 | } | 9695 | } |
| 8863 | } | 9696 | } |
| 8864 | auto stmt = statement->new_ptr<Statement_t>(); | 9697 | auto stmt = statement->new_ptr<Statement_t>(); |
| 8865 | stmt->comments.dup(statement->comments); | ||
| 8866 | auto newAttrib = localAttrib->new_ptr<LocalAttrib_t>(); | 9698 | auto newAttrib = localAttrib->new_ptr<LocalAttrib_t>(); |
| 8867 | newAttrib->attrib.set(localAttrib->attrib); | 9699 | newAttrib->attrib.set(localAttrib->attrib); |
| 8868 | newAttrib->leftList.dup(localAttrib->leftList); | 9700 | newAttrib->leftList.dup(localAttrib->leftList); |
| @@ -8870,7 +9702,7 @@ private: | |||
| 8870 | newAttrib->forceLocal = false; | 9702 | newAttrib->forceLocal = false; |
| 8871 | stmt->content.set(newAttrib); | 9703 | stmt->content.set(newAttrib); |
| 8872 | stmt->appendix.set(statement->appendix); | 9704 | stmt->appendix.set(statement->appendix); |
| 8873 | block->statements.push_back(stmt); | 9705 | block->statementOrComments.push_back(stmt); |
| 8874 | } else if (statement->content.is<Global_t>()) { | 9706 | } else if (statement->content.is<Global_t>()) { |
| 8875 | throw CompileError("global statement is not allowed here"sv, statement->content); | 9707 | throw CompileError("global statement is not allowed here"sv, statement->content); |
| 8876 | } | 9708 | } |
| @@ -8884,7 +9716,7 @@ private: | |||
| 8884 | } | 9716 | } |
| 8885 | } | 9717 | } |
| 8886 | if (!varDefs.empty()) { | 9718 | if (!varDefs.empty()) { |
| 8887 | temp.push_back(indent() + "local "s + join(varDefs, ", "sv) + nll(body)); | 9719 | temp.push_back(indent() + "local "s + join(varDefs, ", "sv) + nl(body)); |
| 8888 | } | 9720 | } |
| 8889 | } | 9721 | } |
| 8890 | std::string parent, parentVar; | 9722 | std::string parent, parentVar; |
| @@ -8894,7 +9726,7 @@ private: | |||
| 8894 | transformExp(extend, temp, ExpUsage::Closure); | 9726 | transformExp(extend, temp, ExpUsage::Closure); |
| 8895 | parent = std::move(temp.back()); | 9727 | parent = std::move(temp.back()); |
| 8896 | temp.pop_back(); | 9728 | temp.pop_back(); |
| 8897 | temp.push_back(indent() + "local "s + parentVar + " = "s + parent + nll(classDecl)); | 9729 | temp.push_back(indent() + "local "s + parentVar + " = "s + parent + nl(classDecl)); |
| 8898 | } | 9730 | } |
| 8899 | auto baseVar = getUnusedName("_base_"sv); | 9731 | auto baseVar = getUnusedName("_base_"sv); |
| 8900 | addToScope(baseVar); | 9732 | addToScope(baseVar); |
| @@ -8913,7 +9745,7 @@ private: | |||
| 8913 | for (; it != members.end(); ++it) { | 9745 | for (; it != members.end(); ++it) { |
| 8914 | auto& member = *it; | 9746 | auto& member = *it; |
| 8915 | if (member.type == MemType::Property) { | 9747 | if (member.type == MemType::Property) { |
| 8916 | statements.push_back(indent() + member.item + nll(content)); | 9748 | statements.push_back(indent() + member.item + nl(content)); |
| 8917 | } else { | 9749 | } else { |
| 8918 | member.item = indent(1) + member.item; | 9750 | member.item = indent(1) + member.item; |
| 8919 | } | 9751 | } |
| @@ -8925,32 +9757,34 @@ private: | |||
| 8925 | } | 9757 | } |
| 8926 | } | 9758 | } |
| 8927 | for (const auto& classVar : classConstVars) { | 9759 | for (const auto& classVar : classConstVars) { |
| 8928 | auto& scope = _scopes.back(); | 9760 | forceAddToScope(classVar); |
| 8929 | scope.vars->insert_or_assign(classVar, VarType::Local); | ||
| 8930 | } | 9761 | } |
| 8931 | for (auto stmt_ : block->statements.objects()) { | 9762 | forceAddToScope("self"s); |
| 8932 | transformStatement(static_cast<Statement_t*>(stmt_), statements); | 9763 | for (auto stmt_ : block->statementOrComments.objects()) { |
| 9764 | if (auto stmt = ast_cast<Statement_t>(stmt_)) { | ||
| 9765 | transformStatement(stmt, statements); | ||
| 9766 | } | ||
| 8933 | } | 9767 | } |
| 8934 | for (auto& member : members) { | 9768 | for (auto& member : members) { |
| 8935 | switch (member.type) { | 9769 | switch (member.type) { |
| 8936 | case MemType::Common: | 9770 | case MemType::Common: |
| 8937 | commons.push_back((commons.empty() ? Empty : ',' + nll(member.node)) + member.item); | 9771 | commons.push_back((commons.empty() ? Empty : ',' + nl(member.node)) + member.item); |
| 8938 | break; | 9772 | break; |
| 8939 | case MemType::Builtin: | 9773 | case MemType::Builtin: |
| 8940 | builtins.push_back((builtins.empty() ? Empty : ',' + nll(member.node)) + member.item); | 9774 | builtins.push_back((builtins.empty() ? Empty : ',' + nl(member.node)) + member.item); |
| 8941 | break; | 9775 | break; |
| 8942 | default: break; | 9776 | default: break; |
| 8943 | } | 9777 | } |
| 8944 | } | 9778 | } |
| 8945 | if (!commons.empty()) { | 9779 | if (!commons.empty()) { |
| 8946 | temp.back() += '{' + nll(body); | 9780 | temp.back() += '{' + nl(body); |
| 8947 | temp.push_back(join(commons) + nll(body)); | 9781 | temp.push_back(join(commons) + nl(body)); |
| 8948 | temp.push_back(indent() + '}' + nll(body)); | 9782 | temp.push_back(indent() + '}' + nl(body)); |
| 8949 | } else { | 9783 | } else { |
| 8950 | temp.back() += "{ }"s + nll(body); | 9784 | temp.back() += "{ }"s + nl(body); |
| 8951 | } | 9785 | } |
| 8952 | } else { | 9786 | } else { |
| 8953 | temp.back() += "{ }"s + nll(classDecl); | 9787 | temp.back() += "{ }"s + nl(classDecl); |
| 8954 | } | 9788 | } |
| 8955 | if (classDecl->mixes) { | 9789 | if (classDecl->mixes) { |
| 8956 | auto item = getUnusedName("_item_"sv); | 9790 | auto item = getUnusedName("_item_"sv); |
| @@ -8983,72 +9817,72 @@ private: | |||
| 8983 | transformAssignment(assignment, tmp); | 9817 | transformAssignment(assignment, tmp); |
| 8984 | } | 9818 | } |
| 8985 | if (extend) { | 9819 | if (extend) { |
| 8986 | _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nll(classDecl); | 9820 | _buf << indent() << "setmetatable("sv << baseVar << ", "sv << parentVar << ".__base)"sv << nl(classDecl); |
| 8987 | } | 9821 | } |
| 8988 | _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl, AccessType::Read) << "({"sv << nll(classDecl); | 9822 | _buf << indent() << classVar << " = "sv << globalVar("setmetatable"sv, classDecl, AccessType::Read) << "({"sv << nl(classDecl); |
| 8989 | if (!builtins.empty()) { | 9823 | if (!builtins.empty()) { |
| 8990 | _buf << join(builtins) << ',' << nll(classDecl); | 9824 | _buf << join(builtins) << ',' << nl(classDecl); |
| 8991 | } else { | 9825 | } else { |
| 8992 | if (extend) { | 9826 | if (extend) { |
| 8993 | _buf << indent(1) << "__init = function(self, ...)"sv << nll(classDecl); | 9827 | _buf << indent(1) << "__init = function(self, ...)"sv << nl(classDecl); |
| 8994 | _buf << indent(2) << "return "sv << classVar << ".__parent.__init(self, ...)"sv << nll(classDecl); | 9828 | _buf << indent(2) << "return "sv << classVar << ".__parent.__init(self, ...)"sv << nl(classDecl); |
| 8995 | _buf << indent(1) << "end,"sv << nll(classDecl); | 9829 | _buf << indent(1) << "end,"sv << nl(classDecl); |
| 8996 | } else { | 9830 | } else { |
| 8997 | _buf << indent(1) << "__init = function() end,"sv << nll(classDecl); | 9831 | _buf << indent(1) << "__init = function() end,"sv << nl(classDecl); |
| 8998 | } | 9832 | } |
| 8999 | } | 9833 | } |
| 9000 | _buf << indent(1) << "__base = "sv << baseVar; | 9834 | _buf << indent(1) << "__base = "sv << baseVar; |
| 9001 | if (!classTextName.empty()) { | 9835 | if (!classTextName.empty()) { |
| 9002 | _buf << ","sv << nll(classDecl); | 9836 | _buf << ","sv << nl(classDecl); |
| 9003 | _buf << indent(1) << "__name = "sv << classTextName; | 9837 | _buf << indent(1) << "__name = "sv << classTextName; |
| 9004 | } | 9838 | } |
| 9005 | if (extend) { | 9839 | if (extend) { |
| 9006 | _buf << ","sv << nll(classDecl); | 9840 | _buf << ","sv << nl(classDecl); |
| 9007 | _buf << indent(1) << "__parent = "sv << parentVar; | 9841 | _buf << indent(1) << "__parent = "sv << parentVar; |
| 9008 | } | 9842 | } |
| 9009 | _buf << nll(classDecl); | 9843 | _buf << nl(classDecl); |
| 9010 | _buf << indent() << "}, {"sv << nll(classDecl); | 9844 | _buf << indent() << "}, {"sv << nl(classDecl); |
| 9011 | if (extend) { | 9845 | if (extend) { |
| 9012 | _buf << indent(1) << "__index = function(cls, name)"sv << nll(classDecl); | 9846 | _buf << indent(1) << "__index = function(cls, name)"sv << nl(classDecl); |
| 9013 | _buf << indent(2) << "local val = rawget("sv << baseVar << ", name)"sv << nll(classDecl); | 9847 | _buf << indent(2) << "local val = rawget("sv << baseVar << ", name)"sv << nl(classDecl); |
| 9014 | _buf << indent(2) << "if val == nil then"sv << nll(classDecl); | 9848 | _buf << indent(2) << "if val == nil then"sv << nl(classDecl); |
| 9015 | _buf << indent(3) << "local parent = rawget(cls, \"__parent\")"sv << nll(classDecl); | 9849 | _buf << indent(3) << "local parent = rawget(cls, \"__parent\")"sv << nl(classDecl); |
| 9016 | _buf << indent(3) << "if parent then"sv << nll(classDecl); | 9850 | _buf << indent(3) << "if parent then"sv << nl(classDecl); |
| 9017 | _buf << indent(4) << "return parent[name]"sv << nll(classDecl); | 9851 | _buf << indent(4) << "return parent[name]"sv << nl(classDecl); |
| 9018 | _buf << indent(3) << "end"sv << nll(classDecl); | 9852 | _buf << indent(3) << "end"sv << nl(classDecl); |
| 9019 | _buf << indent(2) << "else"sv << nll(classDecl); | 9853 | _buf << indent(2) << "else"sv << nl(classDecl); |
| 9020 | _buf << indent(3) << "return val"sv << nll(classDecl); | 9854 | _buf << indent(3) << "return val"sv << nl(classDecl); |
| 9021 | _buf << indent(2) << "end"sv << nll(classDecl); | 9855 | _buf << indent(2) << "end"sv << nl(classDecl); |
| 9022 | _buf << indent(1) << "end,"sv << nll(classDecl); | 9856 | _buf << indent(1) << "end,"sv << nl(classDecl); |
| 9023 | } else { | 9857 | } else { |
| 9024 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nll(classDecl); | 9858 | _buf << indent(1) << "__index = "sv << baseVar << ","sv << nl(classDecl); |
| 9025 | } | 9859 | } |
| 9026 | _buf << indent(1) << "__call = function(cls, ...)"sv << nll(classDecl); | 9860 | _buf << indent(1) << "__call = function(cls, ...)"sv << nl(classDecl); |
| 9027 | pushScope(); | 9861 | pushScope(); |
| 9028 | auto selfVar = getUnusedName("_self_"sv); | 9862 | auto selfVar = getUnusedName("_self_"sv); |
| 9029 | addToScope(selfVar); | 9863 | addToScope(selfVar); |
| 9030 | _buf << indent(1) << "local "sv << selfVar << " = setmetatable({ }, "sv << baseVar << ")"sv << nll(classDecl); | 9864 | _buf << indent(1) << "local "sv << selfVar << " = setmetatable({ }, "sv << baseVar << ")"sv << nl(classDecl); |
| 9031 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nll(classDecl); | 9865 | _buf << indent(1) << "cls.__init("sv << selfVar << ", ...)"sv << nl(classDecl); |
| 9032 | _buf << indent(1) << "return "sv << selfVar << nll(classDecl); | 9866 | _buf << indent(1) << "return "sv << selfVar << nl(classDecl); |
| 9033 | popScope(); | 9867 | popScope(); |
| 9034 | _buf << indent(1) << "end"sv << nll(classDecl); | 9868 | _buf << indent(1) << "end"sv << nl(classDecl); |
| 9035 | _buf << indent() << "})"sv << nll(classDecl); | 9869 | _buf << indent() << "})"sv << nl(classDecl); |
| 9036 | _buf << indent() << baseVar << ".__class = "sv << classVar << nll(classDecl); | 9870 | _buf << indent() << baseVar << ".__class = "sv << classVar << nl(classDecl); |
| 9037 | if (!statements.empty()) { | 9871 | if (!statements.empty()) { |
| 9038 | _buf << indent() << "local self = "sv << classVar << ';' << nll(classDecl); | 9872 | _buf << indent() << "local self = "sv << classVar << ';' << nl(classDecl); |
| 9039 | } | 9873 | } |
| 9040 | _buf << join(statements); | 9874 | _buf << join(statements); |
| 9041 | if (extend) { | 9875 | if (extend) { |
| 9042 | _buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nll(classDecl); | 9876 | _buf << indent() << "if "sv << parentVar << ".__inherited then"sv << nl(classDecl); |
| 9043 | _buf << indent(1) << parentVar << ".__inherited("sv << parentVar << ", "sv << classVar << ")"sv << nll(classDecl); | 9877 | _buf << indent(1) << parentVar << ".__inherited("sv << parentVar << ", "sv << classVar << ")"sv << nl(classDecl); |
| 9044 | _buf << indent() << "end"sv << nll(classDecl); | 9878 | _buf << indent() << "end"sv << nl(classDecl); |
| 9045 | } | 9879 | } |
| 9046 | if (!assignItem.empty()) { | 9880 | if (!assignItem.empty()) { |
| 9047 | _buf << indent() << assignItem << " = "sv << classVar << nll(classDecl); | 9881 | _buf << indent() << assignItem << " = "sv << classVar << nl(classDecl); |
| 9048 | } | 9882 | } |
| 9049 | switch (usage) { | 9883 | switch (usage) { |
| 9050 | case ExpUsage::Return: { | 9884 | case ExpUsage::Return: { |
| 9051 | _buf << indent() << "return "sv << classVar << nlr(classDecl); | 9885 | _buf << indent() << "return "sv << classVar << nl(classDecl); |
| 9052 | break; | 9886 | break; |
| 9053 | } | 9887 | } |
| 9054 | case ExpUsage::Assignment: { | 9888 | case ExpUsage::Assignment: { |
| @@ -9060,7 +9894,7 @@ private: | |||
| 9060 | temp.push_back(clearBuf()); | 9894 | temp.push_back(clearBuf()); |
| 9061 | if (isScoped) { | 9895 | if (isScoped) { |
| 9062 | popScope(); | 9896 | popScope(); |
| 9063 | temp.push_back(indent() + "end"s + nlr(classDecl)); | 9897 | temp.push_back(indent() + "end"s + nl(classDecl)); |
| 9064 | } | 9898 | } |
| 9065 | out.push_back(join(temp)); | 9899 | out.push_back(join(temp)); |
| 9066 | } | 9900 | } |
| @@ -9223,7 +10057,7 @@ private: | |||
| 9223 | pushScope(); | 10057 | pushScope(); |
| 9224 | transformWith(with, temp, nullptr, true); | 10058 | transformWith(with, temp, nullptr, true); |
| 9225 | popScope(); | 10059 | popScope(); |
| 9226 | funcStart = anonFuncStart() + nll(with); | 10060 | funcStart = anonFuncStart() + nl(with); |
| 9227 | temp.push_back(indent() + anonFuncEnd()); | 10061 | temp.push_back(indent() + anonFuncEnd()); |
| 9228 | popAnonVarArg(); | 10062 | popAnonVarArg(); |
| 9229 | popFunctionScope(); | 10063 | popFunctionScope(); |
| @@ -9236,11 +10070,11 @@ private: | |||
| 9236 | std::string withVar; | 10070 | std::string withVar; |
| 9237 | bool needScope = !currentScope().lastStatement && !returnValue; | 10071 | bool needScope = !currentScope().lastStatement && !returnValue; |
| 9238 | bool extraScope = false; | 10072 | bool extraScope = false; |
| 9239 | if (with->assigns) { | 10073 | if (with->assign) { |
| 9240 | auto vars = getAssignVars(with); | 10074 | auto vars = getAssignVars(with); |
| 9241 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { | 10075 | if (vars.front().empty() || isDeclaredAsGlobal(vars.front())) { |
| 9242 | if (with->assigns->values.objects().size() == 1) { | 10076 | if (with->assign->values.objects().size() == 1) { |
| 9243 | auto var = singleVariableFrom(with->assigns->values.objects().front(), AccessType::Read); | 10077 | auto var = singleVariableFrom(with->assign->values.objects().front(), AccessType::Read); |
| 9244 | if (!var.empty() && isLocal(var)) { | 10078 | if (!var.empty() && isLocal(var)) { |
| 9245 | withVar = var; | 10079 | withVar = var; |
| 9246 | } | 10080 | } |
| @@ -9250,11 +10084,11 @@ private: | |||
| 9250 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10084 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9251 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); | 10085 | assignment->expList.set(toAst<ExpList_t>(withVar, x)); |
| 9252 | auto assign = x->new_ptr<Assign_t>(); | 10086 | auto assign = x->new_ptr<Assign_t>(); |
| 9253 | assign->values.push_back(with->assigns->values.objects().front()); | 10087 | assign->values.push_back(with->assign->values.objects().front()); |
| 9254 | assignment->action.set(assign); | 10088 | assignment->action.set(assign); |
| 9255 | if (needScope) { | 10089 | if (needScope) { |
| 9256 | extraScope = true; | 10090 | extraScope = true; |
| 9257 | temp.push_back(indent() + "do"s + nll(with)); | 10091 | temp.push_back(indent() + "do"s + nl(with)); |
| 9258 | pushScope(); | 10092 | pushScope(); |
| 9259 | } | 10093 | } |
| 9260 | transformAssignment(assignment, temp); | 10094 | transformAssignment(assignment, temp); |
| @@ -9264,7 +10098,7 @@ private: | |||
| 9264 | auto assign = x->new_ptr<Assign_t>(); | 10098 | auto assign = x->new_ptr<Assign_t>(); |
| 9265 | assign->values.push_back(toAst<Exp_t>(withVar, x)); | 10099 | assign->values.push_back(toAst<Exp_t>(withVar, x)); |
| 9266 | bool skipFirst = true; | 10100 | bool skipFirst = true; |
| 9267 | for (auto value : with->assigns->values.objects()) { | 10101 | for (auto value : with->assign->values.objects()) { |
| 9268 | if (skipFirst) { | 10102 | if (skipFirst) { |
| 9269 | skipFirst = false; | 10103 | skipFirst = false; |
| 9270 | continue; | 10104 | continue; |
| @@ -9277,10 +10111,10 @@ private: | |||
| 9277 | withVar = vars.front(); | 10111 | withVar = vars.front(); |
| 9278 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10112 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9279 | assignment->expList.set(with->valueList); | 10113 | assignment->expList.set(with->valueList); |
| 9280 | assignment->action.set(with->assigns); | 10114 | assignment->action.set(with->assign); |
| 9281 | if (needScope) { | 10115 | if (needScope) { |
| 9282 | extraScope = true; | 10116 | extraScope = true; |
| 9283 | temp.push_back(indent() + "do"s + nll(with)); | 10117 | temp.push_back(indent() + "do"s + nl(with)); |
| 9284 | pushScope(); | 10118 | pushScope(); |
| 9285 | } | 10119 | } |
| 9286 | transformAssignment(assignment, temp); | 10120 | transformAssignment(assignment, temp); |
| @@ -9296,7 +10130,7 @@ private: | |||
| 9296 | assignment->action.set(assign); | 10130 | assignment->action.set(assign); |
| 9297 | if (needScope) { | 10131 | if (needScope) { |
| 9298 | extraScope = true; | 10132 | extraScope = true; |
| 9299 | temp.push_back(indent() + "do"s + nll(with)); | 10133 | temp.push_back(indent() + "do"s + nl(with)); |
| 9300 | pushScope(); | 10134 | pushScope(); |
| 9301 | } | 10135 | } |
| 9302 | transformAssignment(assignment, temp); | 10136 | transformAssignment(assignment, temp); |
| @@ -9350,27 +10184,69 @@ private: | |||
| 9350 | }); | 10184 | }); |
| 9351 | popScope(); | 10185 | popScope(); |
| 9352 | if (extraScope) { | 10186 | if (extraScope) { |
| 9353 | temp.push_back(indent() + "do"s + nll(with)); | 10187 | temp.push_back(indent() + "do"s + nl(with)); |
| 9354 | pushScope(); | 10188 | pushScope(); |
| 9355 | } | 10189 | } |
| 9356 | } | 10190 | } |
| 9357 | _withVars.push(withVar); | 10191 | _withVars.push(withVar); |
| 10192 | std::string breakWithVar; | ||
| 10193 | if (assignList || returnValue) { | ||
| 10194 | auto breakLoopType = getBreakLoopType(with->body, withVar); | ||
| 10195 | if (hasBreakWithValue(breakLoopType)) { | ||
| 10196 | breakWithVar = withVar; | ||
| 10197 | } | ||
| 10198 | } | ||
| 9358 | if (with->eop) { | 10199 | if (with->eop) { |
| 9359 | auto ifNode = x->new_ptr<If_t>(); | 10200 | auto ifNode = x->new_ptr<If_t>(); |
| 9360 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); | 10201 | ifNode->type.set(toAst<IfType_t>("if"sv, x)); |
| 9361 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); | 10202 | ifNode->nodes.push_back(toAst<IfCond_t>(withVar + "~=nil"s, x)); |
| 9362 | ifNode->nodes.push_back(with->body); | 10203 | ifNode->nodes.push_back(with->body); |
| 9363 | transformIf(ifNode, temp, ExpUsage::Common); | 10204 | if (breakWithVar.empty()) { |
| 10205 | transformIf(ifNode, temp, ExpUsage::Common); | ||
| 10206 | } else { | ||
| 10207 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 10208 | simpleValue->value.set(ifNode); | ||
| 10209 | auto exp = newExp(simpleValue, x); | ||
| 10210 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 10211 | expList->exprs.push_back(exp); | ||
| 10212 | auto expListAssign = x->new_ptr<ExpListAssign_t>(); | ||
| 10213 | expListAssign->expList.set(expList); | ||
| 10214 | auto stmt = x->new_ptr<Statement_t>(); | ||
| 10215 | stmt->content.set(expListAssign); | ||
| 10216 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
| 10217 | auto block = x->new_ptr<Block_t>(); | ||
| 10218 | block->statementOrComments.push_back(stmt); | ||
| 10219 | repeatNode->body.set(block); | ||
| 10220 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 10221 | sVal->value.set(repeatNode); | ||
| 10222 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
| 10223 | transformAssignment(asmt, temp); | ||
| 10224 | } | ||
| 9364 | } else { | 10225 | } else { |
| 9365 | bool transformed = false; | 10226 | bool transformed = false; |
| 9366 | if (!extraScope && assignList) { | 10227 | if (!breakWithVar.empty()) { |
| 10228 | auto repeatNode = toAst<Repeat_t>("repeat\n\t--\nuntil true"s, x); | ||
| 10229 | auto block = x->new_ptr<Block_t>(); | ||
| 10230 | if (auto blk = with->body.as<Block_t>()) { | ||
| 10231 | block->statementOrComments.dup(blk->statementOrComments); | ||
| 10232 | } else { | ||
| 10233 | auto stmt = with->body.to<Statement_t>(); | ||
| 10234 | block->statementOrComments.push_back(stmt); | ||
| 10235 | } | ||
| 10236 | repeatNode->body.set(block); | ||
| 10237 | auto sVal = x->new_ptr<SimpleValue_t>(); | ||
| 10238 | sVal->value.set(repeatNode); | ||
| 10239 | auto asmt = assignmentFrom(toAst<Exp_t>(breakWithVar, x), newExp(sVal, x), x); | ||
| 10240 | transformAssignment(asmt, temp); | ||
| 10241 | transformed = true; | ||
| 10242 | } else if (!extraScope && assignList) { | ||
| 9367 | if (auto block = with->body.as<Block_t>()) { | 10243 | if (auto block = with->body.as<Block_t>()) { |
| 9368 | if (!block->statements.empty()) { | 10244 | if (!block->statementOrComments.empty()) { |
| 9369 | Statement_t* stmt = static_cast<Statement_t*>(block->statements.back()); | 10245 | Statement_t* stmt = lastStatementFrom(block); |
| 9370 | if (stmt->content.is<Return_t>()) { | 10246 | if (stmt && stmt->content.is<Return_t>()) { |
| 9371 | auto newBlock = with->body->new_ptr<Block_t>(); | 10247 | auto newBlock = with->body->new_ptr<Block_t>(); |
| 9372 | newBlock->statements.dup(block->statements); | 10248 | newBlock->statementOrComments.dup(block->statementOrComments); |
| 9373 | newBlock->statements.pop_back(); | 10249 | newBlock->statementOrComments.pop_back(); |
| 9374 | transform_plain_body(newBlock, temp, ExpUsage::Common); | 10250 | transform_plain_body(newBlock, temp, ExpUsage::Common); |
| 9375 | auto newBody = stmt->new_ptr<Body_t>(); | 10251 | auto newBody = stmt->new_ptr<Body_t>(); |
| 9376 | newBody->content.set(stmt); | 10252 | newBody->content.set(stmt); |
| @@ -9408,12 +10284,12 @@ private: | |||
| 9408 | if (returnValue) { | 10284 | if (returnValue) { |
| 9409 | auto last = lastStatementFrom(with->body); | 10285 | auto last = lastStatementFrom(with->body); |
| 9410 | if (last && !last->content.is<Return_t>()) { | 10286 | if (last && !last->content.is<Return_t>()) { |
| 9411 | temp.push_back(indent() + "return "s + withVar + nll(with)); | 10287 | temp.push_back(indent() + "return "s + withVar + nl(with)); |
| 9412 | } | 10288 | } |
| 9413 | } | 10289 | } |
| 9414 | if (extraScope) { | 10290 | if (extraScope) { |
| 9415 | popScope(); | 10291 | popScope(); |
| 9416 | temp.push_back(indent() + "end"s + nll(with)); | 10292 | temp.push_back(indent() + "end"s + nl(with)); |
| 9417 | } | 10293 | } |
| 9418 | out.push_back(join(temp)); | 10294 | out.push_back(join(temp)); |
| 9419 | } | 10295 | } |
| @@ -9428,12 +10304,18 @@ private: | |||
| 9428 | switch (item->get_id()) { | 10304 | switch (item->get_id()) { |
| 9429 | case id<ClassDecl_t>(): { | 10305 | case id<ClassDecl_t>(): { |
| 9430 | auto classDecl = static_cast<ClassDecl_t*>(item); | 10306 | auto classDecl = static_cast<ClassDecl_t*>(item); |
| 10307 | std::string varName; | ||
| 9431 | if (classDecl->name) { | 10308 | if (classDecl->name) { |
| 9432 | if (auto var = classDecl->name->item.as<Variable_t>()) { | 10309 | if (auto var = classDecl->name->item.as<Variable_t>()) { |
| 9433 | addGlobalVar(variableToString(var), classDecl->name->item); | 10310 | varName = variableToString(var); |
| 10311 | addGlobalVar(varName, var); | ||
| 9434 | } | 10312 | } |
| 9435 | } | 10313 | } |
| 10314 | if (varName.empty()) { | ||
| 10315 | throw CompileError("missing name for class", classDecl); | ||
| 10316 | } | ||
| 9436 | transformClassDecl(classDecl, out, ExpUsage::Common); | 10317 | transformClassDecl(classDecl, out, ExpUsage::Common); |
| 10318 | markVarGlobalConst(varName); | ||
| 9437 | break; | 10319 | break; |
| 9438 | } | 10320 | } |
| 9439 | case id<GlobalOp_t>(): | 10321 | case id<GlobalOp_t>(): |
| @@ -9447,9 +10329,11 @@ private: | |||
| 9447 | auto values = global->item.to<GlobalValues_t>(); | 10329 | auto values = global->item.to<GlobalValues_t>(); |
| 9448 | if (values->valueList) { | 10330 | if (values->valueList) { |
| 9449 | auto expList = x->new_ptr<ExpList_t>(); | 10331 | auto expList = x->new_ptr<ExpList_t>(); |
| 10332 | str_list varNames; | ||
| 9450 | for (auto name : values->nameList->names.objects()) { | 10333 | for (auto name : values->nameList->names.objects()) { |
| 9451 | auto var = static_cast<Variable_t*>(name); | 10334 | auto var = static_cast<Variable_t*>(name); |
| 9452 | addGlobalVar(variableToString(var), var); | 10335 | varNames.emplace_back(variableToString(var)); |
| 10336 | addGlobalVar(varNames.back(), var); | ||
| 9453 | auto callable = x->new_ptr<Callable_t>(); | 10337 | auto callable = x->new_ptr<Callable_t>(); |
| 9454 | callable->item.set(name); | 10338 | callable->item.set(name); |
| 9455 | auto chainValue = x->new_ptr<ChainValue_t>(); | 10339 | auto chainValue = x->new_ptr<ChainValue_t>(); |
| @@ -9460,18 +10344,27 @@ private: | |||
| 9460 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 10344 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 9461 | assignment->expList.set(expList); | 10345 | assignment->expList.set(expList); |
| 9462 | auto assign = x->new_ptr<Assign_t>(); | 10346 | auto assign = x->new_ptr<Assign_t>(); |
| 9463 | if (auto expListLow = values->valueList.as<ExpListLow_t>()) { | 10347 | if (auto expList = values->valueList.as<ExpList_t>()) { |
| 9464 | assign->values.dup(expListLow->exprs); | 10348 | assign->values.dup(expList->exprs); |
| 9465 | } else { | 10349 | } else { |
| 9466 | auto tableBlock = values->valueList.to<TableBlock_t>(); | 10350 | auto tableBlock = values->valueList.to<TableBlock_t>(); |
| 9467 | assign->values.push_back(tableBlock); | 10351 | assign->values.push_back(tableBlock); |
| 9468 | } | 10352 | } |
| 9469 | assignment->action.set(assign); | 10353 | assignment->action.set(assign); |
| 9470 | transformAssignment(assignment, out); | 10354 | transformAssignment(assignment, out); |
| 10355 | if (global->constAttrib) { | ||
| 10356 | for (const auto& name : varNames) { | ||
| 10357 | markVarGlobalConst(name); | ||
| 10358 | } | ||
| 10359 | } | ||
| 9471 | } else { | 10360 | } else { |
| 9472 | for (auto name : values->nameList->names.objects()) { | 10361 | for (auto name : values->nameList->names.objects()) { |
| 9473 | auto var = static_cast<Variable_t*>(name); | 10362 | auto var = static_cast<Variable_t*>(name); |
| 9474 | addGlobalVar(variableToString(var), var); | 10363 | auto varName = variableToString(var); |
| 10364 | addGlobalVar(varName, var); | ||
| 10365 | if (global->constAttrib) { | ||
| 10366 | markVarGlobalConst(varName); | ||
| 10367 | } | ||
| 9475 | } | 10368 | } |
| 9476 | } | 10369 | } |
| 9477 | break; | 10370 | break; |
| @@ -9608,7 +10501,7 @@ private: | |||
| 9608 | } | 10501 | } |
| 9609 | } | 10502 | } |
| 9610 | if (_info.exportDefault) { | 10503 | if (_info.exportDefault) { |
| 9611 | out.back().append(indent() + _info.moduleName + " = "s + names.back().first + nlr(exportNode)); | 10504 | out.back().append(indent() + _info.moduleName + " = "s + names.back().first + nl(exportNode)); |
| 9612 | } else { | 10505 | } else { |
| 9613 | str_list lefts, rights; | 10506 | str_list lefts, rights; |
| 9614 | for (const auto& name : names) { | 10507 | for (const auto& name : names) { |
| @@ -9621,7 +10514,7 @@ private: | |||
| 9621 | lefts.push_back(_info.moduleName + "[\""s + realName + "\"]"s); | 10514 | lefts.push_back(_info.moduleName + "[\""s + realName + "\"]"s); |
| 9622 | rights.push_back(name.first); | 10515 | rights.push_back(name.first); |
| 9623 | } | 10516 | } |
| 9624 | out.back().append(indent() + join(lefts, ", "sv) + " = "s + join(rights, ", "sv) + nlr(exportNode)); | 10517 | out.back().append(indent() + join(lefts, ", "sv) + " = "s + join(rights, ", "sv) + nl(exportNode)); |
| 9625 | } | 10518 | } |
| 9626 | } | 10519 | } |
| 9627 | } else { | 10520 | } else { |
| @@ -9705,12 +10598,12 @@ private: | |||
| 9705 | case id<CompForEach_t>(): | 10598 | case id<CompForEach_t>(): |
| 9706 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); | 10599 | transformCompForEach(static_cast<CompForEach_t*>(item), temp); |
| 9707 | break; | 10600 | break; |
| 9708 | case id<CompFor_t>(): | 10601 | case id<CompForNum_t>(): |
| 9709 | transformCompFor(static_cast<CompFor_t*>(item), temp); | 10602 | transformCompForNum(static_cast<CompForNum_t*>(item), temp); |
| 9710 | break; | 10603 | break; |
| 9711 | case id<Exp_t>(): | 10604 | case id<Exp_t>(): |
| 9712 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); | 10605 | transformExp(static_cast<Exp_t*>(item), temp, ExpUsage::Closure); |
| 9713 | temp.back() = indent() + "if "s + temp.back() + " then"s + nll(item); | 10606 | temp.back() = indent() + "if "s + temp.back() + " then"s + nl(item); |
| 9714 | pushScope(); | 10607 | pushScope(); |
| 9715 | break; | 10608 | break; |
| 9716 | default: YUEE("AST node mismatch", item); break; | 10609 | default: YUEE("AST node mismatch", item); break; |
| @@ -9723,27 +10616,27 @@ private: | |||
| 9723 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { | 10616 | for (size_t i = 0; i < compInner->items.objects().size(); ++i) { |
| 9724 | popScope(); | 10617 | popScope(); |
| 9725 | } | 10618 | } |
| 9726 | _buf << indent() << "local "sv << tbl << " = { }"sv << nll(comp); | 10619 | _buf << indent() << "local "sv << tbl << " = { }"sv << nl(comp); |
| 9727 | _buf << join(temp); | 10620 | _buf << join(temp); |
| 9728 | pushScope(); | 10621 | pushScope(); |
| 9729 | if (!comp->value) { | 10622 | if (!comp->value) { |
| 9730 | auto keyVar = getUnusedName("_key_"sv); | 10623 | auto keyVar = getUnusedName("_key_"sv); |
| 9731 | auto valVar = getUnusedName("_val_"sv); | 10624 | auto valVar = getUnusedName("_val_"sv); |
| 9732 | _buf << indent(int(temp.size()) - 1) << "local "sv << keyVar << ", "sv << valVar << " = "sv << kv.front() << nll(comp); | 10625 | _buf << indent(int(temp.size()) - 1) << "local "sv << keyVar << ", "sv << valVar << " = "sv << kv.front() << nl(comp); |
| 9733 | kv.front() = keyVar; | 10626 | kv.front() = keyVar; |
| 9734 | kv.push_back(valVar); | 10627 | kv.push_back(valVar); |
| 9735 | } | 10628 | } |
| 9736 | _buf << indent(int(temp.size()) - 1) << tbl << "["sv << kv.front() << "] = "sv << kv.back() << nll(comp); | 10629 | _buf << indent(int(temp.size()) - 1) << tbl << "["sv << kv.front() << "] = "sv << kv.back() << nl(comp); |
| 9737 | for (int ind = int(temp.size()) - 2; ind > -1; --ind) { | 10630 | for (int ind = int(temp.size()) - 2; ind > -1; --ind) { |
| 9738 | _buf << indent(ind) << "end"sv << nll(comp); | 10631 | _buf << indent(ind) << "end"sv << nl(comp); |
| 9739 | } | 10632 | } |
| 9740 | popScope(); | 10633 | popScope(); |
| 9741 | _buf << indent() << "end"sv << nll(comp); | 10634 | _buf << indent() << "end"sv << nl(comp); |
| 9742 | switch (usage) { | 10635 | switch (usage) { |
| 9743 | case ExpUsage::Closure: | 10636 | case ExpUsage::Closure: |
| 9744 | out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp)); | 10637 | out.push_back(clearBuf() + indent() + "return "s + tbl + nl(comp)); |
| 9745 | popScope(); | 10638 | popScope(); |
| 9746 | out.back().insert(0, anonFuncStart() + nll(comp)); | 10639 | out.back().insert(0, anonFuncStart() + nl(comp)); |
| 9747 | out.back().append(indent() + anonFuncEnd()); | 10640 | out.back().append(indent() + anonFuncEnd()); |
| 9748 | popAnonVarArg(); | 10641 | popAnonVarArg(); |
| 9749 | popFunctionScope(); | 10642 | popFunctionScope(); |
| @@ -9759,21 +10652,21 @@ private: | |||
| 9759 | out.back().append(temp.back()); | 10652 | out.back().append(temp.back()); |
| 9760 | if (extraScope) { | 10653 | if (extraScope) { |
| 9761 | popScope(); | 10654 | popScope(); |
| 9762 | out.back().insert(0, indent() + "do"s + nll(comp)); | 10655 | out.back().insert(0, indent() + "do"s + nl(comp)); |
| 9763 | out.back().append(indent() + "end"s + nlr(comp)); | 10656 | out.back().append(indent() + "end"s + nl(comp)); |
| 9764 | } | 10657 | } |
| 9765 | break; | 10658 | break; |
| 9766 | } | 10659 | } |
| 9767 | case ExpUsage::Return: | 10660 | case ExpUsage::Return: |
| 9768 | out.push_back(clearBuf() + indent() + "return "s + tbl + nlr(comp)); | 10661 | out.push_back(clearBuf() + indent() + "return "s + tbl + nl(comp)); |
| 9769 | break; | 10662 | break; |
| 9770 | default: | 10663 | default: |
| 9771 | break; | 10664 | break; |
| 9772 | } | 10665 | } |
| 9773 | } | 10666 | } |
| 9774 | 10667 | ||
| 9775 | void transformCompFor(CompFor_t* comp, str_list& out) { | 10668 | void transformCompForNum(CompForNum_t* comp, str_list& out) { |
| 9776 | transformForHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); | 10669 | transformForNumHead(comp->varName, comp->startValue, comp->stopValue, comp->stepValue, out); |
| 9777 | } | 10670 | } |
| 9778 | 10671 | ||
| 9779 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { | 10672 | void transformTableBlockIndent(TableBlockIndent_t* table, str_list& out) { |
| @@ -9803,25 +10696,64 @@ private: | |||
| 9803 | funcStart = &temp.emplace_back(); | 10696 | funcStart = &temp.emplace_back(); |
| 9804 | pushScope(); | 10697 | pushScope(); |
| 9805 | } else { | 10698 | } else { |
| 9806 | temp.push_back(indent() + "do"s + nll(doNode)); | 10699 | temp.push_back(indent() + "do"s + nl(doNode)); |
| 9807 | pushScope(); | 10700 | pushScope(); |
| 9808 | } | 10701 | } |
| 9809 | transformBody(doNode->body, temp, usage, assignList); | 10702 | transformBody(doNode->body, temp, usage, assignList); |
| 9810 | if (usage == ExpUsage::Closure) { | 10703 | if (usage == ExpUsage::Closure) { |
| 9811 | popScope(); | 10704 | popScope(); |
| 9812 | *funcStart = anonFuncStart() + nll(doNode); | 10705 | *funcStart = anonFuncStart() + nl(doNode); |
| 9813 | temp.push_back(indent() + anonFuncEnd()); | 10706 | temp.push_back(indent() + anonFuncEnd()); |
| 9814 | popAnonVarArg(); | 10707 | popAnonVarArg(); |
| 9815 | popFunctionScope(); | 10708 | popFunctionScope(); |
| 9816 | } else { | 10709 | } else { |
| 9817 | popScope(); | 10710 | popScope(); |
| 9818 | temp.push_back(indent() + "end"s + nlr(doNode)); | 10711 | temp.push_back(indent() + "end"s + nl(doNode)); |
| 9819 | } | 10712 | } |
| 9820 | out.push_back(join(temp)); | 10713 | out.push_back(join(temp)); |
| 9821 | } | 10714 | } |
| 9822 | 10715 | ||
| 9823 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage) { | 10716 | void transformTry(Try_t* tryNode, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { |
| 9824 | auto x = tryNode; | 10717 | auto x = tryNode; |
| 10718 | if (tryNode->eop && usage == ExpUsage::Assignment) { | ||
| 10719 | str_list rets; | ||
| 10720 | pushScope(); | ||
| 10721 | auto okVar = getUnusedName("_ok_"sv); | ||
| 10722 | for (size_t i = 0; i < assignList->exprs.size(); i++) { | ||
| 10723 | auto retVar = getUnusedName("_ret_"sv); | ||
| 10724 | rets.emplace_back(retVar); | ||
| 10725 | addToScope(retVar); | ||
| 10726 | } | ||
| 10727 | popScope(); | ||
| 10728 | auto varList = join(rets, ","sv); | ||
| 10729 | auto ifNode = toAst<If_t>("if "s + okVar + ',' + varList + ":=try nil then "s + varList, x); | ||
| 10730 | auto exp = ast_to<IfCond_t>(ifNode->nodes.front())->assignment->assign->values.front(); | ||
| 10731 | auto sVal = simpleSingleValueFrom(exp); | ||
| 10732 | auto newTry = sVal->value.to<Try_t>(); | ||
| 10733 | newTry->func.set(tryNode->func); | ||
| 10734 | newTry->catchBlock.set(tryNode->catchBlock); | ||
| 10735 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 10736 | assignment->expList.set(assignList); | ||
| 10737 | auto assign = x->new_ptr<Assign_t>(); | ||
| 10738 | assign->values.push_back(ifNode); | ||
| 10739 | assignment->action.set(assign); | ||
| 10740 | transformAssignment(assignment, out); | ||
| 10741 | return; | ||
| 10742 | } | ||
| 10743 | if (tryNode->eop && usage != ExpUsage::Common) { | ||
| 10744 | auto okVar = getUnusedName("_ok_"sv); | ||
| 10745 | auto code = "do\n\t"s + okVar + ", ... = try nil\n\t... if "s + okVar; | ||
| 10746 | auto doNode = toAst<Do_t>(code, x); | ||
| 10747 | auto block = doNode->body->content.to<Block_t>(); | ||
| 10748 | auto asmt = static_cast<Statement_t*>(block->statementOrComments.front())->content.to<ExpListAssign_t>(); | ||
| 10749 | auto assign = asmt->action.to<Assign_t>(); | ||
| 10750 | auto sVal = simpleSingleValueFrom(assign->values.back()); | ||
| 10751 | auto newTry = sVal->value.to<Try_t>(); | ||
| 10752 | newTry->func.set(tryNode->func); | ||
| 10753 | newTry->catchBlock.set(tryNode->catchBlock); | ||
| 10754 | transformDo(doNode, out, usage); | ||
| 10755 | return; | ||
| 10756 | } | ||
| 9825 | ast_ptr<true, Exp_t> errHandler; | 10757 | ast_ptr<true, Exp_t> errHandler; |
| 9826 | if (tryNode->catchBlock) { | 10758 | if (tryNode->catchBlock) { |
| 9827 | auto catchBlock = tryNode->catchBlock.get(); | 10759 | auto catchBlock = tryNode->catchBlock.get(); |
| @@ -9837,8 +10769,8 @@ private: | |||
| 9837 | tryFunc.set(tryNode->func); | 10769 | tryFunc.set(tryNode->func); |
| 9838 | if (auto tryBlock = tryFunc.as<Block_t>()) { | 10770 | if (auto tryBlock = tryFunc.as<Block_t>()) { |
| 9839 | BLOCK_START | 10771 | BLOCK_START |
| 9840 | BREAK_IF(tryBlock->statements.size() != 1); | 10772 | BREAK_IF(countStatementFrom(tryBlock) != 1); |
| 9841 | auto stmt = static_cast<Statement_t*>(tryBlock->statements.front()); | 10773 | auto stmt = firstStatementFrom(tryBlock); |
| 9842 | auto expListAssign = stmt->content.as<ExpListAssign_t>(); | 10774 | auto expListAssign = stmt->content.as<ExpListAssign_t>(); |
| 9843 | BREAK_IF(!expListAssign); | 10775 | BREAK_IF(!expListAssign); |
| 9844 | BREAK_IF(expListAssign->action); | 10776 | BREAK_IF(expListAssign->action); |
| @@ -9902,7 +10834,7 @@ private: | |||
| 9902 | auto stmt = x->new_ptr<Statement_t>(); | 10834 | auto stmt = x->new_ptr<Statement_t>(); |
| 9903 | stmt->content.set(expListAssign); | 10835 | stmt->content.set(expListAssign); |
| 9904 | auto block = x->new_ptr<Block_t>(); | 10836 | auto block = x->new_ptr<Block_t>(); |
| 9905 | block->statements.push_back(stmt); | 10837 | block->statementOrComments.push_back(stmt); |
| 9906 | tryFunc.set(block); | 10838 | tryFunc.set(block); |
| 9907 | } | 10839 | } |
| 9908 | } | 10840 | } |
| @@ -9930,7 +10862,7 @@ private: | |||
| 9930 | } | 10862 | } |
| 9931 | if (usage == ExpUsage::Common) { | 10863 | if (usage == ExpUsage::Common) { |
| 9932 | out.back().insert(0, indent()); | 10864 | out.back().insert(0, indent()); |
| 9933 | out.back().append(nlr(x)); | 10865 | out.back().append(nl(x)); |
| 9934 | } | 10866 | } |
| 9935 | return; | 10867 | return; |
| 9936 | } | 10868 | } |
| @@ -9955,7 +10887,7 @@ private: | |||
| 9955 | } | 10887 | } |
| 9956 | if (usage == ExpUsage::Common) { | 10888 | if (usage == ExpUsage::Common) { |
| 9957 | out.back().insert(0, indent()); | 10889 | out.back().insert(0, indent()); |
| 9958 | out.back().append(nlr(x)); | 10890 | out.back().append(nl(x)); |
| 9959 | } | 10891 | } |
| 9960 | return; | 10892 | return; |
| 9961 | } else if (auto value = singleValueFrom(tryFunc)) { | 10893 | } else if (auto value = singleValueFrom(tryFunc)) { |
| @@ -10016,7 +10948,7 @@ private: | |||
| 10016 | } | 10948 | } |
| 10017 | if (usage == ExpUsage::Common) { | 10949 | if (usage == ExpUsage::Common) { |
| 10018 | out.back().insert(0, indent()); | 10950 | out.back().insert(0, indent()); |
| 10019 | out.back().append(nlr(x)); | 10951 | out.back().append(nl(x)); |
| 10020 | } | 10952 | } |
| 10021 | return; | 10953 | return; |
| 10022 | BLOCK_END | 10954 | BLOCK_END |
| @@ -10035,13 +10967,13 @@ private: | |||
| 10035 | } | 10967 | } |
| 10036 | if (usage == ExpUsage::Common) { | 10968 | if (usage == ExpUsage::Common) { |
| 10037 | out.back().insert(0, indent()); | 10969 | out.back().insert(0, indent()); |
| 10038 | out.back().append(nlr(x)); | 10970 | out.back().append(nl(x)); |
| 10039 | } | 10971 | } |
| 10040 | } | 10972 | } |
| 10041 | 10973 | ||
| 10042 | void transformImportFrom(ImportFrom_t* importNode, str_list& out) { | 10974 | void transformImportFrom(ImportFrom_t* importNode, str_list& out) { |
| 10043 | str_list temp; | 10975 | str_list temp; |
| 10044 | auto x = importNode; | 10976 | auto x = importNode->item.get(); |
| 10045 | auto objVar = singleVariableFrom(importNode->item, AccessType::Read); | 10977 | auto objVar = singleVariableFrom(importNode->item, AccessType::Read); |
| 10046 | ast_ptr<false, ExpListAssign_t> objAssign; | 10978 | ast_ptr<false, ExpListAssign_t> objAssign; |
| 10047 | if (objVar.empty()) { | 10979 | if (objVar.empty()) { |
| @@ -10111,11 +11043,11 @@ private: | |||
| 10111 | if (objAssign) { | 11043 | if (objAssign) { |
| 10112 | auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); | 11044 | auto preDef = toLocalDecl(transformAssignDefs(expList, DefOp::Mark)); |
| 10113 | if (!preDef.empty()) { | 11045 | if (!preDef.empty()) { |
| 10114 | temp.push_back(preDef + nll(importNode)); | 11046 | temp.push_back(preDef + nl(importNode)); |
| 10115 | } | 11047 | } |
| 10116 | if (!currentScope().lastStatement) { | 11048 | if (!currentScope().lastStatement) { |
| 10117 | extraScope = true; | 11049 | extraScope = true; |
| 10118 | temp.push_back(indent() + "do"s + nll(importNode)); | 11050 | temp.push_back(indent() + "do"s + nl(importNode)); |
| 10119 | pushScope(); | 11051 | pushScope(); |
| 10120 | } | 11052 | } |
| 10121 | transformAssignment(objAssign, temp); | 11053 | transformAssignment(objAssign, temp); |
| @@ -10127,13 +11059,13 @@ private: | |||
| 10127 | if (objAssign) { | 11059 | if (objAssign) { |
| 10128 | if (extraScope) { | 11060 | if (extraScope) { |
| 10129 | popScope(); | 11061 | popScope(); |
| 10130 | temp.push_back(indent() + "end"s + nlr(importNode)); | 11062 | temp.push_back(indent() + "end"s + nl(importNode)); |
| 10131 | } | 11063 | } |
| 10132 | } | 11064 | } |
| 10133 | out.push_back(join(temp)); | 11065 | out.push_back(join(temp)); |
| 10134 | auto vars = getAssignVars(assignment); | 11066 | auto vars = getAssignVars(assignment); |
| 10135 | for (const auto& var : vars) { | 11067 | for (const auto& var : vars) { |
| 10136 | markVarConst(var); | 11068 | markVarLocalConst(var); |
| 10137 | } | 11069 | } |
| 10138 | } | 11070 | } |
| 10139 | 11071 | ||
| @@ -10361,12 +11293,36 @@ private: | |||
| 10361 | transformAssignment(assignment, out); | 11293 | transformAssignment(assignment, out); |
| 10362 | if (auto var = ast_cast<Variable_t>(target)) { | 11294 | if (auto var = ast_cast<Variable_t>(target)) { |
| 10363 | auto moduleName = variableToString(var); | 11295 | auto moduleName = variableToString(var); |
| 10364 | markVarConst(moduleName); | 11296 | markVarLocalConst(moduleName); |
| 10365 | } else { | 11297 | } else { |
| 10366 | markDestructureConst(assignment); | 11298 | markDestructureConst(assignment); |
| 10367 | } | 11299 | } |
| 10368 | } | 11300 | } |
| 10369 | 11301 | ||
| 11302 | void transformImportGlobal(ImportGlobal_t* importNode, str_list& out) { | ||
| 11303 | auto uname = static_cast<UnicodeName_t*>(importNode->segs.front()); | ||
| 11304 | auto var = _parser.toString(uname); | ||
| 11305 | auto isNormal = _parser.match<Name_t>(var) && _parser.match<Variable_t>(var); | ||
| 11306 | auto varName = unicodeVariableFrom(uname); | ||
| 11307 | str_list temp; | ||
| 11308 | auto it = ++importNode->segs.objects().begin(); | ||
| 11309 | for (; it != importNode->segs.objects().end(); ++it) { | ||
| 11310 | temp.emplace_back(_parser.toString(*it)); | ||
| 11311 | } | ||
| 11312 | temp.emplace_front(var); | ||
| 11313 | if (isLocal(varName) || !isNormal) { | ||
| 11314 | temp.emplace_front("_G"s); | ||
| 11315 | } | ||
| 11316 | std::string stmt; | ||
| 11317 | if (importNode->target) { | ||
| 11318 | stmt = "const "s + _parser.toString(importNode->target) + '=' + join(temp, "."sv); | ||
| 11319 | } else { | ||
| 11320 | stmt = "const "s + temp.back() + '=' + join(temp, "."sv); | ||
| 11321 | } | ||
| 11322 | auto localAttrib = toAst<LocalAttrib_t>(stmt, importNode); | ||
| 11323 | transformLocalAttrib(localAttrib, out); | ||
| 11324 | } | ||
| 11325 | |||
| 10370 | void transformImport(Import_t* import, str_list& out) { | 11326 | void transformImport(Import_t* import, str_list& out) { |
| 10371 | auto content = import->content.get(); | 11327 | auto content = import->content.get(); |
| 10372 | switch (content->get_id()) { | 11328 | switch (content->get_id()) { |
| @@ -10379,6 +11335,9 @@ private: | |||
| 10379 | case id<FromImport_t>(): | 11335 | case id<FromImport_t>(): |
| 10380 | transformFromImport(static_cast<FromImport_t*>(content), out); | 11336 | transformFromImport(static_cast<FromImport_t*>(content), out); |
| 10381 | break; | 11337 | break; |
| 11338 | case id<ImportGlobal_t>(): | ||
| 11339 | transformImportGlobal(static_cast<ImportGlobal_t*>(content), out); | ||
| 11340 | break; | ||
| 10382 | default: YUEE("AST node mismatch", content); break; | 11341 | default: YUEE("AST node mismatch", content); break; |
| 10383 | } | 11342 | } |
| 10384 | } | 11343 | } |
| @@ -10390,7 +11349,7 @@ private: | |||
| 10390 | if (expList) { | 11349 | if (expList) { |
| 10391 | if (!currentScope().lastStatement) { | 11350 | if (!currentScope().lastStatement) { |
| 10392 | extraScope = true; | 11351 | extraScope = true; |
| 10393 | temp.push_back(indent() + "do"s + nll(whileNode)); | 11352 | temp.push_back(indent() + "do"s + nl(whileNode)); |
| 10394 | pushScope(); | 11353 | pushScope(); |
| 10395 | } | 11354 | } |
| 10396 | } | 11355 | } |
| @@ -10398,17 +11357,29 @@ private: | |||
| 10398 | addToScope(accumVar); | 11357 | addToScope(accumVar); |
| 10399 | auto lenVar = getUnusedName("_len_"sv); | 11358 | auto lenVar = getUnusedName("_len_"sv); |
| 10400 | addToScope(lenVar); | 11359 | addToScope(lenVar); |
| 10401 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11360 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
| 10402 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11361 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(whileNode); |
| 11362 | temp.emplace_back(clearBuf()); | ||
| 11363 | _buf << indent() << "local "s << lenVar << " = 1"s << nl(whileNode); | ||
| 11364 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
| 10403 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11365 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 10404 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11366 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10405 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11367 | temp.push_back(indent() + "while "s + condStr + " do"s + nl(whileNode)); |
| 10406 | pushScope(); | 11368 | pushScope(); |
| 10407 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11369 | if (hasBreakWithValue(breakLoopType)) { |
| 10408 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11370 | lenAssign.clear(); |
| 10409 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11371 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
| 11372 | } else { | ||
| 11373 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11374 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 11375 | assignLeft->followStmt = followStmt.get(); | ||
| 11376 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11377 | if (!assignLeft->followStmtProcessed) { | ||
| 11378 | lenAssign.clear(); | ||
| 11379 | } | ||
| 11380 | } | ||
| 10410 | popScope(); | 11381 | popScope(); |
| 10411 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11382 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10412 | if (expList) { | 11383 | if (expList) { |
| 10413 | auto assign = x->new_ptr<Assign_t>(); | 11384 | auto assign = x->new_ptr<Assign_t>(); |
| 10414 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | 11385 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); |
| @@ -10418,10 +11389,10 @@ private: | |||
| 10418 | transformAssignment(assignment, temp); | 11389 | transformAssignment(assignment, temp); |
| 10419 | if (extraScope) popScope(); | 11390 | if (extraScope) popScope(); |
| 10420 | } else { | 11391 | } else { |
| 10421 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11392 | temp.push_back(indent() + "return "s + accumVar + nl(whileNode)); |
| 10422 | } | 11393 | } |
| 10423 | if (expList && extraScope) { | 11394 | if (expList && extraScope) { |
| 10424 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11395 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10425 | } | 11396 | } |
| 10426 | out.push_back(join(temp)); | 11397 | out.push_back(join(temp)); |
| 10427 | } | 11398 | } |
| @@ -10442,20 +11413,31 @@ private: | |||
| 10442 | addToScope(accumVar); | 11413 | addToScope(accumVar); |
| 10443 | auto lenVar = getUnusedName("_len_"sv); | 11414 | auto lenVar = getUnusedName("_len_"sv); |
| 10444 | addToScope(lenVar); | 11415 | addToScope(lenVar); |
| 10445 | temp.push_back(indent() + "local "s + accumVar + " = { }"s + nll(whileNode)); | 11416 | auto breakLoopType = getBreakLoopType(whileNode->body, accumVar); |
| 10446 | temp.push_back(indent() + "local "s + lenVar + " = 1"s + nll(whileNode)); | 11417 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(whileNode); |
| 11418 | temp.emplace_back(clearBuf()); | ||
| 11419 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nl(whileNode)); | ||
| 10447 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11420 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 10448 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11421 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10449 | temp.push_back(indent() + "while "s + condStr + " do"s + nll(whileNode)); | 11422 | temp.push_back(indent() + "while "s + condStr + " do"s + nl(whileNode)); |
| 10450 | pushScope(); | 11423 | pushScope(); |
| 10451 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | 11424 | if (hasBreakWithValue(breakLoopType)) { |
| 10452 | auto lenLine = lenVar + " = "s + lenVar + " + 1"s + nlr(whileNode); | 11425 | lenAssign.clear(); |
| 10453 | transformLoopBody(whileNode->body, temp, lenLine, ExpUsage::Assignment, assignLeft); | 11426 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); |
| 11427 | } else { | ||
| 11428 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11429 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, whileNode); | ||
| 11430 | assignLeft->followStmt = followStmt.get(); | ||
| 11431 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11432 | if (!assignLeft->followStmtProcessed) { | ||
| 11433 | lenAssign.clear(); | ||
| 11434 | } | ||
| 11435 | } | ||
| 10454 | popScope(); | 11436 | popScope(); |
| 10455 | temp.push_back(indent() + "end"s + nlr(whileNode)); | 11437 | temp.push_back(indent() + "end"s + nl(whileNode)); |
| 10456 | temp.push_back(indent() + "return "s + accumVar + nlr(whileNode)); | 11438 | temp.push_back(indent() + "return "s + accumVar + nl(whileNode)); |
| 10457 | popScope(); | 11439 | popScope(); |
| 10458 | funcStart = anonFuncStart() + nll(whileNode); | 11440 | funcStart = anonFuncStart() + nl(whileNode); |
| 10459 | temp.push_back(indent() + anonFuncEnd()); | 11441 | temp.push_back(indent() + anonFuncEnd()); |
| 10460 | popAnonVarArg(); | 11442 | popAnonVarArg(); |
| 10461 | popFunctionScope(); | 11443 | popFunctionScope(); |
| @@ -10485,9 +11467,7 @@ private: | |||
| 10485 | expListAssign->expList.set(expList); | 11467 | expListAssign->expList.set(expList); |
| 10486 | auto stmt = x->new_ptr<Statement_t>(); | 11468 | auto stmt = x->new_ptr<Statement_t>(); |
| 10487 | stmt->content.set(expListAssign); | 11469 | stmt->content.set(expListAssign); |
| 10488 | auto body = x->new_ptr<Body_t>(); | 11470 | repeat->body.set(stmt); |
| 10489 | body->content.set(stmt); | ||
| 10490 | repeat->body.set(body); | ||
| 10491 | transformRepeat(repeat, out); | 11471 | transformRepeat(repeat, out); |
| 10492 | return; | 11472 | return; |
| 10493 | } | 11473 | } |
| @@ -10495,14 +11475,115 @@ private: | |||
| 10495 | pushScope(); | 11475 | pushScope(); |
| 10496 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; | 11476 | bool isUntil = _parser.toString(whileNode->type) == "until"sv; |
| 10497 | auto condStr = transformCondExp(whileNode->condition, isUntil); | 11477 | auto condStr = transformCondExp(whileNode->condition, isUntil); |
| 10498 | transformLoopBody(whileNode->body, temp, Empty, ExpUsage::Common); | 11478 | auto breakLoopType = getBreakLoopType(whileNode->body, Empty); |
| 11479 | transformLoopBody(whileNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 10499 | popScope(); | 11480 | popScope(); |
| 10500 | _buf << indent() << "while "sv << condStr << " do"sv << nll(whileNode); | 11481 | _buf << indent() << "while "sv << condStr << " do"sv << nl(whileNode); |
| 10501 | _buf << temp.back(); | 11482 | _buf << temp.back(); |
| 10502 | _buf << indent() << "end"sv << nlr(whileNode); | 11483 | _buf << indent() << "end"sv << nl(whileNode); |
| 10503 | out.push_back(clearBuf()); | 11484 | out.push_back(clearBuf()); |
| 10504 | } | 11485 | } |
| 10505 | 11486 | ||
| 11487 | void transformRepeatInPlace(Repeat_t* repeatNode, str_list& out, ExpList_t* expList = nullptr) { | ||
| 11488 | auto x = repeatNode; | ||
| 11489 | str_list temp; | ||
| 11490 | bool extraScope = false; | ||
| 11491 | if (expList) { | ||
| 11492 | if (!currentScope().lastStatement) { | ||
| 11493 | extraScope = true; | ||
| 11494 | temp.push_back(indent() + "do"s + nl(repeatNode)); | ||
| 11495 | pushScope(); | ||
| 11496 | } | ||
| 11497 | } | ||
| 11498 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 11499 | addToScope(accumVar); | ||
| 11500 | auto lenVar = getUnusedName("_len_"sv); | ||
| 11501 | addToScope(lenVar); | ||
| 11502 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 11503 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(repeatNode); | ||
| 11504 | temp.emplace_back(clearBuf()); | ||
| 11505 | _buf << indent() << "local "s << lenVar << " = 1"s << nl(repeatNode); | ||
| 11506 | auto& lenAssign = temp.emplace_back(clearBuf()); | ||
| 11507 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 11508 | temp.push_back(indent() + "repeat"s + nl(repeatNode)); | ||
| 11509 | pushScope(); | ||
| 11510 | if (hasBreakWithValue(breakLoopType)) { | ||
| 11511 | lenAssign.clear(); | ||
| 11512 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 11513 | } else { | ||
| 11514 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11515 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 11516 | assignLeft->followStmt = followStmt.get(); | ||
| 11517 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11518 | if (!assignLeft->followStmtProcessed) { | ||
| 11519 | lenAssign.clear(); | ||
| 11520 | } | ||
| 11521 | } | ||
| 11522 | popScope(); | ||
| 11523 | temp.push_back(indent() + "until "s + condStr + nl(repeatNode)); | ||
| 11524 | if (expList) { | ||
| 11525 | auto assign = x->new_ptr<Assign_t>(); | ||
| 11526 | assign->values.push_back(toAst<Exp_t>(accumVar, x)); | ||
| 11527 | auto assignment = x->new_ptr<ExpListAssign_t>(); | ||
| 11528 | assignment->expList.set(expList); | ||
| 11529 | assignment->action.set(assign); | ||
| 11530 | transformAssignment(assignment, temp); | ||
| 11531 | if (extraScope) popScope(); | ||
| 11532 | } else { | ||
| 11533 | temp.push_back(indent() + "return "s + accumVar + nl(repeatNode)); | ||
| 11534 | } | ||
| 11535 | if (expList && extraScope) { | ||
| 11536 | temp.push_back(indent() + "end"s + nl(repeatNode)); | ||
| 11537 | } | ||
| 11538 | out.push_back(join(temp)); | ||
| 11539 | } | ||
| 11540 | |||
| 11541 | void transformRepeatClosure(Repeat_t* repeatNode, str_list& out) { | ||
| 11542 | auto x = repeatNode; | ||
| 11543 | auto simpleValue = x->new_ptr<SimpleValue_t>(); | ||
| 11544 | simpleValue->value.set(repeatNode); | ||
| 11545 | if (transformAsUpValueFunc(newExp(simpleValue, x), out)) { | ||
| 11546 | return; | ||
| 11547 | } | ||
| 11548 | str_list temp; | ||
| 11549 | pushAnonFunctionScope(); | ||
| 11550 | pushAnonVarArg(); | ||
| 11551 | std::string& funcStart = temp.emplace_back(); | ||
| 11552 | pushScope(); | ||
| 11553 | auto accumVar = getUnusedName("_accum_"sv); | ||
| 11554 | addToScope(accumVar); | ||
| 11555 | auto lenVar = getUnusedName("_len_"sv); | ||
| 11556 | addToScope(lenVar); | ||
| 11557 | auto breakLoopType = getBreakLoopType(repeatNode->body, accumVar); | ||
| 11558 | _buf << indent() << "local "sv << accumVar << (hasBreakWithValue(breakLoopType) ? ""sv : " = { }"sv) << nl(repeatNode); | ||
| 11559 | temp.emplace_back(clearBuf()); | ||
| 11560 | auto& lenAssign = temp.emplace_back(indent() + "local "s + lenVar + " = 1"s + nl(repeatNode)); | ||
| 11561 | auto condStr = transformCondExp(repeatNode->condition, false); | ||
| 11562 | temp.push_back(indent() + "repeat"s + nl(repeatNode)); | ||
| 11563 | pushScope(); | ||
| 11564 | if (hasBreakWithValue(breakLoopType)) { | ||
| 11565 | lenAssign.clear(); | ||
| 11566 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Common); | ||
| 11567 | } else { | ||
| 11568 | auto assignLeft = toAst<ExpList_t>(accumVar + '[' + lenVar + ']', x); | ||
| 11569 | auto followStmt = toAst<Statement_t>(lenVar + "+=1"s, repeatNode); | ||
| 11570 | assignLeft->followStmt = followStmt.get(); | ||
| 11571 | transformLoopBody(repeatNode->body, temp, breakLoopType, ExpUsage::Assignment, assignLeft); | ||
| 11572 | if (!assignLeft->followStmtProcessed) { | ||
| 11573 | lenAssign.clear(); | ||
| 11574 | } | ||
| 11575 | } | ||
| 11576 | popScope(); | ||
| 11577 | temp.push_back(indent() + "until "s + condStr + nl(repeatNode)); | ||
| 11578 | temp.push_back(indent() + "return "s + accumVar + nl(repeatNode)); | ||
| 11579 | popScope(); | ||
| 11580 | funcStart = anonFuncStart() + nl(repeatNode); | ||
| 11581 | temp.push_back(indent() + anonFuncEnd()); | ||
| 11582 | popAnonVarArg(); | ||
| 11583 | popFunctionScope(); | ||
| 11584 | out.push_back(join(temp)); | ||
| 11585 | } | ||
| 11586 | |||
| 10506 | void transformRepeat(Repeat_t* repeat, str_list& out) { | 11587 | void transformRepeat(Repeat_t* repeat, str_list& out) { |
| 10507 | str_list temp; | 11588 | str_list temp; |
| 10508 | pushScope(); | 11589 | pushScope(); |
| @@ -10513,9 +11594,9 @@ private: | |||
| 10513 | temp.push_back(condVar); | 11594 | temp.push_back(condVar); |
| 10514 | } | 11595 | } |
| 10515 | popScope(); | 11596 | popScope(); |
| 10516 | _buf << indent() << "repeat"sv << nll(repeat); | 11597 | _buf << indent() << "repeat"sv << nl(repeat); |
| 10517 | _buf << temp.front(); | 11598 | _buf << temp.front(); |
| 10518 | _buf << indent() << "until "sv << temp.back() << nlr(repeat); | 11599 | _buf << indent() << "until "sv << temp.back() << nl(repeat); |
| 10519 | out.push_back(clearBuf()); | 11600 | out.push_back(clearBuf()); |
| 10520 | } | 11601 | } |
| 10521 | 11602 | ||
| @@ -10536,12 +11617,28 @@ private: | |||
| 10536 | pushScope(); | 11617 | pushScope(); |
| 10537 | } | 11618 | } |
| 10538 | bool extraScope = false; | 11619 | bool extraScope = false; |
| 11620 | if (switchNode->assignment) { | ||
| 11621 | if (needScope) { | ||
| 11622 | extraScope = true; | ||
| 11623 | temp.push_back(indent() + "do"s + nl(x)); | ||
| 11624 | pushScope(); | ||
| 11625 | } | ||
| 11626 | auto asmt = x->new_ptr<ExpListAssign_t>(); | ||
| 11627 | auto expList = x->new_ptr<ExpList_t>(); | ||
| 11628 | expList->exprs.push_back(switchNode->target); | ||
| 11629 | if (switchNode->assignment->expList) { | ||
| 11630 | expList->exprs.dup(switchNode->assignment->expList->exprs); | ||
| 11631 | } | ||
| 11632 | asmt->expList.set(expList); | ||
| 11633 | asmt->action.set(switchNode->assignment->assign); | ||
| 11634 | transformAssignment(asmt, temp); | ||
| 11635 | } | ||
| 10539 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); | 11636 | auto objVar = singleVariableFrom(switchNode->target, AccessType::Read); |
| 10540 | if (objVar.empty() || !isLocal(objVar)) { | 11637 | if (objVar.empty() || !isLocal(objVar)) { |
| 10541 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { | 11638 | if (usage == ExpUsage::Common || usage == ExpUsage::Assignment) { |
| 10542 | if (needScope) { | 11639 | if (needScope && !extraScope) { |
| 10543 | extraScope = true; | 11640 | extraScope = true; |
| 10544 | temp.push_back(indent() + "do"s + nll(x)); | 11641 | temp.push_back(indent() + "do"s + nl(x)); |
| 10545 | pushScope(); | 11642 | pushScope(); |
| 10546 | } | 11643 | } |
| 10547 | } | 11644 | } |
| @@ -10571,13 +11668,13 @@ private: | |||
| 10571 | } | 11668 | } |
| 10572 | if (tableMatching) { | 11669 | if (tableMatching) { |
| 10573 | if (!firstBranch) { | 11670 | if (!firstBranch) { |
| 10574 | temp.push_back(indent() + "else"s + nll(branch)); | 11671 | temp.push_back(indent() + "else"s + nl(branch)); |
| 10575 | pushScope(); | 11672 | pushScope(); |
| 10576 | addScope++; | 11673 | addScope++; |
| 10577 | } | 11674 | } |
| 10578 | if (tabCheckVar.empty()) { | 11675 | if (tabCheckVar.empty()) { |
| 10579 | if (!extraScope && needScope) { | 11676 | if (!extraScope && needScope) { |
| 10580 | temp.push_back(indent() + "do"s + nll(branch)); | 11677 | temp.push_back(indent() + "do"s + nl(branch)); |
| 10581 | pushScope(); | 11678 | pushScope(); |
| 10582 | extraScope = true; | 11679 | extraScope = true; |
| 10583 | } | 11680 | } |
| @@ -10585,20 +11682,21 @@ private: | |||
| 10585 | forceAddToScope(typeVar); | 11682 | forceAddToScope(typeVar); |
| 10586 | tabCheckVar = getUnusedName("_tab_"sv); | 11683 | tabCheckVar = getUnusedName("_tab_"sv); |
| 10587 | forceAddToScope(tabCheckVar); | 11684 | forceAddToScope(tabCheckVar); |
| 10588 | temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch, AccessType::Read) + '(' + objVar + ')' + nll(branch)); | 11685 | temp.push_back(indent() + "local "s + typeVar + " = "s + globalVar("type"sv, branch, AccessType::Read) + '(' + objVar + ')' + nl(branch)); |
| 10589 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nll(branch)); | 11686 | temp.push_back(indent() + "local "s + tabCheckVar + " = \"table\" == "s + typeVar + " or \"userdata\" == "s + typeVar + nl(branch)); |
| 10590 | } | 11687 | } |
| 10591 | std::string matchVar; | 11688 | std::string matchVar; |
| 10592 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; | 11689 | bool lastBranch = branches.back() == branch_ && !switchNode->lastBranch; |
| 10593 | if (!lastBranch) { | 11690 | if (!lastBranch) { |
| 10594 | matchVar = getUnusedName("_match_"sv); | 11691 | matchVar = getUnusedName("_match_"sv); |
| 10595 | forceAddToScope(matchVar); | 11692 | forceAddToScope(matchVar); |
| 10596 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nll(branch)); | 11693 | temp.push_back(indent() + "local "s + matchVar + " = false"s + nl(branch)); |
| 10597 | } | 11694 | } |
| 10598 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nll(branch)); | 11695 | temp.back().append(indent() + "if "s + tabCheckVar + " then"s + nl(branch)); |
| 10599 | pushScope(); | 11696 | pushScope(); |
| 10600 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), toAst<Exp_t>(objVar, branch), branch); | 11697 | auto chainValue = toAst<ChainValue_t>(objVar, branch); |
| 10601 | auto info = extractDestructureInfo(assignment, true, false); | 11698 | auto assignment = assignmentFrom(static_cast<Exp_t*>(valueList->exprs.front()), newExp(chainValue, branch), branch); |
| 11699 | auto info = extractDestructureInfo(assignment, true, true); | ||
| 10602 | transformAssignment(assignment, temp, true); | 11700 | transformAssignment(assignment, temp, true); |
| 10603 | str_list conds; | 11701 | str_list conds; |
| 10604 | for (const auto& des : info.destructures) { | 11702 | for (const auto& des : info.destructures) { |
| @@ -10608,27 +11706,50 @@ private: | |||
| 10608 | const auto& destruct = std::get<Destructure>(des); | 11706 | const auto& destruct = std::get<Destructure>(des); |
| 10609 | for (const auto& item : destruct.items) { | 11707 | for (const auto& item : destruct.items) { |
| 10610 | if (!item.defVal) { | 11708 | if (!item.defVal) { |
| 10611 | transformExp(item.target, conds, ExpUsage::Closure); | 11709 | if (!isAssignable(item.target)) { |
| 10612 | conds.back().append(" ~= nil"s); | 11710 | auto callable = chainValue->items.front(); |
| 11711 | auto chain = callable->new_ptr<ChainValue_t>(); | ||
| 11712 | chain->items.push_back(callable); | ||
| 11713 | chain->items.dup(item.structure->items); | ||
| 11714 | if (specialChainValue(chain) == ChainType::Common) { | ||
| 11715 | transformChainValue(chain, conds, ExpUsage::Closure); | ||
| 11716 | auto vStr = conds.back(); | ||
| 11717 | conds.pop_back(); | ||
| 11718 | transformExp(item.target, conds, ExpUsage::Closure); | ||
| 11719 | conds.back().append(" == "s); | ||
| 11720 | conds.back().append(vStr); | ||
| 11721 | } else { | ||
| 11722 | auto varName = getUnusedName("_val_"sv); | ||
| 11723 | auto vExp = toAst<Exp_t>(varName, chain); | ||
| 11724 | auto asmt = assignmentFrom(vExp, newExp(chain, chain), chain); | ||
| 11725 | transformAssignment(asmt, temp); | ||
| 11726 | transformExp(item.target, conds, ExpUsage::Closure); | ||
| 11727 | conds.back().append(" == "s); | ||
| 11728 | conds.back().append(varName); | ||
| 11729 | } | ||
| 11730 | } else { | ||
| 11731 | transformExp(item.target, conds, ExpUsage::Closure); | ||
| 11732 | conds.back().append(" ~= nil"s); | ||
| 11733 | } | ||
| 10613 | } | 11734 | } |
| 10614 | } | 11735 | } |
| 10615 | } | 11736 | } |
| 10616 | if (!conds.empty()) { | 11737 | if (!conds.empty()) { |
| 10617 | temp.push_back(indent() + "if "s + join(conds, " and "sv) + " then"s + nll(branch)); | 11738 | temp.push_back(indent() + "if "s + join(conds, " and "sv) + " then"s + nl(branch)); |
| 10618 | pushScope(); | 11739 | pushScope(); |
| 10619 | } | 11740 | } |
| 10620 | if (!lastBranch) { | 11741 | if (!lastBranch) { |
| 10621 | temp.push_back(indent() + matchVar + " = true"s + nll(branch)); | 11742 | temp.push_back(indent() + matchVar + " = true"s + nl(branch)); |
| 10622 | } | 11743 | } |
| 10623 | transform_plain_body(branch->body, temp, usage, assignList); | 11744 | transform_plain_body(branch->body, temp, usage, assignList); |
| 10624 | if (!conds.empty()) { | 11745 | if (!conds.empty()) { |
| 10625 | popScope(); | 11746 | popScope(); |
| 10626 | temp.push_back(indent() + "end"s + nll(branch)); | 11747 | temp.push_back(indent() + "end"s + nl(branch)); |
| 10627 | } | 11748 | } |
| 10628 | if (!lastBranch) { | 11749 | if (!lastBranch) { |
| 10629 | popScope(); | 11750 | popScope(); |
| 10630 | temp.push_back(indent() + "end"s + nll(branch)); | 11751 | temp.push_back(indent() + "end"s + nl(branch)); |
| 10631 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nll(branch)); | 11752 | temp.push_back(indent() + "if not "s + matchVar + " then"s + nl(branch)); |
| 10632 | pushScope(); | 11753 | pushScope(); |
| 10633 | addScope++; | 11754 | addScope++; |
| 10634 | } else { | 11755 | } else { |
| @@ -10648,7 +11769,7 @@ private: | |||
| 10648 | } | 11769 | } |
| 10649 | temp.back().append(' ' + tmp.back() + " == "s + (exp == exprs.back() ? objVar : objVar + " or"s)); | 11770 | temp.back().append(' ' + tmp.back() + " == "s + (exp == exprs.back() ? objVar : objVar + " or"s)); |
| 10650 | } | 11771 | } |
| 10651 | temp.back().append(" then"s + nll(branch)); | 11772 | temp.back().append(" then"s + nl(branch)); |
| 10652 | pushScope(); | 11773 | pushScope(); |
| 10653 | transform_plain_body(branch->body, temp, usage, assignList); | 11774 | transform_plain_body(branch->body, temp, usage, assignList); |
| 10654 | popScope(); | 11775 | popScope(); |
| @@ -10656,7 +11777,7 @@ private: | |||
| 10656 | } | 11777 | } |
| 10657 | if (switchNode->lastBranch) { | 11778 | if (switchNode->lastBranch) { |
| 10658 | if (!firstBranch) { | 11779 | if (!firstBranch) { |
| 10659 | temp.push_back(indent() + "else"s + nll(switchNode->lastBranch)); | 11780 | temp.push_back(indent() + "else"s + nl(switchNode->lastBranch)); |
| 10660 | pushScope(); | 11781 | pushScope(); |
| 10661 | } else { | 11782 | } else { |
| 10662 | addScope--; | 11783 | addScope--; |
| @@ -10666,20 +11787,20 @@ private: | |||
| 10666 | } | 11787 | } |
| 10667 | while (addScope > 0) { | 11788 | while (addScope > 0) { |
| 10668 | addScope--; | 11789 | addScope--; |
| 10669 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11790 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10670 | popScope(); | 11791 | popScope(); |
| 10671 | } | 11792 | } |
| 10672 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11793 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10673 | if (usage == ExpUsage::Closure) { | 11794 | if (usage == ExpUsage::Closure) { |
| 10674 | popFunctionScope(); | 11795 | popFunctionScope(); |
| 10675 | popScope(); | 11796 | popScope(); |
| 10676 | *funcStart = anonFuncStart() + nll(switchNode); | 11797 | *funcStart = anonFuncStart() + nl(switchNode); |
| 10677 | temp.push_back(indent() + anonFuncEnd()); | 11798 | temp.push_back(indent() + anonFuncEnd()); |
| 10678 | popAnonVarArg(); | 11799 | popAnonVarArg(); |
| 10679 | } | 11800 | } |
| 10680 | if (extraScope) { | 11801 | if (extraScope) { |
| 10681 | popScope(); | 11802 | popScope(); |
| 10682 | temp.push_back(indent() + "end"s + nlr(switchNode)); | 11803 | temp.push_back(indent() + "end"s + nl(switchNode)); |
| 10683 | } | 11804 | } |
| 10684 | out.push_back(join(temp)); | 11805 | out.push_back(join(temp)); |
| 10685 | } | 11806 | } |
| @@ -10698,7 +11819,7 @@ private: | |||
| 10698 | } | 11819 | } |
| 10699 | auto preDefine = toLocalDecl(defs); | 11820 | auto preDefine = toLocalDecl(defs); |
| 10700 | if (!preDefine.empty()) { | 11821 | if (!preDefine.empty()) { |
| 10701 | out.push_back(preDefine + nll(local)); | 11822 | out.push_back(preDefine + nl(local)); |
| 10702 | } | 11823 | } |
| 10703 | } | 11824 | } |
| 10704 | } | 11825 | } |
| @@ -10727,8 +11848,8 @@ private: | |||
| 10727 | auto assignment = x->new_ptr<ExpListAssign_t>(); | 11848 | auto assignment = x->new_ptr<ExpListAssign_t>(); |
| 10728 | assignment->expList.set(expList); | 11849 | assignment->expList.set(expList); |
| 10729 | auto assign = x->new_ptr<Assign_t>(); | 11850 | auto assign = x->new_ptr<Assign_t>(); |
| 10730 | if (auto expListLow = values->valueList.as<ExpListLow_t>()) { | 11851 | if (auto expList = values->valueList.as<ExpList_t>()) { |
| 10731 | assign->values.dup(expListLow->exprs); | 11852 | assign->values.dup(expList->exprs); |
| 10732 | } else { | 11853 | } else { |
| 10733 | auto tableBlock = values->valueList.to<TableBlock_t>(); | 11854 | auto tableBlock = values->valueList.to<TableBlock_t>(); |
| 10734 | assign->values.push_back(tableBlock); | 11855 | assign->values.push_back(tableBlock); |
| @@ -10736,7 +11857,7 @@ private: | |||
| 10736 | assignment->action.set(assign); | 11857 | assignment->action.set(assign); |
| 10737 | bool oneLined = transformAssignment(assignment, temp); | 11858 | bool oneLined = transformAssignment(assignment, temp); |
| 10738 | for (auto val : assign->values.objects()) { | 11859 | for (auto val : assign->values.objects()) { |
| 10739 | if (auto value = singleValueFrom(val)) { | 11860 | if (auto value = singleValueFrom(val, true)) { |
| 10740 | if (auto spValue = value->item.as<SimpleValue_t>()) { | 11861 | if (auto spValue = value->item.as<SimpleValue_t>()) { |
| 10741 | if (auto funLit = spValue->value.as<FunLit_t>()) { | 11862 | if (auto funLit = spValue->value.as<FunLit_t>()) { |
| 10742 | if (!funLit->noRecursion) { | 11863 | if (!funLit->noRecursion) { |
| @@ -10903,11 +12024,11 @@ private: | |||
| 10903 | } | 12024 | } |
| 10904 | str_list temp; | 12025 | str_list temp; |
| 10905 | if (localAttrib->forceLocal) { | 12026 | if (localAttrib->forceLocal) { |
| 10906 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 12027 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nl(x)); |
| 10907 | } | 12028 | } |
| 10908 | transformAssignment(assignment, temp); | 12029 | transformAssignment(assignment, temp); |
| 10909 | for (const auto& name : vars) { | 12030 | for (const auto& name : vars) { |
| 10910 | markVarConst(name); | 12031 | markVarLocalConst(name); |
| 10911 | } | 12032 | } |
| 10912 | if (localAttrib->attrib.is<CloseAttrib_t>()) { | 12033 | if (localAttrib->attrib.is<CloseAttrib_t>()) { |
| 10913 | str_list leftVars, rightVars; | 12034 | str_list leftVars, rightVars; |
| @@ -10949,13 +12070,13 @@ private: | |||
| 10949 | auto rit = items.begin(); | 12070 | auto rit = items.begin(); |
| 10950 | str_list tmp; | 12071 | str_list tmp; |
| 10951 | while (lit != vars.end()) { | 12072 | while (lit != vars.end()) { |
| 10952 | tmp.push_back(indent() + "local "s + *lit + (target >= 504 ? " <close> = "s : " = "s) + *rit + nll(x)); | 12073 | tmp.push_back(indent() + "local "s + *lit + (target >= 504 ? " <close> = "s : " = "s) + *rit + nl(x)); |
| 10953 | lit++; | 12074 | lit++; |
| 10954 | rit++; | 12075 | rit++; |
| 10955 | } | 12076 | } |
| 10956 | temp.push_back(join(tmp)); | 12077 | temp.push_back(join(tmp)); |
| 10957 | } else { | 12078 | } else { |
| 10958 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 12079 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + " = "s + join(items, ", "sv) + nl(x)); |
| 10959 | str_list leftVars; | 12080 | str_list leftVars; |
| 10960 | pushScope(); | 12081 | pushScope(); |
| 10961 | for (size_t i = 0; i < vars.size(); i++) { | 12082 | for (size_t i = 0; i < vars.size(); i++) { |
| @@ -10976,10 +12097,10 @@ private: | |||
| 10976 | for (auto item : assignA->values.objects()) { | 12097 | for (auto item : assignA->values.objects()) { |
| 10977 | transformAssignItem(item, items); | 12098 | transformAssignItem(item, items); |
| 10978 | } | 12099 | } |
| 10979 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nll(x)); | 12100 | temp.push_back(indent() + "local "s + join(leftVars, ", "sv) + " = "s + join(items, ", "sv) + nl(x)); |
| 10980 | } | 12101 | } |
| 10981 | for (const auto& var : vars) { | 12102 | for (const auto& var : vars) { |
| 10982 | markVarConst(var); | 12103 | markVarLocalConst(var); |
| 10983 | } | 12104 | } |
| 10984 | } | 12105 | } |
| 10985 | if (!listB->exprs.empty()) { | 12106 | if (!listB->exprs.empty()) { |
| @@ -11001,22 +12122,28 @@ private: | |||
| 11001 | vars.push_back(item.targetVar); | 12122 | vars.push_back(item.targetVar); |
| 11002 | } | 12123 | } |
| 11003 | } | 12124 | } |
| 11004 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nll(x)); | 12125 | temp.push_back(indent() + "local "s + join(vars, ", "sv) + nl(x)); |
| 11005 | transformAssignment(assignment, temp); | 12126 | transformAssignment(assignment, temp); |
| 11006 | for (const auto& name : vars) { | 12127 | for (const auto& name : vars) { |
| 11007 | markVarConst(name); | 12128 | markVarLocalConst(name); |
| 11008 | } | 12129 | } |
| 11009 | } | 12130 | } |
| 11010 | out.push_back(join(temp)); | 12131 | out.push_back(join(temp)); |
| 11011 | } | 12132 | } |
| 11012 | 12133 | ||
| 11013 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { | 12134 | void transformBreakLoop(BreakLoop_t* breakLoop, str_list& out) { |
| 11014 | auto keyword = _parser.toString(breakLoop); | 12135 | auto isBreak = breakLoop->type.is<Break_t>(); |
| 12136 | auto keyword = isBreak ? "break"s : "continue"s; | ||
| 11015 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { | 12137 | if (_enableBreakLoop.empty() || !_enableBreakLoop.top()) { |
| 11016 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); | 12138 | throw CompileError(keyword + " is not inside a loop"s, breakLoop); |
| 11017 | } | 12139 | } |
| 11018 | if (keyword == "break"sv) { | 12140 | if (isBreak) { |
| 11019 | out.push_back(indent() + keyword + nll(breakLoop)); | 12141 | if (breakLoop->value) { |
| 12142 | auto exp = toAst<Exp_t>(breakLoop->varBWV, breakLoop->value); | ||
| 12143 | auto assignment = assignmentFrom(exp, breakLoop->value, breakLoop); | ||
| 12144 | transformAssignment(assignment, out); | ||
| 12145 | } | ||
| 12146 | out.push_back(indent() + keyword + nl(breakLoop)); | ||
| 11020 | return; | 12147 | return; |
| 11021 | } | 12148 | } |
| 11022 | if (_continueVars.empty()) throw CompileError("continue is not inside a loop"sv, breakLoop); | 12149 | if (_continueVars.empty()) throw CompileError("continue is not inside a loop"sv, breakLoop); |
| @@ -11029,8 +12156,8 @@ private: | |||
| 11029 | if (!temp.empty()) { | 12156 | if (!temp.empty()) { |
| 11030 | _buf << temp.back(); | 12157 | _buf << temp.back(); |
| 11031 | } | 12158 | } |
| 11032 | _buf << indent() << item.var << " = true"sv << nll(breakLoop); | 12159 | _buf << indent() << item.var << " = true"sv << nl(breakLoop); |
| 11033 | _buf << indent() << "break"sv << nll(breakLoop); | 12160 | _buf << indent() << "break"sv << nl(breakLoop); |
| 11034 | out.push_back(clearBuf()); | 12161 | out.push_back(clearBuf()); |
| 11035 | } else { | 12162 | } else { |
| 11036 | transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp); | 12163 | transformGoto(toAst<Goto_t>("goto "s + item.var, breakLoop), temp); |
| @@ -11042,7 +12169,7 @@ private: | |||
| 11042 | if (getLuaTarget(label) < 502) { | 12169 | if (getLuaTarget(label) < 502) { |
| 11043 | throw CompileError("label statement is not available when not targeting Lua version 5.2 or higher"sv, label); | 12170 | throw CompileError("label statement is not available when not targeting Lua version 5.2 or higher"sv, label); |
| 11044 | } | 12171 | } |
| 11045 | auto labelStr = unicodeVariableFrom(label->label->name); | 12172 | auto labelStr = unicodeVariableFrom(label->label); |
| 11046 | int currentScope = _gotoScopes.top(); | 12173 | int currentScope = _gotoScopes.top(); |
| 11047 | if (static_cast<int>(_labels.size()) <= currentScope) { | 12174 | if (static_cast<int>(_labels.size()) <= currentScope) { |
| 11048 | _labels.resize(currentScope + 1, std::nullopt); | 12175 | _labels.resize(currentScope + 1, std::nullopt); |
| @@ -11056,16 +12183,16 @@ private: | |||
| 11056 | throw CompileError("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label); | 12183 | throw CompileError("label '"s + labelStr + "' already defined at line "s + std::to_string(it->second.line), label); |
| 11057 | } | 12184 | } |
| 11058 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; | 12185 | scope[labelStr] = {label->m_begin.m_line, static_cast<int>(_scopes.size())}; |
| 11059 | out.push_back(indent() + "::"s + labelStr + "::"s + nll(label)); | 12186 | out.push_back(indent() + "::"s + labelStr + "::"s + nl(label)); |
| 11060 | } | 12187 | } |
| 11061 | 12188 | ||
| 11062 | void transformGoto(Goto_t* gotoNode, str_list& out) { | 12189 | void transformGoto(Goto_t* gotoNode, str_list& out) { |
| 11063 | if (getLuaTarget(gotoNode) < 502) { | 12190 | if (getLuaTarget(gotoNode) < 502) { |
| 11064 | throw CompileError("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode); | 12191 | throw CompileError("goto statement is not available when not targeting Lua version 5.2 or higher"sv, gotoNode); |
| 11065 | } | 12192 | } |
| 11066 | auto labelStr = unicodeVariableFrom(gotoNode->label->name); | 12193 | auto labelStr = unicodeVariableFrom(gotoNode->label); |
| 11067 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); | 12194 | gotos.push_back({gotoNode, labelStr, _gotoScopes.top(), static_cast<int>(_scopes.size())}); |
| 11068 | out.push_back(indent() + "goto "s + labelStr + nll(gotoNode)); | 12195 | out.push_back(indent() + "goto "s + labelStr + nl(gotoNode)); |
| 11069 | } | 12196 | } |
| 11070 | 12197 | ||
| 11071 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { | 12198 | void transformShortTabAppending(ShortTabAppending_t* tab, str_list& out) { |
| @@ -11129,13 +12256,13 @@ private: | |||
| 11129 | temp.push_back(getPreDefineLine(assignment)); | 12256 | temp.push_back(getPreDefineLine(assignment)); |
| 11130 | } | 12257 | } |
| 11131 | assignments.push_front(assignmentFrom(newValue, value, value)); | 12258 | assignments.push_front(assignmentFrom(newValue, value, value)); |
| 11132 | temp.push_back(indent() + "do"s + nll(x)); | 12259 | temp.push_back(indent() + "do"s + nl(x)); |
| 11133 | pushScope(); | 12260 | pushScope(); |
| 11134 | for (auto item : assignments.objects()) { | 12261 | for (auto item : assignments.objects()) { |
| 11135 | transformAssignment(static_cast<ExpListAssign_t*>(item), temp); | 12262 | transformAssignment(static_cast<ExpListAssign_t*>(item), temp); |
| 11136 | } | 12263 | } |
| 11137 | popScope(); | 12264 | popScope(); |
| 11138 | temp.push_back(indent() + "end"s + nll(x)); | 12265 | temp.push_back(indent() + "end"s + nl(x)); |
| 11139 | out.push_back(join(temp)); | 12266 | out.push_back(join(temp)); |
| 11140 | } | 12267 | } |
| 11141 | }; | 12268 | }; |
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 77c5901..f564f6a 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 | |||
| 106 | invalid_interpolation_error = pl::user(true_(), [](const item_t& item) { | ||
| 107 | throw ParserError("invalid string interpolation"sv, item.begin); | ||
| 108 | return false; | ||
| 109 | }); | ||
| 110 | |||
| 111 | confusing_unary_not_error = pl::user(true_(), [](const item_t& item) { | ||
| 112 | throw ParserError("deprecated use for unary operator 'not' to be here"sv, item.begin); | ||
| 113 | return false; | ||
| 114 | }); | ||
| 115 | |||
| 116 | table_key_pair_error = pl::user(true_(), [](const item_t& item) { | ||
| 117 | throw ParserError("can not put hash pair in a list"sv, item.begin); | ||
| 118 | return false; | ||
| 119 | }); | ||
| 120 | 123 | ||
| 121 | if_assignment_syntax_error = pl::user(true_(), [](const item_t& item) { | 124 | empty_block_error = expect_error( |
| 122 | throw ParserError("use := for if-assignment expression"sv, item.begin); | 125 | "expected a valid statement or indented block"sv |
| 123 | return false; | 126 | ); |
| 124 | }); | 127 | export_expression_error = expect_error( |
| 128 | "invalid export expression"sv | ||
| 129 | ); | ||
| 130 | invalid_interpolation_error = expect_error( | ||
| 131 | "invalid string interpolation"sv | ||
| 132 | ); | ||
| 133 | confusing_unary_not_error = expect_error( | ||
| 134 | "deprecated use for unary operator 'not' to be here"sv | ||
| 135 | ); | ||
| 136 | table_key_pair_error = expect_error( | ||
| 137 | "can not put hash pair in a list"sv | ||
| 138 | ); | ||
| 139 | assignment_expression_syntax_error = expect_error( | ||
| 140 | "use := for assignment expression"sv | ||
| 141 | ); | ||
| 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 | ExpList | 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,28 +453,41 @@ 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); | ||
| 466 | |||
| 467 | ImportAllGlobal = key("global"); | ||
| 344 | 468 | ||
| 345 | Import = key("import") >> space >> (ImportAs | ImportFrom) | FromImport; | 469 | Import = key("import") >> space >> (ImportAllGlobal | ImportGlobal | ImportAs | ImportFrom | invalid_import_syntax_error) | FromImport; |
| 346 | 470 | ||
| 347 | Label = "::" >> LabelName >> "::"; | 471 | Label = "::" >> (and_(LuaKeyword >> "::") >> keyword_as_label_error | UnicodeName >> "::"); |
| 348 | 472 | ||
| 349 | Goto = key("goto") >> space >> LabelName; | 473 | Goto = key("goto") >> space >> (and_(LuaKeyword >> not_alpha_num) >> keyword_as_label_error | UnicodeName); |
| 350 | 474 | ||
| 351 | ShortTabAppending = "[]" >> space >> Assign; | 475 | ShortTabAppending = "[]" >> space >> Assign; |
| 352 | 476 | ||
| 353 | BreakLoop = (expr("break") | "continue") >> not_alpha_num; | 477 | Break = key("break"); |
| 478 | Continue = key("continue"); | ||
| 479 | BreakLoop = (Break >> -(space >> Exp) | Continue) >> not_alpha_num; | ||
| 354 | 480 | ||
| 355 | Return = key("return") >> -(space >> (TableBlock | ExpListLow)); | 481 | Return = key("return") >> -(space >> (TableBlock | ExpList)); |
| 356 | 482 | ||
| 357 | with_exp = ExpList >> -(space >> Assign); | 483 | must_exp = Exp | expected_expression_error; |
| 358 | 484 | ||
| 359 | With = key("with") >> -ExistentialOp >> space >> disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do"); | 485 | with_exp = ExpList >> -(space >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error)) | expected_expression_error; |
| 486 | |||
| 487 | With = key("with") >> -ExistentialOp >> space >> ( | ||
| 488 | disable_do_chain_arg_table_block_rule(with_exp) >> space >> body_with("do") | | ||
| 489 | invalid_with_syntax_error | ||
| 490 | ); | ||
| 360 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); | 491 | SwitchCase = key("when") >> space >> disable_chain_rule(disable_arg_table_block_rule(SwitchList)) >> space >> body_with("then"); |
| 361 | switch_else = key("else") >> space >> body; | 492 | switch_else = key("else") >> space >> body; |
| 362 | 493 | ||
| @@ -368,9 +499,11 @@ YueParser::YueParser() { | |||
| 368 | 499 | ||
| 369 | SwitchList = Seperator >> ( | 500 | SwitchList = Seperator >> ( |
| 370 | and_(SimpleTable | TableLit) >> Exp | | 501 | and_(SimpleTable | TableLit) >> Exp | |
| 371 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | 502 | exp_not_tab >> *(space >> ',' >> space >> exp_not_tab) | |
| 503 | expected_expression_error | ||
| 372 | ); | 504 | ); |
| 373 | Switch = key("switch") >> space >> Exp >> | 505 | Switch = key("switch") >> space >> |
| 506 | must_exp >> -(space >> Assignment) >> | ||
| 374 | space >> Seperator >> ( | 507 | space >> Seperator >> ( |
| 375 | SwitchCase >> space >> ( | 508 | SwitchCase >> space >> ( |
| 376 | switch_block | | 509 | switch_block | |
| @@ -379,45 +512,53 @@ YueParser::YueParser() { | |||
| 379 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent | 512 | +space_break >> advance_match >> space >> SwitchCase >> switch_block >> pop_indent |
| 380 | ); | 513 | ); |
| 381 | 514 | ||
| 382 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> if_assignment_syntax_error); | 515 | Assignment = -(',' >> space >> ExpList >> space) >> (':' >> Assign | and_('=') >> assignment_expression_syntax_error); |
| 383 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))); | 516 | IfCond = disable_chain_rule(disable_arg_table_block_rule(Exp >> -(space >> Assignment))) | expected_expression_error; |
| 384 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); | 517 | if_else_if = -(line_break >> *space_break >> check_indent_match) >> space >> key("elseif") >> space >> IfCond >> space >> body_with("then"); |
| 385 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; | 518 | if_else = -(line_break >> *space_break >> check_indent_match) >> space >> key("else") >> space >> body; |
| 386 | IfType = (expr("if") | "unless") >> not_alpha_num; | 519 | IfType = (expr("if") | "unless") >> not_alpha_num; |
| 387 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; | 520 | If = IfType >> space >> IfCond >> space >> opt_body_with("then") >> *if_else_if >> -if_else; |
| 388 | 521 | ||
| 389 | WhileType = (expr("while") | "until") >> not_alpha_num; | 522 | WhileType = (expr("while") | pl::user("until", [](const item_t& item) { |
| 390 | While = WhileType >> space >> disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) >> space >> opt_body_with("do"); | 523 | State* st = reinterpret_cast<State*>(item.user_data); |
| 391 | Repeat = key("repeat") >> space >> Body >> line_break >> *space_break >> check_indent_match >> space >> key("until") >> space >> Exp; | 524 | return st->noUntilStack.empty() || !st->noUntilStack.back(); |
| 525 | })) >> not_alpha_num; | ||
| 526 | While = key(WhileType) >> space >> (disable_do_chain_arg_table_block_rule(Exp >> -(space >> Assignment)) | expected_expression_error) >> space >> opt_body_with("do"); | ||
| 527 | Repeat = key("repeat") >> space >> ( | ||
| 528 | in_block >> line_break >> *space_break >> check_indent_match | | ||
| 529 | disable_until_rule(Statement) | ||
| 530 | ) >> space >> key("until") >> space >> must_exp; | ||
| 392 | 531 | ||
| 393 | for_key = pl::user(key("for"), [](const item_t& item) { | 532 | for_key = pl::user(key("for"), [](const item_t& item) { |
| 394 | State* st = reinterpret_cast<State*>(item.user_data); | 533 | State* st = reinterpret_cast<State*>(item.user_data); |
| 395 | return st->noForStack.empty() || !st->noForStack.top(); | 534 | return st->noForStack.empty() || !st->noForStack.back(); |
| 396 | }); | 535 | }); |
| 397 | ForStepValue = ',' >> space >> Exp; | 536 | ForStepValue = ',' >> space >> must_exp; |
| 398 | for_args = Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> space >> -ForStepValue; | 537 | for_args = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> space >> -ForStepValue; |
| 399 | 538 | ||
| 400 | For = for_key >> space >> disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); | 539 | ForNum = disable_do_chain_arg_table_block_rule(for_args) >> space >> opt_body_with("do"); |
| 401 | 540 | ||
| 402 | for_in = StarExp | ExpList; | 541 | for_in = StarExp | ExpList | expected_expression_error; |
| 403 | 542 | ||
| 404 | ForEach = for_key >> space >> AssignableNameList >> space >> key("in") >> space >> | 543 | ForEach = AssignableNameList >> space >> key("in") >> space >> |
| 405 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); | 544 | disable_do_chain_arg_table_block_rule(for_in) >> space >> opt_body_with("do"); |
| 406 | 545 | ||
| 546 | For = for_key >> space >> (ForNum | ForEach); | ||
| 547 | |||
| 407 | Do = pl::user(key("do"), [](const item_t& item) { | 548 | Do = pl::user(key("do"), [](const item_t& item) { |
| 408 | State* st = reinterpret_cast<State*>(item.user_data); | 549 | State* st = reinterpret_cast<State*>(item.user_data); |
| 409 | return st->noDoStack.empty() || !st->noDoStack.top(); | 550 | return st->noDoStack.empty() || !st->noDoStack.back(); |
| 410 | }) >> space >> Body; | 551 | }) >> space >> Body; |
| 411 | 552 | ||
| 412 | disable_do = pl::user(true_(), [](const item_t& item) { | 553 | disable_do = pl::user(true_(), [](const item_t& item) { |
| 413 | State* st = reinterpret_cast<State*>(item.user_data); | 554 | State* st = reinterpret_cast<State*>(item.user_data); |
| 414 | st->noDoStack.push(true); | 555 | st->noDoStack.push_back(true); |
| 415 | return true; | 556 | return true; |
| 416 | }); | 557 | }); |
| 417 | 558 | ||
| 418 | enable_do = pl::user(true_(), [](const item_t& item) { | 559 | enable_do = pl::user(true_(), [](const item_t& item) { |
| 419 | State* st = reinterpret_cast<State*>(item.user_data); | 560 | State* st = reinterpret_cast<State*>(item.user_data); |
| 420 | st->noDoStack.pop(); | 561 | st->noDoStack.pop_back(); |
| 421 | return true; | 562 | return true; |
| 422 | }); | 563 | }); |
| 423 | 564 | ||
| @@ -435,46 +576,58 @@ YueParser::YueParser() { | |||
| 435 | 576 | ||
| 436 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 577 | disable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 437 | State* st = reinterpret_cast<State*>(item.user_data); | 578 | State* st = reinterpret_cast<State*>(item.user_data); |
| 438 | st->noDoStack.push(true); | 579 | st->noDoStack.push_back(true); |
| 439 | st->noChainBlockStack.push(true); | 580 | st->noChainBlockStack.push_back(true); |
| 440 | st->noTableBlockStack.push(true); | 581 | st->noTableBlockStack.push_back(true); |
| 441 | return true; | 582 | return true; |
| 442 | }); | 583 | }); |
| 443 | 584 | ||
| 444 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { | 585 | enable_do_chain_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 445 | State* st = reinterpret_cast<State*>(item.user_data); | 586 | State* st = reinterpret_cast<State*>(item.user_data); |
| 446 | st->noDoStack.pop(); | 587 | st->noDoStack.pop_back(); |
| 447 | st->noChainBlockStack.pop(); | 588 | st->noChainBlockStack.pop_back(); |
| 448 | st->noTableBlockStack.pop(); | 589 | st->noTableBlockStack.pop_back(); |
| 449 | return true; | 590 | return true; |
| 450 | }); | 591 | }); |
| 451 | 592 | ||
| 452 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 593 | disable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 453 | State* st = reinterpret_cast<State*>(item.user_data); | 594 | State* st = reinterpret_cast<State*>(item.user_data); |
| 454 | st->noTableBlockStack.push(true); | 595 | st->noTableBlockStack.push_back(true); |
| 455 | return true; | 596 | return true; |
| 456 | }); | 597 | }); |
| 457 | 598 | ||
| 458 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { | 599 | enable_arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 459 | State* st = reinterpret_cast<State*>(item.user_data); | 600 | State* st = reinterpret_cast<State*>(item.user_data); |
| 460 | st->noTableBlockStack.pop(); | 601 | st->noTableBlockStack.pop_back(); |
| 461 | return true; | 602 | return true; |
| 462 | }); | 603 | }); |
| 463 | 604 | ||
| 464 | disable_for = pl::user(true_(), [](const item_t& item) { | 605 | disable_for = pl::user(true_(), [](const item_t& item) { |
| 465 | State* st = reinterpret_cast<State*>(item.user_data); | 606 | State* st = reinterpret_cast<State*>(item.user_data); |
| 466 | st->noForStack.push(true); | 607 | st->noForStack.push_back(true); |
| 467 | return true; | 608 | return true; |
| 468 | }); | 609 | }); |
| 469 | 610 | ||
| 470 | enable_for = pl::user(true_(), [](const item_t& item) { | 611 | enable_for = pl::user(true_(), [](const item_t& item) { |
| 471 | State* st = reinterpret_cast<State*>(item.user_data); | 612 | State* st = reinterpret_cast<State*>(item.user_data); |
| 472 | st->noForStack.pop(); | 613 | st->noForStack.pop_back(); |
| 614 | return true; | ||
| 615 | }); | ||
| 616 | |||
| 617 | disable_until = pl::user(true_(), [](const item_t& item) { | ||
| 618 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 619 | st->noUntilStack.push_back(true); | ||
| 620 | return true; | ||
| 621 | }); | ||
| 622 | |||
| 623 | enable_until = pl::user(true_(), [](const item_t& item) { | ||
| 624 | State* st = reinterpret_cast<State*>(item.user_data); | ||
| 625 | st->noUntilStack.pop_back(); | ||
| 473 | return true; | 626 | return true; |
| 474 | }); | 627 | }); |
| 475 | 628 | ||
| 476 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> Variable >> space >> in_block; | 629 | CatchBlock = line_break >> *space_break >> check_indent_match >> space >> key("catch") >> space >> must_variable >> space >> (in_block | invalid_try_syntax_error); |
| 477 | Try = key("try") >> space >> (in_block | Exp) >> -CatchBlock; | 630 | Try = key("try") >> -ExistentialOp >> space >> (in_block | Exp | invalid_try_syntax_error) >> -CatchBlock; |
| 478 | 631 | ||
| 479 | list_value = | 632 | list_value = |
| 480 | and_( | 633 | and_( |
| @@ -496,28 +649,33 @@ YueParser::YueParser() { | |||
| 496 | 649 | ||
| 497 | list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); | 650 | list_lit_lines = +space_break >> list_lit_line >> *(-(space >> ',') >> space_break >> list_lit_line) >> -(space >> ','); |
| 498 | 651 | ||
| 652 | end_brackets_expression = ']' | brackets_expression_error; | ||
| 653 | |||
| 499 | Comprehension = '[' >> not_('[') >> | 654 | Comprehension = '[' >> not_('[') >> |
| 500 | Seperator >> space >> ( | 655 | Seperator >> space >> ( |
| 501 | disable_for_rule(list_value) >> space >> ( | 656 | disable_for_rule(list_value) >> space >> ( |
| 502 | CompInner >> space >> ']' | | 657 | CompFor >> space >> end_brackets_expression | |
| 503 | (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> ']' | 658 | (list_value_list >> -(space >> ',') | space >> ',') >> -list_lit_lines >> white >> end_brackets_expression |
| 504 | ) | | 659 | ) | |
| 505 | list_lit_lines >> white >> ']' | | 660 | list_lit_lines >> white >> end_brackets_expression | |
| 506 | white >> ']' >> not_(space >> '=') | 661 | white >> ']' >> not_(space >> '=') |
| 507 | ); | 662 | ); |
| 508 | 663 | ||
| 509 | CompValue = ',' >> space >> Exp; | 664 | end_braces_expression = '}' | braces_expression_error; |
| 510 | TblComprehension = and_('{') >> ('{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> CompInner >> space >> '}' | braces_expression_error); | 665 | |
| 666 | CompValue = ',' >> space >> must_exp; | ||
| 667 | TblComprehension = '{' >> space >> disable_for_rule(Exp >> space >> -(CompValue >> space)) >> (CompFor | braces_expression_error) >> space >> end_braces_expression; | ||
| 511 | 668 | ||
| 512 | CompInner = Seperator >> (CompForEach | CompFor) >> *(space >> comp_clause); | 669 | CompFor = key("for") >> space >> Seperator >> (CompForNum | CompForEach) >> *(space >> comp_clause); |
| 513 | StarExp = '*' >> space >> Exp; | 670 | StarExp = '*' >> space >> must_exp; |
| 514 | CompForEach = key("for") >> space >> AssignableNameList >> space >> key("in") >> space >> (StarExp | Exp); | 671 | CompForEach = AssignableNameList >> space >> key("in") >> space >> (StarExp | must_exp); |
| 515 | CompFor = key("for") >> space >> Variable >> space >> '=' >> space >> Exp >> space >> ',' >> space >> Exp >> -ForStepValue; | 672 | CompForNum = Variable >> space >> '=' >> space >> must_exp >> space >> ',' >> space >> must_exp >> -ForStepValue; |
| 516 | comp_clause = CompFor | CompForEach | key("when") >> space >> Exp; | 673 | comp_clause = key("when") >> space >> must_exp | key("for") >> space >> (CompForNum | CompForEach); |
| 517 | 674 | ||
| 518 | Assign = '=' >> space >> Seperator >> ( | 675 | Assign = '=' >> space >> Seperator >> ( |
| 519 | With | If | Switch | TableBlock | | 676 | With | If | Switch | TableBlock | |
| 520 | Exp >> *(space >> set(",;") >> space >> Exp) | 677 | (SpreadListExp | Exp) >> *(space >> set(",") >> space >> (SpreadListExp | Exp)) | |
| 678 | expected_expression_error | ||
| 521 | ); | 679 | ); |
| 522 | 680 | ||
| 523 | UpdateOp = | 681 | UpdateOp = |
| @@ -525,7 +683,7 @@ YueParser::YueParser() { | |||
| 525 | ">>" | "<<" | "??" | | 683 | ">>" | "<<" | "??" | |
| 526 | set("+-*/%&|^"); | 684 | set("+-*/%&|^"); |
| 527 | 685 | ||
| 528 | Update = UpdateOp >> '=' >> space >> Exp; | 686 | Update = UpdateOp >> '=' >> space >> must_exp; |
| 529 | 687 | ||
| 530 | Assignable = AssignableChain | Variable | SelfItem; | 688 | Assignable = AssignableChain | Variable | SelfItem; |
| 531 | 689 | ||
| @@ -546,35 +704,38 @@ YueParser::YueParser() { | |||
| 546 | UnaryExp = *(UnaryOperator >> space) >> expo_exp >> -(space >> In); | 704 | UnaryExp = *(UnaryOperator >> space) >> expo_exp >> -(space >> In); |
| 547 | 705 | ||
| 548 | pipe_operator = "|>"; | 706 | pipe_operator = "|>"; |
| 549 | pipe_value = pipe_operator >> *space_break >> space >> UnaryExp; | 707 | pipe_value = pipe_operator >> *space_break >> space >> must_unary_exp; |
| 550 | pipe_exp = UnaryExp >> *(space >> pipe_value); | 708 | pipe_exp = UnaryExp >> *(space >> pipe_value); |
| 551 | 709 | ||
| 552 | BinaryOperator = | 710 | BinaryOperator = ( |
| 553 | key("or") | | 711 | key("or") | |
| 554 | key("and") | | 712 | key("and") | |
| 555 | "<=" | ">=" | "~=" | "!=" | "==" | | 713 | "<=" | ">=" | "~=" | "!=" | "==" | |
| 556 | ".." | "<<" | ">>" | "//" | | 714 | ".." | "<<" | ">>" | "//" | |
| 557 | set("+-*/%><|&~"); | 715 | set("+*/%>|&~") | |
| 716 | '-' >> not_('>') | | ||
| 717 | '<' >> not_('-') | ||
| 718 | ) >> not_('='); | ||
| 558 | 719 | ||
| 559 | ExpOpValue = BinaryOperator >> *space_break >> space >> pipe_exp; | 720 | ExpOpValue = BinaryOperator >> *space_break >> space >> (pipe_exp | expected_expression_error); |
| 560 | Exp = Seperator >> pipe_exp >> *(space >> ExpOpValue) >> -(space >> "??" >> space >> Exp); | 721 | Exp = Seperator >> pipe_exp >> *(space >> ExpOpValue) >> -(space >> "??" >> not_('=') >> *space_break >> space >> must_exp); |
| 561 | 722 | ||
| 562 | disable_chain = pl::user(true_(), [](const item_t& item) { | 723 | disable_chain = pl::user(true_(), [](const item_t& item) { |
| 563 | State* st = reinterpret_cast<State*>(item.user_data); | 724 | State* st = reinterpret_cast<State*>(item.user_data); |
| 564 | st->noChainBlockStack.push(true); | 725 | st->noChainBlockStack.push_back(true); |
| 565 | return true; | 726 | return true; |
| 566 | }); | 727 | }); |
| 567 | 728 | ||
| 568 | enable_chain = pl::user(true_(), [](const item_t& item) { | 729 | enable_chain = pl::user(true_(), [](const item_t& item) { |
| 569 | State* st = reinterpret_cast<State*>(item.user_data); | 730 | State* st = reinterpret_cast<State*>(item.user_data); |
| 570 | st->noChainBlockStack.pop(); | 731 | st->noChainBlockStack.pop_back(); |
| 571 | return true; | 732 | return true; |
| 572 | }); | 733 | }); |
| 573 | 734 | ||
| 574 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; | 735 | chain_line = check_indent_match >> space >> (chain_dot_chain | colon_chain) >> -InvokeArgs; |
| 575 | chain_block = pl::user(true_(), [](const item_t& item) { | 736 | chain_block = pl::user(true_(), [](const item_t& item) { |
| 576 | State* st = reinterpret_cast<State*>(item.user_data); | 737 | State* st = reinterpret_cast<State*>(item.user_data); |
| 577 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.top(); | 738 | return st->noChainBlockStack.empty() || !st->noChainBlockStack.back(); |
| 578 | }) >> +space_break >> advance_match >> ensure( | 739 | }) >> +space_break >> advance_match >> ensure( |
| 579 | chain_line >> *(+space_break >> chain_line), pop_indent); | 740 | chain_line >> *(+space_break >> chain_line), pop_indent); |
| 580 | ChainValue = | 741 | ChainValue = |
| @@ -589,7 +750,7 @@ YueParser::YueParser() { | |||
| 589 | st->expLevel++; | 750 | st->expLevel++; |
| 590 | const int max_exp_level = 100; | 751 | const int max_exp_level = 100; |
| 591 | if (st->expLevel > max_exp_level) { | 752 | if (st->expLevel > max_exp_level) { |
| 592 | throw ParserError("nesting expressions exceeds 100 levels"sv, item.begin); | 753 | RaiseError("nesting expressions exceeds 100 levels"sv, item); |
| 593 | } | 754 | } |
| 594 | return true; | 755 | return true; |
| 595 | }); | 756 | }); |
| @@ -604,14 +765,22 @@ YueParser::YueParser() { | |||
| 604 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); | 765 | Value = inc_exp_level >> ensure(SimpleValue | SimpleTable | ChainValue | String, dec_exp_level); |
| 605 | 766 | ||
| 606 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; | 767 | single_string_inner = '\\' >> set("'\\") | not_('\'') >> any_char; |
| 607 | SingleString = '\'' >> *single_string_inner >> '\''; | 768 | SingleString = '\'' >> *single_string_inner >> ('\'' | unclosed_single_string_error); |
| 608 | 769 | ||
| 609 | interp = "#{" >> space >> (Exp >> space >> '}' | invalid_interpolation_error); | 770 | interp = "#{" >> space >> (Exp >> space >> '}' | invalid_interpolation_error); |
| 610 | double_string_plain = '\\' >> set("\"\\#") | not_('"') >> any_char; | 771 | double_string_plain = '\\' >> set("\"\\#") | not_('"') >> any_char; |
| 611 | DoubleStringInner = +(not_("#{") >> double_string_plain); | 772 | DoubleStringInner = +(not_("#{") >> double_string_plain); |
| 612 | DoubleStringContent = DoubleStringInner | interp; | 773 | DoubleStringContent = DoubleStringInner | interp; |
| 613 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> '"'; | 774 | DoubleString = '"' >> Seperator >> *DoubleStringContent >> ('"' | unclosed_double_string_error); |
| 614 | String = DoubleString | SingleString | LuaString; | 775 | |
| 776 | YAMLIndent = +set(" \t"); | ||
| 777 | YAMLLineInner = +('\\' >> set("\"\\#") | not_("#{" | stop) >> any_char); | ||
| 778 | YAMLLineContent = YAMLLineInner | interp; | ||
| 779 | YAMLLine = check_indent_match >> YAMLIndent >> +(YAMLLineContent) | | ||
| 780 | advance_match >> YAMLIndent >> ensure(+YAMLLineContent, pop_indent); | ||
| 781 | YAMLMultiline = '|' >> space >> Seperator >> +(*set(" \t") >> line_break) >> advance_match >> ensure(YAMLLine >> *(+(*set(" \t") >> line_break) >> YAMLLine), pop_indent); | ||
| 782 | |||
| 783 | String = DoubleString | SingleString | LuaString | YAMLMultiline; | ||
| 615 | 784 | ||
| 616 | lua_string_open = '[' >> *expr('=') >> '['; | 785 | lua_string_open = '[' >> *expr('=') >> '['; |
| 617 | lua_string_close = ']' >> *expr('=') >> ']'; | 786 | lua_string_close = ']' >> *expr('=') >> ']'; |
| @@ -631,15 +800,15 @@ YueParser::YueParser() { | |||
| 631 | 800 | ||
| 632 | LuaStringContent = *(not_(LuaStringClose) >> any_char); | 801 | LuaStringContent = *(not_(LuaStringClose) >> any_char); |
| 633 | 802 | ||
| 634 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> LuaStringClose; | 803 | LuaString = LuaStringOpen >> -line_break >> LuaStringContent >> (LuaStringClose | unclosed_lua_string_error); |
| 635 | 804 | ||
| 636 | Parens = '(' >> *space_break >> space >> Exp >> *space_break >> space >> ')'; | 805 | Parens = '(' >> (*space_break >> space >> Exp >> *space_break >> space >> ')' | parenthesis_error); |
| 637 | Callable = Variable | SelfItem | MacroName | Parens; | 806 | Callable = Variable | SelfItem | MacroName | Parens; |
| 638 | 807 | ||
| 639 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); | 808 | fn_args_value_list = Exp >> *(space >> ',' >> space >> Exp); |
| 640 | 809 | ||
| 641 | fn_args_lit_line = ( | 810 | fn_args_lit_line = ( |
| 642 | push_indent_match >> (space >> fn_args_value_list >> pop_indent | pop_indent) | 811 | push_indent_match >> ensure(space >> fn_args_value_list, pop_indent) |
| 643 | ) | ( | 812 | ) | ( |
| 644 | space | 813 | space |
| 645 | ); | 814 | ); |
| @@ -649,14 +818,14 @@ YueParser::YueParser() { | |||
| 649 | fn_args = | 818 | fn_args = |
| 650 | '(' >> -(space >> fn_args_value_list >> -(space >> ',')) >> | 819 | '(' >> -(space >> fn_args_value_list >> -(space >> ',')) >> |
| 651 | -fn_args_lit_lines >> | 820 | -fn_args_lit_lines >> |
| 652 | white >> ')' | space >> '!' >> not_('='); | 821 | white >> -(and_(',') >> unexpected_comma_error) >>')' | space >> '!' >> not_('='); |
| 653 | 822 | ||
| 654 | meta_index = Name | index | String; | 823 | meta_index = Name | index | String; |
| 655 | Metatable = '<' >> space >> '>'; | 824 | Metatable = '<' >> space >> '>'; |
| 656 | Metamethod = '<' >> space >> meta_index >> space >> '>'; | 825 | Metamethod = '<' >> space >> meta_index >> space >> '>'; |
| 657 | 826 | ||
| 658 | ExistentialOp = '?' >> not_('?'); | 827 | ExistentialOp = '?' >> not_('?'); |
| 659 | TableAppendingOp = and_('[') >> ("[]" | brackets_expression_error); | 828 | TableAppendingOp = and_('[') >> "[]"; |
| 660 | PlainItem = +any_char; | 829 | PlainItem = +any_char; |
| 661 | 830 | ||
| 662 | chain_call = ( | 831 | chain_call = ( |
| @@ -681,7 +850,8 @@ YueParser::YueParser() { | |||
| 681 | chain_with_colon = +chain_item >> -colon_chain; | 850 | chain_with_colon = +chain_item >> -colon_chain; |
| 682 | chain_items = chain_with_colon | colon_chain; | 851 | chain_items = chain_with_colon | colon_chain; |
| 683 | 852 | ||
| 684 | index = '[' >> not_('[') >> space >> Exp >> space >> ']'; | 853 | index = '[' >> not_('[') >> space >> (ReversedIndex >> and_(space >> ']') | Exp) >> space >> ']'; |
| 854 | ReversedIndex = '#' >> space >> -('-' >> space >> Exp); | ||
| 685 | chain_item = | 855 | chain_item = |
| 686 | Invoke >> -ExistentialOp | | 856 | Invoke >> -ExistentialOp | |
| 687 | DotChainItem >> -ExistentialOp | | 857 | DotChainItem >> -ExistentialOp | |
| @@ -720,10 +890,8 @@ YueParser::YueParser() { | |||
| 720 | SpreadExp | | 890 | SpreadExp | |
| 721 | NormalDef; | 891 | NormalDef; |
| 722 | 892 | ||
| 723 | table_value_list = table_value >> *(space >> ',' >> space >> table_value); | ||
| 724 | |||
| 725 | table_lit_line = ( | 893 | table_lit_line = ( |
| 726 | push_indent_match >> (space >> table_value_list >> pop_indent | pop_indent) | 894 | push_indent_match >> (space >> not_(line_break | '}') >> (table_value | expected_expression_error) >> *(space >> ',' >> space >> table_value) >> pop_indent | pop_indent) |
| 727 | ) | ( | 895 | ) | ( |
| 728 | space | 896 | space |
| 729 | ); | 897 | ); |
| @@ -732,13 +900,15 @@ YueParser::YueParser() { | |||
| 732 | 900 | ||
| 733 | TableLit = | 901 | TableLit = |
| 734 | '{' >> Seperator >> | 902 | '{' >> Seperator >> |
| 735 | -(space >> table_value_list >> -(space >> ',')) >> | 903 | -(space >> table_value >> *(space >> ',' >> space >> table_value) >> -(space >> ',')) >> |
| 736 | -table_lit_lines >> | 904 | ( |
| 737 | white >> '}'; | 905 | table_lit_lines >> white >> end_braces_expression | |
| 906 | white >> '}' | ||
| 907 | ); | ||
| 738 | 908 | ||
| 739 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); | 909 | table_block_inner = Seperator >> key_value_line >> *(+space_break >> key_value_line); |
| 740 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); | 910 | TableBlock = +space_break >> advance_match >> ensure(table_block_inner, pop_indent); |
| 741 | TableBlockIndent = '*' >> Seperator >> disable_arg_table_block_rule( | 911 | TableBlockIndent = ('*' | '-' >> space_one) >> Seperator >> disable_arg_table_block_rule( |
| 742 | space >> key_value_list >> -(space >> ',') >> | 912 | space >> key_value_list >> -(space >> ',') >> |
| 743 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); | 913 | -(+space_break >> advance_match >> space >> ensure(key_value_list >> -(space >> ',') >> *(+space_break >> key_value_line), pop_indent))); |
| 744 | 914 | ||
| @@ -753,13 +923,18 @@ YueParser::YueParser() { | |||
| 753 | ClassDecl = | 923 | ClassDecl = |
| 754 | key("class") >> not_(':') >> disable_arg_table_block_rule( | 924 | key("class") >> not_(':') >> disable_arg_table_block_rule( |
| 755 | -(space >> Assignable) >> | 925 | -(space >> Assignable) >> |
| 756 | -(space >> key("extends") >> prevent_indent >> space >> ensure(Exp, pop_indent)) >> | 926 | -(space >> key("extends") >> prevent_indent >> space >> ensure(must_exp, pop_indent)) >> |
| 757 | -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList, pop_indent)) | 927 | -(space >> key("using") >> prevent_indent >> space >> ensure(ExpList | expected_expression_error, pop_indent)) |
| 758 | ) >> -ClassBlock; | 928 | ) >> -ClassBlock; |
| 759 | 929 | ||
| 760 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpListLow)); | 930 | GlobalValues = NameList >> -(space >> '=' >> space >> (TableBlock | ExpList | expected_expression_error)); |
| 761 | GlobalOp = expr('*') | '^'; | 931 | GlobalOp = expr('*') | '^'; |
| 762 | Global = key("global") >> space >> (ClassDecl | GlobalOp | GlobalValues); | 932 | Global = key("global") >> space >> ( |
| 933 | -(ConstAttrib >> space) >> ClassDecl | | ||
| 934 | GlobalOp | | ||
| 935 | -(ConstAttrib >> space) >> GlobalValues | | ||
| 936 | invalid_global_declaration_error | ||
| 937 | ); | ||
| 763 | 938 | ||
| 764 | ExportDefault = key("default"); | 939 | ExportDefault = key("default"); |
| 765 | 940 | ||
| @@ -771,10 +946,10 @@ YueParser::YueParser() { | |||
| 771 | pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { | 946 | pl::user(space >> ExportDefault >> space >> Exp, [](const item_t& item) { |
| 772 | State* st = reinterpret_cast<State*>(item.user_data); | 947 | State* st = reinterpret_cast<State*>(item.user_data); |
| 773 | if (st->exportDefault) { | 948 | if (st->exportDefault) { |
| 774 | throw ParserError("export default has already been declared"sv, item.begin); | 949 | RaiseError("export default has already been declared"sv, item); |
| 775 | } | 950 | } |
| 776 | if (st->exportCount > 1) { | 951 | if (st->exportCount > 1) { |
| 777 | throw ParserError("there are items already being exported"sv, item.begin); | 952 | RaiseError("there are items already being exported"sv, item); |
| 778 | } | 953 | } |
| 779 | st->exportDefault = true; | 954 | st->exportDefault = true; |
| 780 | return true; | 955 | return true; |
| @@ -782,17 +957,17 @@ YueParser::YueParser() { | |||
| 782 | not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { | 957 | not_(space >> ExportDefault) >> pl::user(true_(), [](const item_t& item) { |
| 783 | State* st = reinterpret_cast<State*>(item.user_data); | 958 | State* st = reinterpret_cast<State*>(item.user_data); |
| 784 | if (st->exportDefault && st->exportCount > 1) { | 959 | if (st->exportDefault && st->exportCount > 1) { |
| 785 | throw ParserError("can not export any more items when 'export default' is declared"sv, item.begin); | 960 | RaiseError("can not export any more items when 'export default' is declared"sv, item); |
| 786 | } | 961 | } |
| 787 | return true; | 962 | return true; |
| 788 | }) >> ( | 963 | }) >> ( |
| 789 | and_(set(".[")) >> ((pl::user(and_('.' >> Metatable), [](const item_t& item) { | 964 | and_(set(".[")) >> ((pl::user(and_('.' >> Metatable), [](const item_t& item) { |
| 790 | State* st = reinterpret_cast<State*>(item.user_data); | 965 | State* st = reinterpret_cast<State*>(item.user_data); |
| 791 | if (st->exportMetatable) { | 966 | if (st->exportMetatable) { |
| 792 | throw ParserError("module metatable duplicated"sv, item.begin); | 967 | RaiseError("module metatable duplicated"sv, item); |
| 793 | } | 968 | } |
| 794 | if (st->exportMetamethod) { | 969 | if (st->exportMetamethod) { |
| 795 | throw ParserError("metatable should be exported before metamethod"sv, item.begin); | 970 | RaiseError("metatable should be exported before metamethod"sv, item); |
| 796 | } | 971 | } |
| 797 | st->exportMetatable = true; | 972 | st->exportMetatable = true; |
| 798 | return true; | 973 | return true; |
| @@ -807,8 +982,9 @@ YueParser::YueParser() { | |||
| 807 | State* st = reinterpret_cast<State*>(item.user_data); | 982 | State* st = reinterpret_cast<State*>(item.user_data); |
| 808 | st->exportMacro = true; | 983 | st->exportMacro = true; |
| 809 | return true; | 984 | return true; |
| 810 | }) | 985 | }) | |
| 811 | ) >> not_(space >> StatementAppendix); | 986 | invalid_export_syntax_error |
| 987 | ); | ||
| 812 | 988 | ||
| 813 | VariablePair = ':' >> Variable; | 989 | VariablePair = ':' >> Variable; |
| 814 | 990 | ||
| @@ -817,13 +993,13 @@ YueParser::YueParser() { | |||
| 817 | KeyName | | 993 | KeyName | |
| 818 | '[' >> not_('[') >> space >> Exp >> space >> ']' | | 994 | '[' >> not_('[') >> space >> Exp >> space >> ']' | |
| 819 | String | 995 | String |
| 820 | ) >> ':' >> not_(':') >> space >> | 996 | ) >> ':' >> not_(':' | '=' >> not_('>')) >> space >> |
| 821 | (Exp | TableBlock | +space_break >> space >> Exp); | 997 | (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); |
| 822 | 998 | ||
| 823 | MetaVariablePair = ":<" >> space >> Variable >> space >> '>'; | 999 | MetaVariablePair = ":<" >> space >> must_variable >> space >> '>'; |
| 824 | 1000 | ||
| 825 | MetaNormalPair = '<' >> space >> -meta_index >> space >> ">:" >> space >> | 1001 | MetaNormalPair = '<' >> space >> -meta_index >> space >> ">:" >> space >> |
| 826 | (Exp | TableBlock | +space_break >> space >> Exp); | 1002 | (Exp | TableBlock | +space_break >> space >> Exp | expected_expression_error); |
| 827 | 1003 | ||
| 828 | destruct_def = -(space >> '=' >> space >> Exp); | 1004 | destruct_def = -(space >> '=' >> space >> Exp); |
| 829 | VariablePairDef = VariablePair >> destruct_def; | 1005 | VariablePairDef = VariablePair >> destruct_def; |
| @@ -841,66 +1017,83 @@ YueParser::YueParser() { | |||
| 841 | key_value_line = check_indent_match >> space >> ( | 1017 | key_value_line = check_indent_match >> space >> ( |
| 842 | key_value_list >> -(space >> ',') | | 1018 | key_value_list >> -(space >> ',') | |
| 843 | TableBlockIndent | | 1019 | TableBlockIndent | |
| 844 | '*' >> space >> (SpreadExp | Exp | TableBlock) | 1020 | ('*' | '-' >> space_one) >> space >> (SpreadExp | Exp | TableBlock) |
| 845 | ); | 1021 | ); |
| 846 | 1022 | ||
| 847 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); | 1023 | fn_arg_def_list = FnArgDef >> *(space >> ',' >> space >> FnArgDef); |
| 848 | 1024 | ||
| 849 | fn_arg_def_lit_line = ( | 1025 | fn_arg_def_lit_line = ( |
| 850 | push_indent_match >> (space >> fn_arg_def_list >> pop_indent | pop_indent) | 1026 | push_indent_match >> ensure(space >> fn_arg_def_list, pop_indent) |
| 851 | ) | ( | 1027 | ) | ( |
| 852 | space | 1028 | space |
| 853 | ); | 1029 | ); |
| 854 | 1030 | ||
| 855 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); | 1031 | fn_arg_def_lit_lines = fn_arg_def_lit_line >> *(-(space >> ',') >> space_break >> fn_arg_def_lit_line); |
| 856 | 1032 | ||
| 857 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '=' >> space >> Exp); | 1033 | FnArgDef = (Variable | SelfItem >> -ExistentialOp) >> -(space >> '`' >> space >> Name) >> -(space >> '=' >> space >> Exp) | TableLit | SimpleTable; |
| 858 | 1034 | ||
| 859 | FnArgDefList = Seperator >> ( | 1035 | check_vararg_position = and_(white >> (')' | key("using"))) | white >> -(',' >> white) >> vararg_position_error; |
| 860 | fn_arg_def_lit_lines >> -(-(space >> ',') >> white >> VarArg) | | 1036 | |
| 861 | white >> VarArg | 1037 | var_arg_def = ( |
| 862 | ); | 1038 | VarArgDef | |
| 1039 | +space_break >> push_indent_match >> ensure(space >> VarArgDef >> -(space >> '`' >> space >> Name), pop_indent) | ||
| 1040 | ) >> check_vararg_position; | ||
| 1041 | |||
| 1042 | FnArgDefList = Seperator >> | ||
| 1043 | -fn_arg_def_list >> | ||
| 1044 | -(-(space >> ',') >> +space_break >> fn_arg_def_lit_lines) >> | ||
| 1045 | -(-(space >> ',') >> space >> var_arg_def); | ||
| 863 | 1046 | ||
| 864 | OuterVarShadow = key("using") >> space >> (NameList | key("nil")); | 1047 | OuterVarShadow = key("using") >> space >> (key("nil") | NameList); |
| 865 | 1048 | ||
| 866 | FnArgsDef = '(' >> *space_break >> -FnArgDefList >> -(white >> OuterVarShadow) >> white >> ')'; | 1049 | outer_var_shadow_def = OuterVarShadow | |
| 1050 | +space_break >> push_indent_match >> ensure(space >> OuterVarShadow, pop_indent); | ||
| 1051 | |||
| 1052 | FnArgsDef = '(' >> space >> -FnArgDefList >> -(space >> outer_var_shadow_def) >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; | ||
| 867 | FnArrow = expr("->") | "=>"; | 1053 | FnArrow = expr("->") | "=>"; |
| 868 | FunLit = pl::user(true_(), [](const item_t& item) { | 1054 | FunLit = pl::user(true_(), [](const item_t& item) { |
| 869 | State* st = reinterpret_cast<State*>(item.user_data); | 1055 | State* st = reinterpret_cast<State*>(item.user_data); |
| 870 | return st->fnArrowAvailable; | 1056 | return st->fnArrowAvailable; |
| 871 | }) >> -(FnArgsDef >> | 1057 | }) >> -(FnArgsDef >> |
| 872 | -(':' >> space >> | 1058 | -(':' >> space >> |
| 873 | disable_fun_lit >> ensure(ExpListLow | DefaultValue, enable_fun_lit) | 1059 | disable_fun_lit >> ensure(ExpList | DefaultValue, enable_fun_lit) |
| 874 | ) | 1060 | ) |
| 875 | ) >> space >> FnArrow >> -(space >> Body); | 1061 | ) >> space >> FnArrow >> -(space >> Body); |
| 876 | 1062 | ||
| 877 | MacroName = '$' >> UnicodeName; | 1063 | MacroName = '$' >> UnicodeName; |
| 878 | macro_args_def = '(' >> white >> -FnArgDefList >> white >> ')'; | 1064 | macro_args_def = '(' >> space >> -FnArgDefList >> white >> -(and_(',') >> unexpected_comma_error) >> ')'; |
| 879 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; | 1065 | MacroLit = -(macro_args_def >> space) >> "->" >> space >> Body; |
| 880 | MacroFunc = MacroName >> (Invoke | InvokeArgs); | 1066 | MacroFunc = MacroName >> (Invoke | InvokeArgs); |
| 881 | Macro = key("macro") >> space >> UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc); | 1067 | Macro = key("macro") >> space >> ( |
| 1068 | UnicodeName >> space >> '=' >> space >> (MacroLit | MacroFunc | invalid_macro_definition_error) | | ||
| 1069 | invalid_macro_definition_error | ||
| 1070 | ); | ||
| 882 | MacroInPlace = '$' >> space >> "->" >> space >> Body; | 1071 | MacroInPlace = '$' >> space >> "->" >> space >> Body; |
| 883 | 1072 | ||
| 884 | NameList = Seperator >> Variable >> *(space >> ',' >> space >> Variable); | 1073 | must_variable = Variable | and_(LuaKeyword >> not_alpha_num) >> keyword_as_identifier_syntax_error | expected_indentifier_error; |
| 885 | NameOrDestructure = Variable | TableLit | Comprehension; | 1074 | |
| 1075 | NameList = Seperator >> must_variable >> *(space >> ',' >> space >> must_variable); | ||
| 1076 | NameOrDestructure = Variable | TableLit | Comprehension | SimpleTable | expected_expression_error; | ||
| 886 | AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); | 1077 | AssignableNameList = Seperator >> NameOrDestructure >> *(space >> ',' >> space >> NameOrDestructure); |
| 887 | 1078 | ||
| 888 | FnArrowBack = '<' >> set("-="); | 1079 | FnArrowBack = '<' >> set("-="); |
| 889 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; | 1080 | Backcall = -(FnArgsDef >> space) >> FnArrowBack >> space >> ChainValue; |
| 1081 | SubBackcall = FnArrowBack >> space >> ChainValue; | ||
| 1082 | |||
| 1083 | must_unary_exp = UnaryExp | expected_expression_error; | ||
| 890 | 1084 | ||
| 891 | PipeBody = Seperator >> | 1085 | PipeBody = Seperator >> |
| 892 | pipe_operator >> space >> UnaryExp >> | 1086 | pipe_operator >> space >> must_unary_exp >> |
| 893 | *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> UnaryExp); | 1087 | *(+space_break >> check_indent_match >> space >> pipe_operator >> space >> must_unary_exp); |
| 894 | 1088 | ||
| 895 | ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); | 1089 | ExpList = Seperator >> Exp >> *(space >> ',' >> space >> Exp); |
| 896 | ExpListLow = Seperator >> Exp >> *(space >> set(",;") >> space >> Exp); | ||
| 897 | 1090 | ||
| 898 | arg_line = check_indent_match >> space >> Exp >> *(space >> ',' >> space >> Exp); | 1091 | arg_line = check_indent_match >> space >> Exp >> *(space >> ',' >> space >> Exp); |
| 899 | arg_block = arg_line >> *(space >> ',' >> space_break >> arg_line) >> pop_indent; | 1092 | arg_block = arg_line >> *(space >> ',' >> space_break >> arg_line) >> pop_indent; |
| 900 | 1093 | ||
| 901 | arg_table_block = pl::user(true_(), [](const item_t& item) { | 1094 | arg_table_block = pl::user(true_(), [](const item_t& item) { |
| 902 | State* st = reinterpret_cast<State*>(item.user_data); | 1095 | State* st = reinterpret_cast<State*>(item.user_data); |
| 903 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.top(); | 1096 | return st->noTableBlockStack.empty() || !st->noTableBlockStack.back(); |
| 904 | }) >> TableBlock; | 1097 | }) >> TableBlock; |
| 905 | 1098 | ||
| 906 | invoke_args_with_table = | 1099 | invoke_args_with_table = |
| @@ -909,103 +1102,84 @@ YueParser::YueParser() { | |||
| 909 | space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block) | 1102 | space_break >> advance_match >> arg_block >> -(-(space >> ',') >> arg_table_block) |
| 910 | ) | arg_table_block; | 1103 | ) | arg_table_block; |
| 911 | 1104 | ||
| 912 | leading_spaces_error = pl::user(+space_one >> '(' >> space >> Exp >> +(space >> ',' >> space >> Exp) >> space >> ')', [](const item_t& item) { | ||
| 913 | throw ParserError("write invoke arguments in parentheses without leading spaces or just leading spaces without parentheses"sv, item.begin); | ||
| 914 | return false; | ||
| 915 | }); | ||
| 916 | |||
| 917 | InvokeArgs = | 1105 | InvokeArgs = |
| 918 | not_(set("-~") | "[]") >> space >> Seperator >> ( | 1106 | not_(set("-~") | "[]") >> space >> Seperator >> ( |
| 919 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | | 1107 | Exp >> *(space >> ',' >> space >> Exp) >> -(space >> invoke_args_with_table) | |
| 920 | arg_table_block | | 1108 | arg_table_block |
| 921 | leading_spaces_error | ||
| 922 | ); | 1109 | ); |
| 923 | 1110 | ||
| 924 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; | 1111 | ConstValue = (expr("nil") | "true" | "false") >> not_alpha_num; |
| 925 | 1112 | ||
| 926 | braces_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 927 | throw ParserError("syntax error in brace expression"sv, item.begin); | ||
| 928 | return false; | ||
| 929 | }); | ||
| 930 | |||
| 931 | brackets_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 932 | throw ParserError("syntax error in bracket expression"sv, item.begin); | ||
| 933 | return false; | ||
| 934 | }); | ||
| 935 | |||
| 936 | slice_expression_error = pl::user(true_(), [](const item_t& item) { | ||
| 937 | throw ParserError("syntax error in slice expression"sv, item.begin); | ||
| 938 | return false; | ||
| 939 | }); | ||
| 940 | |||
| 941 | SimpleValue = | 1113 | SimpleValue = |
| 942 | TableLit | ConstValue | If | Switch | Try | With | | 1114 | TableLit | ConstValue | If | Switch | Try | With | |
| 943 | ClassDecl | ForEach | For | While | Do | | 1115 | ClassDecl | For | While | Repeat | Do | |
| 944 | UnaryValue | TblComprehension | Comprehension | | 1116 | UnaryValue | TblComprehension | Comprehension | |
| 945 | FunLit | Num | VarArg; | 1117 | FunLit | Num | VarArg; |
| 946 | 1118 | ||
| 947 | ExpListAssign = ExpList >> -(space >> (Update | Assign)) >> not_(space >> '='); | 1119 | ExpListAssign = ExpList >> -(space >> (Update | Assign | SubBackcall)) >> not_(space >> '='); |
| 948 | 1120 | ||
| 949 | IfLine = IfType >> space >> IfCond; | 1121 | IfLine = IfType >> space >> IfCond; |
| 950 | WhileLine = WhileType >> space >> Exp; | 1122 | WhileLine = WhileType >> space >> Exp; |
| 951 | 1123 | ||
| 952 | YueLineComment = *(not_(set("\r\n")) >> any_char); | ||
| 953 | yue_line_comment = "--" >> YueLineComment >> and_(stop); | ||
| 954 | MultilineCommentInner = multi_line_content; | ||
| 955 | YueMultilineComment = multi_line_open >> MultilineCommentInner >> multi_line_close; | ||
| 956 | yue_comment = check_indent >> ( | ||
| 957 | ( | ||
| 958 | YueMultilineComment >> | ||
| 959 | *(set(" \t") | YueMultilineComment) >> | ||
| 960 | -yue_line_comment | ||
| 961 | ) | yue_line_comment | ||
| 962 | ) >> and_(line_break); | ||
| 963 | |||
| 964 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; | 1124 | ChainAssign = Seperator >> Exp >> +(space >> '=' >> space >> Exp >> space >> and_('=')) >> space >> Assign; |
| 965 | 1125 | ||
| 966 | StatementAppendix = (IfLine | WhileLine | CompInner) >> space; | 1126 | StatementAppendix = IfLine | WhileLine | CompFor; |
| 967 | Statement = | 1127 | Statement = ( |
| 968 | Seperator >> | 1128 | ( |
| 969 | -( | 1129 | Import | Export | Global | Macro | MacroInPlace | Label |
| 970 | yue_comment >> | 1130 | ) | ( |
| 971 | *(line_break >> yue_comment) >> | 1131 | Local | While | Repeat | For | Return | |
| 972 | line_break >> | 1132 | BreakLoop | Goto | ShortTabAppending | |
| 973 | check_indent_match | ||
| 974 | ) >> | ||
| 975 | space >> ( | ||
| 976 | Import | While | Repeat | For | ForEach | | ||
| 977 | Return | Local | Global | Export | Macro | | ||
| 978 | MacroInPlace | BreakLoop | Label | Goto | ShortTabAppending | | ||
| 979 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | | 1133 | LocalAttrib | Backcall | PipeBody | ExpListAssign | ChainAssign | |
| 980 | StatementAppendix >> empty_block_error | 1134 | StatementAppendix >> empty_block_error | |
| 981 | ) >> | 1135 | and_(key("else") | key("elseif") | key("when")) >> dangling_clause_error |
| 982 | space >> | 1136 | ) >> space >> -StatementAppendix |
| 983 | -StatementAppendix; | 1137 | ) >> space; |
| 984 | 1138 | ||
| 985 | StatementSep = white >> (set("('\"") | "[[" | "[="); | 1139 | StatementSep = white >> (set("('\"") | "[[" | "[="); |
| 986 | 1140 | ||
| 987 | Body = in_block | Statement; | 1141 | Body = in_block | Statement; |
| 988 | 1142 | ||
| 989 | empty_line_break = | 1143 | YueLineComment = *(not_(set("\r\n")) >> any_char); |
| 990 | check_indent >> (multi_line_comment >> space | comment) >> and_(stop) | | 1144 | yue_line_comment = "--" >> YueLineComment >> and_(stop); |
| 991 | advance >> ensure(multi_line_comment >> space | comment, pop_indent) >> and_(stop) | | 1145 | YueMultilineComment = multi_line_content; |
| 992 | plain_space >> and_(line_break); | 1146 | yue_multiline_comment = multi_line_open >> YueMultilineComment >> multi_line_close; |
| 1147 | comment_line = | ||
| 1148 | yue_multiline_comment >> *(set(" \t") | yue_multiline_comment) >> plain_space >> -yue_line_comment | | ||
| 1149 | yue_line_comment; | ||
| 1150 | YueComment = | ||
| 1151 | check_indent >> comment_line >> and_(stop) | | ||
| 1152 | advance >> ensure(comment_line, pop_indent) >> and_(stop); | ||
| 1153 | |||
| 1154 | EmptyLine = plain_space >> and_(stop); | ||
| 993 | 1155 | ||
| 994 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { | 1156 | indentation_error = pl::user(not_(pipe_operator | eof()), [](const item_t& item) { |
| 995 | throw ParserError("unexpected indent"sv, item.begin); | 1157 | RaiseError("unexpected indent"sv, item); |
| 996 | return false; | 1158 | return false; |
| 997 | }); | 1159 | }); |
| 998 | 1160 | ||
| 999 | line = ( | 1161 | is_lax = pl::user(true_(), [](const item_t& item) { |
| 1000 | check_indent_match >> Statement | | 1162 | State* st = reinterpret_cast<State*>(item.user_data); |
| 1001 | empty_line_break | | 1163 | return st->lax; |
| 1164 | }); | ||
| 1165 | |||
| 1166 | line = *(EmptyLine >> line_break) >> ( | ||
| 1167 | check_indent_match >> space >> Statement >> *(';' >> space >> (Statement | not_(';'))) | | ||
| 1168 | YueComment | | ||
| 1002 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) | 1169 | advance_match >> ensure(space >> (indentation_error | Statement), pop_indent) |
| 1003 | ); | 1170 | ); |
| 1004 | Block = Seperator >> line >> *(+line_break >> line); | 1171 | Block = Seperator >> ( |
| 1172 | is_lax >> lax_line >> *(line_break >> lax_line) | | ||
| 1173 | line >> *(line_break >> line) | ||
| 1174 | ); | ||
| 1005 | 1175 | ||
| 1006 | shebang = "#!" >> *(not_(stop) >> any_char); | 1176 | shebang = "#!" >> *(not_(stop) >> any_char); |
| 1007 | BlockEnd = Block >> white >> stop; | 1177 | BlockEnd = Block >> plain_white >> stop; |
| 1008 | File = -shebang >> -Block >> white >> stop; | 1178 | File = -shebang >> -Block >> plain_white >> stop; |
| 1179 | |||
| 1180 | lax_line = advance_match >> ensure(*(not_(stop) >> any()), pop_indent) | | ||
| 1181 | line >> and_(stop) | | ||
| 1182 | check_indent_match >> *(not_(stop) >> any()); | ||
| 1009 | } | 1183 | } |
| 1010 | // clang-format on | 1184 | // clang-format on |
| 1011 | 1185 | ||
| @@ -1016,7 +1190,7 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
| 1016 | } | 1190 | } |
| 1017 | try { | 1191 | try { |
| 1018 | if (!codes.empty()) { | 1192 | if (!codes.empty()) { |
| 1019 | converted = std::make_unique<input>(_converter.from_bytes(&codes.front(), &codes.back() + 1)); | 1193 | converted = std::make_unique<input>(utf8_decode({&codes.front(), &codes.back() + 1})); |
| 1020 | } else { | 1194 | } else { |
| 1021 | converted = std::make_unique<input>(); | 1195 | converted = std::make_unique<input>(); |
| 1022 | } | 1196 | } |
| @@ -1035,24 +1209,25 @@ bool YueParser::startWith(std::string_view codes, rule& r) { | |||
| 1035 | return true; | 1209 | return true; |
| 1036 | } | 1210 | } |
| 1037 | 1211 | ||
| 1038 | ParseInfo YueParser::parse(std::string_view codes, rule& r) { | 1212 | ParseInfo YueParser::parse(std::string_view codes, rule& r, bool lax) { |
| 1039 | ParseInfo res; | 1213 | ParseInfo res; |
| 1040 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { | 1214 | if (codes.substr(0, 3) == "\xEF\xBB\xBF"sv) { |
| 1041 | codes = codes.substr(3); | 1215 | codes = codes.substr(3); |
| 1042 | } | 1216 | } |
| 1043 | try { | 1217 | try { |
| 1044 | if (!codes.empty()) { | 1218 | if (!codes.empty()) { |
| 1045 | res.codes = std::make_unique<input>(_converter.from_bytes(&codes.front(), &codes.back() + 1)); | 1219 | res.codes = std::make_unique<input>(utf8_decode({&codes.front(), &codes.back() + 1})); |
| 1046 | } else { | 1220 | } else { |
| 1047 | res.codes = std::make_unique<input>(); | 1221 | res.codes = std::make_unique<input>(); |
| 1048 | } | 1222 | } |
| 1049 | } catch (const std::range_error&) { | 1223 | } catch (const std::exception&) { |
| 1050 | res.error = {"invalid text encoding"s, 1, 1}; | 1224 | res.error = {"invalid text encoding"s, 1, 1}; |
| 1051 | return res; | 1225 | return res; |
| 1052 | } | 1226 | } |
| 1053 | error_list errors; | 1227 | error_list errors; |
| 1054 | try { | 1228 | try { |
| 1055 | State state; | 1229 | State state; |
| 1230 | state.lax = lax; | ||
| 1056 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); | 1231 | res.node.set(::yue::parse(*(res.codes), r, errors, &state)); |
| 1057 | if (state.exportCount > 0) { | 1232 | if (state.exportCount > 0) { |
| 1058 | int index = 0; | 1233 | int index = 0; |
| @@ -1090,29 +1265,31 @@ ParseInfo YueParser::parse(std::string_view codes, rule& r) { | |||
| 1090 | return res; | 1265 | return res; |
| 1091 | } | 1266 | } |
| 1092 | 1267 | ||
| 1093 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes) { | 1268 | ParseInfo YueParser::parse(std::string_view astName, std::string_view codes, bool lax) { |
| 1094 | auto it = _rules.find(astName); | 1269 | auto it = _rules.find(astName); |
| 1095 | if (it != _rules.end()) { | 1270 | if (it != _rules.end()) { |
| 1096 | return parse(codes, *it->second); | 1271 | return parse(codes, *it->second, lax); |
| 1097 | } | 1272 | } |
| 1098 | return {}; | 1273 | ParseInfo info{}; |
| 1274 | info.error = ParseInfo::Error{"invalid rule: "s + std::string{astName}, 1, 1}; | ||
| 1275 | return info; | ||
| 1099 | } | 1276 | } |
| 1100 | 1277 | ||
| 1101 | bool YueParser::match(std::string_view astName, std::string_view codes) { | 1278 | bool YueParser::match(std::string_view astName, std::string_view codes) { |
| 1102 | auto it = _rules.find(astName); | 1279 | auto it = _rules.find(astName); |
| 1103 | if (it != _rules.end()) { | 1280 | if (it != _rules.end()) { |
| 1104 | auto rEnd = rule(*it->second >> eof()); | 1281 | auto rEnd = rule(*it->second >> eof()); |
| 1105 | return parse(codes, rEnd).node; | 1282 | return parse(codes, rEnd, false).node; |
| 1106 | } | 1283 | } |
| 1107 | return false; | 1284 | return false; |
| 1108 | } | 1285 | } |
| 1109 | 1286 | ||
| 1110 | std::string YueParser::toString(ast_node* node) { | 1287 | std::string YueParser::toString(ast_node* node) { |
| 1111 | return _converter.to_bytes(std::wstring(node->m_begin.m_it, node->m_end.m_it)); | 1288 | return utf8_encode({node->m_begin.m_it, node->m_end.m_it}); |
| 1112 | } | 1289 | } |
| 1113 | 1290 | ||
| 1114 | std::string YueParser::toString(input::iterator begin, input::iterator end) { | 1291 | std::string YueParser::toString(input::iterator begin, input::iterator end) { |
| 1115 | return _converter.to_bytes(std::wstring(begin, end)); | 1292 | return utf8_encode({begin, end}); |
| 1116 | } | 1293 | } |
| 1117 | 1294 | ||
| 1118 | bool YueParser::hasAST(std::string_view name) const { | 1295 | bool YueParser::hasAST(std::string_view name) const { |
| @@ -1138,6 +1315,24 @@ void trim(std::string& str) { | |||
| 1138 | str.erase(0, str.find_first_not_of(" \t\r\n")); | 1315 | str.erase(0, str.find_first_not_of(" \t\r\n")); |
| 1139 | str.erase(str.find_last_not_of(" \t\r\n") + 1); | 1316 | str.erase(str.find_last_not_of(" \t\r\n") + 1); |
| 1140 | } | 1317 | } |
| 1318 | |||
| 1319 | std::string toLuaDoubleString(const std::string& input) { | ||
| 1320 | std::string luaStr = "\""; | ||
| 1321 | for (char c : input) { | ||
| 1322 | switch (c) { | ||
| 1323 | case '\"': luaStr += "\\\""; break; | ||
| 1324 | case '\\': luaStr += "\\\\"; break; | ||
| 1325 | case '\n': luaStr += "\\n"; break; | ||
| 1326 | case '\r': luaStr += "\\r"; break; | ||
| 1327 | case '\t': luaStr += "\\t"; break; | ||
| 1328 | default: | ||
| 1329 | luaStr += c; | ||
| 1330 | break; | ||
| 1331 | } | ||
| 1332 | } | ||
| 1333 | luaStr += "\""; | ||
| 1334 | return luaStr; | ||
| 1335 | } | ||
| 1141 | } // namespace Utils | 1336 | } // namespace Utils |
| 1142 | 1337 | ||
| 1143 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { | 1338 | std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCol, int lineOffset) const { |
| @@ -1171,7 +1366,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, int errLine, int errCo | |||
| 1171 | } | 1366 | } |
| 1172 | ++it; | 1367 | ++it; |
| 1173 | } | 1368 | } |
| 1174 | auto line = Converter{}.to_bytes(std::wstring(begin, end)); | 1369 | auto line = utf8_encode({begin, end}); |
| 1175 | while (col < static_cast<int>(line.size()) | 1370 | while (col < static_cast<int>(line.size()) |
| 1176 | && (line[col] == ' ' || line[col] == '\t')) { | 1371 | && (line[col] == ' ' || line[col] == '\t')) { |
| 1177 | col++; | 1372 | col++; |
diff --git a/src/yuescript/yue_parser.h b/src/yuescript/yue_parser.h index 7281ec3..df9f39c 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,18 @@ 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(is_lax); | ||
| 323 | NONE_AST_RULE(lax_line); | ||
| 287 | 324 | ||
| 288 | AST_RULE(Num); | 325 | AST_RULE(Num); |
| 289 | AST_RULE(Name); | 326 | AST_RULE(Name); |
| 290 | AST_RULE(UnicodeName); | 327 | AST_RULE(UnicodeName); |
| 291 | AST_RULE(Variable); | 328 | AST_RULE(Variable); |
| 292 | AST_RULE(LabelName); | ||
| 293 | AST_RULE(LuaKeyword); | 329 | AST_RULE(LuaKeyword); |
| 294 | AST_RULE(Self); | 330 | AST_RULE(Self); |
| 295 | AST_RULE(SelfName); | 331 | AST_RULE(SelfName); |
| @@ -298,6 +334,7 @@ private: | |||
| 298 | AST_RULE(SelfItem); | 334 | AST_RULE(SelfItem); |
| 299 | AST_RULE(KeyName); | 335 | AST_RULE(KeyName); |
| 300 | AST_RULE(VarArg); | 336 | AST_RULE(VarArg); |
| 337 | AST_RULE(VarArgDef); | ||
| 301 | AST_RULE(Seperator); | 338 | AST_RULE(Seperator); |
| 302 | AST_RULE(NameList); | 339 | AST_RULE(NameList); |
| 303 | AST_RULE(LocalFlag); | 340 | AST_RULE(LocalFlag); |
| @@ -315,14 +352,16 @@ private: | |||
| 315 | AST_RULE(ImportAllMacro); | 352 | AST_RULE(ImportAllMacro); |
| 316 | AST_RULE(ImportTabLit); | 353 | AST_RULE(ImportTabLit); |
| 317 | AST_RULE(ImportAs); | 354 | AST_RULE(ImportAs); |
| 355 | AST_RULE(ImportGlobal); | ||
| 356 | AST_RULE(ImportAllGlobal); | ||
| 318 | AST_RULE(Import); | 357 | AST_RULE(Import); |
| 319 | AST_RULE(Label); | 358 | AST_RULE(Label); |
| 320 | AST_RULE(Goto); | 359 | AST_RULE(Goto); |
| 321 | AST_RULE(ShortTabAppending); | 360 | AST_RULE(ShortTabAppending); |
| 322 | AST_RULE(FnArrowBack); | 361 | AST_RULE(FnArrowBack); |
| 323 | AST_RULE(Backcall); | 362 | AST_RULE(Backcall); |
| 363 | AST_RULE(SubBackcall); | ||
| 324 | AST_RULE(PipeBody); | 364 | AST_RULE(PipeBody); |
| 325 | AST_RULE(ExpListLow); | ||
| 326 | AST_RULE(ExpList); | 365 | AST_RULE(ExpList); |
| 327 | AST_RULE(Return); | 366 | AST_RULE(Return); |
| 328 | AST_RULE(With); | 367 | AST_RULE(With); |
| @@ -338,6 +377,7 @@ private: | |||
| 338 | AST_RULE(Repeat); | 377 | AST_RULE(Repeat); |
| 339 | AST_RULE(ForStepValue); | 378 | AST_RULE(ForStepValue); |
| 340 | AST_RULE(For); | 379 | AST_RULE(For); |
| 380 | AST_RULE(ForNum); | ||
| 341 | AST_RULE(ForEach); | 381 | AST_RULE(ForEach); |
| 342 | AST_RULE(Do); | 382 | AST_RULE(Do); |
| 343 | AST_RULE(CatchBlock); | 383 | AST_RULE(CatchBlock); |
| @@ -347,8 +387,8 @@ private: | |||
| 347 | AST_RULE(TblComprehension); | 387 | AST_RULE(TblComprehension); |
| 348 | AST_RULE(StarExp); | 388 | AST_RULE(StarExp); |
| 349 | AST_RULE(CompForEach); | 389 | AST_RULE(CompForEach); |
| 390 | AST_RULE(CompForNum); | ||
| 350 | AST_RULE(CompFor); | 391 | AST_RULE(CompFor); |
| 351 | AST_RULE(CompInner); | ||
| 352 | AST_RULE(Assign); | 392 | AST_RULE(Assign); |
| 353 | AST_RULE(UpdateOp); | 393 | AST_RULE(UpdateOp); |
| 354 | AST_RULE(Update); | 394 | AST_RULE(Update); |
| @@ -359,6 +399,7 @@ private: | |||
| 359 | AST_RULE(ExpOpValue); | 399 | AST_RULE(ExpOpValue); |
| 360 | AST_RULE(Exp); | 400 | AST_RULE(Exp); |
| 361 | AST_RULE(Callable); | 401 | AST_RULE(Callable); |
| 402 | AST_RULE(ReversedIndex); | ||
| 362 | AST_RULE(ChainValue); | 403 | AST_RULE(ChainValue); |
| 363 | AST_RULE(SimpleTable); | 404 | AST_RULE(SimpleTable); |
| 364 | AST_RULE(SimpleValue); | 405 | AST_RULE(SimpleValue); |
| @@ -371,6 +412,11 @@ private: | |||
| 371 | AST_RULE(DoubleStringInner); | 412 | AST_RULE(DoubleStringInner); |
| 372 | AST_RULE(DoubleStringContent); | 413 | AST_RULE(DoubleStringContent); |
| 373 | AST_RULE(DoubleString); | 414 | AST_RULE(DoubleString); |
| 415 | AST_RULE(YAMLIndent); | ||
| 416 | AST_RULE(YAMLLineInner); | ||
| 417 | AST_RULE(YAMLLineContent); | ||
| 418 | AST_RULE(YAMLLine); | ||
| 419 | AST_RULE(YAMLMultiline); | ||
| 374 | AST_RULE(String); | 420 | AST_RULE(String); |
| 375 | AST_RULE(Parens); | 421 | AST_RULE(Parens); |
| 376 | AST_RULE(DotChainItem); | 422 | AST_RULE(DotChainItem); |
| @@ -427,13 +473,16 @@ private: | |||
| 427 | AST_RULE(ExpListAssign); | 473 | AST_RULE(ExpListAssign); |
| 428 | AST_RULE(IfLine); | 474 | AST_RULE(IfLine); |
| 429 | AST_RULE(WhileLine); | 475 | AST_RULE(WhileLine); |
| 476 | AST_RULE(Break); | ||
| 477 | AST_RULE(Continue); | ||
| 430 | AST_RULE(BreakLoop); | 478 | AST_RULE(BreakLoop); |
| 431 | AST_RULE(StatementAppendix); | 479 | AST_RULE(StatementAppendix); |
| 432 | AST_RULE(Statement); | 480 | AST_RULE(Statement); |
| 433 | AST_RULE(StatementSep); | 481 | AST_RULE(StatementSep); |
| 434 | AST_RULE(YueLineComment); | 482 | AST_RULE(YueLineComment); |
| 435 | AST_RULE(MultilineCommentInner); | ||
| 436 | AST_RULE(YueMultilineComment); | 483 | AST_RULE(YueMultilineComment); |
| 484 | AST_RULE(YueComment); | ||
| 485 | AST_RULE(EmptyLine); | ||
| 437 | AST_RULE(ChainAssign); | 486 | AST_RULE(ChainAssign); |
| 438 | AST_RULE(Body); | 487 | AST_RULE(Body); |
| 439 | AST_RULE(Block); | 488 | AST_RULE(Block); |
| @@ -444,6 +493,7 @@ private: | |||
| 444 | namespace Utils { | 493 | namespace Utils { |
| 445 | void replace(std::string& str, std::string_view from, std::string_view to); | 494 | void replace(std::string& str, std::string_view from, std::string_view to); |
| 446 | void trim(std::string& str); | 495 | void trim(std::string& str); |
| 496 | std::string toLuaDoubleString(const std::string& input); | ||
| 447 | } // namespace Utils | 497 | } // namespace Utils |
| 448 | 498 | ||
| 449 | } // namespace yue | 499 | } // 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> |
