aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLi Jin <dragon-fly@qq.com>2020-03-05 16:08:41 +0800
committerLi Jin <dragon-fly@qq.com>2020-03-05 16:08:41 +0800
commit890fc913737c62c5d7e51636e0535b7b318a0d89 (patch)
tree8ca71fc3a2599ad1cbebcd3234dcb06292448037
parent3b94999e55df35d19616e87d7f3b6fddf5b8a30b (diff)
downloadyuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.tar.gz
yuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.tar.bz2
yuescript-890fc913737c62c5d7e51636e0535b7b318a0d89.zip
move functions of old export statement to global statement, make export statement work with Lua module system.
-rw-r--r--.gitignore2
-rw-r--r--MoonPlus.sln31
-rw-r--r--MoonPlus.vcxproj173
-rw-r--r--MoonPlus.vcxproj.filters46
-rw-r--r--MoonPlus.vcxproj.user4
-rw-r--r--spec/inputs/class.moon2
-rw-r--r--spec/inputs/export.moon98
-rw-r--r--spec/inputs/export_default.moon15
-rw-r--r--spec/inputs/global.moon77
-rw-r--r--spec/inputs/import.moon2
-rw-r--r--src/MoonP/moon_ast.h26
-rw-r--r--src/MoonP/moon_compiler.cpp192
-rw-r--r--src/MoonP/moon_parser.cpp74
-rw-r--r--src/MoonP/moon_parser.h19
-rw-r--r--src/moonp.cpp6
15 files changed, 623 insertions, 144 deletions
diff --git a/.gitignore b/.gitignore
index 27acefe..5994846 100644
--- a/.gitignore
+++ b/.gitignore
@@ -4,3 +4,5 @@ build.luarocks
4spec/outputs 4spec/outputs
5moonplus-*.rock* 5moonplus-*.rock*
6!moonplus-dev-1.rockspec 6!moonplus-dev-1.rockspec
7.vs
8bin
diff --git a/MoonPlus.sln b/MoonPlus.sln
new file mode 100644
index 0000000..252e9b4
--- /dev/null
+++ b/MoonPlus.sln
@@ -0,0 +1,31 @@
1
2Microsoft Visual Studio Solution File, Format Version 12.00
3# Visual Studio Version 16
4VisualStudioVersion = 16.0.29806.167
5MinimumVisualStudioVersion = 10.0.40219.1
6Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MoonPlus", "MoonPlus.vcxproj", "{CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}"
7EndProject
8Global
9 GlobalSection(SolutionConfigurationPlatforms) = preSolution
10 Debug|x64 = Debug|x64
11 Debug|x86 = Debug|x86
12 Release|x64 = Release|x64
13 Release|x86 = Release|x86
14 EndGlobalSection
15 GlobalSection(ProjectConfigurationPlatforms) = postSolution
16 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x64.ActiveCfg = Debug|x64
17 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x64.Build.0 = Debug|x64
18 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x86.ActiveCfg = Debug|Win32
19 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Debug|x86.Build.0 = Debug|Win32
20 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x64.ActiveCfg = Release|x64
21 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x64.Build.0 = Release|x64
22 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x86.ActiveCfg = Release|Win32
23 {CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}.Release|x86.Build.0 = Release|Win32
24 EndGlobalSection
25 GlobalSection(SolutionProperties) = preSolution
26 HideSolutionNode = FALSE
27 EndGlobalSection
28 GlobalSection(ExtensibilityGlobals) = postSolution
29 SolutionGuid = {49826A7F-7A92-4CFC-95DD-28B7045BB2F7}
30 EndGlobalSection
31EndGlobal
diff --git a/MoonPlus.vcxproj b/MoonPlus.vcxproj
new file mode 100644
index 0000000..fd502ab
--- /dev/null
+++ b/MoonPlus.vcxproj
@@ -0,0 +1,173 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <ItemGroup Label="ProjectConfigurations">
4 <ProjectConfiguration Include="Debug|Win32">
5 <Configuration>Debug</Configuration>
6 <Platform>Win32</Platform>
7 </ProjectConfiguration>
8 <ProjectConfiguration Include="Release|Win32">
9 <Configuration>Release</Configuration>
10 <Platform>Win32</Platform>
11 </ProjectConfiguration>
12 <ProjectConfiguration Include="Debug|x64">
13 <Configuration>Debug</Configuration>
14 <Platform>x64</Platform>
15 </ProjectConfiguration>
16 <ProjectConfiguration Include="Release|x64">
17 <Configuration>Release</Configuration>
18 <Platform>x64</Platform>
19 </ProjectConfiguration>
20 </ItemGroup>
21 <PropertyGroup Label="Globals">
22 <VCProjectVersion>16.0</VCProjectVersion>
23 <ProjectGuid>{CF4F54DB-61FE-48E0-BA2E-4168BA27ECBD}</ProjectGuid>
24 <RootNamespace>MoonPlus</RootNamespace>
25 <WindowsTargetPlatformVersion>10.0</WindowsTargetPlatformVersion>
26 </PropertyGroup>
27 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
28 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
29 <ConfigurationType>Application</ConfigurationType>
30 <UseDebugLibraries>true</UseDebugLibraries>
31 <PlatformToolset>v142</PlatformToolset>
32 <CharacterSet>Unicode</CharacterSet>
33 </PropertyGroup>
34 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
35 <ConfigurationType>Application</ConfigurationType>
36 <UseDebugLibraries>false</UseDebugLibraries>
37 <PlatformToolset>v142</PlatformToolset>
38 <WholeProgramOptimization>true</WholeProgramOptimization>
39 <CharacterSet>Unicode</CharacterSet>
40 </PropertyGroup>
41 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'" Label="Configuration">
42 <ConfigurationType>Application</ConfigurationType>
43 <UseDebugLibraries>true</UseDebugLibraries>
44 <PlatformToolset>v142</PlatformToolset>
45 <CharacterSet>Unicode</CharacterSet>
46 </PropertyGroup>
47 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'" Label="Configuration">
48 <ConfigurationType>Application</ConfigurationType>
49 <UseDebugLibraries>false</UseDebugLibraries>
50 <PlatformToolset>v142</PlatformToolset>
51 <WholeProgramOptimization>true</WholeProgramOptimization>
52 <CharacterSet>Unicode</CharacterSet>
53 </PropertyGroup>
54 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
55 <ImportGroup Label="ExtensionSettings">
56 </ImportGroup>
57 <ImportGroup Label="Shared">
58 </ImportGroup>
59 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
60 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
61 </ImportGroup>
62 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
63 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
64 </ImportGroup>
65 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
66 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
67 </ImportGroup>
68 <ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
69 <Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
70 </ImportGroup>
71 <PropertyGroup Label="UserMacros" />
72 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
73 <LinkIncremental>true</LinkIncremental>
74 <IntDir>$(SolutionDir)\build\windows\$(Configuration)\</IntDir>
75 <OutDir>$(SolutionDir)\bin\windows\$(Configuration)\</OutDir>
76 </PropertyGroup>
77 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
78 <LinkIncremental>true</LinkIncremental>
79 <OutDir>$(SolutionDir)\bin\windows\$(Platform)\$(Configuration)\</OutDir>
80 <IntDir>$(SolutionDir)\build\windows\$(Platform)\$(Configuration)\</IntDir>
81 </PropertyGroup>
82 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
83 <LinkIncremental>false</LinkIncremental>
84 <IntDir>$(SolutionDir)\build\windows\$(Configuration)\</IntDir>
85 <OutDir>$(SolutionDir)\bin\windows\$(Configuration)\</OutDir>
86 </PropertyGroup>
87 <PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
88 <LinkIncremental>false</LinkIncremental>
89 <OutDir>$(SolutionDir)\bin\windows\$(Platform)\$(Configuration)\</OutDir>
90 <IntDir>$(SolutionDir)\build\windows\$(Platform)\$(Configuration)\</IntDir>
91 </PropertyGroup>
92 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
93 <ClCompile>
94 <WarningLevel>Level3</WarningLevel>
95 <SDLCheck>true</SDLCheck>
96 <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
97 <ConformanceMode>true</ConformanceMode>
98 <LanguageStandard>stdcpplatest</LanguageStandard>
99 <AdditionalIncludeDirectories>.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
100 </ClCompile>
101 <Link>
102 <SubSystem>Console</SubSystem>
103 <GenerateDebugInformation>true</GenerateDebugInformation>
104 </Link>
105 </ItemDefinitionGroup>
106 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|x64'">
107 <ClCompile>
108 <WarningLevel>Level3</WarningLevel>
109 <SDLCheck>true</SDLCheck>
110 <PreprocessorDefinitions>_DEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
111 <ConformanceMode>true</ConformanceMode>
112 <LanguageStandard>stdcpplatest</LanguageStandard>
113 <AdditionalIncludeDirectories>.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
114 </ClCompile>
115 <Link>
116 <SubSystem>Console</SubSystem>
117 <GenerateDebugInformation>true</GenerateDebugInformation>
118 </Link>
119 </ItemDefinitionGroup>
120 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
121 <ClCompile>
122 <WarningLevel>Level3</WarningLevel>
123 <FunctionLevelLinking>true</FunctionLevelLinking>
124 <IntrinsicFunctions>true</IntrinsicFunctions>
125 <SDLCheck>true</SDLCheck>
126 <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
127 <ConformanceMode>true</ConformanceMode>
128 <LanguageStandard>stdcpplatest</LanguageStandard>
129 <AdditionalIncludeDirectories>.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
130 </ClCompile>
131 <Link>
132 <SubSystem>Console</SubSystem>
133 <EnableCOMDATFolding>true</EnableCOMDATFolding>
134 <OptimizeReferences>true</OptimizeReferences>
135 <GenerateDebugInformation>true</GenerateDebugInformation>
136 </Link>
137 </ItemDefinitionGroup>
138 <ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|x64'">
139 <ClCompile>
140 <WarningLevel>Level3</WarningLevel>
141 <FunctionLevelLinking>true</FunctionLevelLinking>
142 <IntrinsicFunctions>true</IntrinsicFunctions>
143 <SDLCheck>true</SDLCheck>
144 <PreprocessorDefinitions>NDEBUG;_CONSOLE;_SILENCE_CXX17_CODECVT_HEADER_DEPRECATION_WARNING;%(PreprocessorDefinitions)</PreprocessorDefinitions>
145 <ConformanceMode>true</ConformanceMode>
146 <LanguageStandard>stdcpplatest</LanguageStandard>
147 <AdditionalIncludeDirectories>.\src;%(AdditionalIncludeDirectories)</AdditionalIncludeDirectories>
148 </ClCompile>
149 <Link>
150 <SubSystem>Console</SubSystem>
151 <EnableCOMDATFolding>true</EnableCOMDATFolding>
152 <OptimizeReferences>true</OptimizeReferences>
153 <GenerateDebugInformation>true</GenerateDebugInformation>
154 </Link>
155 </ItemDefinitionGroup>
156 <ItemGroup>
157 <ClCompile Include="src\moonp.cpp" />
158 <ClCompile Include="src\MoonP\ast.cpp" />
159 <ClCompile Include="src\MoonP\moon_compiler.cpp" />
160 <ClCompile Include="src\MoonP\moon_parser.cpp" />
161 <ClCompile Include="src\MoonP\parser.cpp" />
162 </ItemGroup>
163 <ItemGroup>
164 <ClInclude Include="src\MoonP\ast.hpp" />
165 <ClInclude Include="src\MoonP\moon_ast.h" />
166 <ClInclude Include="src\MoonP\moon_compiler.h" />
167 <ClInclude Include="src\MoonP\moon_parser.h" />
168 <ClInclude Include="src\MoonP\parser.hpp" />
169 </ItemGroup>
170 <Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
171 <ImportGroup Label="ExtensionTargets">
172 </ImportGroup>
173</Project> \ No newline at end of file
diff --git a/MoonPlus.vcxproj.filters b/MoonPlus.vcxproj.filters
new file mode 100644
index 0000000..6550779
--- /dev/null
+++ b/MoonPlus.vcxproj.filters
@@ -0,0 +1,46 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <ItemGroup>
4 <Filter Include="src">
5 <UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
6 <Extensions>h;hh;hpp;hxx;hm;inl;inc;ipp;xsd</Extensions>
7 </Filter>
8 <Filter Include="src\MoonP">
9 <UniqueIdentifier>{c88639d5-457d-42eb-b852-65682c89c618}</UniqueIdentifier>
10 </Filter>
11 </ItemGroup>
12 <ItemGroup>
13 <ClCompile Include="src\MoonP\ast.cpp">
14 <Filter>src\MoonP</Filter>
15 </ClCompile>
16 <ClCompile Include="src\MoonP\moon_compiler.cpp">
17 <Filter>src\MoonP</Filter>
18 </ClCompile>
19 <ClCompile Include="src\MoonP\moon_parser.cpp">
20 <Filter>src\MoonP</Filter>
21 </ClCompile>
22 <ClCompile Include="src\MoonP\parser.cpp">
23 <Filter>src\MoonP</Filter>
24 </ClCompile>
25 <ClCompile Include="src\moonp.cpp">
26 <Filter>src</Filter>
27 </ClCompile>
28 </ItemGroup>
29 <ItemGroup>
30 <ClInclude Include="src\MoonP\ast.hpp">
31 <Filter>src\MoonP</Filter>
32 </ClInclude>
33 <ClInclude Include="src\MoonP\moon_ast.h">
34 <Filter>src\MoonP</Filter>
35 </ClInclude>
36 <ClInclude Include="src\MoonP\moon_compiler.h">
37 <Filter>src\MoonP</Filter>
38 </ClInclude>
39 <ClInclude Include="src\MoonP\moon_parser.h">
40 <Filter>src\MoonP</Filter>
41 </ClInclude>
42 <ClInclude Include="src\MoonP\parser.hpp">
43 <Filter>src\MoonP</Filter>
44 </ClInclude>
45 </ItemGroup>
46</Project> \ No newline at end of file
diff --git a/MoonPlus.vcxproj.user b/MoonPlus.vcxproj.user
new file mode 100644
index 0000000..88a5509
--- /dev/null
+++ b/MoonPlus.vcxproj.user
@@ -0,0 +1,4 @@
1<?xml version="1.0" encoding="utf-8"?>
2<Project ToolsVersion="Current" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3 <PropertyGroup />
4</Project> \ No newline at end of file
diff --git a/spec/inputs/class.moon b/spec/inputs/class.moon
index 3288dc6..533694e 100644
--- a/spec/inputs/class.moon
+++ b/spec/inputs/class.moon
@@ -158,7 +158,7 @@ print (class WhatsUp).__name
158 158
159-- 159--
160 160
161export ^ 161global ^
162class Something 162class Something
163 _ = nil 163 _ = nil
164 164
diff --git a/spec/inputs/export.moon b/spec/inputs/export.moon
index a8c782c..9c906d5 100644
--- a/spec/inputs/export.moon
+++ b/spec/inputs/export.moon
@@ -1,77 +1,45 @@
1 1
2do 2export a,b,c = 223, 343, 123
3 export a,b,c = 223, 343 3export cool = "dad"
4 export cool = "dad"
5 4
6do 5d,e,f = 3, 2, 1
7 export class Something 6export d, e, f
8 umm: "cool"
9 7
10do 8export class Something
11 export a,b,c 9 umm: "cool"
12 a,b,c,d = "hello"
13 10
11export if this
12 232
13else
14 4343
14 15
15do 16export What = if this
16 What = if this 17 232
17 232 18else
18 else 19 4343
19 4343
20 20
21 export ^ 21export y = ->
22 hallo = 3434
22 23
23 another = 3434 24export with tmp
24 Another = 7890 25 j = 2000
25 26
26 if inner then Yeah = "10000" 27export cbVal = do
27 28 h = 100
28 What = if this 29 (x)<- f
29 232 30 return x h
30 else
31 4343
32
33
34do
35 export *
36
37 What = if this
38 232
39 else
40 4343
41
42 x,y,z = 1,2,3
43
44 y = ->
45 hallo = 3434
46
47 with tmp
48 j = 2000
49
50
51do
52 export *
53 x = 3434
54 if y then
55 x = 10
56
57do
58 export *
59 if y then
60 x = 10
61 x = 3434
62
63do
64 do
65 export *
66
67 k = 1212
68 31
69 do 32export y = ->
70 h = 100 33 h = 100
34 k = 100
71 35
72 y = -> 36export switch h
73 h = 100 37 when 100, 150 then 200
74 k = 100 38 when 200 then 300
39 else 0
75 40
76 h = 100 41export Constant = switch value
42 when "good" then 1
43 when "better" then 2
44 when "best" then 3
77 45
diff --git a/spec/inputs/export_default.moon b/spec/inputs/export_default.moon
new file mode 100644
index 0000000..73f43ac
--- /dev/null
+++ b/spec/inputs/export_default.moon
@@ -0,0 +1,15 @@
1
2print "OK"
3
4export default ->
5 print "hello"
6 123
7
8(x, fy)<- f 123, "abc" unless isOff
9print x
10(y, res)<- fy
11return if res
12 abc + y
13else
14 abc
15
diff --git a/spec/inputs/global.moon b/spec/inputs/global.moon
new file mode 100644
index 0000000..7d6cfde
--- /dev/null
+++ b/spec/inputs/global.moon
@@ -0,0 +1,77 @@
1
2do
3 global a,b,c = 223, 343
4 global cool = "dad"
5
6do
7 global class Something
8 umm: "cool"
9
10do
11 global a,b,c
12 a,b,c,d = "hello"
13
14
15do
16 What = if this
17 232
18 else
19 4343
20
21 global ^
22
23 another = 3434
24 Another = 7890
25
26 if inner then Yeah = "10000"
27
28 What = if this
29 232
30 else
31 4343
32
33
34do
35 global *
36
37 What = if this
38 232
39 else
40 4343
41
42 x,y,z = 1,2,3
43
44 y = ->
45 hallo = 3434
46
47 with tmp
48 j = 2000
49
50
51do
52 global *
53 x = 3434
54 if y then
55 x = 10
56
57do
58 global *
59 if y then
60 x = 10
61 x = 3434
62
63do
64 do
65 global *
66
67 k = 1212
68
69 do
70 h = 100
71
72 y = ->
73 h = 100
74 k = 100
75
76 h = 100
77
diff --git a/spec/inputs/import.moon b/spec/inputs/import.moon
index ded1ffd..99981f8 100644
--- a/spec/inputs/import.moon
+++ b/spec/inputs/import.moon
@@ -58,7 +58,7 @@ do
58 import "lpeg" as {:C, :Ct, :Cmt} 58 import "lpeg" as {:C, :Ct, :Cmt}
59 59
60do 60do
61 export * 61 global *
62 import 'module' 62 import 'module'
63 import 'module_x' 63 import 'module_x'
64 import "org.package.module-y" 64 import "org.package.module-y"
diff --git a/src/MoonP/moon_ast.h b/src/MoonP/moon_ast.h
index dd01165..9fab215 100644
--- a/src/MoonP/moon_ast.h
+++ b/src/MoonP/moon_ast.h
@@ -500,18 +500,28 @@ AST_NODE(ClassDecl)
500 AST_MEMBER(ClassDecl, &name, &extend, &body) 500 AST_MEMBER(ClassDecl, &name, &extend, &body)
501AST_END(ClassDecl) 501AST_END(ClassDecl)
502 502
503AST_NODE(export_values) 503AST_NODE(global_values)
504 ast_ptr<true, NameList_t> nameList; 504 ast_ptr<true, NameList_t> nameList;
505 ast_ptr<false, ExpListLow_t> valueList; 505 ast_ptr<false, ExpListLow_t> valueList;
506 AST_MEMBER(export_values, &nameList, &valueList) 506 AST_MEMBER(global_values, &nameList, &valueList)
507AST_END(export_values) 507AST_END(global_values)
508 508
509AST_LEAF(export_op) 509AST_LEAF(global_op)
510AST_END(export_op) 510AST_END(global_op)
511
512AST_NODE(Global)
513 ast_sel<true, ClassDecl_t, global_op_t, global_values_t> item;
514 AST_MEMBER(Global, &item)
515AST_END(Global)
516
517AST_LEAF(export_default)
518AST_END(export_default)
511 519
512AST_NODE(Export) 520AST_NODE(Export)
513 ast_sel<true, ClassDecl_t, export_op_t, export_values_t> item; 521 ast_ptr<false, export_default_t> def;
514 AST_MEMBER(Export, &item) 522 ast_sel<true, ExpList_t, Exp_t> target;
523 ast_ptr<false, Assign_t> assign;
524 AST_MEMBER(Export, &def, &target, &assign)
515AST_END(Export) 525AST_END(Export)
516 526
517AST_NODE(FnArgDef) 527AST_NODE(FnArgDef)
@@ -601,7 +611,7 @@ AST_END(BreakLoop)
601 611
602AST_NODE(Statement) 612AST_NODE(Statement)
603 ast_sel<true, Import_t, While_t, For_t, ForEach_t, 613 ast_sel<true, Import_t, While_t, For_t, ForEach_t,
604 Return_t, Local_t, Export_t, BreakLoop_t, 614 Return_t, Local_t, Global_t, Export_t, BreakLoop_t,
605 Backcall_t, ExpListAssign_t> content; 615 Backcall_t, ExpListAssign_t> content;
606 ast_ptr<false, statement_appendix_t> appendix; 616 ast_ptr<false, statement_appendix_t> appendix;
607 AST_MEMBER(Statement, &content, &appendix) 617 AST_MEMBER(Statement, &content, &appendix)
diff --git a/src/MoonP/moon_compiler.cpp b/src/MoonP/moon_compiler.cpp
index 83b91e6..1adfec9 100644
--- a/src/MoonP/moon_compiler.cpp
+++ b/src/MoonP/moon_compiler.cpp
@@ -32,7 +32,7 @@ inline std::string s(std::string_view sv) {
32} 32}
33 33
34const char* moonScriptVersion() { 34const char* moonScriptVersion() {
35 return "0.5.0-r0.1.5"; 35 return "0.5.0-r0.2.0";
36} 36}
37 37
38class MoonCompilerImpl { 38class MoonCompilerImpl {
@@ -45,7 +45,10 @@ public:
45 try { 45 try {
46 str_list out; 46 str_list out;
47 pushScope(); 47 pushScope();
48 transformBlock(_info.node.to<File_t>()->block, out, config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common); 48 enableReturn.push(_info.moduleName.empty());
49 transformBlock(_info.node.to<File_t>()->block, out,
50 config.implicitReturnRoot ? ExpUsage::Return : ExpUsage::Common,
51 nullptr, true);
49 popScope(); 52 popScope();
50 if (config.lintGlobalVariable) { 53 if (config.lintGlobalVariable) {
51 globals = std::make_unique<std::list<GlobalVar>>(); 54 globals = std::make_unique<std::list<GlobalVar>>();
@@ -86,6 +89,7 @@ private:
86 MoonParser _parser; 89 MoonParser _parser;
87 ParseInfo _info; 90 ParseInfo _info;
88 int _indentOffset = 0; 91 int _indentOffset = 0;
92 std::stack<bool> enableReturn;
89 std::list<std::unique_ptr<input>> _codeCache; 93 std::list<std::unique_ptr<input>> _codeCache;
90 std::stack<std::string> _withVars; 94 std::stack<std::string> _withVars;
91 std::stack<std::string> _continueVars; 95 std::stack<std::string> _continueVars;
@@ -98,16 +102,16 @@ private:
98 Capital = 1, 102 Capital = 1,
99 Any = 2 103 Any = 2
100 }; 104 };
101 enum class ExportMode { 105 enum class GlobalMode {
102 None = 0, 106 None = 0,
103 Capital = 1, 107 Capital = 1,
104 Any = 2 108 Any = 2
105 }; 109 };
106 struct Scope { 110 struct Scope {
107 ExportMode mode = ExportMode::None; 111 GlobalMode mode = GlobalMode::None;
108 std::unique_ptr<std::unordered_set<std::string>> vars; 112 std::unique_ptr<std::unordered_set<std::string>> vars;
109 std::unique_ptr<std::unordered_set<std::string>> allows; 113 std::unique_ptr<std::unordered_set<std::string>> allows;
110 std::unique_ptr<std::unordered_set<std::string>> exports; 114 std::unique_ptr<std::unordered_set<std::string>> globals;
111 }; 115 };
112 std::list<Scope> _scopes; 116 std::list<Scope> _scopes;
113 static const std::string Empty; 117 static const std::string Empty;
@@ -153,11 +157,11 @@ private:
153 157
154 bool isDefined(const std::string& name) const { 158 bool isDefined(const std::string& name) const {
155 bool isDefined = false; 159 bool isDefined = false;
156 int mode = int(std::isupper(name[0]) ? ExportMode::Capital : ExportMode::Any); 160 int mode = int(std::isupper(name[0]) ? GlobalMode::Capital : GlobalMode::Any);
157 const auto& current = _scopes.back(); 161 const auto& current = _scopes.back();
158 if (int(current.mode) >= mode) { 162 if (int(current.mode) >= mode) {
159 if (current.exports) { 163 if (current.globals) {
160 if (current.exports->find(name) != current.exports->end()) { 164 if (current.globals->find(name) != current.globals->end()) {
161 isDefined = true; 165 isDefined = true;
162 current.vars->insert(name); 166 current.vars->insert(name);
163 } 167 }
@@ -202,17 +206,17 @@ private:
202 scope.allows = std::make_unique<std::unordered_set<std::string>>(); 206 scope.allows = std::make_unique<std::unordered_set<std::string>>();
203 } 207 }
204 208
205 void markVarExported(ExportMode mode, bool specified) { 209 void markVarGlobal(GlobalMode mode, bool specified) {
206 auto& scope = _scopes.back(); 210 auto& scope = _scopes.back();
207 scope.mode = mode; 211 scope.mode = mode;
208 if (specified && !scope.exports) { 212 if (specified && !scope.globals) {
209 scope.exports = std::make_unique<std::unordered_set<std::string>>(); 213 scope.globals = std::make_unique<std::unordered_set<std::string>>();
210 } 214 }
211 } 215 }
212 216
213 void addExportedVar(const std::string& name) { 217 void addGlobalVar(const std::string& name) {
214 auto& scope = _scopes.back(); 218 auto& scope = _scopes.back();
215 scope.exports->insert(name); 219 scope.globals->insert(name);
216 } 220 }
217 221
218 void addToAllowList(const std::string& name) { 222 void addToAllowList(const std::string& name) {
@@ -457,6 +461,20 @@ private:
457 return Empty; 461 return Empty;
458 } 462 }
459 463
464 Variable_t* variableFrom(Exp_t* exp) {
465 BLOCK_START
466 auto value = singleValueFrom(exp);
467 BREAK_IF(!value);
468 auto chainValue = value->getByPath<ChainValue_t>();
469 BREAK_IF(!chainValue);
470 BREAK_IF(chainValue->items.size() != 1);
471 auto callable = ast_cast<Callable_t>(chainValue->items.front());
472 BREAK_IF(!callable);
473 return callable->item.as<Variable_t>();
474 BLOCK_END
475 return nullptr;
476 }
477
460 bool isAssignable(const node_container& chainItems) const { 478 bool isAssignable(const node_container& chainItems) const {
461 if (chainItems.size() == 1) { 479 if (chainItems.size() == 1) {
462 auto firstItem = chainItems.back(); 480 auto firstItem = chainItems.back();
@@ -647,6 +665,7 @@ private:
647 case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break; 665 case id<ForEach_t>(): transformForEach(static_cast<ForEach_t*>(content), out); break;
648 case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break; 666 case id<Return_t>(): transformReturn(static_cast<Return_t*>(content), out); break;
649 case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break; 667 case id<Local_t>(): transformLocal(static_cast<Local_t*>(content), out); break;
668 case id<Global_t>(): transformGlobal(static_cast<Global_t*>(content), out); break;
650 case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break; 669 case id<Export_t>(): transformExport(static_cast<Export_t*>(content), out); break;
651 case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break; 670 case id<BreakLoop_t>(): transformBreakLoop(static_cast<BreakLoop_t*>(content), out); break;
652 case id<ExpListAssign_t>(): { 671 case id<ExpListAssign_t>(): {
@@ -693,7 +712,7 @@ private:
693 break; 712 break;
694 } 713 }
695 } 714 }
696 throw std::logic_error(_info.errorMessage("Expression list must appear at the end of body or block."sv, expList)); 715 throw std::logic_error(_info.errorMessage("Expression list is not supported here."sv, expList));
697 } 716 }
698 break; 717 break;
699 } 718 }
@@ -749,8 +768,8 @@ private:
749 return preDefs; 768 return preDefs;
750 } 769 }
751 770
752 str_list transformAssignDefs(ExpList_t* expList) { 771 str_list transformAssignDefs(ExpList_t* expList, bool markDefined = true) {
753 str_list preDefs; 772 str_list defs;
754 for (auto exp_ : expList->exprs.objects()) { 773 for (auto exp_ : expList->exprs.objects()) {
755 auto exp = static_cast<Exp_t*>(exp_); 774 auto exp = static_cast<Exp_t*>(exp_);
756 if (auto value = singleValueFrom(exp)) { 775 if (auto value = singleValueFrom(exp)) {
@@ -766,8 +785,8 @@ private:
766 if (self->name.is<self_t>()) name = "self"sv; 785 if (self->name.is<self_t>()) name = "self"sv;
767 } 786 }
768 BREAK_IF(name.empty()); 787 BREAK_IF(name.empty());
769 if (addToScope(name)) { 788 if (!markDefined || addToScope(name)) {
770 preDefs.push_back(name); 789 defs.push_back(name);
771 } 790 }
772 BLOCK_END 791 BLOCK_END
773 } 792 }
@@ -775,7 +794,7 @@ private:
775 throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp)); 794 throw std::logic_error(_info.errorMessage("Left hand expression is not assignable."sv, exp));
776 } 795 }
777 } 796 }
778 return preDefs; 797 return defs;
779 } 798 }
780 799
781 std::string getPredefine(const str_list& defs) { 800 std::string getPredefine(const str_list& defs) {
@@ -1650,6 +1669,7 @@ private:
1650 } 1669 }
1651 1670
1652 void transformFunLit(FunLit_t* funLit, str_list& out) { 1671 void transformFunLit(FunLit_t* funLit, str_list& out) {
1672 enableReturn.push(true);
1653 str_list temp; 1673 str_list temp;
1654 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv; 1674 bool isFatArrow = _parser.toString(funLit->arrow) == "=>"sv;
1655 pushScope(); 1675 pushScope();
@@ -1698,6 +1718,7 @@ private:
1698 } 1718 }
1699 } 1719 }
1700 out.push_back(clearBuf()); 1720 out.push_back(clearBuf());
1721 enableReturn.pop();
1701 } 1722 }
1702 1723
1703 void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 1724 void transformBody(Body_t* body, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) {
@@ -1711,7 +1732,7 @@ private:
1711 } 1732 }
1712 } 1733 }
1713 1734
1714 void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr) { 1735 void transformBlock(Block_t* block, str_list& out, ExpUsage usage, ExpList_t* assignList = nullptr, bool isRoot = false) {
1715 const auto& nodes = block->statements.objects(); 1736 const auto& nodes = block->statements.objects();
1716 LocalMode mode = LocalMode::None; 1737 LocalMode mode = LocalMode::None;
1717 Local_t* any = nullptr, *capital = nullptr; 1738 Local_t* any = nullptr, *capital = nullptr;
@@ -1768,7 +1789,7 @@ private:
1768 args->swap(a, arg); 1789 args->swap(a, arg);
1769 findPlaceHolder = true; 1790 findPlaceHolder = true;
1770 } else { 1791 } else {
1771 throw std::logic_error(_info.errorMessage("backcall placeholder can be used only in one place."sv, a)); 1792 throw std::logic_error(_info.errorMessage("Backcall placeholder can be used only in one place."sv, a));
1772 } 1793 }
1773 } 1794 }
1774 } 1795 }
@@ -1792,9 +1813,10 @@ private:
1792 auto expListAssign = x->new_ptr<ExpListAssign_t>(); 1813 auto expListAssign = x->new_ptr<ExpListAssign_t>();
1793 expListAssign->expList.set(expList); 1814 expListAssign->expList.set(expList);
1794 newStmt->content.set(expListAssign); 1815 newStmt->content.set(expListAssign);
1816 newStmt->appendix.set(stmt->appendix);
1795 newBlock->statements.push_back(newStmt); 1817 newBlock->statements.push_back(newStmt);
1796 } 1818 }
1797 transformBlock(newBlock, out, usage, assignList); 1819 transformBlock(newBlock, out, usage, assignList, isRoot);
1798 return; 1820 return;
1799 } 1821 }
1800 if (auto local = stmt->content.as<Local_t>()) { 1822 if (auto local = stmt->content.as<Local_t>()) {
@@ -1838,6 +1860,15 @@ private:
1838 } 1860 }
1839 } 1861 }
1840 } 1862 }
1863 if (info.second) {
1864 auto defs = transformAssignDefs(info.second->expList, false);
1865 for (const auto& def : defs) {
1866 if (std::isupper(def[0]) && capital) { capital->decls.push_back(def);
1867 } else if (any) {
1868 any->decls.push_back(def);
1869 }
1870 }
1871 }
1841 BLOCK_START 1872 BLOCK_START
1842 auto assign = assignment->action.as<Assign_t>(); 1873 auto assign = assignment->action.as<Assign_t>();
1843 BREAK_IF(!assign); 1874 BREAK_IF(!assign);
@@ -1865,10 +1896,14 @@ private:
1865 } 1896 }
1866 } 1897 }
1867 } 1898 }
1899 if (isRoot && !_info.moduleName.empty()) {
1900 block->statements.push_front(toAst<Statement_t>(_info.moduleName + s(_info.exportDefault ? "=nil"sv : "={}"sv), block));
1901 }
1868 switch (usage) { 1902 switch (usage) {
1869 case ExpUsage::Closure: 1903 case ExpUsage::Closure:
1870 case ExpUsage::Return: { 1904 case ExpUsage::Return: {
1871 BLOCK_START 1905 BLOCK_START
1906 BREAK_IF(isRoot && !_info.moduleName.empty());
1872 BREAK_IF(nodes.empty()); 1907 BREAK_IF(nodes.empty());
1873 auto last = static_cast<Statement_t*>(nodes.back()); 1908 auto last = static_cast<Statement_t*>(nodes.back());
1874 auto x = last; 1909 auto x = last;
@@ -1920,9 +1955,17 @@ private:
1920 } else { 1955 } else {
1921 out.push_back(Empty); 1956 out.push_back(Empty);
1922 } 1957 }
1958 if (isRoot && !_info.moduleName.empty()) {
1959 out.back().append(indent() + s("return "sv) + _info.moduleName + nlr(block));
1960 }
1923 } 1961 }
1924 1962
1925 void transformReturn(Return_t* returnNode, str_list& out) { 1963 void transformReturn(Return_t* returnNode, str_list& out) {
1964 if (!enableReturn.top()) {
1965 ast_node* target = returnNode->valueList.get();
1966 if (!target) target = returnNode;
1967 throw std::logic_error(_info.errorMessage("Illegal return statement here."sv, target));
1968 }
1926 if (auto valueList = returnNode->valueList.get()) { 1969 if (auto valueList = returnNode->valueList.get()) {
1927 if (valueList->exprs.size() == 1) { 1970 if (valueList->exprs.size() == 1) {
1928 auto exp = static_cast<Exp_t*>(valueList->exprs.back()); 1971 auto exp = static_cast<Exp_t*>(valueList->exprs.back());
@@ -3797,33 +3840,33 @@ private:
3797 out.push_back(_parser.toString(const_value)); 3840 out.push_back(_parser.toString(const_value));
3798 } 3841 }
3799 3842
3800 void transformExport(Export_t* exportNode, str_list& out) { 3843 void transformGlobal(Global_t* global, str_list& out) {
3801 auto x = exportNode; 3844 auto x = global;
3802 auto item = exportNode->item.get(); 3845 auto item = global->item.get();
3803 switch (item->getId()) { 3846 switch (item->getId()) {
3804 case id<ClassDecl_t>(): { 3847 case id<ClassDecl_t>(): {
3805 auto classDecl = static_cast<ClassDecl_t*>(item); 3848 auto classDecl = static_cast<ClassDecl_t*>(item);
3806 if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) { 3849 if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) {
3807 markVarExported(ExportMode::Any, true); 3850 markVarGlobal(GlobalMode::Any, true);
3808 addExportedVar(_parser.toString(classDecl->name->item)); 3851 addGlobalVar(_parser.toString(classDecl->name->item));
3809 } 3852 }
3810 transformClassDecl(classDecl, out, ExpUsage::Common); 3853 transformClassDecl(classDecl, out, ExpUsage::Common);
3811 break; 3854 break;
3812 } 3855 }
3813 case id<export_op_t>(): 3856 case id<global_op_t>():
3814 if (_parser.toString(item) == "*"sv) { 3857 if (_parser.toString(item) == "*"sv) {
3815 markVarExported(ExportMode::Any, false); 3858 markVarGlobal(GlobalMode::Any, false);
3816 } else { 3859 } else {
3817 markVarExported(ExportMode::Capital, false); 3860 markVarGlobal(GlobalMode::Capital, false);
3818 } 3861 }
3819 break; 3862 break;
3820 case id<export_values_t>(): { 3863 case id<global_values_t>(): {
3821 markVarExported(ExportMode::Any, true); 3864 markVarGlobal(GlobalMode::Any, true);
3822 auto values = exportNode->item.to<export_values_t>(); 3865 auto values = global->item.to<global_values_t>();
3823 if (values->valueList) { 3866 if (values->valueList) {
3824 auto expList = x->new_ptr<ExpList_t>(); 3867 auto expList = x->new_ptr<ExpList_t>();
3825 for (auto name : values->nameList->names.objects()) { 3868 for (auto name : values->nameList->names.objects()) {
3826 addExportedVar(_parser.toString(name)); 3869 addGlobalVar(_parser.toString(name));
3827 auto callable = x->new_ptr<Callable_t>(); 3870 auto callable = x->new_ptr<Callable_t>();
3828 callable->item.set(name); 3871 callable->item.set(name);
3829 auto chainValue = x->new_ptr<ChainValue_t>(); 3872 auto chainValue = x->new_ptr<ChainValue_t>();
@@ -3842,7 +3885,7 @@ private:
3842 transformAssignment(assignment, out); 3885 transformAssignment(assignment, out);
3843 } else { 3886 } else {
3844 for (auto name : values->nameList->names.objects()) { 3887 for (auto name : values->nameList->names.objects()) {
3845 addExportedVar(_parser.toString(name)); 3888 addGlobalVar(_parser.toString(name));
3846 } 3889 }
3847 } 3890 }
3848 break; 3891 break;
@@ -3851,6 +3894,85 @@ private:
3851 } 3894 }
3852 } 3895 }
3853 3896
3897 void transformExport(Export_t* exportNode, str_list& out) {
3898 auto x = exportNode;
3899 if (_scopes.size() > 1) {
3900 throw std::logic_error(_info.errorMessage("Can not do module export outside root block."sv, x));
3901 }
3902 if (exportNode->assign) {
3903 auto expList = exportNode->target.to<ExpList_t>();
3904 if (expList->exprs.size() != exportNode->assign->values.size()) {
3905 throw std::logic_error(_info.errorMessage("Left and right expressions must be matched in export statement."sv, x));
3906 }
3907 for (auto _exp : expList->exprs.objects()) {
3908 auto exp = static_cast<Exp_t*>(_exp);
3909 if (!variableFrom(exp) &&
3910 !exp->getByPath<Value_t, SimpleValue_t, TableLit_t>() &&
3911 !exp->getByPath<Value_t, simple_table_t>()) {
3912 throw std::logic_error(_info.errorMessage("Left hand expressions must be variables in export statement."sv, x));
3913 }
3914 }
3915 auto assignment = x->new_ptr<ExpListAssign_t>();
3916 assignment->expList.set(expList);
3917 assignment->action.set(exportNode->assign);
3918 transformAssignment(assignment, out);
3919 str_list names = transformAssignDefs(expList, false);
3920 auto info = extractDestructureInfo(assignment, true);
3921 if (!info.first.empty()) {
3922 for (const auto& destruct : info.first)
3923 for (const auto& item : destruct.items)
3924 if (item.isVariable)
3925 names.push_back(item.name);
3926 }
3927 if (_info.exportDefault) {
3928 out.back().append(indent() + _info.moduleName + s(" = "sv) + names.back() + nlr(exportNode));
3929 } else {
3930 str_list lefts, rights;
3931 for (const auto& name : names) {
3932 lefts.push_back(_info.moduleName + s("[\""sv) + name + s("\"]"sv));
3933 rights.push_back(name);
3934 }
3935 out.back().append(indent() + join(lefts,", "sv) + s(" = "sv) + join(rights, ", "sv) + nlr(exportNode));
3936 }
3937 } else {
3938 if (_info.exportDefault) {
3939 auto exp = exportNode->target.to<Exp_t>();
3940 auto assignment = x->new_ptr<ExpListAssign_t>();
3941 assignment->expList.set(toAst<ExpList_t>(_info.moduleName, x));
3942 auto assign = x->new_ptr<Assign_t>();
3943 assign->values.push_back(exp);
3944 assignment->action.set(assign);
3945 transformAssignment(assignment, out);
3946 } else {
3947 str_list temp;
3948 auto expList = exportNode->target.to<ExpList_t>();
3949 auto assignment = x->new_ptr<ExpListAssign_t>();
3950 auto assignList = toAst<ExpList_t>(_info.moduleName + s("[#"sv) + _info.moduleName + s("+1]"sv), x);
3951 assignment->expList.set(assignList);
3952 for (auto exp : expList->exprs.objects()) {
3953 if (auto classDecl = exp->getByPath<Value_t, SimpleValue_t, ClassDecl_t>()) {
3954 if (classDecl->name && classDecl->name->item->getId() == id<Variable_t>()) {
3955 transformClassDecl(classDecl, temp, ExpUsage::Common);
3956 auto name = _parser.toString(classDecl->name->item);
3957 assignment->expList.set(toAst<ExpList_t>(_info.moduleName + s("[\""sv) + name + s("\"]"sv), x));
3958 auto assign = x->new_ptr<Assign_t>();
3959 assign->values.push_back(toAst<Exp_t>(name, x));
3960 assignment->action.set(assign);
3961 transformAssignment(assignment, temp);
3962 assignment->expList.set(assignList);
3963 continue;
3964 }
3965 }
3966 auto assign = x->new_ptr<Assign_t>();
3967 assign->values.push_back(exp);
3968 assignment->action.set(assign);
3969 transformAssignment(assignment, temp);
3970 }
3971 out.push_back(join(temp));
3972 }
3973 }
3974 }
3975
3854 void transformTable(ast_node* table, const node_container& pairs, str_list& out) { 3976 void transformTable(ast_node* table, const node_container& pairs, str_list& out) {
3855 if (pairs.empty()) { 3977 if (pairs.empty()) {
3856 out.push_back(s("{ }"sv)); 3978 out.push_back(s("{ }"sv));
diff --git a/src/MoonP/moon_parser.cpp b/src/MoonP/moon_parser.cpp
index fecf869..baa8eff 100644
--- a/src/MoonP/moon_parser.cpp
+++ b/src/MoonP/moon_parser.cpp
@@ -28,8 +28,8 @@ std::unordered_set<std::string> Keywords = {
28 "repeat", "return", "then", "true", "until", 28 "repeat", "return", "then", "true", "until",
29 "while", // Lua keywords 29 "while", // Lua keywords
30 "as", "class", "continue", "export", "extends", 30 "as", "class", "continue", "export", "extends",
31 "from", "import", "switch", "unless", "using", 31 "from", "global", "import", "switch", "unless",
32 "when", "with" // Moon keywords 32 "using", "when", "with" // Moon keywords
33}; 33};
34 34
35MoonParser::MoonParser() { 35MoonParser::MoonParser() {
@@ -74,9 +74,15 @@ MoonParser::MoonParser() {
74 Variable = pl::user(Name, [](const item_t& item) { 74 Variable = pl::user(Name, [](const item_t& item) {
75 State* st = reinterpret_cast<State*>(item.user_data); 75 State* st = reinterpret_cast<State*>(item.user_data);
76 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it); 76 for (auto it = item.begin; it != item.end; ++it) st->buffer += static_cast<char>(*it);
77 auto it = Keywords.find(st->buffer); 77 auto isValid = Keywords.find(st->buffer) == Keywords.end();
78 if (isValid) {
79 if (st->buffer == st->moduleName) {
80 st->moduleFix++;
81 st->moduleName = std::string("_module_"sv) + std::to_string(st->moduleFix);
82 }
83 }
78 st->buffer.clear(); 84 st->buffer.clear();
79 return it == Keywords.end(); 85 return isValid;
80 }); 86 });
81 87
82 LuaKeyword = pl::user(Name, [](const item_t& item) { 88 LuaKeyword = pl::user(Name, [](const item_t& item) {
@@ -153,7 +159,7 @@ MoonParser::MoonParser() {
153 return true; 159 return true;
154 }); 160 });
155 161
156 InBlock = Advance >> Block >> PopIndent; 162 InBlock = Advance >> ensure(Block, PopIndent);
157 163
158 local_flag = expr('*') | expr('^'); 164 local_flag = expr('*') | expr('^');
159 Local = key("local") >> ((Space >> local_flag) | NameList); 165 Local = key("local") >> ((Space >> local_flag) | NameList);
@@ -211,21 +217,18 @@ MoonParser::MoonParser() {
211 DisableDo >> ensure(for_in, PopDo) >> 217 DisableDo >> ensure(for_in, PopDo) >>
212 -key("do") >> Body; 218 -key("do") >> Body;
213 219
214 Do = pl::user(key("do") >> Body, [](const item_t& item) 220 Do = pl::user(key("do"), [](const item_t& item) {
215 {
216 State* st = reinterpret_cast<State*>(item.user_data); 221 State* st = reinterpret_cast<State*>(item.user_data);
217 return st->doStack.empty() || st->doStack.top(); 222 return st->doStack.empty() || st->doStack.top();
218 }); 223 }) >> Body;
219 224
220 DisableDo = pl::user(true_(), [](const item_t& item) 225 DisableDo = pl::user(true_(), [](const item_t& item) {
221 {
222 State* st = reinterpret_cast<State*>(item.user_data); 226 State* st = reinterpret_cast<State*>(item.user_data);
223 st->doStack.push(false); 227 st->doStack.push(false);
224 return true; 228 return true;
225 }); 229 });
226 230
227 PopDo = pl::user(true_(), [](const item_t& item) 231 PopDo = pl::user(true_(), [](const item_t& item) {
228 {
229 State* st = reinterpret_cast<State*>(item.user_data); 232 State* st = reinterpret_cast<State*>(item.user_data);
230 st->doStack.pop(); 233 st->doStack.pop();
231 return true; 234 return true;
@@ -312,11 +315,7 @@ MoonParser::MoonParser() {
312 315
313 LuaStringContent = *(not_(LuaStringClose) >> Any); 316 LuaStringContent = *(not_(LuaStringClose) >> Any);
314 317
315 LuaString = pl::user(LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose, [](const item_t& item) { 318 LuaString = LuaStringOpen >> -Break >> LuaStringContent >> LuaStringClose;
316 State* st = reinterpret_cast<State*>(item.user_data);
317 st->stringOpen = -1;
318 return true;
319 });
320 319
321 Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')'); 320 Parens = sym('(') >> *SpaceBreak >> Exp >> *SpaceBreak >> sym(')');
322 Callable = Space >> Variable | SelfName | VarArg | Parens; 321 Callable = Space >> Variable | SelfName | VarArg | Parens;
@@ -392,9 +391,30 @@ MoonParser::MoonParser() {
392 -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >> 391 -(key("extends") >> PreventIndent >> ensure(Exp, PopIndent)) >>
393 -ClassBlock; 392 -ClassBlock;
394 393
395 export_values = NameList >> -(sym('=') >> ExpListLow); 394 global_values = NameList >> -(sym('=') >> ExpListLow);
396 export_op = expr('*') | expr('^'); 395 global_op = expr('*') | expr('^');
397 Export = key("export") >> (ClassDecl | (Space >> export_op) | export_values); 396 Global = key("global") >> (ClassDecl | (Space >> global_op) | global_values);
397
398 export_default = key("default");
399
400 Export = pl::user(key("export"), [](const item_t& item) {
401 State* st = reinterpret_cast<State*>(item.user_data);
402 st->exportCount++;
403 return true;
404 }) >> ((pl::user(export_default, [](const item_t& item) {
405 State* st = reinterpret_cast<State*>(item.user_data);
406 bool isValid = !st->exportDefault && st->exportCount == 1;
407 st->exportDefault = true;
408 return isValid;
409 }) >> Exp)
410 | (pl::user(true_(), [](const item_t& item) {
411 State* st = reinterpret_cast<State*>(item.user_data);
412 if (st->exportDefault && st->exportCount > 1) {
413 return false;
414 } else {
415 return true;
416 }
417 }) >> ExpList >> -Assign)) >> not_(Space >> statement_appendix);
398 418
399 variable_pair = sym(':') >> Variable; 419 variable_pair = sym(':') >> Variable;
400 420
@@ -479,12 +499,12 @@ MoonParser::MoonParser() {
479 statement_appendix = (if_else_line | unless_line | CompInner) >> Space; 499 statement_appendix = (if_else_line | unless_line | CompInner) >> Space;
480 Statement = ( 500 Statement = (
481 Import | While | For | ForEach | 501 Import | While | For | ForEach |
482 Return | Local | Export | Space >> BreakLoop | 502 Return | Local | Global | Export | Space >> BreakLoop |
483 Backcall | ExpListAssign 503 Backcall | ExpListAssign
484 ) >> Space >> 504 ) >> Space >>
485 -statement_appendix; 505 -statement_appendix;
486 506
487 Body = -Space >> Break >> *EmptyLine >> InBlock | Statement; 507 Body = Space >> Break >> *EmptyLine >> InBlock | Statement;
488 508
489 empty_line_stop = Space >> and_(Stop); 509 empty_line_stop = Space >> and_(Stop);
490 Line = CheckIndent >> Statement | empty_line_stop; 510 Line = CheckIndent >> Statement | empty_line_stop;
@@ -498,7 +518,7 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) {
498 ParseInfo res; 518 ParseInfo res;
499 try { 519 try {
500 res.codes = std::make_unique<input>(); 520 res.codes = std::make_unique<input>();
501 *(res.codes) = _converter.from_bytes(codes.begin(), codes.end()); 521 *(res.codes) = _converter.from_bytes(&codes.front(), &codes.back() + 1);
502 } catch (const std::range_error&) { 522 } catch (const std::range_error&) {
503 res.error = "Invalid text encoding."sv; 523 res.error = "Invalid text encoding."sv;
504 return res; 524 return res;
@@ -507,6 +527,10 @@ ParseInfo MoonParser::parse(std::string_view codes, rule& r) {
507 try { 527 try {
508 State state; 528 State state;
509 res.node.set(pl::parse(*(res.codes), r, errors, &state)); 529 res.node.set(pl::parse(*(res.codes), r, errors, &state));
530 if (state.exportCount > 0) {
531 res.moduleName = std::move(state.moduleName);
532 res.exportDefault = state.exportDefault;
533 }
510 } catch (const std::logic_error& err) { 534 } catch (const std::logic_error& err) {
511 res.error = err.what(); 535 res.error = err.what();
512 return res; 536 return res;
@@ -538,7 +562,7 @@ std::string MoonParser::toString(input::iterator begin, input::iterator end) {
538} 562}
539 563
540input MoonParser::encode(std::string_view codes) { 564input MoonParser::encode(std::string_view codes) {
541 return _converter.from_bytes(codes.begin(), codes.end()); 565 return _converter.from_bytes(&codes.front(), &codes.back() + 1);
542} 566}
543 567
544std::string MoonParser::decode(const input& codes) { 568std::string MoonParser::decode(const input& codes) {
@@ -572,7 +596,6 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc
572 count++; 596 count++;
573 } 597 }
574 } 598 }
575 auto line = Converter{}.to_bytes(std::wstring(begin, end));
576 int oldCol = loc->m_begin.m_col; 599 int oldCol = loc->m_begin.m_col;
577 int col = std::max(0, oldCol - 1); 600 int col = std::max(0, oldCol - 1);
578 auto it = begin; 601 auto it = begin;
@@ -582,6 +605,7 @@ std::string ParseInfo::errorMessage(std::string_view msg, const input_range* loc
582 } 605 }
583 ++it; 606 ++it;
584 } 607 }
608 auto line = Converter{}.to_bytes(std::wstring(begin, end));
585 Utils::replace(line, "\t"sv, " "sv); 609 Utils::replace(line, "\t"sv, " "sv);
586 std::ostringstream buf; 610 std::ostringstream buf;
587 buf << loc->m_begin.m_line << ": "sv << msg << 611 buf << loc->m_begin.m_line << ": "sv << msg <<
diff --git a/src/MoonP/moon_parser.h b/src/MoonP/moon_parser.h
index 12f735b..eefcba5 100644
--- a/src/MoonP/moon_parser.h
+++ b/src/MoonP/moon_parser.h
@@ -26,6 +26,8 @@ struct ParseInfo {
26 ast_ptr<false, ast_node> node; 26 ast_ptr<false, ast_node> node;
27 std::string error; 27 std::string error;
28 std::unique_ptr<input> codes; 28 std::unique_ptr<input> codes;
29 bool exportDefault = false;
30 std::string moduleName;
29 std::string errorMessage(std::string_view msg, const input_range* loc) const; 31 std::string errorMessage(std::string_view msg, const input_range* loc) const;
30}; 32};
31 33
@@ -72,10 +74,13 @@ protected:
72 struct State { 74 struct State {
73 State() { 75 State() {
74 indents.push(0); 76 indents.push(0);
75 stringOpen = -1;
76 } 77 }
78 bool exportDefault = false;
79 int exportCount = 0;
80 int moduleFix = 0;
81 size_t stringOpen = 0;
82 std::string moduleName = "_module_0";
77 std::string buffer; 83 std::string buffer;
78 size_t stringOpen;
79 std::stack<int> indents; 84 std::stack<int> indents;
80 std::stack<bool> doStack; 85 std::stack<bool> doStack;
81 }; 86 };
@@ -124,8 +129,8 @@ private:
124 rule ImportNameList; 129 rule ImportNameList;
125 rule import_literal_chain; 130 rule import_literal_chain;
126 rule WithExp; 131 rule WithExp;
127 rule PopDo;
128 rule DisableDo; 132 rule DisableDo;
133 rule PopDo;
129 rule SwitchElse; 134 rule SwitchElse;
130 rule SwitchBlock; 135 rule SwitchBlock;
131 rule IfElseIf; 136 rule IfElseIf;
@@ -181,9 +186,9 @@ private:
181 AST_RULE(SelfName) 186 AST_RULE(SelfName)
182 AST_RULE(KeyName) 187 AST_RULE(KeyName)
183 AST_RULE(VarArg) 188 AST_RULE(VarArg)
184 AST_RULE(local_flag)
185 AST_RULE(Seperator) 189 AST_RULE(Seperator)
186 AST_RULE(NameList) 190 AST_RULE(NameList)
191 AST_RULE(local_flag)
187 AST_RULE(Local) 192 AST_RULE(Local)
188 AST_RULE(colon_import_name) 193 AST_RULE(colon_import_name)
189 AST_RULE(import_literal_inner) 194 AST_RULE(import_literal_inner)
@@ -249,8 +254,10 @@ private:
249 AST_RULE(class_member_list) 254 AST_RULE(class_member_list)
250 AST_RULE(ClassBlock) 255 AST_RULE(ClassBlock)
251 AST_RULE(ClassDecl) 256 AST_RULE(ClassDecl)
252 AST_RULE(export_values) 257 AST_RULE(global_values)
253 AST_RULE(export_op) 258 AST_RULE(global_op)
259 AST_RULE(Global)
260 AST_RULE(export_default)
254 AST_RULE(Export) 261 AST_RULE(Export)
255 AST_RULE(variable_pair) 262 AST_RULE(variable_pair)
256 AST_RULE(normal_pair) 263 AST_RULE(normal_pair)
diff --git a/src/moonp.cpp b/src/moonp.cpp
index ade1a1b..8026d50 100644
--- a/src/moonp.cpp
+++ b/src/moonp.cpp
@@ -81,10 +81,10 @@ int main(int narg, const char** args) {
81 if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') { 81 if (!targetPath.empty() && targetPath.back() != '/' && targetPath.back() != '\\') {
82 targetPath.append("/"); 82 targetPath.append("/");
83 } 83 }
84 std::list<std::future<std::result_of_t<std::decay_t<int()>()>>> results; 84 std::list<std::future<int>> results;
85 for (const auto& file : files) { 85 for (const auto& file : files) {
86 auto task = std::async(std::launch::async, [=]() { 86 auto task = std::async(std::launch::async, [=]() {
87 std::ifstream input(file, input.in); 87 std::ifstream input(file, std::ios::in);
88 if (input) { 88 if (input) {
89 std::string s( 89 std::string s(
90 (std::istreambuf_iterator<char>(input)), 90 (std::istreambuf_iterator<char>(input)),
@@ -135,7 +135,7 @@ int main(int narg, const char** args) {
135 } else { 135 } else {
136 targetFile = resultFile; 136 targetFile = resultFile;
137 } 137 }
138 std::ofstream output(targetFile, output.trunc | output.out); 138 std::ofstream output(targetFile, std::ios::trunc | std::ios::out);
139 if (output) { 139 if (output) {
140 const auto& codes = std::get<0>(result); 140 const auto& codes = std::get<0>(result);
141 output.write(codes.c_str(), codes.size()); 141 output.write(codes.c_str(), codes.size());