diff options
| author | Li Jin <dragon-fly@qq.com> | 2023-07-24 17:55:21 +0800 |
|---|---|---|
| committer | Li Jin <dragon-fly@qq.com> | 2023-07-24 17:55:21 +0800 |
| commit | c03b88e6210818e604d7c755fe8f54fe53696ee1 (patch) | |
| tree | 3d297ce64171481caeb0e86f42a206e8322abeca /src | |
| parent | 00c4bee811b3c92d9885959db30790b01f8cb3e2 (diff) | |
| download | yuescript-c03b88e6210818e604d7c755fe8f54fe53696ee1.tar.gz yuescript-c03b88e6210818e604d7c755fe8f54fe53696ee1.tar.bz2 yuescript-c03b88e6210818e604d7c755fe8f54fe53696ee1.zip | |
try fixing issue #141. fix an AST object life expired before accessing issue.
Diffstat (limited to '')
| -rw-r--r-- | src/3rdParty/LuaMinify.h | 428 | ||||
| -rw-r--r-- | src/yue.cpp | 33 | ||||
| -rw-r--r-- | src/yuescript/yue_compiler.cpp | 4 |
3 files changed, 432 insertions, 33 deletions
diff --git a/src/3rdParty/LuaMinify.h b/src/3rdParty/LuaMinify.h index d01a8fe..5512f5b 100644 --- a/src/3rdParty/LuaMinify.h +++ b/src/3rdParty/LuaMinify.h | |||
| @@ -319,8 +319,6 @@ R"lua_codes( | |||
| 319 | -- ParseLua returns an AST, internally relying on LexLua. | 319 | -- ParseLua returns an AST, internally relying on LexLua. |
| 320 | -- | 320 | -- |
| 321 | 321 | ||
| 322 | local WhiteChars = lookupify{' ', '\n', '\t', '\r'} | ||
| 323 | local EscapeLookup = {['\r'] = '\\r', ['\n'] = '\\n', ['\t'] = '\\t', ['"'] = '\\"', ["'"] = "\\'"} | ||
| 324 | local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', | 322 | local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', |
| 325 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', | 323 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', |
| 326 | 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} | 324 | 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} |
| @@ -549,7 +547,7 @@ local function LexLua(src) | |||
| 549 | --get the initial char | 547 | --get the initial char |
| 550 | local thisLine = line | 548 | local thisLine = line |
| 551 | local thisChar = char | 549 | local thisChar = char |
| 552 | local errorAt = ":"..line..":"..char..":> " | 550 | --local errorAt = ":"..line..":"..char..":> " |
| 553 | local c = peek() | 551 | local c = peek() |
| 554 | 552 | ||
| 555 | --symbol to emit | 553 | --symbol to emit |
| @@ -822,9 +820,9 @@ local function ParseLua(src) | |||
| 822 | return err | 820 | return err |
| 823 | end | 821 | end |
| 824 | -- | 822 | -- |
| 825 | local VarUid = 0 | 823 | -- local VarUid = 0 |
| 826 | -- No longer needed: handled in Scopes now local GlobalVarGetMap = {} | 824 | -- No longer needed: handled in Scopes now local GlobalVarGetMap = {} |
| 827 | local VarDigits = {'_', 'a', 'b', 'c', 'd'} | 825 | -- local VarDigits = {'_', 'a', 'b', 'c', 'd'} |
| 828 | local function CreateScope(parent) | 826 | local function CreateScope(parent) |
| 829 | --[[ | 827 | --[[ |
| 830 | local scope = {} | 828 | local scope = {} |
| @@ -1736,15 +1734,6 @@ R"lua_codes( | |||
| 1736 | -- - All local variables are renamed | 1734 | -- - All local variables are renamed |
| 1737 | -- | 1735 | -- |
| 1738 | 1736 | ||
| 1739 | local LowerChars = lookupify{'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'i', | ||
| 1740 | 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', | ||
| 1741 | 's', 't', 'u', 'v', 'w', 'x', 'y', 'z'} | ||
| 1742 | local UpperChars = lookupify{'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', | ||
| 1743 | 'J', 'K', 'L', 'M', 'N', 'O', 'P', 'Q', 'R', | ||
| 1744 | 'S', 'T', 'U', 'V', 'W', 'X', 'Y', 'Z'} | ||
| 1745 | local Digits = lookupify{'0', '1', '2', '3', '4', '5', '6', '7', '8', '9'} | ||
| 1746 | local Symbols = lookupify{'+', '-', '*', '/', '^', '%', ',', '{', '}', '[', ']', '(', ')', ';', '#'} | ||
| 1747 | |||
| 1748 | local function Format_Mini(ast) | 1737 | local function Format_Mini(ast) |
| 1749 | local formatStatlist, formatExpr; | 1738 | local formatStatlist, formatExpr; |
| 1750 | --local count = 0 | 1739 | --local count = 0 |
| @@ -2092,14 +2081,413 @@ local function Format_Mini(ast) | |||
| 2092 | ast.Scope:ObfuscateVariables() | 2081 | ast.Scope:ObfuscateVariables() |
| 2093 | return formatStatlist(ast) | 2082 | return formatStatlist(ast) |
| 2094 | end | 2083 | end |
| 2084 | )lua_codes" | ||
| 2095 | 2085 | ||
| 2096 | return function(src) | 2086 | R"lua_codes( |
| 2097 | local st, ast = ParseLua(src) | 2087 | local function FormatYue(ast, lineMap) |
| 2098 | if st then | 2088 | local currentLine = 1 |
| 2099 | return Format_Mini(ast) | 2089 | local formatStatlist, formatExpr |
| 2100 | else | 2090 | |
| 2101 | return nil, ast | 2091 | local function joinStatementsSafe(out, b, sep) |
| 2092 | local aa = '' | ||
| 2093 | for i = #out, 1, -1 do | ||
| 2094 | local a = out[i] | ||
| 2095 | aa = a:match("([^%s])%s*$") | ||
| 2096 | if aa then | ||
| 2097 | break | ||
| 2098 | end | ||
| 2099 | end | ||
| 2100 | sep = sep or ' ' | ||
| 2101 | if (out[#out] or ''):sub(-1,-1) == ' ' then | ||
| 2102 | sep = '' | ||
| 2103 | end | ||
| 2104 | local bb = b:match("^%s*([^%s])") | ||
| 2105 | if UpperChars[aa] or LowerChars[aa] or aa == '_' then | ||
| 2106 | if not (UpperChars[bb] or LowerChars[bb] or bb == '_' or Digits[bb]) then | ||
| 2107 | --bb is a symbol, can join without sep | ||
| 2108 | out[#out + 1] = b | ||
| 2109 | elseif bb == '(' then | ||
| 2110 | --prevent ambiguous syntax | ||
| 2111 | out[#out + 1] = sep | ||
| 2112 | out[#out + 1] = b | ||
| 2113 | else | ||
| 2114 | out[#out + 1] = sep | ||
| 2115 | out[#out + 1] = b | ||
| 2116 | end | ||
| 2117 | elseif Digits[aa] then | ||
| 2118 | if bb == '(' then | ||
| 2119 | --can join statements directly | ||
| 2120 | out[#out + 1] = b | ||
| 2121 | elseif Symbols[bb] then | ||
| 2122 | out[#out + 1] = b | ||
| 2123 | else | ||
| 2124 | out[#out + 1] = sep | ||
| 2125 | out[#out + 1] = b | ||
| 2126 | end | ||
| 2127 | elseif aa == '' then | ||
| 2128 | out[#out + 1] = b | ||
| 2129 | else | ||
| 2130 | if bb == '(' then | ||
| 2131 | --don't want to accidentally call last statement, can't join directly | ||
| 2132 | out[#out + 1] = sep | ||
| 2133 | out[#out + 1] = b | ||
| 2134 | else | ||
| 2135 | out[#out + 1] = b | ||
| 2136 | end | ||
| 2137 | end | ||
| 2102 | end | 2138 | end |
| 2139 | |||
| 2140 | formatExpr = function(expr) | ||
| 2141 | local out = {string.rep('(', expr.ParenCount or 0)} | ||
| 2142 | if expr.Tokens then | ||
| 2143 | local line = expr.Tokens[1].Line | ||
| 2144 | local targetLine = lineMap[line] | ||
| 2145 | if targetLine and currentLine < targetLine then | ||
| 2146 | out[#out + 1] = string.rep('\n', targetLine - currentLine) | ||
| 2147 | currentLine = targetLine | ||
| 2148 | end | ||
| 2149 | elseif expr.Value then | ||
| 2150 | local line = expr.Value.Line | ||
| 2151 | local targetLine = lineMap[line] | ||
| 2152 | if targetLine and currentLine < targetLine then | ||
| 2153 | out[#out + 1] = string.rep('\n', targetLine - currentLine) | ||
| 2154 | currentLine = targetLine | ||
| 2155 | end | ||
| 2156 | end | ||
| 2157 | if expr.AstType == 'VarExpr' then | ||
| 2158 | if expr.Variable then | ||
| 2159 | out[#out + 1] = expr.Variable.Name | ||
| 2160 | else | ||
| 2161 | out[#out + 1] = expr.Name | ||
| 2162 | end | ||
| 2163 | |||
| 2164 | elseif expr.AstType == 'NumberExpr' then | ||
| 2165 | out[#out + 1] = expr.Value.Data | ||
| 2166 | |||
| 2167 | elseif expr.AstType == 'StringExpr' then | ||
| 2168 | out[#out + 1] = expr.Value.Data | ||
| 2169 | |||
| 2170 | elseif expr.AstType == 'BooleanExpr' then | ||
| 2171 | out[#out + 1] = tostring(expr.Value) | ||
| 2172 | |||
| 2173 | elseif expr.AstType == 'NilExpr' then | ||
| 2174 | joinStatementsSafe(out, "nil", nil) | ||
| 2175 | |||
| 2176 | elseif expr.AstType == 'BinopExpr' then | ||
| 2177 | joinStatementsSafe(out, formatExpr(expr.Lhs), nil) | ||
| 2178 | out[#out + 1] = " " | ||
| 2179 | joinStatementsSafe(out, expr.Op, nil) | ||
| 2180 | out[#out + 1] = " " | ||
| 2181 | joinStatementsSafe(out, formatExpr(expr.Rhs), nil) | ||
| 2182 | |||
| 2183 | elseif expr.AstType == 'UnopExpr' then | ||
| 2184 | joinStatementsSafe(out, expr.Op, nil) | ||
| 2185 | out[#out + 1] = (#expr.Op ~= 1 and " " or "") | ||
| 2186 | joinStatementsSafe(out, formatExpr(expr.Rhs), nil) | ||
| 2187 | |||
| 2188 | elseif expr.AstType == 'DotsExpr' then | ||
| 2189 | out[#out + 1] = "..." | ||
| 2190 | |||
| 2191 | elseif expr.AstType == 'CallExpr' then | ||
| 2192 | out[#out + 1] = formatExpr(expr.Base) | ||
| 2193 | out[#out + 1] = "(" | ||
| 2194 | for i = 1, #expr.Arguments do | ||
| 2195 | out[#out + 1] = formatExpr(expr.Arguments[i]) | ||
| 2196 | if i ~= #expr.Arguments then | ||
| 2197 | out[#out + 1] = ", " | ||
| 2198 | end | ||
| 2199 | end | ||
| 2200 | out[#out + 1] = ")" | ||
| 2201 | |||
| 2202 | elseif expr.AstType == 'TableCallExpr' then | ||
| 2203 | out[#out + 1] = formatExpr(expr.Base) | ||
| 2204 | out[#out + 1] = " " | ||
| 2205 | out[#out + 1] = formatExpr(expr.Arguments[1]) | ||
| 2206 | |||
| 2207 | elseif expr.AstType == 'StringCallExpr' then | ||
| 2208 | out[#out + 1] = formatExpr(expr.Base) | ||
| 2209 | out[#out + 1] = " " | ||
| 2210 | out[#out + 1] = expr.Arguments[1].Data | ||
| 2211 | |||
| 2212 | elseif expr.AstType == 'IndexExpr' then | ||
| 2213 | out[#out + 1] = formatExpr(expr.Base) | ||
| 2214 | out[#out + 1] = "[" | ||
| 2215 | out[#out + 1] = formatExpr(expr.Index) | ||
| 2216 | out[#out + 1] = "]" | ||
| 2217 | |||
| 2218 | elseif expr.AstType == 'MemberExpr' then | ||
| 2219 | out[#out + 1] = formatExpr(expr.Base) | ||
| 2220 | out[#out + 1] = expr.Indexer | ||
| 2221 | out[#out + 1] = expr.Ident.Data | ||
| 2222 | |||
| 2223 | elseif expr.AstType == 'Function' then | ||
| 2224 | -- anonymous function | ||
| 2225 | out[#out + 1] = "function(" | ||
| 2226 | if #expr.Arguments > 0 then | ||
| 2227 | for i = 1, #expr.Arguments do | ||
| 2228 | out[#out + 1] = expr.Arguments[i].Name | ||
| 2229 | if i ~= #expr.Arguments then | ||
| 2230 | out[#out + 1] = ", " | ||
| 2231 | elseif expr.VarArg then | ||
| 2232 | out[#out + 1] = ", ..." | ||
| 2233 | end | ||
| 2234 | end | ||
| 2235 | elseif expr.VarArg then | ||
| 2236 | out[#out + 1] = "..." | ||
| 2237 | end | ||
| 2238 | out[#out + 1] = ")" | ||
| 2239 | joinStatementsSafe(out, formatStatlist(expr.Body), nil) | ||
| 2240 | joinStatementsSafe(out, "end", nil) | ||
| 2241 | elseif expr.AstType == 'ConstructorExpr' then | ||
| 2242 | out[#out + 1] = "{ " | ||
| 2243 | for i = 1, #expr.EntryList do | ||
| 2244 | local entry = expr.EntryList[i] | ||
| 2245 | if entry.Type == 'Key' then | ||
| 2246 | out[#out + 1] = "[" | ||
| 2247 | out[#out + 1] = formatExpr(entry.Key) | ||
| 2248 | out[#out + 1] = "] = " | ||
| 2249 | out[#out + 1] = formatExpr(entry.Value) | ||
| 2250 | elseif entry.Type == 'Value' then | ||
| 2251 | out[#out + 1] = formatExpr(entry.Value) | ||
| 2252 | elseif entry.Type == 'KeyString' then | ||
| 2253 | out[#out + 1] = entry.Key | ||
| 2254 | out[#out + 1] = " = " | ||
| 2255 | out[#out + 1] = formatExpr(entry.Value) | ||
| 2256 | end | ||
| 2257 | if i ~= #expr.EntryList then | ||
| 2258 | out[#out + 1] = ", " | ||
| 2259 | end | ||
| 2260 | end | ||
| 2261 | out[#out + 1] = " }" | ||
| 2262 | |||
| 2263 | elseif expr.AstType == 'Parentheses' then | ||
| 2264 | out[#out + 1] = "(" | ||
| 2265 | out[#out + 1] = formatExpr(expr.Inner) | ||
| 2266 | out[#out + 1] = ")" | ||
| 2267 | |||
| 2268 | end | ||
| 2269 | out[#out + 1] = string.rep(')', expr.ParenCount or 0) | ||
| 2270 | return table.concat(out) | ||
| 2271 | end | ||
| 2272 | |||
| 2273 | local formatStatement = function(statement) | ||
| 2274 | local out = {""} | ||
| 2275 | if statement.Tokens and statement.Tokens[1] then | ||
| 2276 | local line = statement.Tokens[1].Line | ||
| 2277 | local targetLine = lineMap[line] | ||
| 2278 | if targetLine and currentLine < targetLine then | ||
| 2279 | out[#out + 1] = string.rep('\n', targetLine - currentLine) | ||
| 2280 | currentLine = targetLine | ||
| 2281 | end | ||
| 2282 | end | ||
| 2283 | if statement.AstType == 'AssignmentStatement' then | ||
| 2284 | for i = 1, #statement.Lhs do | ||
| 2285 | out[#out + 1] = formatExpr(statement.Lhs[i]) | ||
| 2286 | if i ~= #statement.Lhs then | ||
| 2287 | out[#out + 1] = ", " | ||
| 2288 | end | ||
| 2289 | end | ||
| 2290 | if #statement.Rhs > 0 then | ||
| 2291 | out[#out + 1] = " = " | ||
| 2292 | for i = 1, #statement.Rhs do | ||
| 2293 | out[#out + 1] = formatExpr(statement.Rhs[i]) | ||
| 2294 | if i ~= #statement.Rhs then | ||
| 2295 | out[#out + 1] = ", " | ||
| 2296 | end | ||
| 2297 | end | ||
| 2298 | end | ||
| 2299 | elseif statement.AstType == 'CallStatement' then | ||
| 2300 | out[#out + 1] = formatExpr(statement.Expression) | ||
| 2301 | elseif statement.AstType == 'LocalStatement' then | ||
| 2302 | out[#out + 1] = "local " | ||
| 2303 | for i = 1, #statement.LocalList do | ||
| 2304 | out[#out + 1] = statement.LocalList[i].Name | ||
| 2305 | if statement.AttrList[i] then | ||
| 2306 | out[#out + 1] = " <" | ||
| 2307 | out[#out + 1] = statement.AttrList[i] | ||
| 2308 | out[#out + 1] = ">" | ||
| 2309 | end | ||
| 2310 | if i ~= #statement.LocalList then | ||
| 2311 | out[#out + 1] = "," | ||
| 2312 | end | ||
| 2313 | end | ||
| 2314 | if #statement.InitList > 0 then | ||
| 2315 | out[#out + 1] = " = " | ||
| 2316 | for i = 1, #statement.InitList do | ||
| 2317 | out[#out + 1] = formatExpr(statement.InitList[i]) | ||
| 2318 | if i ~= #statement.InitList then | ||
| 2319 | out[#out + 1] = ", " | ||
| 2320 | end | ||
| 2321 | end | ||
| 2322 | end | ||
| 2323 | elseif statement.AstType == 'IfStatement' then | ||
| 2324 | out[#out + 1] = "if " | ||
| 2325 | joinStatementsSafe(out, formatExpr(statement.Clauses[1].Condition), nil) | ||
| 2326 | joinStatementsSafe(out, " then", nil) | ||
| 2327 | joinStatementsSafe(out, formatStatlist(statement.Clauses[1].Body), nil) | ||
| 2328 | for i = 2, #statement.Clauses do | ||
| 2329 | local st = statement.Clauses[i] | ||
| 2330 | if st.Condition then | ||
| 2331 | joinStatementsSafe(out, "elseif ", nil) | ||
| 2332 | joinStatementsSafe(out, formatExpr(st.Condition), nil) | ||
| 2333 | joinStatementsSafe(out, " then", nil) | ||
| 2334 | else | ||
| 2335 | joinStatementsSafe(out, "else", nil) | ||
| 2336 | end | ||
| 2337 | joinStatementsSafe(out, formatStatlist(st.Body), nil) | ||
| 2338 | end | ||
| 2339 | joinStatementsSafe(out, "end", nil) | ||
| 2340 | elseif statement.AstType == 'WhileStatement' then | ||
| 2341 | out[#out + 1] = "while " | ||
| 2342 | joinStatementsSafe(out, formatExpr(statement.Condition), nil) | ||
| 2343 | joinStatementsSafe(out, " do", nil) | ||
| 2344 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2345 | joinStatementsSafe(out, "end", nil) | ||
| 2346 | elseif statement.AstType == 'DoStatement' then | ||
| 2347 | joinStatementsSafe(out, "do", nil) | ||
| 2348 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2349 | joinStatementsSafe(out, "end", nil) | ||
| 2350 | elseif statement.AstType == 'ReturnStatement' then | ||
| 2351 | out[#out + 1] = "return " | ||
| 2352 | for i = 1, #statement.Arguments do | ||
| 2353 | joinStatementsSafe(out, formatExpr(statement.Arguments[i]), nil) | ||
| 2354 | if i ~= #statement.Arguments then | ||
| 2355 | out[#out + 1] = ", " | ||
| 2356 | end | ||
| 2357 | end | ||
| 2358 | elseif statement.AstType == 'BreakStatement' then | ||
| 2359 | out[#out + 1] = "break" | ||
| 2360 | elseif statement.AstType == 'RepeatStatement' then | ||
| 2361 | out[#out + 1] = "repeat" | ||
| 2362 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2363 | joinStatementsSafe(out, "until ", nil) | ||
| 2364 | joinStatementsSafe(out, formatExpr(statement.Condition), nil) | ||
| 2365 | elseif statement.AstType == 'Function' then | ||
| 2366 | if statement.IsLocal then | ||
| 2367 | out[#out + 1] = "local " | ||
| 2368 | end | ||
| 2369 | joinStatementsSafe(out, "function ", nil) | ||
| 2370 | if statement.IsLocal then | ||
| 2371 | out[#out + 1] = statement.Name.Name | ||
| 2372 | else | ||
| 2373 | out[#out + 1] = formatExpr(statement.Name) | ||
| 2374 | end | ||
| 2375 | out[#out + 1] = "(" | ||
| 2376 | if #statement.Arguments > 0 then | ||
| 2377 | for i = 1, #statement.Arguments do | ||
| 2378 | out[#out + 1] = statement.Arguments[i].Name | ||
| 2379 | if i ~= #statement.Arguments then | ||
| 2380 | out[#out + 1] = ", " | ||
| 2381 | elseif statement.VarArg then | ||
| 2382 | out[#out + 1] = ",..." | ||
| 2383 | end | ||
| 2384 | end | ||
| 2385 | elseif statement.VarArg then | ||
| 2386 | out[#out + 1] = "..." | ||
| 2387 | end | ||
| 2388 | out[#out + 1] = ")" | ||
| 2389 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2390 | joinStatementsSafe(out, "end", nil) | ||
| 2391 | elseif statement.AstType == 'GenericForStatement' then | ||
| 2392 | out[#out + 1] = "for " | ||
| 2393 | for i = 1, #statement.VariableList do | ||
| 2394 | out[#out + 1] = statement.VariableList[i].Name | ||
| 2395 | if i ~= #statement.VariableList then | ||
| 2396 | out[#out + 1] = ", " | ||
| 2397 | end | ||
| 2398 | end | ||
| 2399 | out[#out + 1] = " in " | ||
| 2400 | for i = 1, #statement.Generators do | ||
| 2401 | joinStatementsSafe(out, formatExpr(statement.Generators[i]), nil) | ||
| 2402 | if i ~= #statement.Generators then | ||
| 2403 | joinStatementsSafe(out, ', ', nil) | ||
| 2404 | end | ||
| 2405 | end | ||
| 2406 | joinStatementsSafe(out, " do", nil) | ||
| 2407 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2408 | joinStatementsSafe(out, "end", nil) | ||
| 2409 | elseif statement.AstType == 'NumericForStatement' then | ||
| 2410 | out[#out + 1] = "for " | ||
| 2411 | out[#out + 1] = statement.Variable.Name | ||
| 2412 | out[#out + 1] = " = " | ||
| 2413 | out[#out + 1] = formatExpr(statement.Start) | ||
| 2414 | out[#out + 1] = ", " | ||
| 2415 | out[#out + 1] = formatExpr(statement.End) | ||
| 2416 | if statement.Step then | ||
| 2417 | out[#out + 1] = ", " | ||
| 2418 | out[#out + 1] = formatExpr(statement.Step) | ||
| 2419 | end | ||
| 2420 | joinStatementsSafe(out, " do", nil) | ||
| 2421 | joinStatementsSafe(out, formatStatlist(statement.Body), nil) | ||
| 2422 | joinStatementsSafe(out, "end", nil) | ||
| 2423 | elseif statement.AstType == 'LabelStatement' then | ||
| 2424 | out[#out + 1] = "::" | ||
| 2425 | out[#out + 1] = statement.Label | ||
| 2426 | out[#out + 1] = "::" | ||
| 2427 | elseif statement.AstType == 'GotoStatement' then | ||
| 2428 | out[#out + 1] = "goto " | ||
| 2429 | out[#out + 1] = statement.Label | ||
| 2430 | elseif statement.AstType == 'Comment' then | ||
| 2431 | -- Ignore | ||
| 2432 | elseif statement.AstType == 'Eof' then | ||
| 2433 | -- Ignore | ||
| 2434 | else | ||
| 2435 | print("Unknown AST Type: ", statement.AstType) | ||
| 2436 | end | ||
| 2437 | return table.concat(out) | ||
| 2438 | end | ||
| 2439 | |||
| 2440 | formatStatlist = function(statList) | ||
| 2441 | local out = {""} | ||
| 2442 | for _, stat in pairs(statList.Body) do | ||
| 2443 | joinStatementsSafe(out, formatStatement(stat), ';') | ||
| 2444 | end | ||
| 2445 | return table.concat(out) | ||
| 2446 | end | ||
| 2447 | |||
| 2448 | return formatStatlist(ast) | ||
| 2449 | end | ||
| 2450 | |||
| 2451 | local function GetYueLineMap(luaCodes) | ||
| 2452 | local current = 1 | ||
| 2453 | local lastLine = 1 | ||
| 2454 | local lineMap = { } | ||
| 2455 | for lineCode in luaCodes:gmatch("[^\n\r]*") do | ||
| 2456 | local num = lineCode:match("--%s*(%d+)%s*$") | ||
| 2457 | if num then | ||
| 2458 | local line = tonumber(num) | ||
| 2459 | if line > lastLine then | ||
| 2460 | lastLine = line | ||
| 2461 | end | ||
| 2462 | end | ||
| 2463 | lineMap[current] = lastLine | ||
| 2464 | current = current + 1 | ||
| 2465 | end | ||
| 2466 | return lineMap | ||
| 2103 | end | 2467 | end |
| 2468 | |||
| 2469 | return { | ||
| 2470 | FormatMini = function(src) | ||
| 2471 | local st, ast = ParseLua(src) | ||
| 2472 | if st then | ||
| 2473 | return Format_Mini(ast) | ||
| 2474 | else | ||
| 2475 | return nil, ast | ||
| 2476 | end | ||
| 2477 | end, | ||
| 2478 | |||
| 2479 | FormatYue = function(src) | ||
| 2480 | local st, ast = ParseLua(src) | ||
| 2481 | if st then | ||
| 2482 | local lineMap = GetYueLineMap(src) | ||
| 2483 | if #lineMap == 0 then | ||
| 2484 | return src | ||
| 2485 | end | ||
| 2486 | return FormatYue(ast, lineMap) | ||
| 2487 | else | ||
| 2488 | return nil, ast | ||
| 2489 | end | ||
| 2490 | end | ||
| 2491 | } | ||
| 2104 | )lua_codes"; | 2492 | )lua_codes"; |
| 2105 | 2493 | ||
diff --git a/src/yue.cpp b/src/yue.cpp index 98bf4b4..4dec0e4 100644 --- a/src/yue.cpp +++ b/src/yue.cpp | |||
| @@ -246,6 +246,7 @@ int main(int narg, const char** args) { | |||
| 246 | #ifndef YUE_COMPILER_ONLY | 246 | #ifndef YUE_COMPILER_ONLY |
| 247 | " -e str Execute a file or raw codes\n" | 247 | " -e str Execute a file or raw codes\n" |
| 248 | " -m Generate minified codes\n" | 248 | " -m Generate minified codes\n" |
| 249 | " -r Rewrite output to match original line numbers\n" | ||
| 249 | #endif // YUE_COMPILER_ONLY | 250 | #endif // YUE_COMPILER_ONLY |
| 250 | " -t path Specify where to place compiled files\n" | 251 | " -t path Specify where to place compiled files\n" |
| 251 | " -o file Write output to file\n" | 252 | " -o file Write output to file\n" |
| @@ -409,6 +410,7 @@ int main(int narg, const char** args) { | |||
| 409 | return 0; | 410 | return 0; |
| 410 | } | 411 | } |
| 411 | bool minify = false; | 412 | bool minify = false; |
| 413 | bool rewrite = false; | ||
| 412 | #endif // YUE_COMPILER_ONLY | 414 | #endif // YUE_COMPILER_ONLY |
| 413 | yue::YueConfig config; | 415 | yue::YueConfig config; |
| 414 | config.implicitReturnRoot = true; | 416 | config.implicitReturnRoot = true; |
| @@ -522,6 +524,8 @@ int main(int narg, const char** args) { | |||
| 522 | } | 524 | } |
| 523 | } else if (arg == "-m"sv) { | 525 | } else if (arg == "-m"sv) { |
| 524 | minify = true; | 526 | minify = true; |
| 527 | } else if (arg == "-r"sv) { | ||
| 528 | rewrite = true; | ||
| 525 | #endif // YUE_COMPILER_ONLY | 529 | #endif // YUE_COMPILER_ONLY |
| 526 | } else if (arg == "-s"sv) { | 530 | } else if (arg == "-s"sv) { |
| 527 | config.useSpaceOverTab = true; | 531 | config.useSpaceOverTab = true; |
| @@ -607,6 +611,16 @@ int main(int narg, const char** args) { | |||
| 607 | std::cout << "Error: -o can not be used with multiple input files\n"sv; | 611 | std::cout << "Error: -o can not be used with multiple input files\n"sv; |
| 608 | return 1; | 612 | return 1; |
| 609 | } | 613 | } |
| 614 | #ifndef YUE_COMPILER_ONLY | ||
| 615 | if (minify || rewrite) { | ||
| 616 | if (minify) { | ||
| 617 | rewrite = false; | ||
| 618 | } | ||
| 619 | if (rewrite) { | ||
| 620 | config.reserveLineNumber = true; | ||
| 621 | } | ||
| 622 | } | ||
| 623 | #endif // YUE_COMPILER_ONLY | ||
| 610 | #ifndef YUE_NO_WATCHER | 624 | #ifndef YUE_NO_WATCHER |
| 611 | if (watchFiles) { | 625 | if (watchFiles) { |
| 612 | auto fullWorkPath = fs::absolute(fs::path(workPath)).string(); | 626 | auto fullWorkPath = fs::absolute(fs::path(workPath)).string(); |
| @@ -744,7 +758,7 @@ int main(int narg, const char** args) { | |||
| 744 | DEFER({ | 758 | DEFER({ |
| 745 | if (L) lua_close(L); | 759 | if (L) lua_close(L); |
| 746 | }); | 760 | }); |
| 747 | if (minify) { | 761 | if (minify || rewrite) { |
| 748 | L = luaL_newstate(); | 762 | L = luaL_newstate(); |
| 749 | luaL_openlibs(L); | 763 | luaL_openlibs(L); |
| 750 | pushLuaminify(L); | 764 | pushLuaminify(L); |
| @@ -766,7 +780,7 @@ int main(int narg, const char** args) { | |||
| 766 | errs.push_back(msg); | 780 | errs.push_back(msg); |
| 767 | } else { | 781 | } else { |
| 768 | #ifndef YUE_COMPILER_ONLY | 782 | #ifndef YUE_COMPILER_ONLY |
| 769 | if (minify) { | 783 | if (minify || rewrite) { |
| 770 | std::ifstream input(file, std::ios::in); | 784 | std::ifstream input(file, std::ios::in); |
| 771 | if (input) { | 785 | if (input) { |
| 772 | std::string s; | 786 | std::string s; |
| @@ -780,27 +794,24 @@ int main(int narg, const char** args) { | |||
| 780 | input.close(); | 794 | input.close(); |
| 781 | int top = lua_gettop(L); | 795 | int top = lua_gettop(L); |
| 782 | DEFER(lua_settop(L, top)); | 796 | DEFER(lua_settop(L, top)); |
| 783 | lua_pushvalue(L, -1); | 797 | lua_getfield(L, -1, rewrite ? "FormatYue" : "FormatMini"); |
| 784 | lua_pushlstring(L, s.c_str(), s.size()); | 798 | lua_pushlstring(L, s.c_str(), s.size()); |
| 785 | if (lua_pcall(L, 1, 1, 0) != 0) { | 799 | if (lua_pcall(L, 1, 1, 0) != 0) { |
| 786 | ret = 2; | 800 | ret = 2; |
| 787 | std::string err = lua_tostring(L, -1); | 801 | std::string err = lua_tostring(L, -1); |
| 788 | errs.push_back("Failed to minify: "s + file + '\n' + err + '\n'); | 802 | errs.push_back((rewrite ? "Failed to rewrite: "s : "Failed to minify: "s) + file + '\n' + err + '\n'); |
| 789 | } else { | 803 | } else { |
| 790 | size_t size = 0; | 804 | size_t size = 0; |
| 791 | const char* minifiedCodes = lua_tolstring(L, -1, &size); | 805 | const char* transformedCodes = lua_tolstring(L, -1, &size); |
| 792 | if (writeToFile) { | 806 | if (writeToFile) { |
| 793 | std::ofstream output(file, std::ios::trunc | std::ios::out); | 807 | std::ofstream output(file, std::ios::trunc | std::ios::out); |
| 794 | output.write(minifiedCodes, size); | 808 | output.write(transformedCodes, size); |
| 795 | output.close(); | 809 | output.close(); |
| 796 | std::cout << "Minified built "sv << file << '\n'; | 810 | std::cout << (rewrite ? "Rewrited built "sv : "Minified built "sv) << file << '\n'; |
| 797 | } else { | 811 | } else { |
| 798 | std::cout << minifiedCodes << '\n'; | 812 | std::cout << transformedCodes << '\n'; |
| 799 | } | 813 | } |
| 800 | } | 814 | } |
| 801 | } else { | ||
| 802 | ret = 2; | ||
| 803 | errs.push_back("Failed to minify: "s + file + '\n'); | ||
| 804 | } | 815 | } |
| 805 | } else { | 816 | } else { |
| 806 | std::cout << msg; | 817 | std::cout << msg; |
diff --git a/src/yuescript/yue_compiler.cpp b/src/yuescript/yue_compiler.cpp index 09da047..2a3cb8c 100644 --- a/src/yuescript/yue_compiler.cpp +++ b/src/yuescript/yue_compiler.cpp | |||
| @@ -72,7 +72,7 @@ static std::unordered_set<std::string> Metamethods = { | |||
| 72 | "close"s // Lua 5.4 | 72 | "close"s // Lua 5.4 |
| 73 | }; | 73 | }; |
| 74 | 74 | ||
| 75 | const std::string_view version = "0.17.8"sv; | 75 | const std::string_view version = "0.17.9"sv; |
| 76 | const std::string_view extension = "yue"sv; | 76 | const std::string_view extension = "yue"sv; |
| 77 | 77 | ||
| 78 | class CompileError : public std::logic_error { | 78 | class CompileError : public std::logic_error { |
| @@ -435,7 +435,7 @@ private: | |||
| 435 | struct ClassMember { | 435 | struct ClassMember { |
| 436 | std::string item; | 436 | std::string item; |
| 437 | MemType type; | 437 | MemType type; |
| 438 | ast_node* node; | 438 | ast_ptr<true, ast_node> node; |
| 439 | }; | 439 | }; |
| 440 | 440 | ||
| 441 | struct DestructItem { | 441 | struct DestructItem { |
