├── .gitignore ├── Development ├── CSharpCodegenTest │ ├── MultipleDispatchAst │ │ ├── App.config │ │ ├── MultipleDispatchAst.csproj │ │ └── Properties │ │ │ └── AssemblyInfo.cs │ ├── StandardLibraryAst │ │ ├── App.config │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ └── StandardLibraryAst.csproj │ ├── TinymoeDotNet │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── TinymoeDotNet.csproj │ │ └── TinymoeObject.cs │ ├── UnitTestAst │ │ ├── App.config │ │ ├── Properties │ │ │ └── AssemblyInfo.cs │ │ ├── UnitTestAst.csproj │ │ └── UnitTestAst.csproj.user │ └── YieldReturnAst │ │ ├── App.config │ │ ├── Properties │ │ └── AssemblyInfo.cs │ │ └── YieldReturnAst.csproj ├── Draft │ ├── CounterRepeat.txt │ ├── Repeat.txt │ ├── TryCatch.txt │ └── TryResume.txt ├── Library │ └── StandardLibrary.txt ├── Source │ ├── Ast │ │ ├── TinymoeAst.cpp │ │ ├── TinymoeAst.h │ │ ├── TinymoeAst_CollectSideEffectExpressions.cpp │ │ ├── TinymoeAst_CollectUsedVariables.cpp │ │ ├── TinymoeAst_ExpandBlock.cpp │ │ ├── TinymoeAst_GetRootLeftValue.cpp │ │ ├── TinymoeAst_Print.cpp │ │ ├── TinymoeAst_RemoveUnnecessaryVariables.cpp │ │ ├── TinymoeAst_RoughlyOptimize.cpp │ │ └── TinymoeAst_SetParent.cpp │ ├── Compiler │ │ ├── TinymoeAstCodegen.cpp │ │ ├── TinymoeAstCodegen.h │ │ ├── TinymoeAstCodegen_Declaration.cpp │ │ ├── TinymoeAstCodegen_Expression.cpp │ │ ├── TinymoeAstCodegen_Statement.cpp │ │ ├── TinymoeDeclarationAnalyzer.cpp │ │ ├── TinymoeDeclarationAnalyzer.h │ │ ├── TinymoeExpressionAnalyzer.cpp │ │ ├── TinymoeExpressionAnalyzer.h │ │ ├── TinymoeLexicalAnalyzer.cpp │ │ ├── TinymoeLexicalAnalyzer.h │ │ ├── TinymoeStatementAnalyzer.cpp │ │ └── TinymoeStatementAnalyzer.h │ ├── Tinymoe.cpp │ ├── Tinymoe.h │ └── TinymoeSTL.h ├── TestCases │ ├── Coroutine.txt │ ├── HelloWorld.txt │ ├── MultipleDispatch.txt │ └── UnitTest.txt ├── Tinymoe.sln └── TinymoeUnitTest │ ├── CSharpCodegen.cpp │ ├── Main.cpp │ ├── TestAstCodegen.cpp │ ├── TestDeclarationAnalyzer.cpp │ ├── TestExpressionAnalyzer.cpp │ ├── TestLexicalAnalyzer.cpp │ ├── TestStatementAnalyzer.cpp │ ├── TinymoeUnitTest.vcxproj │ ├── TinymoeUnitTest.vcxproj.filters │ ├── TinymoeUnitTest.vcxproj.user │ ├── TinymoeUnitTest.vcxproj.vspscc │ ├── UnitTest.cpp │ ├── UnitTest.h │ └── makefile ├── Docx ├── vczhcp-0.docx ├── vczhcp-1.docx ├── vczhcp-2.docx └── vczhcp-3.docx └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | *.sdf 2 | *.suo 3 | *.opensdf 4 | **/Debug/** 5 | **/Release/** 6 | **/Bin/** 7 | *.test.txt 8 | ~$*.docx 9 | ~*.tmp 10 | *~ 11 | *.o 12 | GeneratedAst.txt 13 | TinymoeProgram.cs 14 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/MultipleDispatchAst/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/MultipleDispatchAst/MultipleDispatchAst.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6} 8 | Exe 9 | Properties 10 | MultipleDispatchAst 11 | MultipleDispatchAst 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {c38641b3-0b11-40be-98b2-31ef800926ac} 53 | TinymoeDotNet 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/MultipleDispatchAst/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("MultipleDispatchAst")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft IT")] 12 | [assembly: AssemblyProduct("MultipleDispatchAst")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft IT 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("a5292d56-1390-4475-892d-a9c979fc8641")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/StandardLibraryAst/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/StandardLibraryAst/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("StandardLibraryAst")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft IT")] 12 | [assembly: AssemblyProduct("StandardLibraryAst")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft IT 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("0345342f-5178-41c5-8af3-28464085d456")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/StandardLibraryAst/StandardLibraryAst.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E} 8 | Exe 9 | Properties 10 | StandardLibraryAst 11 | StandardLibraryAst 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {c38641b3-0b11-40be-98b2-31ef800926ac} 53 | TinymoeDotNet 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/TinymoeDotNet/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("TinymoeDotNet")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft IT")] 12 | [assembly: AssemblyProduct("TinymoeDotNet")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft IT 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("858627e2-6b7f-4895-bffc-4922080126b2")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/TinymoeDotNet/TinymoeDotNet.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {C38641B3-0B11-40BE-98B2-31EF800926AC} 8 | Library 9 | Properties 10 | TinymoeDotNet 11 | TinymoeDotNet 12 | v4.5 13 | 512 14 | 15 | 16 | true 17 | full 18 | false 19 | bin\Debug\ 20 | DEBUG;TRACE 21 | prompt 22 | 4 23 | 24 | 25 | pdbonly 26 | true 27 | bin\Release\ 28 | TRACE 29 | prompt 30 | 4 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 53 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/UnitTestAst/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/UnitTestAst/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("UnitTestAst")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("")] 12 | [assembly: AssemblyProduct("UnitTestAst")] 13 | [assembly: AssemblyCopyright("Copyright © 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("bb8e6250-56eb-457a-9eb2-6ea31768c3f5")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/UnitTestAst/UnitTestAst.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678} 8 | Exe 9 | Properties 10 | UnitTestAst 11 | UnitTestAst 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {c38641b3-0b11-40be-98b2-31ef800926ac} 53 | TinymoeDotNet 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/UnitTestAst/UnitTestAst.csproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | ProjectFiles 5 | 6 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/YieldReturnAst/App.config: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | 6 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/YieldReturnAst/Properties/AssemblyInfo.cs: -------------------------------------------------------------------------------- 1 | using System.Reflection; 2 | using System.Runtime.CompilerServices; 3 | using System.Runtime.InteropServices; 4 | 5 | // General Information about an assembly is controlled through the following 6 | // set of attributes. Change these attribute values to modify the information 7 | // associated with an assembly. 8 | [assembly: AssemblyTitle("YieldReturnAst")] 9 | [assembly: AssemblyDescription("")] 10 | [assembly: AssemblyConfiguration("")] 11 | [assembly: AssemblyCompany("Microsoft IT")] 12 | [assembly: AssemblyProduct("YieldReturnAst")] 13 | [assembly: AssemblyCopyright("Copyright © Microsoft IT 2014")] 14 | [assembly: AssemblyTrademark("")] 15 | [assembly: AssemblyCulture("")] 16 | 17 | // Setting ComVisible to false makes the types in this assembly not visible 18 | // to COM components. If you need to access a type in this assembly from 19 | // COM, set the ComVisible attribute to true on that type. 20 | [assembly: ComVisible(false)] 21 | 22 | // The following GUID is for the ID of the typelib if this project is exposed to COM 23 | [assembly: Guid("cd04207a-42f6-4982-8d1a-0badb1000614")] 24 | 25 | // Version information for an assembly consists of the following four values: 26 | // 27 | // Major Version 28 | // Minor Version 29 | // Build Number 30 | // Revision 31 | // 32 | // You can specify all the values or you can default the Build and Revision Numbers 33 | // by using the '*' as shown below: 34 | // [assembly: AssemblyVersion("1.0.*")] 35 | [assembly: AssemblyVersion("1.0.0.0")] 36 | [assembly: AssemblyFileVersion("1.0.0.0")] 37 | -------------------------------------------------------------------------------- /Development/CSharpCodegenTest/YieldReturnAst/YieldReturnAst.csproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | AnyCPU 7 | {850F7E6F-7C55-4242-832E-F677E1224B56} 8 | Exe 9 | Properties 10 | YieldReturnAst 11 | YieldReturnAst 12 | v4.5 13 | 512 14 | 15 | 16 | AnyCPU 17 | true 18 | full 19 | false 20 | bin\Debug\ 21 | DEBUG;TRACE 22 | prompt 23 | 4 24 | 25 | 26 | AnyCPU 27 | pdbonly 28 | true 29 | bin\Release\ 30 | TRACE 31 | prompt 32 | 4 33 | 34 | 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | {c38641b3-0b11-40be-98b2-31ef800926ac} 53 | TinymoeDotNet 54 | 55 | 56 | 57 | 64 | -------------------------------------------------------------------------------- /Development/Draft/CounterRepeat.txt: -------------------------------------------------------------------------------- 1 | cps (state) 2 | block (sentence body) repeat (count) times 3 | set counter to 0 4 | repeat while counter < count 5 | body 6 | if field flag of state <> continuing repeating 7 | if field flag of state <> exiting function 8 | set continuation state state to null 9 | end 10 | break 11 | end 12 | add 1 to counter 13 | end 14 | end 15 | 16 | ============================================ 17 | 18 | function repeat_$expression_times($state, body, $continuation) 19 | { 20 | var counter = 0; 21 | repeat( 22 | $state, 23 | function ($state, $continuation_1) 24 | { 25 | body( 26 | $state, 27 | function ($state) 28 | { 29 | if_$expression( 30 | $state, 31 | function ($state, $continuation_2) 32 | { 33 | if_$expression( 34 | $state, 35 | function ($state, $continuation_3) 36 | { 37 | set_continuation_state_$expression_to $expression( 38 | $state, 39 | null, 40 | $continuation_3 41 | ); 42 | }, 43 | function ($state, $signal) 44 | { 45 | break( 46 | $state, 47 | $continuation_2 48 | ); 49 | } 50 | ); 51 | }, 52 | function ($state, $signal) 53 | { 54 | counter = counter + 1; 55 | $continuation_1($state); 56 | } 57 | ); 58 | } 59 | ); 60 | }, 61 | $continuation 62 | ); 63 | } -------------------------------------------------------------------------------- /Development/Draft/Repeat.txt: -------------------------------------------------------------------------------- 1 | cps (state) 2 | block (body) repeat : repeat statement 3 | call invoke body with (state) 4 | select field flag of state 5 | case breaking repeating 6 | reset continuation state state to null 7 | case continuing repeating 8 | reset continuation state state to null 9 | tail call invoke repeat statement with (state, body) 10 | end 11 | end 12 | 13 | ============================================ 14 | 15 | function repeat($state, body, $continuation) 16 | { 17 | body( 18 | $state, 19 | function ($state) 20 | { 21 | if($state.flag == breaking_repeating) 22 | { 23 | reset_continuation_state_$expression_to_$expression( 24 | &state, 25 | null, 26 | $continuation 27 | ); 28 | } 29 | else if($state.flag == continuing_repeating) 30 | { 31 | reset_continuation_state_$expression_to_$expression( 32 | &state, 33 | null, 34 | function ($state) 35 | { 36 | repeat($state, body, $continuation); 37 | } 38 | ); 39 | } 40 | } 41 | ); 42 | } -------------------------------------------------------------------------------- /Development/Draft/TryCatch.txt: -------------------------------------------------------------------------------- 1 | phrase main 2 | try 3 | set a to 1 4 | set b to 0 5 | set c = a / b 6 | catch the exception 7 | print the exception 8 | end 9 | end 10 | 11 | ============================================ 12 | 13 | function main($state, $continuation) 14 | { 15 | try( 16 | $state, 17 | function ($state, $continuation_1) 18 | { 19 | var a = 1; 20 | var b = 0; 21 | var c = a / b; 22 | $continuation_1($state); 23 | }, 24 | function ($state, $signal) 25 | { 26 | catch_$expression( 27 | $state, 28 | $signal, 29 | function ($state, $signal, the_exception, $continuation_2) 30 | { 31 | print_$expression( 32 | $state, 33 | the_exception, 34 | $$continuation_2 35 | ); 36 | }, 37 | $continuation 38 | ); 39 | } 40 | ); 41 | } -------------------------------------------------------------------------------- /Development/Draft/TryResume.txt: -------------------------------------------------------------------------------- 1 | block (sentence body) do 2 | try 3 | body 4 | print "Succeed!" 5 | catch the exception 6 | print the exception 7 | end 8 | end 9 | 10 | phrase main 11 | do 12 | set a to 1 13 | set b to 0 14 | set c to a / b 15 | end 16 | end 17 | 18 | ============================================ 19 | 20 | function do($state, body, $continuation) 21 | { 22 | try( 23 | $state, 24 | function ($state, $continuation_1) 25 | { 26 | body( 27 | $state, 28 | function ($state) 29 | { 30 | print_$expression( 31 | $state, 32 | "Succeed!", 33 | $continuation_1 34 | ); 35 | } 36 | ); 37 | }, 38 | function ($state, $signal) 39 | { 40 | catch_$expression( 41 | $state, 42 | $signal, 43 | function ($state, $signal, the_exception, $continuation_2) 44 | { 45 | print_$expression( 46 | $state, 47 | the_exception, 48 | $continuation_2 49 | ); 50 | }, 51 | $continuation 52 | ); 53 | } 54 | ); 55 | } 56 | 57 | function main($state, $continuation) 58 | { 59 | do( 60 | $state, 61 | function ($state) 62 | { 63 | var a = 1; 64 | var b = 0; 65 | var c = a / b; 66 | }, 67 | $continuation 68 | ); 69 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstNode 9 | *************************************************************/ 10 | 11 | AstNode::AstNode() 12 | { 13 | } 14 | 15 | AstNode::~AstNode() 16 | { 17 | } 18 | 19 | /************************************************************* 20 | Visitor 21 | *************************************************************/ 22 | 23 | AstVisitor::AstVisitor() 24 | { 25 | } 26 | 27 | AstVisitor::~AstVisitor() 28 | { 29 | } 30 | 31 | AstTypeVisitor::AstTypeVisitor() 32 | { 33 | } 34 | 35 | AstTypeVisitor::~AstTypeVisitor() 36 | { 37 | } 38 | 39 | AstExpressionVisitor::AstExpressionVisitor() 40 | { 41 | } 42 | 43 | AstExpressionVisitor::~AstExpressionVisitor() 44 | { 45 | } 46 | 47 | AstStatementVisitor::AstStatementVisitor() 48 | { 49 | } 50 | 51 | AstStatementVisitor::~AstStatementVisitor() 52 | { 53 | } 54 | 55 | AstDeclarationVisitor::AstDeclarationVisitor() 56 | { 57 | } 58 | 59 | AstDeclarationVisitor::~AstDeclarationVisitor() 60 | { 61 | } 62 | 63 | /************************************************************* 64 | Node 65 | *************************************************************/ 66 | 67 | void AstType::Accept(AstVisitor* visitor) 68 | { 69 | visitor->Visit(this); 70 | } 71 | 72 | void AstExpression::Accept(AstVisitor* visitor) 73 | { 74 | visitor->Visit(this); 75 | } 76 | 77 | void AstStatement::Accept(AstVisitor* visitor) 78 | { 79 | visitor->Visit(this); 80 | } 81 | 82 | void AstDeclaration::Accept(AstVisitor* visitor) 83 | { 84 | visitor->Visit(this); 85 | } 86 | 87 | void AstAssembly::Accept(AstVisitor* visitor) 88 | { 89 | visitor->Visit(this); 90 | } 91 | 92 | /************************************************************* 93 | Type 94 | *************************************************************/ 95 | 96 | void AstPredefinedType::Accept(AstTypeVisitor* visitor) 97 | { 98 | visitor->Visit(this); 99 | } 100 | 101 | void AstReferenceType::Accept(AstTypeVisitor* visitor) 102 | { 103 | visitor->Visit(this); 104 | } 105 | 106 | /************************************************************* 107 | Expression 108 | *************************************************************/ 109 | 110 | void AstLiteralExpression::Accept(AstExpressionVisitor* visitor) 111 | { 112 | visitor->Visit(this); 113 | } 114 | 115 | void AstIntegerExpression::Accept(AstExpressionVisitor* visitor) 116 | { 117 | visitor->Visit(this); 118 | } 119 | 120 | void AstFloatExpression::Accept(AstExpressionVisitor* visitor) 121 | { 122 | visitor->Visit(this); 123 | } 124 | 125 | void AstStringExpression::Accept(AstExpressionVisitor* visitor) 126 | { 127 | visitor->Visit(this); 128 | } 129 | 130 | void AstExternalSymbolExpression::Accept(AstExpressionVisitor* visitor) 131 | { 132 | visitor->Visit(this); 133 | } 134 | 135 | void AstReferenceExpression::Accept(AstExpressionVisitor* visitor) 136 | { 137 | visitor->Visit(this); 138 | } 139 | 140 | void AstNewTypeExpression::Accept(AstExpressionVisitor* visitor) 141 | { 142 | visitor->Visit(this); 143 | } 144 | 145 | void AstTestTypeExpression::Accept(AstExpressionVisitor* visitor) 146 | { 147 | visitor->Visit(this); 148 | } 149 | 150 | void AstNewArrayExpression::Accept(AstExpressionVisitor* visitor) 151 | { 152 | visitor->Visit(this); 153 | } 154 | 155 | void AstNewArrayLiteralExpression::Accept(AstExpressionVisitor* visitor) 156 | { 157 | visitor->Visit(this); 158 | } 159 | 160 | void AstArrayLengthExpression::Accept(AstExpressionVisitor* visitor) 161 | { 162 | visitor->Visit(this); 163 | } 164 | 165 | void AstArrayAccessExpression::Accept(AstExpressionVisitor* visitor) 166 | { 167 | visitor->Visit(this); 168 | } 169 | 170 | void AstFieldAccessExpression::Accept(AstExpressionVisitor* visitor) 171 | { 172 | visitor->Visit(this); 173 | } 174 | 175 | void AstInvokeExpression::Accept(AstExpressionVisitor* visitor) 176 | { 177 | visitor->Visit(this); 178 | } 179 | 180 | void AstLambdaExpression::Accept(AstExpressionVisitor* visitor) 181 | { 182 | visitor->Visit(this); 183 | } 184 | 185 | /************************************************************* 186 | Statement 187 | *************************************************************/ 188 | 189 | void AstBlockStatement::Accept(AstStatementVisitor* visitor) 190 | { 191 | visitor->Visit(this); 192 | } 193 | 194 | void AstExpressionStatement::Accept(AstStatementVisitor* visitor) 195 | { 196 | visitor->Visit(this); 197 | } 198 | 199 | void AstDeclarationStatement::Accept(AstStatementVisitor* visitor) 200 | { 201 | visitor->Visit(this); 202 | } 203 | 204 | void AstAssignmentStatement::Accept(AstStatementVisitor* visitor) 205 | { 206 | visitor->Visit(this); 207 | } 208 | 209 | void AstIfStatement::Accept(AstStatementVisitor* visitor) 210 | { 211 | visitor->Visit(this); 212 | } 213 | 214 | /************************************************************* 215 | Declaration 216 | *************************************************************/ 217 | 218 | void AstSymbolDeclaration::Accept(AstDeclarationVisitor* visitor) 219 | { 220 | visitor->Visit(this); 221 | } 222 | 223 | void AstTypeDeclaration::Accept(AstDeclarationVisitor* visitor) 224 | { 225 | visitor->Visit(this); 226 | } 227 | 228 | void AstFunctionDeclaration::Accept(AstDeclarationVisitor* visitor) 229 | { 230 | visitor->Visit(this); 231 | } 232 | 233 | } 234 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_AST_TINYMOEAST 2 | #define VCZH_AST_TINYMOEAST 3 | 4 | #include "../TinymoeSTL.h" 5 | 6 | namespace tinymoe 7 | { 8 | namespace ast 9 | { 10 | /************************************************************* 11 | Common 12 | *************************************************************/ 13 | 14 | class AstType; 15 | class AstExpression; 16 | class AstStatement; 17 | class AstDeclaration; 18 | 19 | class AstVisitor; 20 | class AstTypeVisitor; 21 | class AstExpressionVisitor; 22 | class AstStatementVisitor; 23 | class AstDeclarationVisitor; 24 | 25 | class AstNode : public enable_shared_from_this 26 | { 27 | public: 28 | typedef shared_ptr Ptr; 29 | typedef weak_ptr WeakPtr; 30 | 31 | WeakPtr parent; 32 | 33 | AstNode(); 34 | virtual ~AstNode(); 35 | 36 | virtual void Accept(AstVisitor* visitor) = 0; 37 | }; 38 | 39 | class AstType : public AstNode 40 | { 41 | public: 42 | typedef shared_ptr Ptr; 43 | typedef weak_ptr WeakPtr; 44 | typedef vector List; 45 | 46 | void Accept(AstVisitor* visitor)override; 47 | virtual void Accept(AstTypeVisitor* visitor) = 0; 48 | }; 49 | 50 | class AstExpression : public AstNode 51 | { 52 | public: 53 | typedef shared_ptr Ptr; 54 | typedef weak_ptr WeakPtr; 55 | typedef vector List; 56 | 57 | void Accept(AstVisitor* visitor)override; 58 | virtual void Accept(AstExpressionVisitor* visitor) = 0; 59 | }; 60 | 61 | class AstStatement : public AstNode 62 | { 63 | public: 64 | typedef shared_ptr Ptr; 65 | typedef weak_ptr WeakPtr; 66 | typedef vector List; 67 | 68 | void Accept(AstVisitor* visitor)override; 69 | virtual void Accept(AstStatementVisitor* visitor) = 0; 70 | }; 71 | 72 | class AstDeclaration : public AstNode 73 | { 74 | public: 75 | typedef shared_ptr Ptr; 76 | typedef weak_ptr WeakPtr; 77 | typedef vector List; 78 | 79 | string_t composedName; 80 | 81 | void Accept(AstVisitor* visitor)override; 82 | virtual void Accept(AstDeclarationVisitor* visitor) = 0; 83 | }; 84 | 85 | /************************************************************* 86 | Declaration 87 | *************************************************************/ 88 | 89 | class AstSymbolDeclaration : public AstDeclaration 90 | { 91 | public: 92 | typedef shared_ptr Ptr; 93 | typedef vector List; 94 | 95 | void Accept(AstDeclarationVisitor* visitor)override; 96 | }; 97 | 98 | class AstTypeDeclaration : public AstDeclaration 99 | { 100 | public: 101 | typedef shared_ptr Ptr; 102 | 103 | AstType::WeakPtr baseType; 104 | AstSymbolDeclaration::List fields; 105 | 106 | void Accept(AstDeclarationVisitor* visitor)override; 107 | }; 108 | 109 | class AstFunctionDeclaration : public AstDeclaration 110 | { 111 | public: 112 | typedef shared_ptr Ptr; 113 | 114 | AstType::Ptr ownerType; // (optional) if ownerType is not null, this function is added to this type as a virtual function. 115 | AstSymbolDeclaration::List arguments; 116 | map readArgumentAstMap; 117 | map writeArgumentAstMap; 118 | AstStatement::Ptr statement; 119 | 120 | AstSymbolDeclaration::Ptr resultVariable; 121 | 122 | AstSymbolDeclaration::Ptr stateArgument; // for function 123 | AstSymbolDeclaration::Ptr signalArgument; // (optional) for block 124 | AstSymbolDeclaration::Ptr blockBodyArgument; // (optional) for block 125 | AstSymbolDeclaration::Ptr continuationArgument; // for function 126 | 127 | void Accept(AstDeclarationVisitor* visitor)override; 128 | }; 129 | 130 | /************************************************************* 131 | Expression 132 | *************************************************************/ 133 | 134 | enum class AstLiteralName 135 | { 136 | Null, 137 | True, 138 | False, 139 | }; 140 | 141 | class AstLiteralExpression : public AstExpression 142 | { 143 | public: 144 | AstLiteralName literalName; 145 | 146 | void Accept(AstExpressionVisitor* visitor)override; 147 | }; 148 | 149 | class AstIntegerExpression : public AstExpression 150 | { 151 | public: 152 | int64_t value; 153 | 154 | void Accept(AstExpressionVisitor* visitor)override; 155 | }; 156 | 157 | class AstFloatExpression : public AstExpression 158 | { 159 | public: 160 | double value; 161 | 162 | void Accept(AstExpressionVisitor* visitor)override; 163 | }; 164 | 165 | class AstStringExpression : public AstExpression 166 | { 167 | public: 168 | string_t value; 169 | 170 | void Accept(AstExpressionVisitor* visitor)override; 171 | }; 172 | 173 | class AstExternalSymbolExpression : public AstExpression 174 | { 175 | public: 176 | string_t name; 177 | 178 | void Accept(AstExpressionVisitor* visitor)override; 179 | }; 180 | 181 | class AstReferenceExpression : public AstExpression 182 | { 183 | public: 184 | AstDeclaration::WeakPtr reference; // could be 185 | // AstSymbolDeclaration 186 | // AstFunctionDeclaration 187 | 188 | void Accept(AstExpressionVisitor* visitor)override; 189 | }; 190 | 191 | class AstNewTypeExpression : public AstExpression 192 | { 193 | public: 194 | AstType::Ptr type; 195 | AstExpression::List fields; 196 | 197 | void Accept(AstExpressionVisitor* visitor)override; 198 | }; 199 | 200 | class AstTestTypeExpression : public AstExpression 201 | { 202 | public: 203 | AstExpression::Ptr target; 204 | AstType::Ptr type; 205 | 206 | void Accept(AstExpressionVisitor* visitor)override; 207 | }; 208 | 209 | class AstNewArrayExpression : public AstExpression 210 | { 211 | public: 212 | AstExpression::Ptr length; 213 | 214 | void Accept(AstExpressionVisitor* visitor)override; 215 | }; 216 | 217 | class AstNewArrayLiteralExpression : public AstExpression 218 | { 219 | public: 220 | AstExpression::List elements; 221 | 222 | void Accept(AstExpressionVisitor* visitor)override; 223 | }; 224 | 225 | class AstArrayLengthExpression : public AstExpression 226 | { 227 | public: 228 | AstExpression::Ptr target; 229 | 230 | void Accept(AstExpressionVisitor* visitor)override; 231 | }; 232 | 233 | class AstArrayAccessExpression : public AstExpression 234 | { 235 | public: 236 | AstExpression::Ptr target; 237 | AstExpression::Ptr index; 238 | 239 | void Accept(AstExpressionVisitor* visitor)override; 240 | }; 241 | 242 | class AstFieldAccessExpression : public AstExpression 243 | { 244 | public: 245 | AstExpression::Ptr target; 246 | string_t composedFieldName; 247 | 248 | void Accept(AstExpressionVisitor* visitor)override; 249 | }; 250 | 251 | class AstInvokeExpression : public AstExpression 252 | { 253 | public: 254 | AstExpression::Ptr function; 255 | AstExpression::List arguments; 256 | 257 | void Accept(AstExpressionVisitor* visitor)override; 258 | }; 259 | 260 | class AstLambdaExpression : public AstExpression 261 | { 262 | public: 263 | AstSymbolDeclaration::List arguments; 264 | AstStatement::Ptr statement; 265 | 266 | void Accept(AstExpressionVisitor* visitor)override; 267 | }; 268 | 269 | /************************************************************* 270 | Statement 271 | *************************************************************/ 272 | 273 | class AstBlockStatement : public AstStatement 274 | { 275 | public: 276 | AstStatement::List statements; 277 | 278 | void Accept(AstStatementVisitor* visitor)override; 279 | }; 280 | 281 | class AstExpressionStatement : public AstStatement 282 | { 283 | public: 284 | AstExpression::Ptr expression; 285 | 286 | void Accept(AstStatementVisitor* visitor)override; 287 | }; 288 | 289 | class AstDeclarationStatement : public AstStatement 290 | { 291 | public: 292 | AstDeclaration::Ptr declaration; 293 | 294 | void Accept(AstStatementVisitor* visitor)override; 295 | }; 296 | 297 | class AstAssignmentStatement : public AstStatement 298 | { 299 | public: 300 | AstExpression::Ptr target; // could be 301 | // AstReferenceExpression 302 | // AstFieldAccessExpression 303 | // AstArrayAccessExpression 304 | AstExpression::Ptr value; 305 | 306 | void Accept(AstStatementVisitor* visitor)override; 307 | }; 308 | 309 | 310 | class AstIfStatement : public AstStatement 311 | { 312 | public: 313 | AstExpression::Ptr condition; 314 | AstStatement::Ptr trueBranch; 315 | AstStatement::Ptr falseBranch; // (optional) 316 | 317 | void Accept(AstStatementVisitor* visitor)override; 318 | }; 319 | 320 | /************************************************************* 321 | Type 322 | *************************************************************/ 323 | 324 | enum class AstPredefinedTypeName 325 | { 326 | Object, 327 | Symbol, 328 | Array, 329 | Boolean, 330 | Integer, 331 | Float, 332 | String, 333 | Function, 334 | }; 335 | 336 | class AstPredefinedType : public AstType 337 | { 338 | public: 339 | AstPredefinedTypeName typeName; 340 | 341 | void Accept(AstTypeVisitor* visitor)override; 342 | }; 343 | 344 | class AstReferenceType : public AstType 345 | { 346 | public: 347 | weak_ptr typeDeclaration; 348 | 349 | void Accept(AstTypeVisitor* visitor)override; 350 | }; 351 | 352 | /************************************************************* 353 | Assembly 354 | *************************************************************/ 355 | 356 | class AstAssembly : public AstNode 357 | { 358 | public: 359 | typedef shared_ptr Ptr; 360 | 361 | AstDeclaration::List declarations; 362 | 363 | void Accept(AstVisitor* visitor)override; 364 | }; 365 | 366 | /************************************************************* 367 | Visitors 368 | *************************************************************/ 369 | 370 | class AstVisitor 371 | { 372 | public: 373 | AstVisitor(); 374 | virtual ~AstVisitor(); 375 | 376 | virtual void Visit(AstType* node) = 0; 377 | virtual void Visit(AstExpression* node) = 0; 378 | virtual void Visit(AstStatement* node) = 0; 379 | virtual void Visit(AstDeclaration* node) = 0; 380 | virtual void Visit(AstAssembly* node) = 0; 381 | }; 382 | 383 | class AstTypeVisitor 384 | { 385 | public: 386 | AstTypeVisitor(); 387 | virtual ~AstTypeVisitor(); 388 | 389 | virtual void Visit(AstPredefinedType* node) = 0; 390 | virtual void Visit(AstReferenceType* node) = 0; 391 | }; 392 | 393 | class AstExpressionVisitor 394 | { 395 | public: 396 | AstExpressionVisitor(); 397 | virtual ~AstExpressionVisitor(); 398 | 399 | virtual void Visit(AstLiteralExpression* node) = 0; 400 | virtual void Visit(AstIntegerExpression* node) = 0; 401 | virtual void Visit(AstFloatExpression* node) = 0; 402 | virtual void Visit(AstStringExpression* node) = 0; 403 | virtual void Visit(AstExternalSymbolExpression* node) = 0; 404 | virtual void Visit(AstReferenceExpression* node) = 0; 405 | virtual void Visit(AstNewTypeExpression* node) = 0; 406 | virtual void Visit(AstTestTypeExpression* node) = 0; 407 | virtual void Visit(AstNewArrayExpression* node) = 0; 408 | virtual void Visit(AstNewArrayLiteralExpression* node) = 0; 409 | virtual void Visit(AstArrayLengthExpression* node) = 0; 410 | virtual void Visit(AstArrayAccessExpression* node) = 0; 411 | virtual void Visit(AstFieldAccessExpression* node) = 0; 412 | virtual void Visit(AstInvokeExpression* node) = 0; 413 | virtual void Visit(AstLambdaExpression* node) = 0; 414 | }; 415 | 416 | class AstStatementVisitor 417 | { 418 | public: 419 | AstStatementVisitor(); 420 | virtual ~AstStatementVisitor(); 421 | 422 | virtual void Visit(AstBlockStatement* node) = 0; 423 | virtual void Visit(AstExpressionStatement* node) = 0; 424 | virtual void Visit(AstDeclarationStatement* node) = 0; 425 | virtual void Visit(AstAssignmentStatement* node) = 0; 426 | virtual void Visit(AstIfStatement* node) = 0; 427 | }; 428 | 429 | class AstDeclarationVisitor 430 | { 431 | public: 432 | AstDeclarationVisitor(); 433 | virtual ~AstDeclarationVisitor(); 434 | 435 | virtual void Visit(AstSymbolDeclaration* node) = 0; 436 | virtual void Visit(AstTypeDeclaration* node) = 0; 437 | virtual void Visit(AstFunctionDeclaration* node) = 0; 438 | }; 439 | 440 | /************************************************************* 441 | Helper Functions 442 | *************************************************************/ 443 | 444 | extern void SetParent(AstNode::Ptr node, AstNode::WeakPtr _parent = AstNode::WeakPtr()); 445 | extern void Print(AstNode::Ptr node, ostream_t& o, int indentation, AstNode::WeakPtr _parent = AstNode::WeakPtr()); 446 | 447 | extern void CollectSideEffectExpressions(AstExpression::Ptr node, AstExpression::List& exprs); 448 | extern void CollectUsedVariables(AstExpression::Ptr node, bool rightValue, set>& defined, set>& used); 449 | extern void CollectUsedVariables(AstStatement::Ptr node, set>& defined, set>& used); 450 | extern void ExpandBlock(AstStatement::Ptr node, AstStatement::List& stats, bool lastStatement); 451 | extern AstDeclaration::Ptr GetRootLeftValue(AstExpression::Ptr node); 452 | extern void RemoveUnnecessaryVariables(AstExpression::Ptr node, set>& defined, set>& used); 453 | extern void RemoveUnnecessaryVariables(AstStatement::Ptr node, set>& defined, set>& used, AstStatement::Ptr& replacement); 454 | 455 | extern void RoughlyOptimize(AstDeclaration::Ptr node); 456 | extern void RoughlyOptimize(AstExpression::Ptr node, AstExpression::Ptr& _replacement); 457 | extern void RoughlyOptimize(AstStatement::Ptr node, AstStatement::Ptr& _replacement); 458 | extern void RoughlyOptimize(AstAssembly::Ptr node); 459 | } 460 | } 461 | 462 | #endif -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_CollectSideEffectExpressions.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstExpression::CollectSideEffectExpressions 9 | *************************************************************/ 10 | 11 | class AstExpression_CollectSideEffectExpressions : public AstExpressionVisitor 12 | { 13 | private: 14 | AstExpression::List& exprs; 15 | 16 | public: 17 | AstExpression_CollectSideEffectExpressions(AstExpression::List& _exprs) 18 | :exprs(_exprs) 19 | { 20 | } 21 | 22 | void Visit(AstLiteralExpression* node)override 23 | { 24 | } 25 | 26 | void Visit(AstIntegerExpression* node)override 27 | { 28 | } 29 | 30 | void Visit(AstFloatExpression* node)override 31 | { 32 | } 33 | 34 | void Visit(AstStringExpression* node)override 35 | { 36 | } 37 | 38 | void Visit(AstExternalSymbolExpression* node)override 39 | { 40 | } 41 | 42 | void Visit(AstReferenceExpression* node)override 43 | { 44 | } 45 | 46 | void Visit(AstNewTypeExpression* node)override 47 | { 48 | for (auto field : node->fields) 49 | { 50 | CollectSideEffectExpressions(field, exprs); 51 | } 52 | } 53 | 54 | void Visit(AstTestTypeExpression* node)override 55 | { 56 | CollectSideEffectExpressions(node->target, exprs); 57 | } 58 | 59 | void Visit(AstNewArrayExpression* node)override 60 | { 61 | CollectSideEffectExpressions(node->length, exprs); 62 | } 63 | 64 | void Visit(AstNewArrayLiteralExpression* node)override 65 | { 66 | for (auto element : node->elements) 67 | { 68 | CollectSideEffectExpressions(element, exprs); 69 | } 70 | } 71 | 72 | void Visit(AstArrayLengthExpression* node)override 73 | { 74 | CollectSideEffectExpressions(node->target, exprs); 75 | } 76 | 77 | void Visit(AstArrayAccessExpression* node)override 78 | { 79 | CollectSideEffectExpressions(node->target, exprs); 80 | CollectSideEffectExpressions(node->index, exprs); 81 | } 82 | 83 | void Visit(AstFieldAccessExpression* node)override 84 | { 85 | CollectSideEffectExpressions(node->target, exprs); 86 | } 87 | 88 | void Visit(AstInvokeExpression* node)override 89 | { 90 | exprs.push_back(dynamic_pointer_cast(node->shared_from_this())); 91 | } 92 | 93 | void Visit(AstLambdaExpression* node)override 94 | { 95 | } 96 | }; 97 | 98 | /************************************************************* 99 | AstExpression::CollectSideEffectExpressions 100 | *************************************************************/ 101 | 102 | void CollectSideEffectExpressions(AstExpression::Ptr node, AstExpression::List& exprs) 103 | { 104 | AstExpression_CollectSideEffectExpressions visitor(exprs); 105 | node->Accept(&visitor); 106 | } 107 | } 108 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_CollectUsedVariables.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstExpression::CollectUsedVariables 9 | *************************************************************/ 10 | 11 | class AstExpression_CollectUsedVariables : public AstExpressionVisitor 12 | { 13 | private: 14 | bool rightValue; 15 | set>& defined; 16 | set>& used; 17 | public: 18 | AstExpression_CollectUsedVariables(bool _rightValue, set>& _defined, set>& _used) 19 | :rightValue(_rightValue), defined(_defined), used(_used) 20 | { 21 | 22 | } 23 | 24 | void Visit(AstLiteralExpression* node)override 25 | { 26 | } 27 | 28 | void Visit(AstIntegerExpression* node)override 29 | { 30 | } 31 | 32 | void Visit(AstFloatExpression* node)override 33 | { 34 | } 35 | 36 | void Visit(AstStringExpression* node)override 37 | { 38 | } 39 | 40 | void Visit(AstExternalSymbolExpression* node)override 41 | { 42 | } 43 | 44 | void Visit(AstReferenceExpression* node)override 45 | { 46 | if (rightValue) 47 | { 48 | used.insert(node->reference.lock()); 49 | } 50 | } 51 | 52 | void Visit(AstNewTypeExpression* node)override 53 | { 54 | for (auto field : node->fields) 55 | { 56 | CollectUsedVariables(field, true, defined, used); 57 | } 58 | } 59 | 60 | void Visit(AstTestTypeExpression* node)override 61 | { 62 | CollectUsedVariables(node->target, true, defined, used); 63 | } 64 | 65 | void Visit(AstNewArrayExpression* node)override 66 | { 67 | CollectUsedVariables(node->length, true, defined, used); 68 | } 69 | 70 | void Visit(AstNewArrayLiteralExpression* node)override 71 | { 72 | for (auto element : node->elements) 73 | { 74 | CollectUsedVariables(element, true, defined, used); 75 | } 76 | } 77 | 78 | void Visit(AstArrayLengthExpression* node)override 79 | { 80 | CollectUsedVariables(node->target, true, defined, used); 81 | } 82 | 83 | void Visit(AstArrayAccessExpression* node)override 84 | { 85 | CollectUsedVariables(node->target, rightValue, defined, used); 86 | CollectUsedVariables(node->index, true, defined, used); 87 | } 88 | 89 | void Visit(AstFieldAccessExpression* node)override 90 | { 91 | if (rightValue) 92 | { 93 | CollectUsedVariables(node->target, true, defined, used); 94 | } 95 | } 96 | 97 | void Visit(AstInvokeExpression* node)override 98 | { 99 | CollectUsedVariables(node->function, true, defined, used); 100 | for (auto argument : node->arguments) 101 | { 102 | CollectUsedVariables(argument, true, defined, used); 103 | } 104 | } 105 | 106 | void Visit(AstLambdaExpression* node)override 107 | { 108 | CollectUsedVariables(node->statement, defined, used); 109 | } 110 | }; 111 | 112 | /************************************************************* 113 | AstStatement::CollectUsedVariables 114 | *************************************************************/ 115 | 116 | class AstStatement_CollectUsedVariables : public AstStatementVisitor 117 | { 118 | private: 119 | set>& defined; 120 | set>& used; 121 | public: 122 | AstStatement_CollectUsedVariables(set>& _defined, set>& _used) 123 | :defined(_defined), used(_used) 124 | { 125 | 126 | } 127 | 128 | void Visit(AstBlockStatement* node)override 129 | { 130 | for (auto stat : node->statements) 131 | { 132 | CollectUsedVariables(stat, defined, used); 133 | } 134 | } 135 | 136 | void Visit(AstExpressionStatement* node)override 137 | { 138 | CollectUsedVariables(node->expression, true, defined, used); 139 | } 140 | 141 | void Visit(AstDeclarationStatement* node)override 142 | { 143 | defined.insert(node->declaration); 144 | } 145 | 146 | void Visit(AstAssignmentStatement* node)override 147 | { 148 | CollectUsedVariables(node->target, false, defined, used); 149 | CollectUsedVariables(node->value, true, defined, used); 150 | } 151 | 152 | void Visit(AstIfStatement* node)override 153 | { 154 | CollectUsedVariables(node->condition, true, defined, used); 155 | CollectUsedVariables(node->trueBranch, defined, used); 156 | if (node->falseBranch) 157 | { 158 | CollectUsedVariables(node->falseBranch, defined, used); 159 | } 160 | } 161 | }; 162 | 163 | /************************************************************* 164 | CollectUsedVariables 165 | *************************************************************/ 166 | 167 | void CollectUsedVariables(AstExpression::Ptr node, bool rightValue, set>& defined, set>& used) 168 | { 169 | AstExpression_CollectUsedVariables visitor(rightValue, defined, used); 170 | node->Accept(&visitor); 171 | } 172 | 173 | void CollectUsedVariables(AstStatement::Ptr node, set>& defined, set>& used) 174 | { 175 | AstStatement_CollectUsedVariables visitor(defined, used); 176 | node->Accept(&visitor); 177 | } 178 | } 179 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_ExpandBlock.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstStatement::ExpandBlock 9 | *************************************************************/ 10 | 11 | class AstStatement_ExpandBlock : public AstStatementVisitor 12 | { 13 | private: 14 | AstStatement::List& stats; 15 | bool lastStatement; 16 | 17 | public: 18 | AstStatement_ExpandBlock(AstStatement::List& _stats, bool _lastStatement) 19 | :stats(_stats), lastStatement(_lastStatement) 20 | { 21 | 22 | } 23 | 24 | void Visit(AstBlockStatement* node)override 25 | { 26 | if (!lastStatement) 27 | { 28 | for (auto stat : node->statements) 29 | { 30 | if (dynamic_pointer_cast(stat)) 31 | { 32 | stats.push_back(dynamic_pointer_cast(node->shared_from_this())); 33 | return; 34 | } 35 | } 36 | } 37 | 38 | for (auto stat : node->statements) 39 | { 40 | ExpandBlock(stat, stats, stat == *(node->statements.end() - 1)); 41 | } 42 | } 43 | 44 | void Visit(AstExpressionStatement* node)override 45 | { 46 | stats.push_back(dynamic_pointer_cast(node->shared_from_this())); 47 | } 48 | 49 | void Visit(AstDeclarationStatement* node)override 50 | { 51 | stats.push_back(dynamic_pointer_cast(node->shared_from_this())); 52 | } 53 | 54 | void Visit(AstAssignmentStatement* node)override 55 | { 56 | stats.push_back(dynamic_pointer_cast(node->shared_from_this())); 57 | } 58 | 59 | void Visit(AstIfStatement* node)override 60 | { 61 | stats.push_back(dynamic_pointer_cast(node->shared_from_this())); 62 | } 63 | }; 64 | 65 | /************************************************************* 66 | ExpandBlock 67 | *************************************************************/ 68 | 69 | void ExpandBlock(AstStatement::Ptr node, AstStatement::List& stats, bool lastStatement) 70 | { 71 | AstStatement_ExpandBlock visitor(stats, lastStatement); 72 | node->Accept(&visitor); 73 | } 74 | } 75 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_GetRootLeftValue.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstExpression::GetRootLeftValue 9 | *************************************************************/ 10 | 11 | class AstExpression_GetRootLeftValue : public AstExpressionVisitor 12 | { 13 | public: 14 | shared_ptr result; 15 | 16 | void Visit(AstLiteralExpression* node)override 17 | { 18 | } 19 | 20 | void Visit(AstIntegerExpression* node)override 21 | { 22 | } 23 | 24 | void Visit(AstFloatExpression* node)override 25 | { 26 | } 27 | 28 | void Visit(AstStringExpression* node)override 29 | { 30 | } 31 | 32 | void Visit(AstExternalSymbolExpression* node)override 33 | { 34 | } 35 | 36 | void Visit(AstReferenceExpression* node)override 37 | { 38 | result = node->reference.lock(); 39 | } 40 | 41 | void Visit(AstNewTypeExpression* node)override 42 | { 43 | } 44 | 45 | void Visit(AstTestTypeExpression* node)override 46 | { 47 | } 48 | 49 | void Visit(AstNewArrayExpression* node)override 50 | { 51 | } 52 | 53 | void Visit(AstNewArrayLiteralExpression* node)override 54 | { 55 | } 56 | 57 | void Visit(AstArrayLengthExpression* node)override 58 | { 59 | } 60 | 61 | void Visit(AstArrayAccessExpression* node)override 62 | { 63 | result = GetRootLeftValue(node->target); 64 | } 65 | 66 | void Visit(AstFieldAccessExpression* node)override 67 | { 68 | result = GetRootLeftValue(node->target); 69 | } 70 | 71 | void Visit(AstInvokeExpression* node)override 72 | { 73 | } 74 | 75 | void Visit(AstLambdaExpression* node)override 76 | { 77 | } 78 | }; 79 | 80 | /************************************************************* 81 | GetRootLeftValue 82 | *************************************************************/ 83 | 84 | AstDeclaration::Ptr GetRootLeftValue(AstExpression::Ptr node) 85 | { 86 | AstExpression_GetRootLeftValue visitor; 87 | node->Accept(&visitor); 88 | return visitor.result; 89 | } 90 | } 91 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_Print.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | // find: void (\w+)::PrintInternal\(ostream_t& o, int indentation\) 4 | // replace: void Visit($1* node)override 5 | 6 | namespace tinymoe 7 | { 8 | namespace ast 9 | { 10 | string_t Indent(int indentation) 11 | { 12 | string_t s; 13 | for (int i = 0; i < indentation; i++) 14 | { 15 | s += T(" "); 16 | } 17 | return s; 18 | } 19 | 20 | /************************************************************* 21 | AstDeclaration::Print 22 | *************************************************************/ 23 | 24 | class AstDeclaration_Print : public AstDeclarationVisitor 25 | { 26 | private: 27 | ostream_t& o; 28 | int indentation; 29 | public: 30 | AstDeclaration_Print(ostream_t& _o, int _indentation) 31 | :o(_o), indentation(_indentation) 32 | { 33 | } 34 | 35 | void Visit(AstSymbolDeclaration* node)override 36 | { 37 | o << Indent(indentation) << T("$symbol ") << node->composedName << T(";"); 38 | } 39 | 40 | void Visit(AstTypeDeclaration* node)override 41 | { 42 | o << Indent(indentation) << T("$type ") << node->composedName; 43 | if (!node->baseType.expired()) 44 | { 45 | o << T(" : "); 46 | Print(node->baseType.lock(), o, indentation); 47 | } 48 | o << endl << Indent(indentation) << T("{") << endl; 49 | for (auto field : node->fields) 50 | { 51 | Print(field, o, indentation + 1, node->shared_from_this()); 52 | o << endl; 53 | } 54 | o << Indent(indentation) << T("}"); 55 | } 56 | 57 | void Visit(AstFunctionDeclaration* node)override 58 | { 59 | o << Indent(indentation) << T("$procedure "); 60 | if (node->ownerType) 61 | { 62 | o << T("("); 63 | Print(node->ownerType, o, indentation, node->shared_from_this()); 64 | o << T(")."); 65 | } 66 | o << node->composedName << T("("); 67 | for (auto it = node->arguments.begin(); it != node->arguments.end(); it++) 68 | { 69 | o << (*it)->composedName; 70 | if (it + 1 != node->arguments.end()) 71 | { 72 | o << T(", "); 73 | } 74 | } 75 | 76 | o << T(")") << endl; 77 | Print(node->statement, o, indentation, node->shared_from_this()); 78 | } 79 | }; 80 | 81 | /************************************************************* 82 | AstExpression::Print 83 | *************************************************************/ 84 | 85 | class AstExpression_Print : public AstExpressionVisitor 86 | { 87 | private: 88 | ostream_t& o; 89 | int indentation; 90 | public: 91 | AstExpression_Print(ostream_t& _o, int _indentation) 92 | :o(_o), indentation(_indentation) 93 | { 94 | } 95 | 96 | void Visit(AstLiteralExpression* node)override 97 | { 98 | switch (node->literalName) 99 | { 100 | case AstLiteralName::Null: 101 | o << T("$null"); 102 | break; 103 | case AstLiteralName::True: 104 | o << T("$true"); 105 | break; 106 | case AstLiteralName::False: 107 | o << T("$false"); 108 | break; 109 | } 110 | } 111 | 112 | void Visit(AstIntegerExpression* node)override 113 | { 114 | o << node->value; 115 | } 116 | 117 | void Visit(AstFloatExpression* node)override 118 | { 119 | o << node->value; 120 | } 121 | 122 | void Visit(AstStringExpression* node)override 123 | { 124 | o << T("\"") << node->value << T("\""); 125 | } 126 | 127 | void Visit(AstExternalSymbolExpression* node)override 128 | { 129 | o << T("$external (\"") << node->name << T("\")"); 130 | } 131 | 132 | void Visit(AstReferenceExpression* node)override 133 | { 134 | o << node->reference.lock()->composedName; 135 | } 136 | 137 | void Visit(AstNewTypeExpression* node)override 138 | { 139 | o << T("new "); 140 | Print(node->type, o, indentation, node->shared_from_this()); 141 | o << T("("); 142 | for (auto it = node->fields.begin(); it != node->fields.end(); it++) 143 | { 144 | Print((*it), o, indentation, node->shared_from_this()); 145 | if (it + 1 != node->fields.end()) 146 | { 147 | o << T(", "); 148 | } 149 | } 150 | o << T(")"); 151 | } 152 | 153 | void Visit(AstTestTypeExpression* node)override 154 | { 155 | o << T("("); 156 | Print(node->target, o, indentation, node->shared_from_this()); 157 | o << T(" is "); 158 | Print(node->type, o, indentation, node->shared_from_this()); 159 | o << T(")"); 160 | } 161 | 162 | void Visit(AstNewArrayExpression* node)override 163 | { 164 | o << T("new $Array("); 165 | Print(node->length, o, indentation, node->shared_from_this()); 166 | o << T(")"); 167 | } 168 | 169 | void Visit(AstNewArrayLiteralExpression* node)override 170 | { 171 | o << T("["); 172 | for (auto it = node->elements.begin(); it != node->elements.end(); it++) 173 | { 174 | Print((*it), o, indentation, node->shared_from_this()); 175 | if (it + 1 != node->elements.end()) 176 | { 177 | o << T(", "); 178 | } 179 | } 180 | o << T("]"); 181 | } 182 | 183 | void Visit(AstArrayLengthExpression* node)override 184 | { 185 | o << T("$ArrayLength("); 186 | Print(node->target, o, indentation, node->shared_from_this()); 187 | o << T(")"); 188 | } 189 | 190 | void Visit(AstArrayAccessExpression* node)override 191 | { 192 | Print(node->target, o, indentation, node->shared_from_this()); 193 | o << T("["); 194 | Print(node->index, o, indentation, node->shared_from_this()); 195 | o << T("]"); 196 | } 197 | 198 | void Visit(AstFieldAccessExpression* node)override 199 | { 200 | Print(node->target, o, indentation, node->shared_from_this()); 201 | o << T(".") << node->composedFieldName; 202 | } 203 | 204 | void Visit(AstInvokeExpression* node)override 205 | { 206 | Print(node->function, o, indentation, node->shared_from_this()); 207 | o << T("(") << endl; 208 | for (auto it = node->arguments.begin(); it != node->arguments.end(); it++) 209 | { 210 | o << Indent(indentation + 1); 211 | Print((*it), o, indentation + 1, node->shared_from_this()); 212 | if (it + 1 != node->arguments.end()) 213 | { 214 | o << T(", "); 215 | } 216 | o << endl; 217 | } 218 | o << Indent(indentation + 1) << T(")"); 219 | } 220 | 221 | void Visit(AstLambdaExpression* node)override 222 | { 223 | o << T("$lambda ("); 224 | for (auto it = node->arguments.begin(); it != node->arguments.end(); it++) 225 | { 226 | o << (*it)->composedName; 227 | if (it + 1 != node->arguments.end()) 228 | { 229 | o << T(", "); 230 | } 231 | } 232 | o << T(")") << endl; 233 | Print(node->statement, o, indentation + 1, node->shared_from_this()); 234 | } 235 | }; 236 | 237 | /************************************************************* 238 | AstStatement::Print 239 | *************************************************************/ 240 | 241 | class AstStatement_Print : public AstStatementVisitor 242 | { 243 | private: 244 | ostream_t& o; 245 | int indentation; 246 | public: 247 | AstStatement_Print(ostream_t& _o, int _indentation) 248 | :o(_o), indentation(_indentation) 249 | { 250 | } 251 | 252 | void Visit(AstBlockStatement* node)override 253 | { 254 | o << Indent(indentation) << T("{") << endl; 255 | for (auto statement : node->statements) 256 | { 257 | Print(statement, o, indentation + 1, node->shared_from_this()); 258 | o << endl; 259 | } 260 | o << Indent(indentation) << T("}"); 261 | } 262 | 263 | void Visit(AstExpressionStatement* node)override 264 | { 265 | o << Indent(indentation); 266 | Print(node->expression, o, indentation, node->shared_from_this()); 267 | o << T(";"); 268 | } 269 | 270 | void Visit(AstDeclarationStatement* node)override 271 | { 272 | Print(node->declaration, o, indentation, node->shared_from_this()); 273 | } 274 | 275 | void Visit(AstAssignmentStatement* node)override 276 | { 277 | o << Indent(indentation); 278 | Print(node->target, o, indentation, node->shared_from_this()); 279 | o << T(" = "); 280 | Print(node->value, o, indentation, node->shared_from_this()); 281 | o << T(";"); 282 | } 283 | 284 | void Visit(AstIfStatement* node)override 285 | { 286 | o << Indent(indentation) << T("if ("); 287 | Print(node->condition, o, indentation, node->shared_from_this()); 288 | o << endl; 289 | Print(node->trueBranch, o, indentation + 1, node->shared_from_this()); 290 | if (node->falseBranch) 291 | { 292 | o << endl << Indent(indentation) << T("else") << endl; 293 | Print(node->falseBranch, o, indentation + 1, node->shared_from_this()); 294 | } 295 | } 296 | }; 297 | 298 | /************************************************************* 299 | AstType::Print 300 | *************************************************************/ 301 | 302 | class AstType_Print : public AstTypeVisitor 303 | { 304 | private: 305 | ostream_t& o; 306 | int indentation; 307 | public: 308 | AstType_Print(ostream_t& _o, int _indentation) 309 | :o(_o), indentation(_indentation) 310 | { 311 | } 312 | 313 | void Visit(AstPredefinedType* node)override 314 | { 315 | switch (node->typeName) 316 | { 317 | case AstPredefinedTypeName::Object: 318 | o << T("$Object"); 319 | break; 320 | case AstPredefinedTypeName::Symbol: 321 | o << T("$Symbol"); 322 | break; 323 | case AstPredefinedTypeName::Array: 324 | o << T("$Array"); 325 | break; 326 | case AstPredefinedTypeName::Boolean: 327 | o << T("$Boolean"); 328 | break; 329 | case AstPredefinedTypeName::Integer: 330 | o << T("$Integer"); 331 | break; 332 | case AstPredefinedTypeName::Float: 333 | o << T("$Float"); 334 | break; 335 | case AstPredefinedTypeName::String: 336 | o << T("$Function"); 337 | break; 338 | } 339 | } 340 | 341 | void Visit(AstReferenceType* node)override 342 | { 343 | o << node->typeDeclaration.lock()->composedName; 344 | } 345 | }; 346 | 347 | /************************************************************* 348 | AstAssembly::Print 349 | *************************************************************/ 350 | 351 | class AstNode_Print : public AstVisitor 352 | { 353 | private: 354 | ostream_t& o; 355 | int indentation; 356 | public: 357 | AstNode_Print(ostream_t& _o, int _indentation) 358 | :o(_o), indentation(_indentation) 359 | { 360 | } 361 | 362 | void Visit(AstType* node)override 363 | { 364 | AstType_Print visitor(o, indentation); 365 | node->Accept(&visitor); 366 | } 367 | 368 | void Visit(AstExpression* node)override 369 | { 370 | AstExpression_Print visitor(o, indentation); 371 | node->Accept(&visitor); 372 | } 373 | 374 | void Visit(AstStatement* node)override 375 | { 376 | AstStatement_Print visitor(o, indentation); 377 | node->Accept(&visitor); 378 | } 379 | 380 | void Visit(AstDeclaration* node)override 381 | { 382 | AstDeclaration_Print visitor(o, indentation); 383 | node->Accept(&visitor); 384 | } 385 | 386 | void Visit(AstAssembly* node)override 387 | { 388 | for (auto decl : node->declarations) 389 | { 390 | Print(decl, o, indentation, node->shared_from_this()); 391 | o << endl << endl; 392 | } 393 | } 394 | }; 395 | 396 | /************************************************************* 397 | Print 398 | *************************************************************/ 399 | 400 | void Print(AstNode::Ptr node, ostream_t& o, int indentation, AstNode::WeakPtr _parent) 401 | { 402 | ASSERT(_parent.expired() || node->parent.lock() == _parent.lock()); 403 | AstNode_Print visitor(o, indentation); 404 | node->Accept(&visitor); 405 | } 406 | } 407 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_RemoveUnnecessaryVariables.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstExpression::RemoveUnnecessaryVariables 9 | *************************************************************/ 10 | 11 | class AstExpression_RemoveUnnecessaryVariables : public AstExpressionVisitor 12 | { 13 | private: 14 | set>& defined; 15 | set>& used; 16 | public: 17 | AstExpression_RemoveUnnecessaryVariables(set>& _defined, set>& _used) 18 | :defined(_defined), used(_used) 19 | { 20 | } 21 | 22 | void Visit(AstLiteralExpression* node)override 23 | { 24 | } 25 | 26 | void Visit(AstIntegerExpression* node)override 27 | { 28 | } 29 | 30 | void Visit(AstFloatExpression* node)override 31 | { 32 | } 33 | 34 | void Visit(AstStringExpression* node)override 35 | { 36 | } 37 | 38 | void Visit(AstExternalSymbolExpression* node)override 39 | { 40 | } 41 | 42 | void Visit(AstReferenceExpression* node)override 43 | { 44 | } 45 | 46 | void Visit(AstNewTypeExpression* node)override 47 | { 48 | for (auto field : node->fields) 49 | { 50 | RemoveUnnecessaryVariables(field, defined, used); 51 | } 52 | } 53 | 54 | void Visit(AstTestTypeExpression* node)override 55 | { 56 | RemoveUnnecessaryVariables(node->target, defined, used); 57 | } 58 | 59 | void Visit(AstNewArrayExpression* node)override 60 | { 61 | RemoveUnnecessaryVariables(node->length, defined, used); 62 | } 63 | 64 | void Visit(AstNewArrayLiteralExpression* node)override 65 | { 66 | for (auto element : node->elements) 67 | { 68 | RemoveUnnecessaryVariables(element, defined, used); 69 | } 70 | } 71 | 72 | void Visit(AstArrayLengthExpression* node)override 73 | { 74 | RemoveUnnecessaryVariables(node->target, defined, used); 75 | } 76 | 77 | void Visit(AstArrayAccessExpression* node)override 78 | { 79 | RemoveUnnecessaryVariables(node->target, defined, used); 80 | RemoveUnnecessaryVariables(node->index, defined, used); 81 | } 82 | 83 | void Visit(AstFieldAccessExpression* node)override 84 | { 85 | RemoveUnnecessaryVariables(node->target, defined, used); 86 | } 87 | 88 | void Visit(AstInvokeExpression* node)override 89 | { 90 | RemoveUnnecessaryVariables(node->function, defined, used); 91 | for (auto argument : node->arguments) 92 | { 93 | RemoveUnnecessaryVariables(argument, defined, used); 94 | } 95 | } 96 | 97 | void Visit(AstLambdaExpression* node)override 98 | { 99 | RemoveUnnecessaryVariables(node->statement, defined, used, node->statement); 100 | } 101 | }; 102 | 103 | /************************************************************* 104 | AstStatement::RemoveUnnecessaryVariables 105 | *************************************************************/ 106 | 107 | class AstStatement_RemoveUnnecessaryVariables : public AstStatementVisitor 108 | { 109 | private: 110 | set>& defined; 111 | set>& used; 112 | AstStatement::Ptr& replacement; 113 | public: 114 | AstStatement_RemoveUnnecessaryVariables(set>& _defined, set>& _used, AstStatement::Ptr& _replacement) 115 | :defined(_defined), used(_used), replacement(_replacement) 116 | { 117 | } 118 | 119 | void Visit(AstBlockStatement* node)override 120 | { 121 | for (int i = node->statements.size() - 1; i >= 0; i--) 122 | { 123 | RemoveUnnecessaryVariables(node->statements[i], defined, used, node->statements[i]); 124 | } 125 | } 126 | 127 | void Visit(AstExpressionStatement* node)override 128 | { 129 | RemoveUnnecessaryVariables(node->expression, defined, used); 130 | } 131 | 132 | void Visit(AstDeclarationStatement* node)override 133 | { 134 | if (defined.find(node->declaration) != defined.end() && used.find(node->declaration) == used.end()) 135 | { 136 | replacement = make_shared(); 137 | } 138 | } 139 | 140 | void Visit(AstAssignmentStatement* node)override 141 | { 142 | auto leftValue = GetRootLeftValue(node->target); 143 | if (defined.find(leftValue) != defined.end() && used.find(leftValue) == used.end()) 144 | { 145 | AstExpression::List exprs; 146 | CollectSideEffectExpressions(node->target, exprs); 147 | CollectSideEffectExpressions(node->value, exprs); 148 | 149 | auto block = make_shared(); 150 | for (auto expr : exprs) 151 | { 152 | auto stat = make_shared(); 153 | stat->expression = expr; 154 | block->statements.push_back(stat); 155 | } 156 | replacement = block; 157 | } 158 | } 159 | 160 | void Visit(AstIfStatement* node)override 161 | { 162 | RemoveUnnecessaryVariables(node->trueBranch, defined, used, node->trueBranch); 163 | if (node->falseBranch) 164 | { 165 | RemoveUnnecessaryVariables(node->falseBranch, defined, used, node->falseBranch); 166 | } 167 | } 168 | }; 169 | 170 | /************************************************************* 171 | RemoveUnnecessaryVariables 172 | *************************************************************/ 173 | 174 | void RemoveUnnecessaryVariables(AstExpression::Ptr node, set>& defined, set>& used) 175 | { 176 | AstExpression_RemoveUnnecessaryVariables visitor(defined, used); 177 | node->Accept(&visitor); 178 | } 179 | 180 | void RemoveUnnecessaryVariables(AstStatement::Ptr node, set>& defined, set>& used, AstStatement::Ptr& replacement) 181 | { 182 | AstStatement_RemoveUnnecessaryVariables visitor(defined, used, replacement); 183 | node->Accept(&visitor); 184 | } 185 | } 186 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_RoughlyOptimize.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstDeclaration::RoughlyOptimize 9 | *************************************************************/ 10 | 11 | class AstDeclaration_RoughlyOptimize : public AstDeclarationVisitor 12 | { 13 | public: 14 | void Visit(AstSymbolDeclaration* node)override 15 | { 16 | } 17 | 18 | void Visit(AstTypeDeclaration* node)override 19 | { 20 | } 21 | 22 | void Visit(AstFunctionDeclaration* node)override 23 | { 24 | RoughlyOptimize(node->statement, node->statement); 25 | 26 | set defined, used; 27 | CollectUsedVariables(node->statement, defined, used); 28 | RemoveUnnecessaryVariables(node->statement, defined, used, node->statement); 29 | 30 | RoughlyOptimize(node->statement, node->statement); 31 | } 32 | }; 33 | 34 | /************************************************************* 35 | AstExpression::RoughlyOptimize 36 | *************************************************************/ 37 | 38 | class AstExpression_RoughlyOptimize : public AstExpressionVisitor 39 | { 40 | private: 41 | AstExpression::Ptr& replacement; 42 | 43 | public: 44 | AstExpression_RoughlyOptimize(AstExpression::Ptr& _replacement) 45 | :replacement(_replacement) 46 | { 47 | 48 | } 49 | 50 | void Visit(AstLiteralExpression* node)override 51 | { 52 | } 53 | 54 | void Visit(AstIntegerExpression* node)override 55 | { 56 | } 57 | 58 | void Visit(AstFloatExpression* node)override 59 | { 60 | } 61 | 62 | void Visit(AstStringExpression* node)override 63 | { 64 | } 65 | 66 | void Visit(AstExternalSymbolExpression* node)override 67 | { 68 | } 69 | 70 | void Visit(AstReferenceExpression* node)override 71 | { 72 | } 73 | 74 | void Visit(AstNewTypeExpression* node)override 75 | { 76 | for (auto& field : node->fields) 77 | { 78 | RoughlyOptimize(field, field); 79 | } 80 | } 81 | 82 | void Visit(AstTestTypeExpression* node)override 83 | { 84 | RoughlyOptimize(node->target, node->target); 85 | } 86 | 87 | void Visit(AstNewArrayExpression* node)override 88 | { 89 | RoughlyOptimize(node->length, node->length); 90 | } 91 | 92 | void Visit(AstNewArrayLiteralExpression* node)override 93 | { 94 | for (auto& element : node->elements) 95 | { 96 | RoughlyOptimize(element, element); 97 | } 98 | } 99 | 100 | void Visit(AstArrayLengthExpression* node)override 101 | { 102 | RoughlyOptimize(node->target, node->target); 103 | } 104 | 105 | void Visit(AstArrayAccessExpression* node)override 106 | { 107 | RoughlyOptimize(node->target, node->target); 108 | RoughlyOptimize(node->index, node->index); 109 | } 110 | 111 | void Visit(AstFieldAccessExpression* node)override 112 | { 113 | RoughlyOptimize(node->target, node->target); 114 | } 115 | 116 | void Visit(AstInvokeExpression* node)override 117 | { 118 | RoughlyOptimize(node->function, node->function); 119 | for (auto& argument : node->arguments) 120 | { 121 | RoughlyOptimize(argument, argument); 122 | } 123 | } 124 | 125 | void Visit(AstLambdaExpression* node)override 126 | { 127 | shared_ptr stat; 128 | if (!(stat = dynamic_pointer_cast(node->statement))) 129 | { 130 | if (auto block = dynamic_pointer_cast(node->statement)) 131 | { 132 | if (block->statements.size() == 1) 133 | { 134 | stat = dynamic_pointer_cast(block->statements[0]); 135 | } 136 | } 137 | } 138 | 139 | if (stat) 140 | { 141 | if (auto invoke = dynamic_pointer_cast(stat->expression)) 142 | { 143 | if (node->arguments.size() != invoke->arguments.size()) 144 | { 145 | goto FAIL_TO_OPTIMIZE; 146 | } 147 | if (auto ref = dynamic_pointer_cast(invoke->function)) 148 | { 149 | auto decl = ref->reference.lock(); 150 | for (auto argument : node->arguments) 151 | { 152 | if (decl == argument) 153 | { 154 | goto FAIL_TO_OPTIMIZE; 155 | } 156 | } 157 | 158 | for (int i = 0; (size_t)i < node->arguments.size(); i++) 159 | { 160 | if (auto arg = dynamic_pointer_cast(invoke->arguments[i])) 161 | { 162 | if (arg->reference.lock() != node->arguments[i]) 163 | { 164 | goto FAIL_TO_OPTIMIZE; 165 | } 166 | } 167 | else 168 | { 169 | goto FAIL_TO_OPTIMIZE; 170 | } 171 | } 172 | 173 | replacement = invoke->function; 174 | return; 175 | } 176 | } 177 | } 178 | 179 | FAIL_TO_OPTIMIZE: 180 | RoughlyOptimize(node->statement, node->statement); 181 | } 182 | }; 183 | 184 | /************************************************************* 185 | AstStatement::RoughlyOptimize 186 | *************************************************************/ 187 | 188 | class AstStatement_RoughlyOptimize : public AstStatementVisitor 189 | { 190 | private: 191 | AstStatement::Ptr& replacement; 192 | 193 | public: 194 | AstStatement_RoughlyOptimize(AstStatement::Ptr& _replacement) 195 | :replacement(_replacement) 196 | { 197 | 198 | } 199 | 200 | void Visit(AstBlockStatement* node)override 201 | { 202 | for (auto& stat : node->statements) 203 | { 204 | RoughlyOptimize(stat, stat); 205 | } 206 | 207 | AstStatement::List stats; 208 | for (auto stat : node->statements) 209 | { 210 | ExpandBlock(stat, stats, stat == *(node->statements.end() - 1)); 211 | } 212 | node->statements = std::move(stats); 213 | } 214 | 215 | void Visit(AstExpressionStatement* node)override 216 | { 217 | RoughlyOptimize(node->expression, node->expression); 218 | if (auto invoke = dynamic_pointer_cast(node->expression)) 219 | { 220 | if (auto lambda = dynamic_pointer_cast(invoke->function)) 221 | { 222 | auto block = make_shared(); 223 | for (int i = 0; (size_t)i < lambda->arguments.size(); i++) 224 | { 225 | { 226 | auto stat = make_shared(); 227 | stat->declaration = lambda->arguments[i]; 228 | block->statements.push_back(stat); 229 | } 230 | { 231 | auto ref = make_shared(); 232 | ref->reference = lambda->arguments[i]; 233 | 234 | auto stat = make_shared(); 235 | stat->target = ref; 236 | stat->value = invoke->arguments[i]; 237 | 238 | block->statements.push_back(stat); 239 | } 240 | } 241 | block->statements.push_back(lambda->statement); 242 | 243 | replacement = block; 244 | goto END_OF_REPLACEMENT; 245 | } 246 | } 247 | 248 | { 249 | AstExpression::List exprs; 250 | CollectSideEffectExpressions(node->expression, exprs); 251 | if (exprs.size() == 0) 252 | { 253 | replacement = make_shared(); 254 | } 255 | else if (exprs[0].get() != node->expression.get()) 256 | { 257 | auto block = make_shared(); 258 | for (auto expr : exprs) 259 | { 260 | auto stat = make_shared(); 261 | stat->expression = expr; 262 | block->statements.push_back(stat); 263 | } 264 | replacement = block; 265 | } 266 | } 267 | 268 | END_OF_REPLACEMENT: 269 | if (replacement.get() != node) 270 | { 271 | RoughlyOptimize(replacement, replacement); 272 | } 273 | } 274 | 275 | void Visit(AstDeclarationStatement* node)override 276 | { 277 | } 278 | 279 | void Visit(AstAssignmentStatement* node)override 280 | { 281 | RoughlyOptimize(node->target, node->target); 282 | RoughlyOptimize(node->value, node->value); 283 | } 284 | 285 | void Visit(AstIfStatement* node)override 286 | { 287 | RoughlyOptimize(node->condition, node->condition); 288 | RoughlyOptimize(node->trueBranch, node->trueBranch); 289 | if (node->falseBranch) 290 | { 291 | RoughlyOptimize(node->falseBranch, node->falseBranch); 292 | } 293 | } 294 | }; 295 | 296 | /************************************************************* 297 | RoughlyOptimize 298 | *************************************************************/ 299 | 300 | void RoughlyOptimize(AstDeclaration::Ptr node) 301 | { 302 | AstDeclaration_RoughlyOptimize visitor; 303 | node->Accept(&visitor); 304 | } 305 | 306 | void RoughlyOptimize(AstExpression::Ptr node, AstExpression::Ptr& _replacement) 307 | { 308 | AstExpression_RoughlyOptimize visitor(_replacement); 309 | node->Accept(&visitor); 310 | } 311 | 312 | void RoughlyOptimize(AstStatement::Ptr node, AstStatement::Ptr& _replacement) 313 | { 314 | AstStatement_RoughlyOptimize visitor(_replacement); 315 | node->Accept(&visitor); 316 | } 317 | 318 | void RoughlyOptimize(AstAssembly::Ptr node) 319 | { 320 | for (auto decl : node->declarations) 321 | { 322 | RoughlyOptimize(decl); 323 | } 324 | } 325 | } 326 | } -------------------------------------------------------------------------------- /Development/Source/Ast/TinymoeAst_SetParent.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAst.h" 2 | 3 | namespace tinymoe 4 | { 5 | namespace ast 6 | { 7 | /************************************************************* 8 | AstDeclaration::SetParent 9 | *************************************************************/ 10 | 11 | class AstDeclaration_SetParent : public AstDeclarationVisitor 12 | { 13 | public: 14 | 15 | void Visit(AstSymbolDeclaration* node)override 16 | { 17 | } 18 | 19 | void Visit(AstTypeDeclaration* node)override 20 | { 21 | for (auto field : node->fields) 22 | { 23 | SetParent(field, node->shared_from_this()); 24 | } 25 | } 26 | 27 | void Visit(AstFunctionDeclaration* node)override 28 | { 29 | if (node->ownerType) 30 | { 31 | SetParent(node->ownerType, node->shared_from_this()); 32 | } 33 | for (auto argument : node->arguments) 34 | { 35 | SetParent(argument, node->shared_from_this()); 36 | } 37 | 38 | SetParent(node->statement, node->shared_from_this()); 39 | } 40 | }; 41 | 42 | /************************************************************* 43 | AstExpression::SetParent 44 | *************************************************************/ 45 | 46 | class AstExpression_SetParent : public AstExpressionVisitor 47 | { 48 | public: 49 | 50 | void Visit(AstLiteralExpression* node)override 51 | { 52 | } 53 | 54 | void Visit(AstIntegerExpression* node)override 55 | { 56 | } 57 | 58 | void Visit(AstFloatExpression* node)override 59 | { 60 | } 61 | 62 | void Visit(AstStringExpression* node)override 63 | { 64 | } 65 | 66 | void Visit(AstExternalSymbolExpression* node)override 67 | { 68 | } 69 | 70 | void Visit(AstReferenceExpression* node)override 71 | { 72 | } 73 | 74 | void Visit(AstNewTypeExpression* node)override 75 | { 76 | SetParent(node->type, node->shared_from_this()); 77 | for (auto field : node->fields) 78 | { 79 | SetParent(field, node->shared_from_this()); 80 | } 81 | } 82 | 83 | void Visit(AstTestTypeExpression* node)override 84 | { 85 | SetParent(node->target, node->shared_from_this()); 86 | SetParent(node->type, node->shared_from_this()); 87 | } 88 | 89 | void Visit(AstNewArrayExpression* node)override 90 | { 91 | SetParent(node->length, node->shared_from_this()); 92 | } 93 | 94 | void Visit(AstNewArrayLiteralExpression* node)override 95 | { 96 | for (auto element : node->elements) 97 | { 98 | SetParent(element, node->shared_from_this()); 99 | } 100 | } 101 | 102 | void Visit(AstArrayLengthExpression* node)override 103 | { 104 | SetParent(node->target, node->shared_from_this()); 105 | } 106 | 107 | void Visit(AstArrayAccessExpression* node)override 108 | { 109 | SetParent(node->target, node->shared_from_this()); 110 | SetParent(node->index, node->shared_from_this()); 111 | } 112 | 113 | void Visit(AstFieldAccessExpression* node)override 114 | { 115 | SetParent(node->target, node->shared_from_this()); 116 | } 117 | 118 | void Visit(AstInvokeExpression* node)override 119 | { 120 | SetParent(node->function, node->shared_from_this()); 121 | for (auto argument : node->arguments) 122 | { 123 | SetParent(argument, node->shared_from_this()); 124 | } 125 | } 126 | 127 | void Visit(AstLambdaExpression* node)override 128 | { 129 | for (auto argument : node->arguments) 130 | { 131 | SetParent(argument, node->shared_from_this()); 132 | } 133 | SetParent(node->statement, node->shared_from_this()); 134 | } 135 | }; 136 | 137 | /************************************************************* 138 | AstStatement::SetParentInternal 139 | *************************************************************/ 140 | 141 | class AstStatement_SetParent : public AstStatementVisitor 142 | { 143 | public: 144 | 145 | void Visit(AstBlockStatement* node)override 146 | { 147 | for (auto statement : node->statements) 148 | { 149 | SetParent(statement, node->shared_from_this()); 150 | } 151 | } 152 | 153 | void Visit(AstExpressionStatement* node)override 154 | { 155 | SetParent(node->expression, node->shared_from_this()); 156 | } 157 | 158 | void Visit(AstDeclarationStatement* node)override 159 | { 160 | SetParent(node->declaration, node->shared_from_this()); 161 | } 162 | 163 | void Visit(AstAssignmentStatement* node)override 164 | { 165 | SetParent(node->target, node->shared_from_this()); 166 | SetParent(node->value, node->shared_from_this()); 167 | } 168 | 169 | void Visit(AstIfStatement* node)override 170 | { 171 | SetParent(node->condition, node->shared_from_this()); 172 | SetParent(node->trueBranch, node->shared_from_this()); 173 | if (node->falseBranch) 174 | { 175 | SetParent(node->falseBranch, node->shared_from_this()); 176 | } 177 | } 178 | }; 179 | 180 | /************************************************************* 181 | AstType::SetParent 182 | *************************************************************/ 183 | 184 | class AstType_SetParent : public AstTypeVisitor 185 | { 186 | public: 187 | 188 | void Visit(AstPredefinedType* node)override 189 | { 190 | } 191 | 192 | void Visit(AstReferenceType* node)override 193 | { 194 | } 195 | }; 196 | 197 | /************************************************************* 198 | AstAssembly::SetParent 199 | *************************************************************/ 200 | 201 | class AstNode_SetParent : public AstVisitor 202 | { 203 | public: 204 | 205 | void Visit(AstType* node)override 206 | { 207 | AstType_SetParent visitor; 208 | node->Accept(&visitor); 209 | } 210 | 211 | void Visit(AstExpression* node)override 212 | { 213 | AstExpression_SetParent visitor; 214 | node->Accept(&visitor); 215 | } 216 | 217 | void Visit(AstStatement* node)override 218 | { 219 | AstStatement_SetParent visitor; 220 | node->Accept(&visitor); 221 | } 222 | 223 | void Visit(AstDeclaration* node)override 224 | { 225 | AstDeclaration_SetParent visitor; 226 | node->Accept(&visitor); 227 | } 228 | 229 | void Visit(AstAssembly* node)override 230 | { 231 | for (auto decl : node->declarations) 232 | { 233 | SetParent(decl, node->shared_from_this()); 234 | } 235 | } 236 | }; 237 | 238 | /************************************************************* 239 | SetParent 240 | *************************************************************/ 241 | 242 | void SetParent(AstNode::Ptr node, AstNode::WeakPtr _parent) 243 | { 244 | ASSERT(node->parent.expired()); 245 | node->parent = _parent; 246 | AstNode_SetParent visitor; 247 | node->Accept(&visitor); 248 | } 249 | } 250 | } -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeAstCodegen.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_COMPILER_TINYMOEASTCODEGEN 2 | #define VCZH_COMPILER_TINYMOEASTCODEGEN 3 | 4 | #include "TinymoeStatementAnalyzer.h" 5 | #include "../Ast/TinymoeAst.h" 6 | 7 | namespace tinymoe 8 | { 9 | namespace compiler 10 | { 11 | class SymbolAstScope 12 | { 13 | public: 14 | typedef shared_ptr Ptr; 15 | typedef map SymbolAstDeclarationMap; 16 | typedef map SymbolAstFunctionDeclarationMap; 17 | 18 | SymbolAstDeclarationMap readAsts; 19 | SymbolAstDeclarationMap writeAsts; 20 | SymbolAstFunctionDeclarationMap functionPrototypes; 21 | ast::AstDeclaration::Ptr opPos, opNeg, opNot, opConcat, opAdd, opSub, opMul, opDiv, opIntDiv, opMod, opLT, opGT, opLE, opGE, opEQ, opNE, opAnd, opOr; 22 | 23 | ast::AstType::Ptr GetType(GrammarSymbol::Ptr symbol); 24 | }; 25 | 26 | struct SymbolAstContext 27 | { 28 | int uniqueId = 0; 29 | ast::AstFunctionDeclaration::Ptr function; 30 | ast::AstSymbolDeclaration::Ptr continuation; 31 | GrammarSymbol::List createdVariables; 32 | 33 | string_t GetUniquePostfix(); 34 | }; 35 | 36 | struct SymbolAstResult 37 | { 38 | shared_ptr value; 39 | shared_ptr statement; 40 | shared_ptr continuation; 41 | 42 | SymbolAstResult(); 43 | SymbolAstResult(shared_ptr _value); 44 | SymbolAstResult(shared_ptr _statement); 45 | SymbolAstResult(shared_ptr _value, shared_ptr _statement, shared_ptr _continuation); 46 | 47 | bool RequireCps()const; 48 | SymbolAstResult ReplaceValue(shared_ptr _value); 49 | SymbolAstResult ReplaceValue(shared_ptr _value, shared_ptr _continuation); 50 | void MergeForExpression(const SymbolAstResult& result, SymbolAstContext& context, vector& exprs, int& exprStart, ast::AstDeclaration::Ptr& state); 51 | static void AppendStatement(ast::AstStatement::Ptr& target, ast::AstStatement::Ptr statement); 52 | void AppendStatement(ast::AstStatement::Ptr _statement); 53 | void MergeForStatement(const SymbolAstResult& result, ast::AstDeclaration::Ptr& state); 54 | }; 55 | 56 | extern ast::AstAssembly::Ptr GenerateAst(SymbolAssembly::Ptr symbolAssembly); 57 | } 58 | } 59 | 60 | #endif -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeAstCodegen_Declaration.cpp: -------------------------------------------------------------------------------- 1 | #include "TinymoeAstCodegen.h" 2 | 3 | using namespace tinymoe::ast; 4 | 5 | namespace tinymoe 6 | { 7 | namespace compiler 8 | { 9 | 10 | /************************************************************* 11 | Declaration::GenerateAst 12 | *************************************************************/ 13 | 14 | shared_ptr SymbolDeclaration::GenerateAst(shared_ptr symbolModule) 15 | { 16 | auto ast = make_shared(); 17 | ast->composedName = symbolModule->module->name->GetComposedName() + T("::") + name->GetComposedName(); 18 | return ast; 19 | } 20 | 21 | shared_ptr TypeDeclaration::GenerateAst(shared_ptr symbolModule) 22 | { 23 | auto ast = make_shared(); 24 | ast->composedName = symbolModule->module->name->GetComposedName() + T("::") + name->GetComposedName(); 25 | for (auto field : fields) 26 | { 27 | auto astField = make_shared(); 28 | astField->composedName = field->GetComposedName(); 29 | ast->fields.push_back(astField); 30 | } 31 | return ast; 32 | } 33 | 34 | string_t FunctionDeclaration::GetComposedName() 35 | { 36 | string_t result; 37 | for (auto it = name.begin(); it != name.end(); it++) 38 | { 39 | result += (*it)->GetComposedName(type == FunctionDeclarationType::Phrase && (it == name.begin() || it + 1 == name.end())); 40 | if (it + 1 != name.end()) 41 | { 42 | result += T("_"); 43 | } 44 | } 45 | return result; 46 | } 47 | 48 | shared_ptr FunctionDeclaration::GenerateAst(shared_ptr symbolModule) 49 | { 50 | auto ast = make_shared(); 51 | ast->composedName = symbolModule->module->name->GetComposedName() + T("::") + GetComposedName(); 52 | 53 | { 54 | auto argument = make_shared(); 55 | argument->composedName = T("$the_result"); 56 | ast->resultVariable = argument; 57 | } 58 | { 59 | auto argument = make_shared(); 60 | if (cps && cps->stateName) 61 | { 62 | argument->composedName = cps->stateName->GetComposedName(); 63 | } 64 | else 65 | { 66 | argument->composedName = T("$state"); 67 | } 68 | ast->arguments.push_back(argument); 69 | ast->stateArgument = argument; 70 | } 71 | if (category && category->signalName) 72 | { 73 | auto argument = make_shared(); 74 | argument->composedName = category->signalName->GetComposedName(); 75 | ast->arguments.push_back(argument); 76 | ast->signalArgument = argument; 77 | } 78 | if (bodyName) 79 | { 80 | auto argument = bodyName->CreateAst(ast).first; 81 | ast->arguments.push_back(argument); 82 | ast->blockBodyArgument = argument; 83 | } 84 | 85 | for (auto it = name.begin(); it != name.end(); it++) 86 | { 87 | auto pair = (*it)->CreateAst(ast); 88 | if (pair.first) 89 | { 90 | ast->readArgumentAstMap.insert(make_pair(it - name.begin(), ast->arguments.size())); 91 | ast->arguments.push_back(pair.first); 92 | } 93 | if (pair.second) 94 | { 95 | ast->writeArgumentAstMap.insert(make_pair(it - name.begin(), ast->arguments.size())); 96 | ast->arguments.push_back(pair.second); 97 | } 98 | } 99 | 100 | { 101 | auto argument = make_shared(); 102 | if (cps && cps->continuationName) 103 | { 104 | argument->composedName = cps->continuationName->GetComposedName(); 105 | } 106 | else 107 | { 108 | argument->composedName = T("$continuation"); 109 | } 110 | ast->arguments.push_back(argument); 111 | ast->continuationArgument = argument; 112 | } 113 | return ast; 114 | } 115 | } 116 | } -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeDeclarationAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_COMPILER_TINYMOEDECLARATIONANALYZER 2 | #define VCZH_COMPILER_TINYMOEDECLARATIONANALYZER 3 | 4 | #include "TinymoeLexicalAnalyzer.h" 5 | 6 | namespace tinymoe 7 | { 8 | namespace ast 9 | { 10 | class AstNode; 11 | class AstDeclaration; 12 | class AstSymbolDeclaration; 13 | } 14 | 15 | namespace compiler 16 | { 17 | class GrammarSymbol; 18 | class SymbolModule; 19 | class SymbolAstScope; 20 | 21 | /************************************************************* 22 | Function Components 23 | *************************************************************/ 24 | 25 | enum class FunctionDeclarationType 26 | { 27 | Phrase, // expression, cannot be an statement 28 | Sentence, // statement 29 | Block, // block statement 30 | }; 31 | 32 | enum class FunctionArgumentType 33 | { 34 | Normal, // a normal function argument 35 | List, // a tuple marshalled as array 36 | Argument, // for block only, represents an argument to the block body 37 | Expression, // for sentence and block only, represnets a re-evaluable expression 38 | Assignable, // for sentence and block only, represnets a assignable expression 39 | }; 40 | 41 | class FunctionCps : public CodeFragment 42 | { 43 | public: 44 | typedef shared_ptr Ptr; 45 | 46 | SymbolName::Ptr stateName; // for accessing the CPS state object 47 | SymbolName::Ptr continuationName; // (optional) for accessing the CPS continuation function, statement only 48 | 49 | static FunctionCps::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors, int& lineIndex); 50 | }; 51 | 52 | class FunctionCategory : public CodeFragment 53 | { 54 | public: 55 | typedef shared_ptr Ptr; 56 | 57 | SymbolName::Ptr signalName; // (optional) for non-first block (like else if, catch, etc) to access the result from the previous block 58 | SymbolName::Ptr categoryName; // (optional) category for this block 59 | SymbolName::List followCategories; // (optional) categories to follow 60 | SymbolName::List insideCategories; // (optional) categories to be contained 61 | bool closable = false; // (optional) true means this block can be the end of a block series 62 | 63 | static FunctionCategory::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors, int& lineIndex); 64 | }; 65 | 66 | class FunctionFragment abstract : public CodeFragment 67 | { 68 | public: 69 | typedef shared_ptr Ptr; 70 | typedef vector List; 71 | 72 | CodeToken keywordToken; 73 | 74 | virtual shared_ptr CreateSymbol() = 0; 75 | virtual void AppendFunctionSymbol(shared_ptr symbol, bool primitive) = 0; 76 | virtual string_t GetComposedName(bool primitive) = 0; 77 | 78 | typedef pair, shared_ptr> AstPair; 79 | virtual AstPair CreateAst(weak_ptr parent) = 0; 80 | }; 81 | 82 | /************************************************************* 83 | Declarations 84 | *************************************************************/ 85 | 86 | class Declaration abstract : public CodeFragment, public enable_shared_from_this 87 | { 88 | public: 89 | typedef shared_ptr Ptr; 90 | typedef vector List; 91 | 92 | CodeToken keywordToken; 93 | 94 | virtual shared_ptr CreateSymbol(bool secondary) = 0; 95 | virtual shared_ptr GenerateAst(shared_ptr symbolModule) = 0; 96 | }; 97 | 98 | class SymbolDeclaration : public Declaration 99 | { 100 | public: 101 | typedef shared_ptr Ptr; 102 | 103 | SymbolName::Ptr name; 104 | 105 | static SymbolDeclaration::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors, int& lineIndex); 106 | 107 | shared_ptr CreateSymbol(bool secondary)override; 108 | shared_ptr GenerateAst(shared_ptr symbolModule)override; 109 | }; 110 | 111 | class TypeDeclaration : public Declaration 112 | { 113 | public: 114 | typedef shared_ptr Ptr; 115 | 116 | SymbolName::Ptr name; 117 | SymbolName::Ptr parent; // (optional) 118 | SymbolName::List fields; 119 | 120 | static TypeDeclaration::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors, int& lineIndex); 121 | 122 | shared_ptr CreateSymbol(bool secondary)override; 123 | shared_ptr GenerateAst(shared_ptr symbolModule)override; 124 | }; 125 | 126 | class FunctionDeclaration : public Declaration 127 | { 128 | public: 129 | typedef shared_ptr Ptr; 130 | 131 | FunctionCps::Ptr cps; // (optional) for statement and block only 132 | FunctionCategory::Ptr category; // (optional) for block only 133 | FunctionDeclarationType type = FunctionDeclarationType::Phrase; 134 | FunctionFragment::Ptr bodyName; // (optional) argument for block body, block only 135 | FunctionFragment::List name; // function name and arguments 136 | SymbolName::Ptr alias; // (optional) a name that referencing this function 137 | int beginLineIndex = -1; 138 | int codeLineIndex = -1; 139 | int endLineIndex = -1; 140 | 141 | static FunctionDeclaration::Ptr Parse(CodeToken::List::iterator& it, CodeToken::List::iterator end, FunctionDeclaration::Ptr decl, CodeToken ownerToken, CodeError::List& errors); 142 | static FunctionDeclaration::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors, int& lineIndex); 143 | 144 | string_t GetComposedName(); 145 | shared_ptr CreateSymbol(bool secondary)override; 146 | shared_ptr GenerateAst(shared_ptr symbolModule)override; 147 | }; 148 | 149 | /************************************************************* 150 | Function Fragments 151 | *************************************************************/ 152 | 153 | class ArgumentFragment abstract : public FunctionFragment 154 | { 155 | public: 156 | FunctionArgumentType type = FunctionArgumentType::Normal; 157 | 158 | static ArgumentFragment::Ptr Parse(CodeToken::List::iterator& it, CodeToken::List::iterator end, CodeToken ownerToken, CodeError::List& errors); 159 | }; 160 | 161 | class NameFragment : public FunctionFragment 162 | { 163 | public: 164 | SymbolName::Ptr name; // part of the function name 165 | 166 | shared_ptr CreateSymbol()override; 167 | void AppendFunctionSymbol(shared_ptr symbol, bool primitive)override; 168 | string_t GetComposedName(bool primitive)override; 169 | AstPair CreateAst(weak_ptr parent)override; 170 | }; 171 | 172 | class VariableArgumentFragment : public ArgumentFragment 173 | { 174 | public: 175 | FunctionArgumentType type; // type of the form 176 | SymbolName::Ptr name; // name of the argument 177 | SymbolName::Ptr receivingType; // (optional) receiving type for Normal argument only to do multiple dispatching 178 | 179 | shared_ptr CreateSymbol()override; 180 | void AppendFunctionSymbol(shared_ptr symbol, bool primitive)override; 181 | string_t GetComposedName(bool primitive)override; 182 | AstPair CreateAst(weak_ptr parent)override; 183 | }; 184 | 185 | class FunctionArgumentFragment : public ArgumentFragment 186 | { 187 | public: 188 | FunctionDeclaration::Ptr declaration; // declaration for the argument representing a function 189 | 190 | shared_ptr CreateSymbol()override; 191 | void AppendFunctionSymbol(shared_ptr symbol, bool primitive)override; 192 | string_t GetComposedName(bool primitive)override; 193 | AstPair CreateAst(weak_ptr parent)override; 194 | }; 195 | 196 | /************************************************************* 197 | Module 198 | *************************************************************/ 199 | 200 | class Module : public CodeFragment 201 | { 202 | public: 203 | typedef shared_ptr Ptr; 204 | typedef vector List; 205 | 206 | SymbolName::Ptr name; // name of the module 207 | SymbolName::List usings; // other modules whose declarations can be referred in this module 208 | Declaration::List declarations; // declarations in this module 209 | 210 | static Module::Ptr Parse(CodeFile::Ptr codeFile, CodeError::List& errors); 211 | }; 212 | } 213 | } 214 | 215 | #endif -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeExpressionAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_COMPILER_TINYMOEEXPRESSIONANALYZER 2 | #define VCZH_COMPILER_TINYMOEEXPRESSIONANALYZER 3 | 4 | #include "TinymoeLexicalAnalyzer.h" 5 | 6 | namespace tinymoe 7 | { 8 | namespace ast 9 | { 10 | class AstNode; 11 | class AstExpression; 12 | class AstLambdaExpression; 13 | class AstDeclaration; 14 | } 15 | 16 | namespace compiler 17 | { 18 | class SymbolModule; 19 | class SymbolAstScope; 20 | struct SymbolAstContext; 21 | struct SymbolAstResult; 22 | class FunctionFragment; 23 | 24 | /************************************************************* 25 | Symbol 26 | *************************************************************/ 27 | 28 | enum class GrammarFragmentType 29 | { 30 | Name, // for identifier list, e.g. [repeat with] the current number [from] 1 [to] 100 31 | Type, // for type name, e.g. set names to new [hash set] 32 | Primitive, // for primitive expression, e.g. sum from 1 to [10] 33 | Expression, // for all kinds of expressions, e.g. repeat with the current number from [1] to [100] 34 | List, // for tuple (marshalled as array), e.g. set names to collection of [("a", "b", "c")] 35 | Assignable, // for variable, or create a new symbolif the does not exist 36 | // e.g. [a variable] 37 | Argument, // always create a new symbol in the block body 38 | // e.g. repeat with [the current number] from 1 to sum from 1 to 10 39 | }; 40 | 41 | class GrammarFragment 42 | { 43 | public: 44 | typedef shared_ptr Ptr; 45 | typedef vector List; 46 | 47 | GrammarFragmentType type; 48 | vector identifiers; 49 | shared_ptr functionFragment; 50 | 51 | GrammarFragment(GrammarFragmentType _type); 52 | 53 | string_t GetUniqueIdFragment(); 54 | }; 55 | 56 | enum class GrammarSymbolTarget 57 | { 58 | Custom, // user defined symbol 59 | 60 | Object, // (type) object 61 | Array, // (type) array 62 | Symbol, // (type) symbol 63 | Boolean, // (type) boolean 64 | Integer, // (type) integer 65 | Float, // (type) float 66 | String, // (type) string_t 67 | Function, // (type) function 68 | 69 | True, // (primitive) true 70 | False, // (primitive) false 71 | Null, // (primitive) null 72 | TheResult, // (primitive) the result 73 | 74 | Invoke, // (primitive) of 75 | InvokeContinuation, // (primitive) continuation of 76 | NewTypeOfFields, // (primitive) new of 77 | NewArray, // (primitive) new array of items 78 | GetArrayItem, // (primitive) item of array 79 | GetArrayLength, // (primitive) length of array 80 | IsType, // (primitive) is 81 | IsNotType, // (primitive) is not 82 | GetField, // (primitive) field of 83 | 84 | End, // (sentence) end 85 | Select, // (block) select 86 | Case, // (sentence) case 87 | CaseElse, // (sentence) case else 88 | RedirectTo, // (sentence) redirect to 89 | Assign, // (sentence) set to 90 | SetArrayItem, // (sentence) set item of array to 91 | SetField, // (sentence) set field of to 92 | }; 93 | 94 | enum class GrammarSymbolType : int 95 | { 96 | Type = 1, // 97 | Symbol = 2, // 98 | Phrase = 4, // 99 | Sentence = 8, // 100 | Block = 16, // 101 | }; 102 | 103 | class GrammarSymbol 104 | { 105 | public: 106 | typedef shared_ptr Ptr; 107 | typedef vector List; 108 | typedef multimap MultiMap; 109 | 110 | GrammarFragment::List fragments; // grammar fragments for this symbol 111 | // a statement cannot be an expression 112 | // the top invoke expression's function of a statement should reference to a statement symbol 113 | string_t uniqueId; // a string_t that identifies the grammar structure 114 | GrammarSymbolTarget target; 115 | GrammarSymbolType type; 116 | 117 | GrammarSymbol(GrammarSymbolType _type, GrammarSymbolTarget _target = GrammarSymbolTarget::Custom); 118 | 119 | void CalculateUniqueId(); 120 | }; 121 | 122 | GrammarSymbol::Ptr operator+(GrammarSymbol::Ptr symbol, const string_t& name); 123 | GrammarSymbol::Ptr operator+(GrammarSymbol::Ptr symbol, GrammarFragmentType type); 124 | 125 | /************************************************************* 126 | Expression 127 | *************************************************************/ 128 | 129 | class Expression : public CodeFragment 130 | { 131 | public: 132 | typedef shared_ptr Ptr; 133 | typedef vector List; 134 | 135 | virtual string_t ToLog() = 0; 136 | virtual string_t ToCode() = 0; 137 | virtual void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables) = 0; 138 | virtual SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state) = 0; 139 | static shared_ptr GenerateContinuationLambdaAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state); 140 | }; 141 | 142 | // for numbers and strings 143 | class LiteralExpression : public Expression 144 | { 145 | public: 146 | CodeToken token; 147 | 148 | string_t ToLog()override; 149 | string_t ToCode()override; 150 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 151 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 152 | }; 153 | 154 | // for new created symbols in and 155 | class ArgumentExpression : public Expression 156 | { 157 | public: 158 | SymbolName::Ptr name; 159 | 160 | string_t ToLog()override; 161 | string_t ToCode()override; 162 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 163 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 164 | }; 165 | 166 | // for symbol referencing 167 | class ReferenceExpression : public Expression 168 | { 169 | public: 170 | GrammarSymbol::Ptr symbol; 171 | 172 | string_t ToLog()override; 173 | string_t ToCode()override; 174 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 175 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 176 | }; 177 | 178 | // for function invoking 179 | class InvokeExpression : public Expression 180 | { 181 | public: 182 | typedef shared_ptr Ptr; 183 | 184 | Expression::Ptr function; 185 | Expression::List arguments; 186 | 187 | string_t ToLog()override; 188 | string_t ToCode()override; 189 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 190 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 191 | }; 192 | 193 | // for 194 | class ListExpression : public Expression 195 | { 196 | public: 197 | Expression::List elements; 198 | 199 | string_t ToLog()override; 200 | string_t ToCode()override; 201 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 202 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 203 | }; 204 | 205 | enum class UnaryOperator 206 | { 207 | Positive, 208 | Negative, 209 | Not, 210 | }; 211 | 212 | // for unary operator invoking 213 | class UnaryExpression : public Expression 214 | { 215 | public: 216 | Expression::Ptr operand; 217 | UnaryOperator op; 218 | 219 | string_t ToLog()override; 220 | string_t ToCode()override; 221 | void CollectNewAssignable(Expression::List& newAssignables, Expression::List& newArguments, Expression::List& modifiedAssignables)override; 222 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 223 | }; 224 | 225 | enum class BinaryOperator 226 | { 227 | Concat, 228 | Add, 229 | Sub, 230 | Mul, 231 | Div, 232 | IntDiv, 233 | Mod, 234 | LT, 235 | GT, 236 | LE, 237 | GE, 238 | EQ, 239 | NE, 240 | And, 241 | Or, 242 | }; 243 | 244 | // for binary operator invoking 245 | class BinaryExpression : public Expression 246 | { 247 | public: 248 | Expression::Ptr first; 249 | Expression::Ptr second; 250 | BinaryOperator op; 251 | 252 | string_t ToLog()override; 253 | string_t ToCode()override; 254 | void CollectNewAssignable(Expression::List& assignables, Expression::List& arguments, Expression::List& modifiedAssignables)override; 255 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state)override; 256 | }; 257 | 258 | /************************************************************* 259 | Symbol Stack 260 | *************************************************************/ 261 | 262 | class GrammarStackItem 263 | { 264 | public: 265 | typedef shared_ptr Ptr; 266 | typedef vector List; 267 | 268 | GrammarSymbol::List symbols; 269 | 270 | void FillPredefinedSymbols(); 271 | }; 272 | 273 | class GrammarStack 274 | { 275 | public: 276 | typedef shared_ptr Ptr; 277 | typedef CodeToken::List::iterator Iterator; 278 | typedef pair ResultItem; 279 | typedef vector ResultList; 280 | typedef CodeError(GrammarStack::* ParseFunctionType)(Iterator, Iterator, ResultList&); 281 | 282 | GrammarStackItem::List stackItems; // available symbols organized in a scope based structure 283 | GrammarSymbol::MultiMap availableSymbols; // available symbols grouped by the unique identifier 284 | GrammarSymbol::Ptr resultSymbol; 285 | // the last symbol overrides all other symbols in the same group 286 | 287 | struct ExpressionLink 288 | { 289 | typedef shared_ptr Ptr; 290 | 291 | Expression::Ptr expression; 292 | Ptr previous; 293 | }; 294 | 295 | void Push(GrammarStackItem::Ptr stackItem); 296 | GrammarStackItem::Ptr Pop(); 297 | 298 | CodeError SuccessError(); 299 | CodeError ParseToken(const string_t& token, Iterator input, Iterator end, vector& result); 300 | CodeError FoldError(CodeError error1, CodeError error2); 301 | 302 | CodeError ParseGrammarFragment(GrammarFragment::Ptr fragment, Iterator input, Iterator end, ResultList& result); 303 | CodeError ParseGrammarSymbolStep(GrammarSymbol::Ptr symbol, int fragmentIndex, ExpressionLink::Ptr previousExpression, Iterator input, Iterator end, vector>& result); 304 | CodeError ParseGrammarSymbol(GrammarSymbol::Ptr symbol, int beginFragment, ExpressionLink::Ptr previousExpression, Iterator input, Iterator end, ResultList& result); 305 | CodeError ParseGrammarSymbol(GrammarSymbol::Ptr symbol, Iterator input, Iterator end, ResultList& result); 306 | 307 | CodeError ParseType(Iterator input, Iterator end, ResultList& result); // 308 | CodeError ParseShortPrimitive(Iterator input, Iterator end, ResultList& result); // , op , (), 309 | CodeError ParsePrimitive(Iterator input, Iterator end, ResultList& result); // left recursive 310 | CodeError ParseList(Iterator input, Iterator end, ResultList& result); // (, ...) 311 | CodeError ParseAssignable(Iterator input, Iterator end, ResultList& result); // or 312 | CodeError ParseArgument(Iterator input, Iterator end, ResultList& result); // 313 | 314 | CodeError ParseBinary(Iterator input, Iterator end, ParseFunctionType parser, CodeTokenType* tokenTypes, BinaryOperator* binaryOperators, int count, ResultList& result); 315 | CodeError ParseExp1(Iterator input, Iterator end, ResultList& result); // * / 316 | CodeError ParseExp2(Iterator input, Iterator end, ResultList& result); // + - 317 | CodeError ParseExp3(Iterator input, Iterator end, ResultList& result); // & 318 | CodeError ParseExp4(Iterator input, Iterator end, ResultList& result); // < > <= >= = <> 319 | CodeError ParseExp5(Iterator input, Iterator end, ResultList& result); // and 320 | CodeError ParseExpression(Iterator input, Iterator end, ResultList& result); // or, aka. 321 | 322 | CodeError ParseStatement(Iterator input, Iterator end, ResultList& result); 323 | int CountStatementAssignables(Expression::List& assignables); // -1: illegal assignable (e.g. the assignable is a legal expression) 324 | int CountStatementAssignables(Expression::List& assignables, Expression::Ptr& illegalConvertedAssignable); 325 | }; 326 | } 327 | } 328 | 329 | #endif -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeLexicalAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_COMPILER_TINYMOELEXICALANALYZER 2 | #define VCZH_COMPILER_TINYMOELEXICALANALYZER 3 | 4 | #include "../TinymoeSTL.h" 5 | 6 | namespace tinymoe 7 | { 8 | namespace compiler 9 | { 10 | enum class CodeTokenType 11 | { 12 | Integer, 13 | Float, 14 | String, 15 | Identifier, 16 | 17 | Module, // module declaration 18 | Using, // import module declaration 19 | Phrase, // phrase declaration 20 | Sentence, // sentence declaration 21 | Block, // block declaration 22 | Symbol, // symbol declaration 23 | Type, // type declaration 24 | 25 | CPS, // continuation decoration 26 | Category, // block category definition 27 | Expression, // expression argument 28 | Argument, // argument argument 29 | Assignable, // assignable argument 30 | List, // list 31 | 32 | End, // end of an entity 33 | 34 | OpenBracket, // ( 35 | CloseBracket, // ) 36 | Comma, // , 37 | Colon, // : 38 | Concat, // & 39 | Add, // + 40 | Sub, // - 41 | Mul, // * 42 | Div, // / 43 | IntDiv, // \ (can apply on floats) 44 | Mod, // % 45 | LT, // < 46 | GT, // > 47 | LE, // <= 48 | GE, // >= 49 | EQ, // = 50 | NE, // <> 51 | And, // and 52 | Or, // or 53 | Not, // not 54 | 55 | Comment, // -- xxxx 56 | Unknown, 57 | }; 58 | 59 | struct CodeToken 60 | { 61 | typedef vector List; 62 | 63 | CodeTokenType type = CodeTokenType::Unknown; 64 | int row = -1; 65 | int column = -1; 66 | string_t value; 67 | int codeIndex = -1; 68 | 69 | bool IsNameFragmentToken(); 70 | 71 | static string_t EscapeString(string_t value); 72 | static string_t UnescapeString(string_t str); 73 | }; 74 | 75 | struct CodeError 76 | { 77 | typedef vector List; 78 | 79 | CodeToken position; 80 | string_t message; 81 | }; 82 | 83 | struct CodeLine 84 | { 85 | typedef shared_ptr Ptr; 86 | typedef vector List; 87 | 88 | CodeToken::List tokens; 89 | }; 90 | 91 | struct CodeFile 92 | { 93 | typedef shared_ptr Ptr; 94 | typedef vector List; 95 | 96 | CodeLine::List lines; 97 | 98 | static CodeFile::Ptr Parse(const string_t& code, int codeIndex, CodeError::List& errors); 99 | }; 100 | 101 | class CodeFragment 102 | { 103 | public: 104 | CodeFragment(); 105 | virtual ~CodeFragment(); 106 | }; 107 | 108 | class SymbolName : public CodeFragment 109 | { 110 | public: 111 | typedef shared_ptr Ptr; 112 | typedef vector List; 113 | 114 | vector identifiers; 115 | 116 | string_t GetName(); 117 | string_t GetComposedName(); 118 | 119 | static bool ConsumeToken(CodeToken::List::iterator& it, CodeToken::List::iterator end, CodeTokenType tokenType, const string_t& content, CodeToken ownerToken, CodeError::List& errors); 120 | static SymbolName::Ptr ParseToEnd(CodeToken::List::iterator it, CodeToken::List::iterator end, const string_t& ownerName, CodeToken ownerToken, CodeError::List& errors); 121 | static SymbolName::Ptr ParseToFarest(CodeToken::List::iterator& it, CodeToken::List::iterator end, const string_t& ownerName, CodeToken ownerToken, CodeError::List& errors); 122 | }; 123 | } 124 | } 125 | 126 | #endif 127 | -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeStatementAnalyzer.cpp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vczh/tinymoe/673e09e44c5dc6dedad5f802e41537c03fd044f0/Development/Source/Compiler/TinymoeStatementAnalyzer.cpp -------------------------------------------------------------------------------- /Development/Source/Compiler/TinymoeStatementAnalyzer.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_COMPILER_TINYMOESTATEMENTANALYZER 2 | #define VCZH_COMPILER_TINYMOESTATEMENTANALYZER 3 | 4 | #include "TinymoeDeclarationAnalyzer.h" 5 | #include "TinymoeExpressionAnalyzer.h" 6 | 7 | namespace tinymoe 8 | { 9 | namespace ast 10 | { 11 | class AstNode; 12 | class AstDeclaration; 13 | class AstSymbolDeclaration; 14 | class AstStatement; 15 | class AstExpression; 16 | } 17 | 18 | namespace compiler 19 | { 20 | class SymbolModule; 21 | class SymbolAstScope; 22 | struct SymbolAstContext; 23 | struct SymbolAstResult; 24 | 25 | /************************************************************* 26 | Statement 27 | *************************************************************/ 28 | 29 | class Statement : public CodeFragment 30 | { 31 | public: 32 | typedef shared_ptr Ptr; 33 | typedef weak_ptr WeakPtr; 34 | typedef vector List; 35 | typedef map SymbolExpressionMap; 36 | 37 | CodeToken keywordToken; 38 | Statement::WeakPtr parentStatement; 39 | GrammarSymbol::Ptr statementSymbol; 40 | InvokeExpression::Ptr statementExpression; 41 | SymbolExpressionMap newVariables; 42 | SymbolExpressionMap blockArguments; 43 | Statement::List statements; 44 | bool connectToPreviousBlock = false; 45 | 46 | static SymbolAstResult GenerateExitAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state); 47 | static void GenerateAssignableArgumentPairAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal, shared_ptr assignable, vector>::iterator& itvar, shared_ptr& reader, shared_ptr& writer); 48 | static void GenerateExpressionArgumentAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal, shared_ptr expression, shared_ptr& reader); 49 | void CreateNewVariableDeclarations(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal, vector>& newVariableDecls, SymbolAstResult& statResult); 50 | void CreateBlockArgumentDeclarations(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal, vector>& blockArgumentDecls); 51 | SymbolAstResult GeneratePredefinedAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal); 52 | SymbolAstResult GenerateAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr signal); 53 | SymbolAstResult GenerateBodyAst(shared_ptr scope, SymbolAstContext& context, shared_ptr state, shared_ptr continuation); 54 | }; 55 | 56 | /************************************************************* 57 | Symbol 58 | *************************************************************/ 59 | 60 | class SymbolFunction 61 | { 62 | public: 63 | typedef shared_ptr Ptr; 64 | typedef weak_ptr WeakPtr; 65 | typedef vector List; 66 | typedef map SymbolFragmentMap; 67 | typedef map FragmentSymbolMap; 68 | 69 | FunctionDeclaration::Ptr function; // the original function 70 | SymbolFunction::WeakPtr multipleDispatchingRoot; // the multiple-dispatching root declaration 71 | GrammarSymbol::List arguments; // all arguments 72 | SymbolFragmentMap argumentFragments; // map an argument symbol to it's fragment 73 | FragmentSymbolMap argumentTypes; // map an argument to its receiving type 74 | 75 | GrammarSymbol::Ptr resultVariable; 76 | GrammarSymbol::Ptr cpsStateVariable; 77 | GrammarSymbol::Ptr cpsContinuationVariable; 78 | GrammarSymbol::Ptr categorySignalVariable; 79 | 80 | Statement::Ptr statement; // the function body 81 | }; 82 | 83 | class SymbolModule 84 | { 85 | public: 86 | typedef shared_ptr Ptr; 87 | typedef vector List; 88 | typedef weak_ptr WeakPtr; 89 | typedef vector WeakList; 90 | typedef map SymbolDeclarationMap; 91 | typedef map DeclarationFunctionMap; 92 | typedef map DeclarationSymbolMap; 93 | 94 | struct ParsingFailedException{}; 95 | 96 | CodeFile::Ptr codeFile; // the original code file 97 | Module::Ptr module; // the original module 98 | WeakList usingSymbolModules; // all referenced modules 99 | SymbolDeclarationMap symbolDeclarations; // map a grammar symbol to the creator declaration 100 | DeclarationFunctionMap declarationFunctions; // map a declaration to the symbol function 101 | DeclarationSymbolMap baseTypes; // map a type to its base type 102 | 103 | bool IsOverloading(GrammarSymbol::Ptr a, GrammarSymbol::Ptr b); 104 | bool IsMultipleDispatchingChild(FunctionDeclaration::Ptr func); 105 | void CheckOverloading(SymbolModule* modulea, GrammarSymbol::Ptr symbola, Declaration::Ptr decla, SymbolModule* moduleb, GrammarSymbol::Ptr symbolb, Declaration::Ptr declb, bool foreignCheck, CodeError::List& errors); 106 | void BuildSymbols(CodeError::List& errors); // sync step: build all declaration symbols 107 | void BuildFunctions(CodeError::List& errors); // sync step: build all symbol functions 108 | void BuildFunctionLinkings(CodeError::List& errors); // sync step: link all multiple-dispatching functions to it's parent 109 | 110 | void FindOverridedSymbols(GrammarStack::Ptr stack, GrammarStackItem::Ptr item, GrammarSymbol::List& symbols); 111 | void BuildNameSymbol(vector& tokens, GrammarSymbol::Ptr& symbol, CodeToken& token); 112 | FunctionDeclaration::Ptr FindSymbolFunction(GrammarSymbol::Ptr symbol, GrammarSymbolType acceptableType); 113 | Statement::Ptr ParseBlock(CodeFile::Ptr codeFile, GrammarStack::Ptr stack, Statement::Ptr statement, int& lineIndex, int endLineIndex, CodeError::List& errors); 114 | GrammarSymbol::Ptr FindType(SymbolName::Ptr name, GrammarStack::Ptr stack, CodeError::List& errors); 115 | Declaration::Ptr FindDeclaration(GrammarSymbol::Ptr symbol); 116 | void BuildStatements(GrammarStack::Ptr stack, CodeError::List& errors); // sync step: parse all statements 117 | }; 118 | 119 | class SymbolAssembly 120 | { 121 | public: 122 | typedef shared_ptr Ptr; 123 | 124 | SymbolModule::List symbolModules; 125 | 126 | static SymbolAssembly::Ptr Parse(vector& codes, CodeError::List& errors); 127 | }; 128 | } 129 | } 130 | 131 | #endif -------------------------------------------------------------------------------- /Development/Source/Tinymoe.cpp: -------------------------------------------------------------------------------- 1 | #include "Tinymoe.h" 2 | 3 | namespace tinymoe 4 | { 5 | /************************************************************* 6 | Helper Functions 7 | *************************************************************/ 8 | } -------------------------------------------------------------------------------- /Development/Source/Tinymoe.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_TINYMOE 2 | #define VCZH_TINYMOE 3 | 4 | #include "Compiler/TinymoeLexicalAnalyzer.h" 5 | #include "Compiler/TinymoeDeclarationAnalyzer.h" 6 | #include "Compiler/TinymoeExpressionAnalyzer.h" 7 | #include "Compiler/TinymoeStatementAnalyzer.h" 8 | #include "Compiler/TinymoeAstCodegen.h" 9 | 10 | #include "Ast/TinymoeAst.h" 11 | 12 | namespace tinymoe 13 | { 14 | } 15 | 16 | #endif -------------------------------------------------------------------------------- /Development/Source/TinymoeSTL.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_TINYMOESTL 2 | #define VCZH_TINYMOESTL 3 | 4 | #include 5 | #include 6 | #include 7 | #include 8 | #include 9 | #include 10 | #include 11 | #include 12 | #include 13 | #include 14 | #include 15 | #include 16 | 17 | #ifndef _MSC_VER 18 | #define abstract 19 | #endif 20 | 21 | using namespace std; 22 | 23 | namespace tinymoe 24 | { 25 | struct AssertFailedException{}; 26 | } 27 | 28 | #define ASSERT(CONDITION) do{if(!(CONDITION)) throw AssertFailedException();}while(0) 29 | 30 | #ifdef UNICODE_TINYMOE 31 | #define _UNICODE_TINYMOE 32 | #endif 33 | 34 | namespace tinymoe 35 | { 36 | #ifdef _UNICODE_TINYMOE 37 | typedef wchar_t char_t; 38 | typedef std::wstring string_t; 39 | typedef std::wifstream ifstream_t; 40 | typedef std::wofstream ofstream_t; 41 | typedef std::wistream istream_t; 42 | typedef std::wostream ostream_t; 43 | typedef std::wstringstream stringstream_t; 44 | 45 | #define T(X) L ## X 46 | #define strtol_t wcstol 47 | #define strtod_t wcstod 48 | #else 49 | typedef char char_t; 50 | typedef std::string string_t; 51 | typedef std::ifstream ifstream_t; 52 | typedef std::ofstream ofstream_t; 53 | typedef std::istream istream_t; 54 | typedef std::ostream ostream_t; 55 | typedef std::stringstream stringstream_t; 56 | 57 | #define T(X) X 58 | #define strtol_t strtol 59 | #define strtod_t strtod 60 | #endif 61 | } 62 | 63 | #endif 64 | -------------------------------------------------------------------------------- /Development/TestCases/Coroutine.txt: -------------------------------------------------------------------------------- 1 | module enumerable 2 | using standard library 3 | 4 | symbol yielding return 5 | symbol yielding break 6 | 7 | type enumerable collection 8 | body 9 | end 10 | 11 | type collection enumerator 12 | value 13 | coroutine 14 | end 15 | 16 | cps (state) (continuation) 17 | category 18 | inside ENUMERATING 19 | sentence yield return (value) 20 | pause coroutine to yielding return with continuation and value 21 | end 22 | 23 | cps (state) (continuation) 24 | category 25 | inside ENUMERATING 26 | sentence yield break 27 | pause coroutine to yielding break with continuation and null 28 | end 29 | 30 | phrase new enumerator from (enumerable) 31 | set coroutine to new coroutine from (field body of enumerable) 32 | set the result to new collection enumerator of (null, coroutine) 33 | end 34 | 35 | cps (state) (continuation) 36 | sentence move (enumerator) to the next 37 | set coroutine to field coroutine of enumerator 38 | if not (coroutine coroutine stopped) 39 | run coroutine coroutine 40 | 41 | select field flag of state 42 | case yielding return 43 | set field value of enumerator to field argument of state 44 | continue coroutine coroutine 45 | case yielding break 46 | set field value of enumerator to null 47 | stop coroutine coroutine 48 | case null 49 | set field value of enumerator to null 50 | stop coroutine coroutine 51 | case else 52 | fall into the previous trap 53 | end 54 | end 55 | end 56 | 57 | phrase (enumerator) reaches the end 58 | set the result to coroutine field coroutine of enumerator stopped 59 | end 60 | 61 | phrase current value of (enumerator) 62 | set the result to field value of (field value of enumerator) 63 | end 64 | 65 | cps (state) 66 | category 67 | start ENUMERATING 68 | closable 69 | block (body) create enumerable to (assignable receiver) 70 | set receiver to new enumerable collection of () 71 | set field body of receiver to body 72 | end 73 | 74 | block (sentence deal with (item)) repeat with (argument item) in (items : enumerable collection) 75 | set enumerator to new enumerator from items 76 | repeat while not (enumerator reaches the end) 77 | move enumerator to the next 78 | deal with current value of enumerator 79 | end 80 | end 81 | 82 | sentence print (message) 83 | redirect to "Print" 84 | end 85 | 86 | phrase main 87 | create enumerable to numbers 88 | repeat with i from 1 to 10 89 | print "Enumerating " & i 90 | yield return i 91 | end 92 | end 93 | 94 | repeat with number in numbers 95 | if number >= 5 96 | break 97 | end 98 | print "Printing " & number 99 | end 100 | end -------------------------------------------------------------------------------- /Development/TestCases/HelloWorld.txt: -------------------------------------------------------------------------------- 1 | module hello world 2 | using standard library 3 | 4 | sentence print (message) 5 | redirect to "Print" 6 | end 7 | 8 | phrase sum from (first number) to (last number) 9 | set the result to 0 10 | repeat with the current number from first number to last number 11 | add the current number to the result 12 | end 13 | end 14 | 15 | phrase main 16 | print "1+ ... +10 = " & sum from 1 to 10 17 | 18 | try 19 | print "I will raise an exception." 20 | raise "exception" 21 | print "The world is mad!" 22 | catch exception 23 | print "So the exception will be caught" 24 | end 25 | 26 | try 27 | print "I will not raise an exception." 28 | print "So there is no exception to catch" 29 | catch exception 30 | print "The world is mad!" 31 | end 32 | end -------------------------------------------------------------------------------- /Development/TestCases/MultipleDispatch.txt: -------------------------------------------------------------------------------- 1 | module geometry 2 | using standard library 3 | 4 | phrase square root of (number) 5 | redirect to "Sqrt" 6 | end 7 | 8 | sentence print (message) 9 | redirect to "Print" 10 | end 11 | 12 | type rectangle 13 | width 14 | height 15 | end 16 | 17 | type triangle 18 | a 19 | b 20 | c 21 | end 22 | 23 | type circle 24 | radius 25 | end 26 | 27 | phrase area of (shape) 28 | raise "This is not a shape." 29 | end 30 | 31 | phrase area of (shape : rectangle) 32 | set the result to field width of shape * field height of shape 33 | end 34 | 35 | phrase area of (shape : triangle) 36 | set a to field a of shape 37 | set b to field b of shape 38 | set c to field c of shape 39 | set p to (a + b + c) / 2 40 | set the result to square root of (p * (p - a) * (p - b) * (p - c)) 41 | end 42 | 43 | phrase area of (shape : circle) 44 | set r to field radius of shape 45 | set the result to r * r * 3.14 46 | end 47 | 48 | phrase (a) and (b) are the same shape 49 | set the result to false 50 | end 51 | 52 | phrase (a : rectangle) and (b : rectangle) are the same shape 53 | set the result to true 54 | end 55 | 56 | phrase (a : triangle) and (b : triangle) are the same shape 57 | set the result to true 58 | end 59 | 60 | phrase (a : circle) and (b : circle) are the same shape 61 | set the result to true 62 | end 63 | 64 | phrase main 65 | set shape one to new triangle of (2, 3, 4) 66 | set shape two to new rectangle of (1, 2) 67 | if shape one and shape two are the same shape 68 | print "This world is mad!" 69 | else 70 | print "Triangle and rectangle are not the same shape!" 71 | end 72 | end -------------------------------------------------------------------------------- /Development/TestCases/UnitTest.txt: -------------------------------------------------------------------------------- 1 | module unit test 2 | using standard library 3 | 4 | sentence print (message) 5 | redirect to "Print" 6 | end 7 | 8 | block (sentence run the test case) test case (name) 9 | try 10 | run the test case 11 | print "PASS: " & name 12 | catch exception 13 | select exception 14 | case "AssertionFailure" 15 | print "FAIL: " & name 16 | case else 17 | print "HALT: " & name 18 | end 19 | end 20 | end 21 | 22 | sentence assert (actual value) should be (expected value) 23 | if actual value <> expected value 24 | assert fail 25 | end 26 | end 27 | 28 | sentence assert fail 29 | raise "AssertionFailure" 30 | end 31 | 32 | phrase pi 33 | set the result to 3.14 34 | end 35 | 36 | phrase main 37 | test case "1+1=2" 38 | assert (1 + 1) should be 2 39 | assert pi should be 3.14 40 | end 41 | 42 | test case "Predefined array functions should work" 43 | set numbers to new array of 10 items 44 | repeat with i from 1 to length of array numbers 45 | set item i of array numbers to i 46 | end 47 | 48 | set sum to 0 49 | repeat with i from 1 to length of array numbers 50 | add item i of array numbers to sum 51 | end 52 | assert sum should be 55 53 | 54 | set the numbers to array of (1, 2, 3, 4, 5, 6, 7, 8, 9, 10) 55 | 56 | set sum to 0 57 | repeat with i in numbers 58 | add i to sum 59 | end 60 | assert sum should be 55 61 | end 62 | 63 | test case "Break should stop the repeating (1)" 64 | set sum to 0 65 | repeat with i from 1 to 10 66 | if i > 5 67 | break 68 | end 69 | add i to sum 70 | end 71 | assert sum should be 15 72 | end 73 | 74 | test case "Break should stop the repeating (2)" 75 | set sum to 0 76 | repeat with i from 1 to 10 77 | add i to sum 78 | if i >= 5 79 | break 80 | end 81 | end 82 | assert sum should be 15 83 | end 84 | 85 | test case "Continue should restart the next repeating" 86 | set sum to 0 87 | repeat with i from 1 to 10 88 | if i > 5 89 | continue 90 | end 91 | add i to sum 92 | end 93 | assert sum should be 15 94 | end 95 | 96 | test case "Only one branch of the if-else statement will be executed" 97 | set a to 0 98 | set b to 0 99 | set c to 0 100 | 101 | if true 102 | set a to 1 103 | else if true 104 | set a to 2 105 | else 106 | set a to 3 107 | end 108 | 109 | if false 110 | set b to 1 111 | else if true 112 | set b to 2 113 | else 114 | set b to 3 115 | end 116 | 117 | if false 118 | set c to 1 119 | else if false 120 | set c to 2 121 | else 122 | set c to 3 123 | end 124 | 125 | assert a should be 1 126 | assert b should be 2 127 | assert c should be 3 128 | end 129 | 130 | test case "A raised exception should be able to catch" 131 | set e to 0 132 | try 133 | raise "exception" 134 | set e to 0 135 | catch exception 136 | set e to exception 137 | end 138 | 139 | assert e should be "exception" 140 | end 141 | 142 | test case "Finally should always be executed" 143 | set e to 0 144 | try 145 | add 1 to e 146 | raise "exception" 147 | add 2 to e 148 | catch exception 149 | add 4 to e 150 | finally 151 | add 8 to e 152 | end 153 | 154 | assert e should be 13 155 | end 156 | 157 | test case "Only one branch of the try-else statement will be executed" 158 | set a to 0 159 | set b to 0 160 | set c to 0 161 | 162 | try 163 | set a to 1 164 | else try 165 | set a to 2 166 | catch exception 167 | set a to 3 168 | end 169 | 170 | try 171 | set b to 1 172 | raise "exception" 173 | else try 174 | set b to 2 175 | catch exception 176 | set b to 3 177 | end 178 | 179 | try 180 | set c to 1 181 | raise "exception" 182 | else try 183 | set c to 2 184 | raise "exception" 185 | catch exception 186 | set c to 3 187 | end 188 | 189 | assert a should be 1 190 | assert b should be 2 191 | assert c should be 3 192 | end 193 | 194 | test case "Exit block should jump out of the correct box" 195 | set e to 0 196 | named block one 197 | add 1 to e 198 | named block two 199 | add 2 to e 200 | named block three 201 | add 4 to e 202 | exit block two 203 | add 8 to e 204 | end 205 | add 16 to e 206 | end 207 | add 32 to e 208 | end 209 | add 64 to e 210 | 211 | assert e should be 103 212 | end 213 | end -------------------------------------------------------------------------------- /Development/Tinymoe.sln: -------------------------------------------------------------------------------- 1 |  2 | Microsoft Visual Studio Solution File, Format Version 12.00 3 | # Visual Studio 2013 4 | VisualStudioVersion = 12.0.21005.1 5 | MinimumVisualStudioVersion = 10.0.40219.1 6 | Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TinymoeUnitTest", "TinymoeUnitTest\TinymoeUnitTest.vcxproj", "{5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}" 7 | EndProject 8 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "CSharpCodegenTest", "CSharpCodegenTest", "{F8034BE6-E11C-4C94-A095-F01E28AA6E4D}" 9 | EndProject 10 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "TinymoeDotNet", "CSharpCodegenTest\TinymoeDotNet\TinymoeDotNet.csproj", "{C38641B3-0B11-40BE-98B2-31EF800926AC}" 11 | EndProject 12 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "StandardLibraryAst", "CSharpCodegenTest\StandardLibraryAst\StandardLibraryAst.csproj", "{9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}" 13 | EndProject 14 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MultipleDispatchAst", "CSharpCodegenTest\MultipleDispatchAst\MultipleDispatchAst.csproj", "{F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}" 15 | EndProject 16 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "YieldReturnAst", "CSharpCodegenTest\YieldReturnAst\YieldReturnAst.csproj", "{850F7E6F-7C55-4242-832E-F677E1224B56}" 17 | EndProject 18 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "UnitTestAst", "CSharpCodegenTest\UnitTestAst\UnitTestAst.csproj", "{4601BB55-CE51-4DC7-8D0B-EABA0AC71678}" 19 | EndProject 20 | Global 21 | GlobalSection(SolutionConfigurationPlatforms) = preSolution 22 | Debug|Any CPU = Debug|Any CPU 23 | Debug|Mixed Platforms = Debug|Mixed Platforms 24 | Debug|Win32 = Debug|Win32 25 | Release|Any CPU = Release|Any CPU 26 | Release|Mixed Platforms = Release|Mixed Platforms 27 | Release|Win32 = Release|Win32 28 | EndGlobalSection 29 | GlobalSection(ProjectConfigurationPlatforms) = postSolution 30 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Debug|Any CPU.ActiveCfg = Debug|Win32 31 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Debug|Mixed Platforms.ActiveCfg = Debug|Win32 32 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Debug|Mixed Platforms.Build.0 = Debug|Win32 33 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Debug|Win32.ActiveCfg = Debug|Win32 34 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Debug|Win32.Build.0 = Debug|Win32 35 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Release|Any CPU.ActiveCfg = Release|Win32 36 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Release|Mixed Platforms.ActiveCfg = Release|Win32 37 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Release|Mixed Platforms.Build.0 = Release|Win32 38 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Release|Win32.ActiveCfg = Release|Win32 39 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD}.Release|Win32.Build.0 = Release|Win32 40 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 41 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Any CPU.Build.0 = Debug|Any CPU 42 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 43 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 44 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Win32.ActiveCfg = Debug|Any CPU 45 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Debug|Win32.Build.0 = Debug|Any CPU 46 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Any CPU.ActiveCfg = Release|Any CPU 47 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Any CPU.Build.0 = Release|Any CPU 48 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 49 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Mixed Platforms.Build.0 = Release|Any CPU 50 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Win32.ActiveCfg = Release|Any CPU 51 | {C38641B3-0B11-40BE-98B2-31EF800926AC}.Release|Win32.Build.0 = Release|Any CPU 52 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 53 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Any CPU.Build.0 = Debug|Any CPU 54 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 55 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 56 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Win32.ActiveCfg = Debug|Any CPU 57 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Debug|Win32.Build.0 = Debug|Any CPU 58 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Any CPU.ActiveCfg = Release|Any CPU 59 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Any CPU.Build.0 = Release|Any CPU 60 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 61 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Mixed Platforms.Build.0 = Release|Any CPU 62 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Win32.ActiveCfg = Release|Any CPU 63 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E}.Release|Win32.Build.0 = Release|Any CPU 64 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 65 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Any CPU.Build.0 = Debug|Any CPU 66 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 67 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 68 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Win32.ActiveCfg = Debug|Any CPU 69 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Debug|Win32.Build.0 = Debug|Any CPU 70 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Any CPU.ActiveCfg = Release|Any CPU 71 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Any CPU.Build.0 = Release|Any CPU 72 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 73 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Mixed Platforms.Build.0 = Release|Any CPU 74 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Win32.ActiveCfg = Release|Any CPU 75 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6}.Release|Win32.Build.0 = Release|Any CPU 76 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 77 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Any CPU.Build.0 = Debug|Any CPU 78 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 79 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 80 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Win32.ActiveCfg = Debug|Any CPU 81 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Debug|Win32.Build.0 = Debug|Any CPU 82 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Any CPU.ActiveCfg = Release|Any CPU 83 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Any CPU.Build.0 = Release|Any CPU 84 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 85 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Mixed Platforms.Build.0 = Release|Any CPU 86 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Win32.ActiveCfg = Release|Any CPU 87 | {850F7E6F-7C55-4242-832E-F677E1224B56}.Release|Win32.Build.0 = Release|Any CPU 88 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Any CPU.ActiveCfg = Debug|Any CPU 89 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Any CPU.Build.0 = Debug|Any CPU 90 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Mixed Platforms.ActiveCfg = Debug|Any CPU 91 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Mixed Platforms.Build.0 = Debug|Any CPU 92 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Win32.ActiveCfg = Debug|Any CPU 93 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Debug|Win32.Build.0 = Debug|Any CPU 94 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Any CPU.ActiveCfg = Release|Any CPU 95 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Any CPU.Build.0 = Release|Any CPU 96 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Mixed Platforms.ActiveCfg = Release|Any CPU 97 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Mixed Platforms.Build.0 = Release|Any CPU 98 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Win32.ActiveCfg = Release|Any CPU 99 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678}.Release|Win32.Build.0 = Release|Any CPU 100 | EndGlobalSection 101 | GlobalSection(SolutionProperties) = preSolution 102 | HideSolutionNode = FALSE 103 | EndGlobalSection 104 | GlobalSection(NestedProjects) = preSolution 105 | {C38641B3-0B11-40BE-98B2-31EF800926AC} = {F8034BE6-E11C-4C94-A095-F01E28AA6E4D} 106 | {9FB5DEF7-F5BB-4C2D-9515-7C6A07C40E1E} = {F8034BE6-E11C-4C94-A095-F01E28AA6E4D} 107 | {F6EF18A5-F9FE-4144-8B9D-71B2E29F79F6} = {F8034BE6-E11C-4C94-A095-F01E28AA6E4D} 108 | {850F7E6F-7C55-4242-832E-F677E1224B56} = {F8034BE6-E11C-4C94-A095-F01E28AA6E4D} 109 | {4601BB55-CE51-4DC7-8D0B-EABA0AC71678} = {F8034BE6-E11C-4C94-A095-F01E28AA6E4D} 110 | EndGlobalSection 111 | EndGlobal 112 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/Main.cpp: -------------------------------------------------------------------------------- 1 | #ifdef _MSC_VER 2 | #define _CRT_SECURE_NO_WARNINGS 3 | #define _CRTDBG_MAP_ALLOC 4 | #include 5 | #include 6 | #endif 7 | 8 | #include "UnitTest.h" 9 | #include "../Source/Tinymoe.h" 10 | 11 | using namespace tinymoe; 12 | 13 | wstring atow(const string& s) 14 | { 15 | wstring buffer; 16 | buffer.resize(s.size() + 1); 17 | mbstowcs(&buffer[0], &s[0], s.size()); 18 | return buffer.c_str(); 19 | } 20 | 21 | string wtoa(const wstring& s) 22 | { 23 | string buffer; 24 | buffer.resize(s.size() * 3 + 1); 25 | wcstombs(&buffer[0], &s[0], s.size()); 26 | return buffer.c_str(); 27 | } 28 | 29 | void WriteAnsiFile(string_t fileName, stringstream_t& ss) 30 | { 31 | #ifdef _UNICODE_TINYMOE 32 | string buffer = wtoa(ss.str()); 33 | #else 34 | string buffer = ss.str(); 35 | #endif 36 | 37 | ofstream o(fileName, ios_base::binary); 38 | o.write(&buffer[0], buffer.size()); 39 | } 40 | 41 | string_t ReadAnsiFile(string_t fileName) 42 | { 43 | ifstream i(fileName, ios_base::binary); 44 | i.seekg(0, ios_base::end); 45 | auto pos = i.tellg(); 46 | i.seekg(0, ios_base::beg); 47 | 48 | string buffer; 49 | buffer.resize((size_t)pos); 50 | i.read(&buffer[0], pos); 51 | 52 | #ifdef _UNICODE_TINYMOE 53 | return atow(buffer); 54 | #else 55 | return buffer; 56 | #endif 57 | } 58 | 59 | string_t GetCodeForStandardLibrary() 60 | { 61 | return ReadAnsiFile(T("../Library/StandardLibrary.txt")); 62 | } 63 | 64 | #ifdef _MSC_VER 65 | int wmain(int argc, wchar_t* args[]) 66 | #else 67 | int main() 68 | #endif 69 | { 70 | #ifdef _MSC_VER 71 | _CrtDumpMemoryLeaks(); 72 | #endif 73 | return 0; 74 | } 75 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TestAstCodegen.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest.h" 2 | #include "../Source/Tinymoe.h" 3 | 4 | using namespace tinymoe; 5 | using namespace tinymoe::compiler; 6 | using namespace tinymoe::ast; 7 | 8 | extern void WriteAnsiFile(string_t fileName, stringstream_t& ss); 9 | extern string_t ReadAnsiFile(string_t fileName); 10 | extern string_t GetCodeForStandardLibrary(); 11 | extern void GenerateCSharpCode(AstAssembly::Ptr assembly, ostream_t& o); 12 | 13 | void CodeGen(vector& codes, string_t name) 14 | { 15 | CodeError::List errors; 16 | auto assembly = SymbolAssembly::Parse(codes, errors); 17 | TEST_ASSERT(errors.size() == 0); 18 | TEST_ASSERT(assembly->symbolModules.size() == codes.size()); 19 | 20 | auto ast = GenerateAst(assembly); 21 | { 22 | stringstream_t o; 23 | Print(ast, o, 0); 24 | WriteAnsiFile(T("../CSharpCodegenTest/") + name + T("/GeneratedAst.txt"), o); 25 | } 26 | { 27 | stringstream_t o; 28 | GenerateCSharpCode(ast, o); 29 | WriteAnsiFile(T("../CSharpCodegenTest/") + name + T("/TinymoeProgram.cs"), o); 30 | } 31 | } 32 | 33 | /************************************************************* 34 | Hello World 35 | *************************************************************/ 36 | 37 | TEST_CASE(TestStandardLibraryAstCodegen) 38 | { 39 | vector codes; 40 | codes.push_back(GetCodeForStandardLibrary()); 41 | codes.push_back(ReadAnsiFile(T("../TestCases/HelloWorld.txt"))); 42 | CodeGen(codes, T("StandardLibraryAst")); 43 | } 44 | 45 | /************************************************************* 46 | Multiple Dispatch 47 | *************************************************************/ 48 | 49 | TEST_CASE(TestMultipleDispatchAstCodegen) 50 | { 51 | vector codes; 52 | codes.push_back(GetCodeForStandardLibrary()); 53 | codes.push_back(ReadAnsiFile(T("../TestCases/MultipleDispatch.txt"))); 54 | CodeGen(codes, T("MultipleDispatchAst")); 55 | } 56 | 57 | /************************************************************* 58 | Yield Return 59 | *************************************************************/ 60 | 61 | TEST_CASE(TestYieldReturnAstCodegen) 62 | { 63 | vector codes; 64 | codes.push_back(GetCodeForStandardLibrary()); 65 | codes.push_back(ReadAnsiFile(T("../TestCases/Coroutine.txt"))); 66 | CodeGen(codes, T("YieldReturnAst")); 67 | } 68 | 69 | /************************************************************* 70 | Unit Test 71 | *************************************************************/ 72 | 73 | TEST_CASE(TestUnitTestAstCodegen) 74 | { 75 | vector codes; 76 | codes.push_back(GetCodeForStandardLibrary()); 77 | codes.push_back(ReadAnsiFile(T("../TestCases/UnitTest.txt"))); 78 | CodeGen(codes, T("UnitTestAst")); 79 | } -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TestExpressionAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest.h" 2 | #include "../Source/Tinymoe.h" 3 | 4 | using namespace tinymoe; 5 | using namespace tinymoe::compiler; 6 | 7 | void Tokenize(const string_t& code, CodeToken::List& tokens) 8 | { 9 | CodeError::List errors; 10 | auto codeFile = CodeFile::Parse(code, 0, errors); 11 | TEST_ASSERT(errors.size() == 0); 12 | TEST_ASSERT(codeFile->lines.size() == 1); 13 | tokens = codeFile->lines[0]->tokens; 14 | } 15 | 16 | TEST_CASE(TestGrammarStack) 17 | { 18 | auto stack = make_shared(); 19 | auto item = make_shared(); 20 | item->FillPredefinedSymbols(); 21 | 22 | stack->Push(item); 23 | TEST_ASSERT(stack->stackItems.size() == 1); 24 | TEST_ASSERT(stack->availableSymbols.size() == item->symbols.size()); 25 | for (auto symbol : item->symbols) 26 | { 27 | auto it = stack->availableSymbols.find(symbol->uniqueId); 28 | TEST_ASSERT(it != stack->availableSymbols.end()); 29 | TEST_ASSERT(it->first == symbol->uniqueId); 30 | TEST_ASSERT(it->second == symbol); 31 | } 32 | 33 | TEST_ASSERT(stack->Pop() == item); 34 | TEST_ASSERT(stack->stackItems.size() == 0); 35 | TEST_ASSERT(stack->availableSymbols.size() == 0); 36 | } 37 | 38 | TEST_CASE(TestParseNameExpression) 39 | { 40 | auto item = make_shared(); 41 | item->FillPredefinedSymbols(); 42 | auto stack = make_shared(); 43 | stack->Push(item); 44 | 45 | CodeToken::List tokens; 46 | GrammarStack::ResultList result; 47 | 48 | { 49 | Tokenize(T("true"), tokens); 50 | result.clear(); 51 | stack->ParsePrimitive(tokens.begin(), tokens.end(), result); 52 | TEST_ASSERT(result.size() == 1); 53 | 54 | auto expr = dynamic_pointer_cast(result[0].second); 55 | TEST_ASSERT(expr); 56 | TEST_ASSERT(expr->symbol->uniqueId == T("true")); 57 | } 58 | { 59 | Tokenize(T("false"), tokens); 60 | result.clear(); 61 | stack->ParsePrimitive(tokens.begin(), tokens.end(), result); 62 | TEST_ASSERT(result.size() == 1); 63 | 64 | auto expr = dynamic_pointer_cast(result[0].second); 65 | TEST_ASSERT(expr); 66 | TEST_ASSERT(expr->symbol->uniqueId == T("false")); 67 | } 68 | { 69 | Tokenize(T("null"), tokens); 70 | result.clear(); 71 | stack->ParsePrimitive(tokens.begin(), tokens.end(), result); 72 | TEST_ASSERT(result.size() == 1); 73 | 74 | auto expr = dynamic_pointer_cast(result[0].second); 75 | TEST_ASSERT(expr); 76 | TEST_ASSERT(expr->symbol->uniqueId == T("null")); 77 | } 78 | } 79 | 80 | TEST_CASE(TestParseTypeExpression) 81 | { 82 | auto item = make_shared(); 83 | item->FillPredefinedSymbols(); 84 | auto stack = make_shared(); 85 | stack->Push(item); 86 | 87 | CodeToken::List tokens; 88 | GrammarStack::ResultList result; 89 | 90 | { 91 | Tokenize(T("array"), tokens); 92 | result.clear(); 93 | stack->ParseType(tokens.begin(), tokens.end(), result); 94 | TEST_ASSERT(result.size() == 1); 95 | 96 | auto expr = dynamic_pointer_cast(result[0].second); 97 | TEST_ASSERT(expr); 98 | TEST_ASSERT(expr->symbol->uniqueId == T("array")); 99 | } 100 | { 101 | Tokenize(T("integer"), tokens); 102 | result.clear(); 103 | stack->ParseType(tokens.begin(), tokens.end(), result); 104 | TEST_ASSERT(result.size() == 1); 105 | 106 | auto expr = dynamic_pointer_cast(result[0].second); 107 | TEST_ASSERT(expr); 108 | TEST_ASSERT(expr->symbol->uniqueId == T("integer")); 109 | } 110 | { 111 | Tokenize(T("float"), tokens); 112 | result.clear(); 113 | stack->ParseType(tokens.begin(), tokens.end(), result); 114 | TEST_ASSERT(result.size() == 1); 115 | 116 | auto expr = dynamic_pointer_cast(result[0].second); 117 | TEST_ASSERT(expr); 118 | TEST_ASSERT(expr->symbol->uniqueId == T("float")); 119 | } 120 | { 121 | Tokenize(T("string"), tokens); 122 | result.clear(); 123 | stack->ParseType(tokens.begin(), tokens.end(), result); 124 | TEST_ASSERT(result.size() == 1); 125 | 126 | auto expr = dynamic_pointer_cast(result[0].second); 127 | TEST_ASSERT(expr); 128 | TEST_ASSERT(expr->symbol->uniqueId == T("string")); 129 | } 130 | { 131 | Tokenize(T("symbol"), tokens); 132 | result.clear(); 133 | stack->ParseType(tokens.begin(), tokens.end(), result); 134 | TEST_ASSERT(result.size() == 1); 135 | 136 | auto expr = dynamic_pointer_cast(result[0].second); 137 | TEST_ASSERT(expr); 138 | TEST_ASSERT(expr->symbol->uniqueId == T("symbol")); 139 | } 140 | } 141 | 142 | TEST_CASE(TestParseArgumentExpression) 143 | { 144 | auto item = make_shared(); 145 | item->FillPredefinedSymbols(); 146 | auto stack = make_shared(); 147 | stack->Push(item); 148 | 149 | CodeToken::List tokens; 150 | GrammarStack::ResultList result; 151 | 152 | Tokenize(T("true end"), tokens); 153 | result.clear(); 154 | stack->ParseArgument(tokens.begin(), tokens.end(), result); 155 | TEST_ASSERT(result.size() == 2); 156 | { 157 | auto expr = dynamic_pointer_cast(result[0].second); 158 | TEST_ASSERT(expr); 159 | TEST_ASSERT(expr->name->identifiers.size() == 1); 160 | TEST_ASSERT(expr->name->identifiers[0].value == T("true")); 161 | } 162 | { 163 | auto expr = dynamic_pointer_cast(result[1].second); 164 | TEST_ASSERT(expr); 165 | TEST_ASSERT(expr->name->identifiers.size() == 2); 166 | TEST_ASSERT(expr->name->identifiers[0].value == T("true")); 167 | TEST_ASSERT(expr->name->identifiers[1].value == T("end")); 168 | } 169 | } 170 | 171 | TEST_CASE(TestParseAssignableExpression) 172 | { 173 | auto item = make_shared(); 174 | item->FillPredefinedSymbols(); 175 | auto stack = make_shared(); 176 | stack->Push(item); 177 | 178 | CodeToken::List tokens; 179 | GrammarStack::ResultList result; 180 | 181 | Tokenize(T("true end"), tokens); 182 | stack->ParseAssignable(tokens.begin(), tokens.end(), result); 183 | TEST_ASSERT(result.size() == 2); 184 | { 185 | auto expr = dynamic_pointer_cast(result[0].second); 186 | TEST_ASSERT(expr); 187 | TEST_ASSERT(expr->symbol->uniqueId == T("true")); 188 | } 189 | { 190 | auto expr = dynamic_pointer_cast(result[1].second); 191 | TEST_ASSERT(expr); 192 | TEST_ASSERT(expr->name->identifiers.size() == 2); 193 | TEST_ASSERT(expr->name->identifiers[0].value == T("true")); 194 | TEST_ASSERT(expr->name->identifiers[1].value == T("end")); 195 | } 196 | } 197 | 198 | Expression::Ptr ParseNonAmbiguousExpression(const string_t& code) 199 | { 200 | auto item = make_shared(); 201 | item->FillPredefinedSymbols(); 202 | auto stack = make_shared(); 203 | stack->Push(item); 204 | 205 | CodeToken::List tokens; 206 | GrammarStack::ResultList result; 207 | 208 | Tokenize(code, tokens); 209 | stack->ParseExpression(tokens.begin(), tokens.end(), result); 210 | 211 | Expression::List fullExpressions; 212 | for (auto r : result) 213 | { 214 | if (r.first == tokens.end()) 215 | { 216 | fullExpressions.push_back(r.second); 217 | } 218 | } 219 | 220 | TEST_ASSERT(fullExpressions.size() == 1); 221 | return fullExpressions[0]; 222 | } 223 | 224 | TEST_CASE(TestParsePrimitiveExpression) 225 | { 226 | auto expr = ParseNonAmbiguousExpression(T("item 1 of array new array of 10 items is not integer")); 227 | auto log = expr->ToLog(); 228 | auto code = expr->ToCode(); 229 | TEST_ASSERT(log == T(" is not (item of array (1, new array of items(10)), integer)")); 230 | TEST_ASSERT(code == T("((item 1 of array (new array of 10 items)) is not (integer))")); 231 | } 232 | 233 | TEST_CASE(TestParseUnaryExpression) 234 | { 235 | auto expr = ParseNonAmbiguousExpression(T("not (-1 is string)")); 236 | auto log = expr->ToLog(); 237 | auto code = expr->ToCode(); 238 | TEST_ASSERT(log == T("not( is (-(1), string))")); 239 | TEST_ASSERT(code == T("(not((-1) is (string)))")); 240 | } 241 | 242 | TEST_CASE(TestParseBinaryExpression) 243 | { 244 | auto expr = ParseNonAmbiguousExpression(T("1+2*3+4")); 245 | auto log = expr->ToLog(); 246 | auto code = expr->ToCode(); 247 | TEST_ASSERT(log == T("+(+(1, *(2, 3)), 4)")); 248 | TEST_ASSERT(code == T("((1 + (2 * 3)) + 4)")); 249 | } 250 | 251 | TEST_CASE(TestParseListExpression) 252 | { 253 | auto expr = ParseNonAmbiguousExpression(T("new object of (1, 2, 3)")); 254 | auto log = expr->ToLog(); 255 | auto code = expr->ToCode(); 256 | TEST_ASSERT(log == T("new of (object, (list: 1, 2, 3))")); 257 | TEST_ASSERT(code == T("(new (object) of (1, 2, 3))")); 258 | } 259 | 260 | Expression::Ptr ParseNonAmbiguousStatement(const string_t& code, GrammarStack::Ptr stack = nullptr) 261 | { 262 | if (!stack) 263 | { 264 | auto item = make_shared(); 265 | item->FillPredefinedSymbols(); 266 | 267 | stack = make_shared(); 268 | stack->Push(item); 269 | } 270 | 271 | CodeToken::List tokens; 272 | GrammarStack::ResultList result; 273 | 274 | Tokenize(code, tokens); 275 | stack->ParseStatement(tokens.begin(), tokens.end(), result); 276 | TEST_ASSERT(result.size() == 1); 277 | return result[0].second; 278 | } 279 | 280 | GrammarStack::Ptr ParseAmbiguousStatement(const string_t& code, Expression::List& expressionResult, GrammarStack::Ptr stack = nullptr) 281 | { 282 | if (!stack) 283 | { 284 | auto item = make_shared(); 285 | item->FillPredefinedSymbols(); 286 | 287 | stack = make_shared(); 288 | stack->Push(item); 289 | } 290 | 291 | CodeToken::List tokens; 292 | GrammarStack::ResultList result; 293 | 294 | Tokenize(code, tokens); 295 | stack->ParseStatement(tokens.begin(), tokens.end(), result); 296 | 297 | for (auto r : result) 298 | { 299 | expressionResult.push_back(r.second); 300 | } 301 | return stack; 302 | } 303 | 304 | TEST_CASE(TestParseStatement) 305 | { 306 | { 307 | auto stat = ParseNonAmbiguousStatement(T("end")); 308 | auto log = stat->ToLog(); 309 | auto code = stat->ToCode(); 310 | TEST_ASSERT(log == T("end()")); 311 | TEST_ASSERT(code == T("(end)")); 312 | } 313 | { 314 | auto stat = ParseNonAmbiguousStatement(T("select item 1 of array new array of 10 items + 1")); 315 | auto log = stat->ToLog(); 316 | auto code = stat->ToCode(); 317 | TEST_ASSERT(log == T("select (+(item of array (1, new array of items(10)), 1))")); 318 | TEST_ASSERT(code == T("(select ((item 1 of array (new array of 10 items)) + 1))")); 319 | } 320 | { 321 | auto stat = ParseNonAmbiguousStatement(T("set true to false")); 322 | auto log = stat->ToLog(); 323 | auto code = stat->ToCode(); 324 | TEST_ASSERT(log == T("set to (true, false)")); 325 | TEST_ASSERT(code == T("(set (true) to (false))")); 326 | } 327 | { 328 | auto stat = ParseNonAmbiguousStatement(T("set new variable to false")); 329 | auto log = stat->ToLog(); 330 | auto code = stat->ToCode(); 331 | TEST_ASSERT(log == T("set to ((argument: new variable), false)")); 332 | TEST_ASSERT(code == T("(set (new variable) to (false))")); 333 | } 334 | } 335 | 336 | TEST_CASE(TestParseAmbiguousStatement) 337 | { 338 | { 339 | Expression::List stats; 340 | auto stack = ParseAmbiguousStatement(T("set field something wrong of null to true"), stats); 341 | TEST_ASSERT(stats.size() == 2); 342 | { 343 | auto stat = stats[0]; 344 | auto log = stat->ToLog(); 345 | auto code = stat->ToCode(); 346 | 347 | Expression::List assignables, arguments, modifiedAssignables; 348 | stat->CollectNewAssignable(assignables, arguments, modifiedAssignables); 349 | auto assignable = stack->CountStatementAssignables(assignables); 350 | 351 | TEST_ASSERT(log == T("set to ((argument: field something wrong of null), true)")); 352 | TEST_ASSERT(code == T("(set (field something wrong of null) to (true))")); 353 | TEST_ASSERT(assignable == -1); 354 | } 355 | { 356 | auto stat = stats[1]; 357 | auto log = stat->ToLog(); 358 | auto code = stat->ToCode(); 359 | 360 | Expression::List assignables, arguments, modifiedAssignables; 361 | stat->CollectNewAssignable(assignables, arguments, modifiedAssignables); 362 | auto assignable = stack->CountStatementAssignables(assignables); 363 | 364 | TEST_ASSERT(log == T("set field of to ((argument: something wrong), null, true)")); 365 | TEST_ASSERT(code == T("(set field (something wrong) of (null) to (true))")); 366 | TEST_ASSERT(assignable == 0); 367 | } 368 | } 369 | } 370 | 371 | TEST_CASE(TestParseStatementInContext) 372 | { 373 | auto stack = make_shared(); 374 | { 375 | auto item = make_shared(); 376 | item->FillPredefinedSymbols(); 377 | stack->Push(item); 378 | } 379 | { 380 | auto item = make_shared(); 381 | 382 | item->symbols.push_back( 383 | make_shared(GrammarSymbolType::Sentence) 384 | + T("print") + GrammarFragmentType::Expression 385 | ); 386 | 387 | item->symbols.push_back( 388 | make_shared(GrammarSymbolType::Phrase) 389 | + T("sum") + T("from") + GrammarFragmentType::Expression + T("to") + GrammarFragmentType::Primitive 390 | ); 391 | 392 | stack->Push(item); 393 | } 394 | { 395 | auto stat = ParseNonAmbiguousStatement(T("print \"1+ ... +100 = \" & sum from 1 to 100"), stack); 396 | auto log = stat->ToLog(); 397 | auto code = stat->ToCode(); 398 | TEST_ASSERT(log == T("print (&(\"1+ ... +100 = \", sum from to (1, 100)))")); 399 | TEST_ASSERT(code == T("(print (\"1+ ... +100 = \" & (sum from 1 to 100)))")); 400 | } 401 | } -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TestLexicalAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest.h" 2 | #include "../Source/Tinymoe.h" 3 | 4 | using namespace tinymoe; 5 | using namespace tinymoe::compiler; 6 | 7 | #define FIRST_LINE(COUNT) TEST_ASSERT(codeFile->lines.size() == COUNT); auto lineIterator = codeFile->lines.begin(); { 8 | #define NEXT_LINE } lineIterator++; { 9 | #define LAST_LINE } lineIterator++; TEST_ASSERT(lineIterator == codeFile->lines.end()) 10 | #define FIRST_TOKEN(COUNT) auto line = *lineIterator; TEST_ASSERT(line->tokens.size() == COUNT); auto tokenIterator = line->tokens.begin() 11 | #define TOKEN(ROW, COLUMN, VALUE, TYPE) TEST_ASSERT(tokenIterator->row == ROW); TEST_ASSERT(tokenIterator->column == COLUMN); TEST_ASSERT(tokenIterator->value == VALUE); TEST_ASSERT(tokenIterator->type == TYPE); tokenIterator++ 12 | #define LAST_TOKEN TEST_ASSERT(tokenIterator == line->tokens.end()) 13 | 14 | TEST_CASE(TestLexerIdentifier) 15 | { 16 | string_t code = T(R"tinymoe( 17 | module test 18 | 19 | phrase main 20 | print "Hello, world!" 21 | end 22 | )tinymoe"); 23 | 24 | CodeError::List errors; 25 | auto codeFile = CodeFile::Parse(code, 0, errors); 26 | 27 | FIRST_LINE(4); 28 | FIRST_TOKEN(2); 29 | TOKEN(2, 1, T("module"), CodeTokenType::Module); 30 | TOKEN(2, 8, T("test"), CodeTokenType::Identifier); 31 | LAST_TOKEN; 32 | NEXT_LINE; 33 | FIRST_TOKEN(2); 34 | TOKEN(4, 1, T("phrase"), CodeTokenType::Phrase); 35 | TOKEN(4, 8, T("main"), CodeTokenType::Identifier); 36 | LAST_TOKEN; 37 | NEXT_LINE; 38 | FIRST_TOKEN(2); 39 | TOKEN(5, 2, T("print"), CodeTokenType::Identifier); 40 | TOKEN(5, 9, T("Hello, world!"), CodeTokenType::String); 41 | LAST_TOKEN; 42 | NEXT_LINE; 43 | FIRST_TOKEN(1); 44 | TOKEN(6, 1, T("end"), CodeTokenType::End); 45 | LAST_TOKEN; 46 | LAST_LINE; 47 | } 48 | 49 | TEST_CASE(TestLexerNumber) 50 | { 51 | string_t code = T(R"tinymoe( 52 | 11 22. 33.44 53 | )tinymoe"); 54 | 55 | CodeError::List errors; 56 | auto codeFile = CodeFile::Parse(code, 0, errors); 57 | 58 | FIRST_LINE(1); 59 | FIRST_TOKEN(3); 60 | TOKEN(2, 1, T("11"), CodeTokenType::Integer); 61 | TOKEN(2, 4, T("22"), CodeTokenType::Integer); 62 | TOKEN(2, 8, T("33.44"), CodeTokenType::Float); 63 | LAST_TOKEN; 64 | LAST_LINE; 65 | 66 | TEST_ASSERT(errors.size() == 1); 67 | TEST_ASSERT(errors[0].position.value == T(".")); 68 | } 69 | 70 | TEST_CASE(TestLexerOperators) 71 | { 72 | string_t code = T(R"tinymoe( 73 | (),:&+-*/<<=>>==<>--xxx 74 | - - 75 | )tinymoe"); 76 | 77 | CodeError::List errors; 78 | auto codeFile = CodeFile::Parse(code, 0, errors); 79 | 80 | FIRST_LINE(2); 81 | FIRST_TOKEN(15); 82 | TOKEN(2, 1, T("("), CodeTokenType::OpenBracket); 83 | TOKEN(2, 2, T(")"), CodeTokenType::CloseBracket); 84 | TOKEN(2, 3, T(","), CodeTokenType::Comma); 85 | TOKEN(2, 4, T(":"), CodeTokenType::Colon); 86 | TOKEN(2, 5, T("&"), CodeTokenType::Concat); 87 | TOKEN(2, 6, T("+"), CodeTokenType::Add); 88 | TOKEN(2, 7, T("-"), CodeTokenType::Sub); 89 | TOKEN(2, 8, T("*"), CodeTokenType::Mul); 90 | TOKEN(2, 9, T("/"), CodeTokenType::Div); 91 | TOKEN(2, 10, T("<"), CodeTokenType::LT); 92 | TOKEN(2, 11, T("<="), CodeTokenType::LE); 93 | TOKEN(2, 13, T(">"), CodeTokenType::GT); 94 | TOKEN(2, 14, T(">="), CodeTokenType::GE); 95 | TOKEN(2, 16, T("="), CodeTokenType::EQ); 96 | TOKEN(2, 17, T("<>"), CodeTokenType::NE); 97 | LAST_TOKEN; 98 | NEXT_LINE; 99 | FIRST_TOKEN(2); 100 | TOKEN(3, 1, T("-"), CodeTokenType::Sub); 101 | TOKEN(3, 3, T("-"), CodeTokenType::Sub); 102 | LAST_TOKEN; 103 | LAST_LINE; 104 | } 105 | 106 | TEST_CASE(TestLexerKeywords) 107 | { 108 | string_t code = T(R"tinymoe( 109 | module using 110 | phrase sentence block symbol type 111 | cps category expression argument 112 | end and or not 113 | )tinymoe"); 114 | 115 | CodeError::List errors; 116 | auto codeFile = CodeFile::Parse(code, 0, errors); 117 | 118 | FIRST_LINE(4); 119 | FIRST_TOKEN(2); 120 | TOKEN(2, 1, T("module"), CodeTokenType::Module); 121 | TOKEN(2, 8, T("using"), CodeTokenType::Using); 122 | LAST_TOKEN; 123 | NEXT_LINE; 124 | FIRST_TOKEN(5); 125 | TOKEN(3, 1, T("phrase"), CodeTokenType::Phrase); 126 | TOKEN(3, 8, T("sentence"), CodeTokenType::Sentence); 127 | TOKEN(3, 17, T("block"), CodeTokenType::Block); 128 | TOKEN(3, 23, T("symbol"), CodeTokenType::Symbol); 129 | TOKEN(3, 30, T("type"), CodeTokenType::Type); 130 | LAST_TOKEN; 131 | NEXT_LINE; 132 | FIRST_TOKEN(4); 133 | TOKEN(4, 1, T("cps"), CodeTokenType::CPS); 134 | TOKEN(4, 5, T("category"), CodeTokenType::Category); 135 | TOKEN(4, 14, T("expression"), CodeTokenType::Expression); 136 | TOKEN(4, 25, T("argument"), CodeTokenType::Argument); 137 | LAST_TOKEN; 138 | NEXT_LINE; 139 | FIRST_TOKEN(4); 140 | TOKEN(5, 1, T("end"), CodeTokenType::End); 141 | TOKEN(5, 5, T("and"), CodeTokenType::And); 142 | TOKEN(5, 9, T("or"), CodeTokenType::Or); 143 | TOKEN(5, 12, T("not"), CodeTokenType::Not); 144 | LAST_TOKEN; 145 | LAST_LINE; 146 | } 147 | 148 | TEST_CASE(TestLexerString) 149 | { 150 | string_t code = T(R"tinymoe( 151 | "First line\r\nSecond \"line\"" 152 | "Unfinished line 153 | "Unfinished escaping\ 154 | "Third line\r\nFourth line" 155 | )tinymoe"); 156 | 157 | CodeError::List errors; 158 | auto codeFile = CodeFile::Parse(code, 0, errors); 159 | 160 | FIRST_LINE(2); 161 | FIRST_TOKEN(1); 162 | TOKEN(2, 2, T("First line\r\nSecond \"line\""), CodeTokenType::String); 163 | LAST_TOKEN; 164 | NEXT_LINE; 165 | FIRST_TOKEN(1); 166 | TOKEN(5, 2, T("Third line\r\nFourth line"), CodeTokenType::String); 167 | LAST_TOKEN; 168 | LAST_LINE; 169 | 170 | TEST_ASSERT(errors.size() == 2); 171 | TEST_ASSERT(errors[0].position.value == T("\"Unfinished line")); 172 | TEST_ASSERT(errors[1].position.value == T("\"Unfinished escaping\\")); 173 | } -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TestStatementAnalyzer.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest.h" 2 | #include "../Source/Tinymoe.h" 3 | 4 | using namespace tinymoe; 5 | using namespace tinymoe::compiler; 6 | 7 | extern string_t GetCodeForStandardLibrary(); 8 | 9 | TEST_CASE(TestParseStandardLibraryModule) 10 | { 11 | vector codes; 12 | CodeError::List errors; 13 | codes.push_back(GetCodeForStandardLibrary()); 14 | auto assembly = SymbolAssembly::Parse(codes, errors); 15 | TEST_ASSERT(errors.size() == 0); 16 | TEST_ASSERT(assembly->symbolModules.size() == 1); 17 | } 18 | 19 | TEST_CASE(TestParseHelloWorldModule) 20 | { 21 | string_t code = T(R"tinymoe( 22 | module hello world 23 | using standard library 24 | 25 | sentence print (message) 26 | redirect to "printf" 27 | end 28 | 29 | phrase sum from (first number) to (last number) 30 | set the result to 0 31 | repeat with the current number from first number to last number 32 | add the current number to the result 33 | end 34 | end 35 | 36 | phrase main 37 | print "1+ ... +100 = " & sum from 1 to 100 38 | end 39 | )tinymoe"); 40 | 41 | vector codes; 42 | CodeError::List errors; 43 | codes.push_back(GetCodeForStandardLibrary()); 44 | codes.push_back(code); 45 | auto assembly = SymbolAssembly::Parse(codes, errors); 46 | TEST_ASSERT(errors.size() == 0); 47 | TEST_ASSERT(assembly->symbolModules.size() == 2); 48 | } 49 | 50 | TEST_CASE(TestParseNamedBlockModule) 51 | { 52 | string_t code = T(R"tinymoe( 53 | module hello world 54 | using standard library 55 | 56 | sentence print (message) 57 | redirect to "printf" 58 | end 59 | 60 | phrase sum from (first number) to (last number) 61 | set the result to 0 62 | set the current number to first number 63 | named block calculating 64 | add the current number to the result 65 | add 1 to the current number 66 | if the current number > last number 67 | exit block calculating 68 | end 69 | end 70 | end 71 | 72 | phrase main 73 | print "1+ ... +100 = " & sum from 1 to 100 74 | end 75 | )tinymoe"); 76 | 77 | vector codes; 78 | CodeError::List errors; 79 | codes.push_back(GetCodeForStandardLibrary()); 80 | codes.push_back(code); 81 | auto assembly = SymbolAssembly::Parse(codes, errors); 82 | TEST_ASSERT(errors.size() == 0); 83 | TEST_ASSERT(assembly->symbolModules.size() == 2); 84 | } 85 | 86 | TEST_CASE(TestParsePotentialAmbiguousModule) 87 | { 88 | string_t code = T(R"tinymoe( 89 | module hello world 90 | using standard library 91 | 92 | type dog 93 | name 94 | end 95 | 96 | sentence print (message) 97 | redirect to "printf" 98 | end 99 | 100 | phrase console input 101 | redirect to "scanf" 102 | end 103 | 104 | phrase main 105 | set kula to new dog of () 106 | set field name of kula to console input 107 | print "kula's name is " & field name of kula & "." 108 | end 109 | )tinymoe"); 110 | 111 | vector codes; 112 | CodeError::List errors; 113 | codes.push_back(GetCodeForStandardLibrary()); 114 | codes.push_back(code); 115 | auto assembly = SymbolAssembly::Parse(codes, errors); 116 | TEST_ASSERT(errors.size() == 0); 117 | TEST_ASSERT(assembly->symbolModules.size() == 2); 118 | 119 | auto decl = assembly->symbolModules[1]->module->declarations[3]; 120 | auto func = assembly->symbolModules[1]->declarationFunctions.find(decl)->second; 121 | TEST_ASSERT(func->function->name.size() == 1); 122 | TEST_ASSERT(dynamic_pointer_cast(func->function->name[0])->name->GetName() == T("main")); 123 | } 124 | 125 | TEST_CASE(TestParseConnectedBlocksModule) 126 | { 127 | string_t code = T(R"tinymoe( 128 | module hello world 129 | using standard library 130 | 131 | sentence print (message) 132 | redirect to "printf" 133 | end 134 | 135 | phrase console input 136 | redirect to "scanf" 137 | end 138 | 139 | phrase main 140 | set the score to console input 141 | if the score < 0 or the score > 100 142 | print "Illegal score." 143 | else if the score = 100 144 | print "Perfect!" 145 | else if the score >= 90 146 | print "Good!" 147 | else if the score >= 70 148 | print "Normal." 149 | else if the score >- 60 150 | print "OK." 151 | else 152 | print "Unacceptable." 153 | end 154 | end 155 | )tinymoe"); 156 | 157 | vector codes; 158 | CodeError::List errors; 159 | codes.push_back(GetCodeForStandardLibrary()); 160 | codes.push_back(code); 161 | auto assembly = SymbolAssembly::Parse(codes, errors); 162 | TEST_ASSERT(errors.size() == 0); 163 | TEST_ASSERT(assembly->symbolModules.size() == 2); 164 | } 165 | 166 | TEST_CASE(TestParseCategorizedSentenceModule) 167 | { 168 | string_t code = T(R"tinymoe( 169 | module hello world 170 | using standard library 171 | 172 | sentence print (message) 173 | redirect to "printf" 174 | end 175 | 176 | phrase console input 177 | redirect to "scanf" 178 | end 179 | 180 | phrase main 181 | set lower bound to console input 182 | set upper bound to console input 183 | set sum to 0 184 | set the current number to lower bound 185 | 186 | repeat 187 | add the current number to sum 188 | add 1 to the current number 189 | if the current number > upper bound 190 | break 191 | end 192 | end 193 | print "The sum is " & sum & "." 194 | end 195 | )tinymoe"); 196 | 197 | vector codes; 198 | CodeError::List errors; 199 | codes.push_back(GetCodeForStandardLibrary()); 200 | codes.push_back(code); 201 | auto assembly = SymbolAssembly::Parse(codes, errors); 202 | TEST_ASSERT(errors.size() == 0); 203 | TEST_ASSERT(assembly->symbolModules.size() == 2); 204 | } 205 | 206 | TEST_CASE(TestParseWrongModule) 207 | { 208 | { 209 | string_t code = T(R"tinymoe( 210 | module hello world 211 | using standard library 212 | 213 | phrase main 214 | if true 215 | catch the exception 216 | end 217 | end 218 | )tinymoe"); 219 | 220 | vector codes; 221 | CodeError::List errors; 222 | codes.push_back(GetCodeForStandardLibrary()); 223 | codes.push_back(code); 224 | auto assembly = SymbolAssembly::Parse(codes, errors); 225 | TEST_ASSERT(errors.size() == 2); 226 | TEST_ASSERT(assembly->symbolModules.size() == 2); 227 | } 228 | { 229 | string_t code = T(R"tinymoe( 230 | module hello world 231 | using standard library 232 | 233 | phrase main 234 | if true 235 | break 236 | end 237 | end 238 | )tinymoe"); 239 | 240 | vector codes; 241 | CodeError::List errors; 242 | codes.push_back(GetCodeForStandardLibrary()); 243 | codes.push_back(code); 244 | auto assembly = SymbolAssembly::Parse(codes, errors); 245 | TEST_ASSERT(errors.size() == 1); 246 | TEST_ASSERT(assembly->symbolModules.size() == 2); 247 | } 248 | } -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TinymoeUnitTest.vcxproj: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | Debug 6 | Win32 7 | 8 | 9 | Release 10 | Win32 11 | 12 | 13 | 14 | {5FABE03F-C0DD-495A-B3AE-ED2270A9A6CD} 15 | Win32Proj 16 | TinymoeUnitTest 17 | SAK 18 | SAK 19 | SAK 20 | SAK 21 | 22 | 23 | 24 | Application 25 | true 26 | v120 27 | Unicode 28 | 29 | 30 | Application 31 | false 32 | v120 33 | true 34 | Unicode 35 | 36 | 37 | 38 | 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | true 48 | 49 | 50 | false 51 | 52 | 53 | 54 | 55 | 56 | Level3 57 | Disabled 58 | WIN32;_DEBUG;_CONSOLE;_LIB;UNICODE_TINYMOE;%(PreprocessorDefinitions) 59 | true 60 | 61 | 62 | Console 63 | true 64 | 65 | 66 | 67 | 68 | Level3 69 | 70 | 71 | MaxSpeed 72 | true 73 | true 74 | WIN32;NDEBUG;_CONSOLE;_LIB;UNICODE_TINYMOE;%(PreprocessorDefinitions) 75 | true 76 | 77 | 78 | Console 79 | true 80 | true 81 | true 82 | 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | 92 | 93 | 94 | 95 | 96 | 97 | 98 | 99 | 100 | 101 | 102 | 103 | 104 | 105 | 106 | 107 | 108 | 109 | 110 | 111 | 112 | 113 | 114 | 115 | 116 | 117 | 118 | 119 | 120 | 121 | 122 | 123 | 124 | 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TinymoeUnitTest.vcxproj.filters: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | 5 | {4FC737F1-C7A5-4376-A066-2A32D752A2FF} 6 | cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx 7 | 8 | 9 | {93995380-89BD-4b04-88EB-625FBE52EBFB} 10 | h;hh;hpp;hxx;hm;inl;inc;xsd 11 | 12 | 13 | {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} 14 | rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms 15 | 16 | 17 | {12df8507-9cbd-4a6d-9e05-4fb7954e2f9e} 18 | 19 | 20 | {9685582c-5f07-44f2-aefd-c88422be8af6} 21 | 22 | 23 | {56cf71b8-87ec-4438-8230-020750d4afa6} 24 | 25 | 26 | {2084a9c6-098d-4b14-a6b9-cca482686604} 27 | 28 | 29 | {d875d851-148c-4a0a-9ac1-ee0d44dde8a2} 30 | 31 | 32 | 33 | 34 | Source Files 35 | 36 | 37 | Source Files 38 | 39 | 40 | Tinymoe 41 | 42 | 43 | Source Files 44 | 45 | 46 | Source Files 47 | 48 | 49 | Source Files 50 | 51 | 52 | Tinymoe\Compiler 53 | 54 | 55 | Tinymoe\Compiler 56 | 57 | 58 | Tinymoe\Compiler 59 | 60 | 61 | Tinymoe\Compiler 62 | 63 | 64 | Source Files 65 | 66 | 67 | Tinymoe\Ast 68 | 69 | 70 | Tinymoe\Compiler 71 | 72 | 73 | Source Files 74 | 75 | 76 | Tinymoe\Compiler 77 | 78 | 79 | Tinymoe\Compiler 80 | 81 | 82 | Tinymoe\Compiler 83 | 84 | 85 | Source Files 86 | 87 | 88 | Tinymoe\Ast 89 | 90 | 91 | Tinymoe\Ast 92 | 93 | 94 | Tinymoe\Ast 95 | 96 | 97 | Tinymoe\Ast 98 | 99 | 100 | Tinymoe\Ast 101 | 102 | 103 | Tinymoe\Ast 104 | 105 | 106 | Tinymoe\Ast 107 | 108 | 109 | Tinymoe\Ast 110 | 111 | 112 | 113 | 114 | Header Files 115 | 116 | 117 | Tinymoe 118 | 119 | 120 | Tinymoe 121 | 122 | 123 | Tinymoe\Compiler 124 | 125 | 126 | Tinymoe\Compiler 127 | 128 | 129 | Tinymoe\Compiler 130 | 131 | 132 | Tinymoe\Compiler 133 | 134 | 135 | Tinymoe\Ast 136 | 137 | 138 | Tinymoe\Compiler 139 | 140 | 141 | 142 | 143 | Resource Files\Library 144 | 145 | 146 | Resource Files\TestCases 147 | 148 | 149 | Resource Files\TestCases 150 | 151 | 152 | Resource Files\TestCases 153 | 154 | 155 | Resource Files\TestCases 156 | 157 | 158 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TinymoeUnitTest.vcxproj.user: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | WindowsLocalDebugger 5 | 6 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/TinymoeUnitTest.vcxproj.vspscc: -------------------------------------------------------------------------------- 1 | "" 2 | { 3 | "FILE_VERSION" = "9237" 4 | "ENLISTMENT_CHOICE" = "NEVER" 5 | "PROJECT_FILE_RELATIVE_PATH" = "" 6 | "NUMBER_OF_EXCLUDED_FILES" = "0" 7 | "ORIGINAL_PROJECT_FILE_PATH" = "" 8 | "NUMBER_OF_NESTED_PROJECTS" = "0" 9 | "SOURCE_CONTROL_SETTINGS_PROVIDER" = "PROVIDER" 10 | } 11 | -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/UnitTest.cpp: -------------------------------------------------------------------------------- 1 | #include "UnitTest.h" -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/UnitTest.h: -------------------------------------------------------------------------------- 1 | #ifndef VCZH_TINYMOE_UNITTEST 2 | #define VCZH_TINYMOE_UNITTEST 3 | 4 | #include 5 | #include 6 | 7 | #define TEST_CASE(NAME) \ 8 | extern void TEST_CASE_FUNCTION_##NAME(void); \ 9 | class TEST_CASE_CLASS_##NAME \ 10 | { \ 11 | public: \ 12 | TEST_CASE_CLASS_##NAME() \ 13 | { \ 14 | std::cout << #NAME << std::endl; \ 15 | TEST_CASE_FUNCTION_##NAME(); \ 16 | } \ 17 | } TEST_CASE_INSTANCE_##NAME; \ 18 | void TEST_CASE_FUNCTION_##NAME(void) 19 | 20 | #define TEST_ASSERT(CONDITION) do{ if (!(CONDITION)) throw 0; } while (0) 21 | #define TEST_PRINT(MESSAGE) std::cout << (MESSAGE) << std::endl; 22 | 23 | #endif -------------------------------------------------------------------------------- /Development/TinymoeUnitTest/makefile: -------------------------------------------------------------------------------- 1 | CPP = g++ -std=c++11 2 | 3 | BIN = ./Bin/ 4 | TIN = ../Source/ 5 | AST = ../Source/Ast/ 6 | COM = ../Source/Compiler/ 7 | 8 | TIN_OBJS = $(BIN)Tinymoe.o 9 | 10 | AST_OBJS = $(BIN)TinymoeAst.o $(BIN)TinymoeAst_CollectSideEffectExpressions.o $(BIN)TinymoeAst_CollectUsedVariables.o $(BIN)TinymoeAst_ExpandBlock.o $(BIN)TinymoeAst_GetRootLeftValue.o $(BIN)TinymoeAst_Print.o $(BIN)TinymoeAst_RemoveUnnecessaryVariables.o $(BIN)TinymoeAst_RoughlyOptimize.o $(BIN)TinymoeAst_SetParent.o 11 | 12 | COM_OBJS = $(BIN)TinymoeAstCodegen.o $(BIN)TinymoeAstCodegen_Declaration.o $(BIN)TinymoeAstCodegen_Expression.o $(BIN)TinymoeAstCodegen_Statement.o $(BIN)TinymoeDeclarationAnalyzer.o $(BIN)TinymoeExpressionAnalyzer.o $(BIN)TinymoeLexicalAnalyzer.o $(BIN)TinymoeStatementAnalyzer.o 13 | 14 | UNITTEST_OBJS = $(BIN)CSharpCodegen.o $(BIN)UnitTest.o $(BIN)Main.o 15 | 16 | TESTCASE_OBJS = $(BIN)TestAstCodegen.o 17 | #$(BIN)TestDeclarationAnalyzer.o $(BIN)TestExpressionAnalyzer.o $(BIN)TestLexicalAnalyzer.o $(BIN)TestStatementAnalyzer.o 18 | 19 | all: 20 | mkdir -p $(BIN) 21 | $(CPP) -o $(BIN)CSharpCodegen.o -c CSharpCodegen.cpp 22 | $(CPP) -o $(BIN)TestAstCodegen.o -c TestAstCodegen.cpp 23 | #$(CPP) -o $(BIN)TestDeclarationAnalyzer.o -c TestDeclarationAnalyzer.cpp 24 | #$(CPP) -o $(BIN)TestExpressionAnalyzer.o -c TestExpressionAnalyzer.cpp 25 | #$(CPP) -o $(BIN)TestLexicalAnalyzer.o -c TestLexicalAnalyzer.cpp 26 | #$(CPP) -o $(BIN)TestStatementAnalyzer.o -c TestStatementAnalyzer.cpp 27 | $(CPP) -o $(BIN)UnitTest.o -c UnitTest.cpp 28 | $(CPP) -o $(BIN)Main.o -c Main.cpp 29 | $(CPP) -o $(BIN)Tinymoe.o -c $(TIN)Tinymoe.cpp 30 | $(CPP) -o $(BIN)TinymoeAst.o -c $(AST)TinymoeAst.cpp 31 | $(CPP) -o $(BIN)TinymoeAst_CollectSideEffectExpressions.o -c $(AST)TinymoeAst_CollectSideEffectExpressions.cpp 32 | $(CPP) -o $(BIN)TinymoeAst_CollectUsedVariables.o -c $(AST)TinymoeAst_CollectUsedVariables.cpp 33 | $(CPP) -o $(BIN)TinymoeAst_ExpandBlock.o -c $(AST)TinymoeAst_ExpandBlock.cpp 34 | $(CPP) -o $(BIN)TinymoeAst_GetRootLeftValue.o -c $(AST)TinymoeAst_GetRootLeftValue.cpp 35 | $(CPP) -o $(BIN)TinymoeAst_Print.o -c $(AST)TinymoeAst_Print.cpp 36 | $(CPP) -o $(BIN)TinymoeAst_RemoveUnnecessaryVariables.o -c $(AST)TinymoeAst_RemoveUnnecessaryVariables.cpp 37 | $(CPP) -o $(BIN)TinymoeAst_RoughlyOptimize.o -c $(AST)TinymoeAst_RoughlyOptimize.cpp 38 | $(CPP) -o $(BIN)TinymoeAst_SetParent.o -c $(AST)TinymoeAst_SetParent.cpp 39 | $(CPP) -o $(BIN)TinymoeAstCodegen.o -c $(COM)TinymoeAstCodegen.cpp 40 | $(CPP) -o $(BIN)TinymoeAstCodegen_Declaration.o -c $(COM)TinymoeAstCodegen_Declaration.cpp 41 | $(CPP) -o $(BIN)TinymoeAstCodegen_Expression.o -c $(COM)TinymoeAstCodegen_Expression.cpp 42 | $(CPP) -o $(BIN)TinymoeAstCodegen_Statement.o -c $(COM)TinymoeAstCodegen_Statement.cpp 43 | $(CPP) -o $(BIN)TinymoeDeclarationAnalyzer.o -c $(COM)TinymoeDeclarationAnalyzer.cpp 44 | $(CPP) -o $(BIN)TinymoeExpressionAnalyzer.o -c $(COM)TinymoeExpressionAnalyzer.cpp 45 | $(CPP) -o $(BIN)TinymoeLexicalAnalyzer.o -c $(COM)TinymoeLexicalAnalyzer.cpp 46 | $(CPP) -o $(BIN)TinymoeStatementAnalyzer.o -c $(COM)TinymoeStatementAnalyzer.cpp 47 | $(CPP) -o $(BIN)UnitTest $(TIN_OBJS) $(AST_OBJS) $(COM_OBJS) $(UNITTEST_OBJS) $(TESTCASE_OBJS) 48 | 49 | clean: 50 | rm $(BIN)* 51 | -------------------------------------------------------------------------------- /Docx/vczhcp-0.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vczh/tinymoe/673e09e44c5dc6dedad5f802e41537c03fd044f0/Docx/vczhcp-0.docx -------------------------------------------------------------------------------- /Docx/vczhcp-1.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vczh/tinymoe/673e09e44c5dc6dedad5f802e41537c03fd044f0/Docx/vczhcp-1.docx -------------------------------------------------------------------------------- /Docx/vczhcp-2.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vczh/tinymoe/673e09e44c5dc6dedad5f802e41537c03fd044f0/Docx/vczhcp-2.docx -------------------------------------------------------------------------------- /Docx/vczhcp-3.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/vczh/tinymoe/673e09e44c5dc6dedad5f802e41537c03fd044f0/Docx/vczhcp-3.docx -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | tinymoe 2 | ======= 3 | ### English-like programming language 4 | ###### For DSL (Domain Specific Language) building and embedding, with dynamic typing, multiple dispatching and build-in continuation. 5 | 6 | Here are several samples to introduce this language: 7 | 8 | #### Hello world 9 | 10 | module hello world 11 | using standard library 12 | 13 | sentence print (message) 14 | redirect to "printf" 15 | end 16 | 17 | phrase sum from (start) to (end) 18 | set the result to 0 19 | repeat with the current number from start to end 20 | add the current number to the result 21 | end 22 | end 23 | 24 | phrase main 25 | print "1+ ... +100 = " & sum from 1 to 100 26 | end 27 | 28 | #### Geometry (Multiple dispatching) 29 | 30 | module geometry 31 | using standard library 32 | 33 | phrase square root of (number) 34 | redirect to "Sqrt" 35 | end 36 | 37 | sentence print (message) 38 | redirect to "Print" 39 | end 40 | 41 | type rectangle 42 | width 43 | height 44 | end 45 | 46 | type triangle 47 | a 48 | b 49 | c 50 | end 51 | 52 | type circle 53 | radius 54 | end 55 | 56 | phrase area of (shape) 57 | raise "This is not a shape." 58 | end 59 | 60 | phrase area of (shape : rectangle) 61 | set the result to field width of shape * field height of shape 62 | end 63 | 64 | phrase area of (shape : triangle) 65 | set a to field a of shape 66 | set b to field b of shape 67 | set c to field c of shape 68 | set p to (a + b + c) / 2 69 | set the result to square root of (p * (p - a) * (p - b) * (p - c)) 70 | end 71 | 72 | phrase area of (shape : circle) 73 | set r to field radius of shape 74 | set the result to r * r * 22/7 75 | end 76 | 77 | phrase (a) and (b) are the same shape 78 | set the result to false 79 | end 80 | 81 | phrase (a : rectangle) and (b : rectangle) are the same shape 82 | set the result to true 83 | end 84 | 85 | phrase (a : triangle) and (b : triangle) are the same shape 86 | set the result to true 87 | end 88 | 89 | phrase (a : circle) and (b : circle) are the same shape 90 | set the result to true 91 | end 92 | 93 | phrase main 94 | set shape one to new triangle of (2, 3, 4) 95 | set shape two to new rectangle of (1, 2) 96 | if shape one and shape two are the same shape 97 | print "This world is mad!" 98 | else 99 | print "Triangle and rectangle are not the same shape!" 100 | end 101 | end 102 | 103 | #### Make your own "yield return" (coroutine) 104 | 105 | module enumerable 106 | using standard library 107 | 108 | symbol yielding return 109 | symbol yielding break 110 | 111 | type enumerable collection 112 | body 113 | end 114 | 115 | type collection enumerator 116 | value 117 | coroutine 118 | end 119 | 120 | cps (state) (continuation) 121 | category 122 | inside ENUMERATING 123 | sentence yield return (value) 124 | pause coroutine to yielding return with continuation and value 125 | end 126 | 127 | cps (state) (continuation) 128 | category 129 | inside ENUMERATING 130 | sentence yield break 131 | pause coroutine to yielding break with continuation and null 132 | end 133 | 134 | phrase new enumerator from (enumerable) 135 | set coroutine to new coroutine from (field body of enumerable) 136 | set the result to new collection enumerator of (null, coroutine) 137 | end 138 | 139 | cps (state) (continuation) 140 | sentence move (enumerator) to the next 141 | set coroutine to field coroutine of enumerator 142 | if not (coroutine coroutine stopped) 143 | run coroutine coroutine 144 | 145 | select field flag of state 146 | case yielding return 147 | set field value of enumerator to field argument of state 148 | continue coroutine coroutine 149 | case yielding break 150 | set field value of enumerator to null 151 | stop coroutine coroutine 152 | case null 153 | set field value of enumerator to null 154 | stop coroutine coroutine 155 | case else 156 | fall into the previous trap 157 | end 158 | end 159 | end 160 | 161 | phrase (enumerator) reaches the end 162 | set the result to coroutine field coroutine of enumerator stopped 163 | end 164 | 165 | phrase current value of (enumerator) 166 | set the result to field value of (field value of enumerator) 167 | end 168 | 169 | cps (state) 170 | category 171 | start ENUMERATING 172 | closable 173 | block (body) create enumerable to (assignable receiver) 174 | set receiver to new enumerable collection of () 175 | set field body of receiver to body 176 | end 177 | 178 | block (sentence deal with (item)) repeat with (argument item) in (items : enumerable collection) 179 | set enumerator to new enumerator from items 180 | repeat while not (enumerator reaches the end) 181 | move enumerator to the next 182 | deal with current value of enumerator 183 | end 184 | end 185 | 186 | sentence print (message) 187 | redirect to "Print" 188 | end 189 | 190 | phrase main 191 | create enumerable to numbers 192 | repeat with i from 1 to 10 193 | print "Enumerating " & i 194 | yield return i 195 | end 196 | end 197 | 198 | repeat with number in numbers 199 | if number >= 5 200 | break 201 | end 202 | print "Printing " & number 203 | end 204 | end 205 | 206 | #### Make your tinymoe-unit (Unit test and assertion) 207 | 208 | module unit test 209 | using standard library 210 | 211 | sentence print (message) 212 | redirect to "Print" 213 | end 214 | 215 | block (sentence run the test case) test case (name) 216 | try 217 | run the test case 218 | print "PASS: " & name 219 | catch exception 220 | select exception 221 | case "AssertionFailure" 222 | print "FAIL: " & name 223 | case else 224 | print "HALT: " & name 225 | end 226 | end 227 | end 228 | 229 | sentence assert (actual value) should be (expected value) 230 | if actual value <> expected value 231 | assert fail 232 | end 233 | end 234 | 235 | sentence assert fail 236 | raise "AssertionFailure" 237 | end 238 | 239 | phrase main 240 | test case "1+1=2" 241 | assert (1 + 1) should be 2 242 | end 243 | end 244 | --------------------------------------------------------------------------------