32 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/partials/logo.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 | {{_appName}}
6 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/partials/navbar.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 | {{>partials/logo}}
7 |
8 |
9 |
10 |
11 |
12 |
13 |
14 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/partials/scripts.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 |
7 |
8 |
9 |
10 |
11 |
12 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/partials/toc.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/styles/colors.css:
--------------------------------------------------------------------------------
1 | /* Color schemes */
2 | :root
3 | {
4 | /* General */
5 | --main-bg-color: #36393f;
6 | --footer-bg-color: rgba(0,0,0,.4);
7 | --table-strip-bg-color: #121315;
8 | --table-header-bg-color: #202225;;
9 | --table-header-color: hsla(0,0%,100%,.8);
10 | --table-header-border-color: #040405;
11 |
12 | /* Text */
13 | --text-color: #dcddde;
14 | --link-color: #00b0f4;
15 | --link-hover-color: #4bd5ff;
16 | --link-active-color: #fff;
17 | --link-active-bg-color: #7289da;
18 | --h3-color: #ffffff85;
19 | --h4-color: #ffffffeb;
20 | --h5-color: #ffffffd1;
21 |
22 | /* Topbar */
23 | --topbar-bg-color: #18191c;
24 |
25 | /* Button */
26 | --button-color: #747f8d;
27 |
28 | /* Sidebar */
29 | --separator-color: #4f545c;
30 | --sidebar-bg-color: #2f3136;
31 | --sidebar-item-color: #b9bbbe;
32 | --sidebar-item-2nd-color: hsla(0,0%,100%,.35);
33 | --sidebar-item-3rd-color: hsla(0,0%,100%,.25);
34 |
35 | /* Scrollbar */
36 | --scrollbar-bg-color: transparent;
37 | --scrollbar-thumb-bg-color: rgba(0,0,0,.4);
38 | --scrollbar-thumb-border-color: transparent;
39 |
40 | /* Alerts and Blocks */
41 | --alert-info-border-color: rgba(114,137,218,.5);
42 | --alert-info-bg-color: rgba(114,137,218,.1);
43 |
44 | --alert-warning-border-color: rgba(250,166,26,.5);
45 | --alert-warning-bg-color: rgba(250,166,26,.1);
46 |
47 | --alert-danger-border-color: rgba(240,71,71,.5);
48 | --alert-danger-bg-color: rgba(240,71,71,.1);
49 |
50 | --alert-tip-border-color: rgba(255,255,255,.5);
51 | --alert-tip-bg-color: rgba(255,255,255,.1);
52 |
53 | --blockquote-border-color: rgba(255,255,255,.5);
54 | --blockquote-bg-color: rgba(255,255,255,.1);
55 |
56 | --breadcrumb-bg-color: #2f3136;
57 |
58 | /* Code Higlighting */
59 | --code-bg-color: #18191c;
60 | --code-color: #8790A3;
61 | --code-keyword-color: #569cd6;
62 | --code-comment-color: #57a64a;
63 | --code-macro-color: #beb7ff;
64 | --code-string-color: #d69d85;
65 | --code-string-escape-color: #ffd68f;
66 | --code-field-color: #c8c8c8;
67 | --code-function-color: #dcdcaa;
68 | --code-control-color: #d8a0df;
69 | --code-class-color: #4ec9b0;
70 | --code-number-color: #b5cea8;
71 | --code-params-color: #9a9a9a;
72 | --code-breakpoint-color: #8c2f2f;
73 | }
74 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/styles/down-arrow.svg:
--------------------------------------------------------------------------------
1 |
2 |
3 |
45 |
--------------------------------------------------------------------------------
/docs/templates/discordfx/styles/main.css:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/ConcreteMC/MolangSharp/f181d498ec7a1e2325fb55656dcb4e59a86d1fba/docs/templates/discordfx/styles/main.css
--------------------------------------------------------------------------------
/docs/templates/discordfx/styles/main.js:
--------------------------------------------------------------------------------
1 | // Copyright (c) Microsoft. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.
2 |
3 | function toggleMenu() {
4 |
5 | var x = document.getElementById("sidebar");
6 | var b = document.getElementById("blackout");
7 |
8 | if (x.style.left === "0px")
9 | {
10 | x.style.left = "-350px";
11 | b.classList.remove("showThat");
12 | b.classList.add("hideThat");
13 | }
14 | else
15 | {
16 | x.style.left = "0px";
17 | b.classList.remove("hideThat");
18 | b.classList.add("showThat");
19 | }
20 | }
--------------------------------------------------------------------------------
/docs/templates/discordfx/styles/url.min.js:
--------------------------------------------------------------------------------
1 | /*! url - v1.8.6 - 2013-11-22 */window.url=function(){function a(a){return!isNaN(parseFloat(a))&&isFinite(a)}return function(b,c){var d=c||window.location.toString();if(!b)return d;b=b.toString(),"//"===d.substring(0,2)?d="http:"+d:1===d.split("://").length&&(d="http://"+d),c=d.split("/");var e={auth:""},f=c[2].split("@");1===f.length?f=f[0].split(":"):(e.auth=f[0],f=f[1].split(":")),e.protocol=c[0],e.hostname=f[0],e.port=f[1]||("https"===e.protocol.split(":")[0].toLowerCase()?"443":"80"),e.pathname=(c.length>3?"/":"")+c.slice(3,c.length).join("/").split("?")[0].split("#")[0];var g=e.pathname;"/"===g.charAt(g.length-1)&&(g=g.substring(0,g.length-1));var h=e.hostname,i=h.split("."),j=g.split("/");if("hostname"===b)return h;if("domain"===b)return/^(([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])\.){3}([0-9]|[1-9][0-9]|1[0-9]{2}|2[0-4][0-9]|25[0-5])$/.test(h)?h:i.slice(-2).join(".");if("sub"===b)return i.slice(0,i.length-2).join(".");if("port"===b)return e.port;if("protocol"===b)return e.protocol.split(":")[0];if("auth"===b)return e.auth;if("user"===b)return e.auth.split(":")[0];if("pass"===b)return e.auth.split(":")[1]||"";if("path"===b)return e.pathname;if("."===b.charAt(0)){if(b=b.substring(1),a(b))return b=parseInt(b,10),i[0>b?i.length+b:b-1]||""}else{if(a(b))return b=parseInt(b,10),j[0>b?j.length+b:b]||"";if("file"===b)return j.slice(-1)[0];if("filename"===b)return j.slice(-1)[0].split(".")[0];if("fileext"===b)return j.slice(-1)[0].split(".")[1]||"";if("?"===b.charAt(0)||"#"===b.charAt(0)){var k=d,l=null;if("?"===b.charAt(0)?k=(k.split("?")[1]||"").split("#")[0]:"#"===b.charAt(0)&&(k=k.split("#")[1]||""),!b.charAt(1))return k;b=b.substring(1),k=k.split("&");for(var m=0,n=k.length;n>m;m++)if(l=k[m].split("="),l[0]===b)return l[1]||"";return null}}return""}}(),"undefined"!=typeof jQuery&&jQuery.extend({url:function(a,b){return window.url(a,b)}});
--------------------------------------------------------------------------------
/docs/templates/material/partials/head.tmpl.partial:
--------------------------------------------------------------------------------
1 | {{!Copyright (c) Oscar Vasquez. All rights reserved. Licensed under the MIT license. See LICENSE file in the project root for full license information.}}
2 |
3 |
4 |
5 |
6 | {{#title}}{{title}}{{/title}}{{^title}}{{>partials/title}}{{/title}} {{#_appTitle}}| {{_appTitle}} {{/_appTitle}}
7 |
8 |
9 |
10 | {{#_description}}{{/_description}}
11 |
12 |
13 |
14 |
15 |
16 |
17 |
18 | {{#_noindex}}{{/_noindex}}
19 | {{#_enableSearch}}{{/_enableSearch}}
20 | {{#_enableNewTab}}{{/_enableNewTab}}
21 |
--------------------------------------------------------------------------------
/docs/templates/material/styles/main.css:
--------------------------------------------------------------------------------
1 | /* COLOR VARIABLES*/
2 | :root {
3 | --header-bg-color: #0d47a1;
4 | --header-ft-color: #fff;
5 | --highlight-light: #5e92f3;
6 | --highlight-dark: #003c8f;
7 | --font-color: #34393e;
8 | --custom-box-shadow: 0 1px 2px 0 rgba(61, 65, 68, 0.06), 0 1px 3px 1px rgba(61, 65, 68, 0.16);
9 | }
10 |
11 | body {
12 | color: var(--font-color);
13 | font-family: "Roboto", sans-serif;
14 | line-height: 1.5;
15 | font-size: 16px;
16 | -ms-text-size-adjust: 100%;
17 | -webkit-text-size-adjust: 100%;
18 | word-wrap: break-word;
19 | }
20 |
21 | /* HIGHLIGHT COLOR */
22 |
23 | button,
24 | a {
25 | color: var(--highlight-dark);
26 | cursor: pointer;
27 | }
28 |
29 | button:hover,
30 | button:focus,
31 | a:hover,
32 | a:focus {
33 | color: var(--highlight-light);
34 | text-decoration: none;
35 | }
36 |
37 | .toc .nav > li.active > a {
38 | color: var(--highlight-dark);
39 | }
40 |
41 | .toc .nav > li.active > a:hover,
42 | .toc .nav > li.active > a:focus {
43 | color: var(--highlight-light);
44 | }
45 |
46 | .pagination > .active > a {
47 | background-color: var(--header-bg-color);
48 | border-color: var(--header-bg-color);
49 | }
50 |
51 | .pagination > .active > a,
52 | .pagination > .active > a:focus,
53 | .pagination > .active > a:hover,
54 | .pagination > .active > span,
55 | .pagination > .active > span:focus,
56 | .pagination > .active > span:hover {
57 | background-color: var(--highlight-light);
58 | border-color: var(--highlight-light);
59 | }
60 |
61 | /* HEADINGS */
62 |
63 | h1 {
64 | font-weight: 600;
65 | font-size: 32px;
66 | }
67 |
68 | h2 {
69 | font-weight: 600;
70 | font-size: 24px;
71 | line-height: 1.8;
72 | }
73 |
74 | h3 {
75 | font-weight: 600;
76 | font-size: 20px;
77 | line-height: 1.8;
78 | }
79 |
80 | h5 {
81 | font-size: 14px;
82 | padding: 10px 0px;
83 | }
84 |
85 | article h1,
86 | article h2,
87 | article h3,
88 | article h4 {
89 | margin-top: 35px;
90 | margin-bottom: 15px;
91 | }
92 |
93 | article h4 {
94 | padding-bottom: 8px;
95 | border-bottom: 2px solid #ddd;
96 | }
97 |
98 | /* NAVBAR */
99 |
100 | .navbar-brand > img {
101 | color: var(--header-ft-color);
102 | }
103 |
104 | .navbar {
105 | border: none;
106 | /* Both navbars use box-shadow */
107 | -webkit-box-shadow: var(--custom-box-shadow);
108 | -moz-box-shadow: var(--custom-box-shadow);
109 | box-shadow: var(--custom-box-shadow);
110 | }
111 |
112 | .subnav {
113 | border-top: 1px solid #ddd;
114 | background-color: #fff;
115 | }
116 |
117 | .navbar-inverse {
118 | background-color: var(--header-bg-color);
119 | z-index: 100;
120 | }
121 |
122 | .navbar-inverse .navbar-nav > li > a,
123 | .navbar-inverse .navbar-text {
124 | color: var(--header-ft-color);
125 | background-color: var(--header-bg-color);
126 | border-bottom: 3px solid transparent;
127 | padding-bottom: 12px;
128 | }
129 |
130 | .navbar-inverse .navbar-nav > li > a:focus,
131 | .navbar-inverse .navbar-nav > li > a:hover {
132 | color: var(--header-ft-color);
133 | background-color: var(--header-bg-color);
134 | border-bottom: 3px solid white;
135 | }
136 |
137 | .navbar-inverse .navbar-nav > .active > a,
138 | .navbar-inverse .navbar-nav > .active > a:focus,
139 | .navbar-inverse .navbar-nav > .active > a:hover {
140 | color: var(--header-ft-color);
141 | background-color: var(--header-bg-color);
142 | border-bottom: 3px solid white;
143 | }
144 |
145 | .navbar-form .form-control {
146 | border: none;
147 | border-radius: 20px;
148 | }
149 |
150 | /* SIDEBAR */
151 |
152 | .toc .level1 > li {
153 | font-weight: 400;
154 | }
155 |
156 | .toc .nav > li > a {
157 | color: var(--font-color);
158 | }
159 |
160 | .sidefilter {
161 | background-color: #fff;
162 | border-left: none;
163 | border-right: none;
164 | }
165 |
166 | .sidefilter {
167 | background-color: #fff;
168 | border-left: none;
169 | border-right: none;
170 | }
171 |
172 | .toc-filter {
173 | padding: 10px;
174 | margin: 0;
175 | }
176 |
177 | .toc-filter > input {
178 | border: 2px solid #ddd;
179 | border-radius: 20px;
180 | }
181 |
182 | .toc-filter > .filter-icon {
183 | display: none;
184 | }
185 |
186 | .sidetoc > .toc {
187 | background-color: #fff;
188 | overflow-x: hidden;
189 | }
190 |
191 | .sidetoc {
192 | background-color: #fff;
193 | border: none;
194 | }
195 |
196 | /* ALERTS */
197 |
198 | .alert {
199 | padding: 0px 0px 5px 0px;
200 | color: inherit;
201 | background-color: inherit;
202 | border: none;
203 | box-shadow: var(--custom-box-shadow);
204 | }
205 |
206 | .alert > p {
207 | margin-bottom: 0;
208 | padding: 5px 10px;
209 | }
210 |
211 | .alert > ul {
212 | margin-bottom: 0;
213 | padding: 5px 40px;
214 | }
215 |
216 | .alert > h5 {
217 | padding: 10px 15px;
218 | margin-top: 0;
219 | text-transform: uppercase;
220 | font-weight: bold;
221 | border-radius: 4px 4px 0 0;
222 | }
223 |
224 | .alert-info > h5 {
225 | color: #1976d2;
226 | border-bottom: 4px solid #1976d2;
227 | background-color: #e3f2fd;
228 | }
229 |
230 | .alert-warning > h5 {
231 | color: #f57f17;
232 | border-bottom: 4px solid #f57f17;
233 | background-color: #fff3e0;
234 | }
235 |
236 | .alert-danger > h5 {
237 | color: #d32f2f;
238 | border-bottom: 4px solid #d32f2f;
239 | background-color: #ffebee;
240 | }
241 |
242 | /* CODE HIGHLIGHT */
243 | pre {
244 | padding: 9.5px;
245 | margin: 0 0 10px;
246 | font-size: 13px;
247 | word-break: break-all;
248 | word-wrap: break-word;
249 | background-color: #fffaef;
250 | border-radius: 4px;
251 | border: none;
252 | box-shadow: var(--custom-box-shadow);
253 | }
254 |
--------------------------------------------------------------------------------
/docs/toc.yml:
--------------------------------------------------------------------------------
1 | - name: Articles
2 | href: articles/
3 | homepage: articles/index.md
4 |
5 | - name: Api Documentation
6 | href: api/
7 | homepage: api/index.md
8 |
--------------------------------------------------------------------------------
/src/Alex.MoLang.sln:
--------------------------------------------------------------------------------
1 |
2 | Microsoft Visual Studio Solution File, Format Version 12.00
3 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MolangSharp", "MolangSharp\MolangSharp.csproj", "{8A34F8E0-CAB4-4D73-A7B4-8977EF3A7DA3}"
4 | EndProject
5 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MolangSharp.Tests", "MolangSharp.Tests\MolangSharp.Tests.csproj", "{3FF89B16-9D85-4E87-83C7-D937F2ED7F5B}"
6 | EndProject
7 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Examples", "Examples", "{D73569B7-CCA2-458B-98CE-CC7531D414FA}"
8 | EndProject
9 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MolangSharp.Examples.Basic", "Examples\MolangSharp.Examples.Basic\MolangSharp.Examples.Basic.csproj", "{30FD4BFD-0792-495D-A6F6-600713011C77}"
10 | EndProject
11 | Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Extensibility", "Extensibility", "{EC0FCA2E-4326-4F6A-9210-684F90267012}"
12 | EndProject
13 | Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "MolangSharp.Json.Newtonsoft", "Extensibility\MolangSharp.Json.Newtonsoft\MolangSharp.Json.Newtonsoft.csproj", "{D5E15128-EB40-4263-B9C9-9544F3ACA4CB}"
14 | EndProject
15 | Global
16 | GlobalSection(SolutionConfigurationPlatforms) = preSolution
17 | Debug|Any CPU = Debug|Any CPU
18 | Release|Any CPU = Release|Any CPU
19 | EndGlobalSection
20 | GlobalSection(ProjectConfigurationPlatforms) = postSolution
21 | {8A34F8E0-CAB4-4D73-A7B4-8977EF3A7DA3}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
22 | {8A34F8E0-CAB4-4D73-A7B4-8977EF3A7DA3}.Debug|Any CPU.Build.0 = Debug|Any CPU
23 | {8A34F8E0-CAB4-4D73-A7B4-8977EF3A7DA3}.Release|Any CPU.ActiveCfg = Release|Any CPU
24 | {8A34F8E0-CAB4-4D73-A7B4-8977EF3A7DA3}.Release|Any CPU.Build.0 = Release|Any CPU
25 | {3FF89B16-9D85-4E87-83C7-D937F2ED7F5B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
26 | {3FF89B16-9D85-4E87-83C7-D937F2ED7F5B}.Debug|Any CPU.Build.0 = Debug|Any CPU
27 | {3FF89B16-9D85-4E87-83C7-D937F2ED7F5B}.Release|Any CPU.ActiveCfg = Release|Any CPU
28 | {3FF89B16-9D85-4E87-83C7-D937F2ED7F5B}.Release|Any CPU.Build.0 = Release|Any CPU
29 | {30FD4BFD-0792-495D-A6F6-600713011C77}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
30 | {30FD4BFD-0792-495D-A6F6-600713011C77}.Debug|Any CPU.Build.0 = Debug|Any CPU
31 | {30FD4BFD-0792-495D-A6F6-600713011C77}.Release|Any CPU.ActiveCfg = Release|Any CPU
32 | {30FD4BFD-0792-495D-A6F6-600713011C77}.Release|Any CPU.Build.0 = Release|Any CPU
33 | {D5E15128-EB40-4263-B9C9-9544F3ACA4CB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
34 | {D5E15128-EB40-4263-B9C9-9544F3ACA4CB}.Debug|Any CPU.Build.0 = Debug|Any CPU
35 | {D5E15128-EB40-4263-B9C9-9544F3ACA4CB}.Release|Any CPU.ActiveCfg = Release|Any CPU
36 | {D5E15128-EB40-4263-B9C9-9544F3ACA4CB}.Release|Any CPU.Build.0 = Release|Any CPU
37 | EndGlobalSection
38 | GlobalSection(NestedProjects) = preSolution
39 | {30FD4BFD-0792-495D-A6F6-600713011C77} = {D73569B7-CCA2-458B-98CE-CC7531D414FA}
40 | {D5E15128-EB40-4263-B9C9-9544F3ACA4CB} = {EC0FCA2E-4326-4F6A-9210-684F90267012}
41 | EndGlobalSection
42 | EndGlobal
43 |
--------------------------------------------------------------------------------
/src/Examples/MolangSharp.Examples.Basic/BaseEntity.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using ConcreteMC.MolangSharp.Attributes;
3 | using ConcreteMC.MolangSharp.Runtime;
4 | using ConcreteMC.MolangSharp.Runtime.Struct;
5 |
6 | namespace MolangSharp.Examples.Basic;
7 |
8 | public class BaseEntity : MoLangEnvironment
9 | {
10 | private Stopwatch _stopwatch = Stopwatch.StartNew();
11 | public BaseEntity()
12 | {
13 | Structs["query"] = new InteropStruct(this);
14 | }
15 |
16 | [MoProperty("life_time")]
17 | public double LifeTime => _stopwatch.Elapsed.TotalSeconds;
18 | }
--------------------------------------------------------------------------------
/src/Examples/MolangSharp.Examples.Basic/MolangSharp.Examples.Basic.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Exe
5 | net6.0
6 | enable
7 | enable
8 |
9 |
10 |
11 |
12 |
13 |
14 |
15 |
--------------------------------------------------------------------------------
/src/Examples/MolangSharp.Examples.Basic/Program.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using System.Globalization;
3 | using ConcreteMC.MolangSharp.Parser;
4 | using ConcreteMC.MolangSharp.Runtime;
5 | using MolangSharp.Examples.Basic;
6 |
7 | Thread.CurrentThread.CurrentUICulture = CultureInfo.InvariantCulture;
8 | Thread.CurrentThread.CurrentCulture = CultureInfo.InvariantCulture;
9 |
10 | //Create a new Entity which will use Interop to allow for MoLang->C# communication
11 | var myEntity = new BaseEntity();
12 |
13 | //Initialize the runtime
14 | MoLangRuntime runtime = new MoLangRuntime(myEntity);
15 |
16 | //Parse our MoLang expression
17 | var parsed = MoLangParser.Parse("math.cos(query.life_time * 60) * -45.0");
18 |
19 | Stopwatch sw = Stopwatch.StartNew();
20 | while (true)
21 | {
22 | var value = runtime.Execute(parsed);
23 | Console.WriteLine($"[{sw.Elapsed.ToString("mm\\:ss\\.fff")}] Rotation: {value.AsDouble():F3}");
24 | Thread.Sleep(100);
25 | }
--------------------------------------------------------------------------------
/src/Extensibility/MolangSharp.Json.Newtonsoft/MolangExpressionConverter.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Parser;
3 | using ConcreteMC.MolangSharp.Parser.Expressions;
4 | using Newtonsoft.Json;
5 | using Newtonsoft.Json.Linq;
6 |
7 | namespace MolangSharp.Json.Newtonsoft
8 | {
9 | ///
10 | /// Implements a JsonConverter for reading
11 | ///
12 | public class MolangExpressionConverter : JsonConverter
13 | {
14 | public MolangExpressionConverter()
15 | {
16 |
17 | }
18 |
19 | public override bool CanWrite => false;
20 |
21 | public override void WriteJson(JsonWriter writer, object value, JsonSerializer serializer)
22 | {
23 | throw new NotSupportedException();
24 | }
25 |
26 | public override object ReadJson(JsonReader reader, Type objectType, object existingValue,
27 | JsonSerializer serializer)
28 | {
29 | JToken token = JToken.Load(reader);
30 | if (token.Type == JTokenType.String)
31 | {
32 | string molang = token.Value();
33 | return MoLangParser.Parse(molang);
34 | }
35 | else if (token.Type == JTokenType.Integer)
36 | {
37 | return new NumberExpression(token.Value());
38 | }
39 | else if (token.Type == JTokenType.Float)
40 | {
41 | return new NumberExpression(token.Value());
42 | }
43 | else if (token.Type == JTokenType.Boolean)
44 | {
45 | return new BooleanExpression(token.Value());
46 | }
47 |
48 | return existingValue;
49 | }
50 |
51 | public override bool CanConvert(Type objectType)
52 | {
53 | return typeof(IExpression).IsAssignableFrom(objectType);
54 | }
55 | }
56 | }
--------------------------------------------------------------------------------
/src/Extensibility/MolangSharp.Json.Newtonsoft/MolangSharp.Json.Newtonsoft.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | netstandard2.1; netcoreapp6.0
5 | disable
6 | disable
7 | true
8 | ConcreteMC.MolangSharp.Json.Newtonsoft
9 | ConcreteMC.MolangSharp.Json.Newtonsoft
10 | ConcreteMC.MolangSharp.Json.Newtonsoft
11 | Implements a JsonConverter for Molang expressions
12 | Kenny van Vulpen
13 | Kenny van Vulpen
14 | Copyright Kenny van Vulpen 2019-2022
15 | Minecraft Molang MCPE MoLang bedrock mojang alex json newtonsoft newtonsoft.json
16 |
17 | git
18 | https://github.com/ConcreteMC/MolangSharp.git
19 | https://github.com/ConcreteMC/MolangSharp
20 |
21 | 1.0.0
22 |
23 | - Initial release
24 |
25 |
26 |
27 |
28 |
29 |
30 |
31 |
32 |
33 |
34 |
35 |
36 |
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/BinaryOpTest.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Value;
4 | using ConcreteMC.MolangSharp.Utils;
5 | using Microsoft.VisualStudio.TestTools.UnitTesting;
6 |
7 | namespace ConcreteMC.MolangSharp.Tests;
8 |
9 | [TestClass]
10 | public class BinaryOpTest
11 | {
12 | private MoLangRuntime _runtime;
13 |
14 | [TestInitialize]
15 | public void Setup()
16 | {
17 | _runtime = new MoLangRuntime();
18 | }
19 |
20 | [TestMethod]
21 | public void ZeroReturnsFalse()
22 | {
23 | var parsed = MoLangParser.Parse("return 0 ?? 'test'");
24 | var result = _runtime.Execute(parsed);
25 |
26 | Assert.AreEqual(result.AsString(), "test");
27 | }
28 |
29 | [TestMethod]
30 | public void ZeroVariableReturnsFalse()
31 | {
32 | _runtime.Environment.SetValue(new MoPath("variable.lastNumber"), new DoubleValue(0));
33 | var parsed = MoLangParser.Parse("return variable.lastNumber ?? 'test'");
34 | var result = _runtime.Execute(parsed);
35 |
36 | Assert.AreEqual(result.AsString(), "test");
37 | }
38 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/EqualityTest.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using Microsoft.VisualStudio.TestTools.UnitTesting;
4 |
5 | namespace ConcreteMC.MolangSharp.Tests;
6 |
7 | [TestClass]
8 | public class EqualityTest
9 | {
10 | private MoLangRuntime _runtime;
11 |
12 | [TestInitialize]
13 | public void Setup()
14 | {
15 | _runtime = new MoLangRuntime();
16 | }
17 |
18 | [TestMethod("Break Execution (Bigger or Equal)")]
19 | public void BiggerOrEqualTest()
20 | {
21 | var parsed = MoLangParser.Parse(@"
22 | t.a = 1;
23 | loop(10, {
24 | t.a = t.a + 1;
25 | t.a >= 5 ? break : continue;
26 | });
27 | return t.a;
28 | ");
29 |
30 | Assert.IsNotNull(parsed);
31 |
32 | var result = _runtime.Execute(parsed);
33 | Assert.AreEqual(5, result.AsDouble());
34 | }
35 |
36 | [TestMethod("Break Execution (Smaller or Equal)")]
37 | public void SmallerOrEqualTest()
38 | {
39 | var parsed = MoLangParser.Parse(@"
40 | t.a = 10;
41 | loop(10, {
42 | t.a = t.a - 1;
43 | t.a <= 5 ? break : continue;
44 | });
45 | return t.a;
46 | ");
47 |
48 | Assert.IsNotNull(parsed);
49 |
50 | var result = _runtime.Execute(parsed);
51 | Assert.AreEqual(5, result.AsDouble());
52 | }
53 |
54 | [TestMethod("Break Execution (Equal)")]
55 | public void EqualityOperatorTest()
56 | {
57 | var parsed = MoLangParser.Parse(@"
58 | t.a = 10;
59 | loop(10, {
60 | t.a = t.a - 1;
61 | t.a == 5 ? break : continue;
62 | });
63 | return t.a;
64 | ");
65 |
66 | Assert.IsNotNull(parsed);
67 |
68 | var result = _runtime.Execute(parsed);
69 | Assert.AreEqual(5, result.AsDouble());
70 | }
71 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/InteropOptimizationVisitorTest.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Attributes;
2 | using ConcreteMC.MolangSharp.Parser;
3 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
4 | using ConcreteMC.MolangSharp.Parser.Visitors.InteropOptimization;
5 | using ConcreteMC.MolangSharp.Runtime;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace ConcreteMC.MolangSharp.Tests;
9 |
10 | [TestClass]
11 | public class InteropOptimizationVisitorTest
12 | {
13 | [TestMethod]
14 | public void VerifyFunctionCallOptimization()
15 | {
16 | var entity = new TestEntity();
17 | var parser = new MoLangParser(new TokenIterator("query.getHealth()"));
18 | parser.ExpressionTraverser.Visitors.Add(new InteropOptimizationVisitor(new InteropOptimizationVisitorOptions()
19 | {
20 | InteropEntries = new []
21 | {
22 | new InteropEntry("query", entity)
23 | }
24 | }));
25 |
26 | var expression = parser.Parse();
27 | Assert.IsInstanceOfType(expression, typeof(OptimizedFunctionCallExpression));
28 |
29 | var runtime = new MoLangRuntime();
30 | var result = runtime.Execute(expression);
31 | Assert.IsNotNull(result);
32 | Assert.AreEqual(20, result.AsDouble());
33 | }
34 |
35 | [TestMethod]
36 | public void VerifyPropertyAccessOptimization()
37 | {
38 | var entity = new TestEntity();
39 | var parser = new MoLangParser(new TokenIterator("query.health"));
40 | parser.ExpressionTraverser.Visitors.Add(new InteropOptimizationVisitor(new InteropOptimizationVisitorOptions()
41 | {
42 | InteropEntries = new []
43 | {
44 | new InteropEntry("query", entity)
45 | }
46 | }));
47 |
48 | var expression = parser.Parse();
49 | Assert.IsInstanceOfType(expression, typeof(OptimizedNameExpression));
50 |
51 | var runtime = new MoLangRuntime();
52 | var result = runtime.Execute(expression);
53 | Assert.IsNotNull(result);
54 | Assert.AreEqual(20, result.AsDouble());
55 | }
56 |
57 | [TestMethod]
58 | public void VerifyPropertyAssignOptimization()
59 | {
60 | var entity = new TestEntity();
61 | var parser = new MoLangParser(new TokenIterator("query.health = 21"));
62 | parser.ExpressionTraverser.Visitors.Add(new InteropOptimizationVisitor(new InteropOptimizationVisitorOptions()
63 | {
64 | InteropEntries = new []
65 | {
66 | new InteropEntry("query", entity)
67 | }
68 | }));
69 |
70 | var expression = parser.Parse();
71 | Assert.IsInstanceOfType(expression, typeof(OptimizedAssignExpression));
72 |
73 | var runtime = new MoLangRuntime();
74 | var result = runtime.Execute(expression);
75 | Assert.IsNotNull(result);
76 | Assert.AreEqual(21, entity.Health);
77 | }
78 |
79 | private class TestEntity
80 | {
81 | [MoProperty("health")]
82 | public double Health { get; set; }
83 |
84 | public TestEntity()
85 | {
86 | Health = 20;
87 | }
88 |
89 | [MoFunction("getHealth")]
90 | public double GetHealth()
91 | {
92 | return Health;
93 | }
94 | }
95 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/InteropTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Attributes;
3 | using ConcreteMC.MolangSharp.Parser;
4 | using ConcreteMC.MolangSharp.Runtime;
5 | using ConcreteMC.MolangSharp.Runtime.Struct;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace ConcreteMC.MolangSharp.Tests;
9 |
10 | [TestClass]
11 | public class InteropTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | //Init static
17 | var a = MoLangMath.Library;
18 | }
19 |
20 | [TestMethod]
21 | public void PropertyRead()
22 | {
23 | var expression = MoLangParser.Parse("query.life_time");
24 |
25 | var expected = Environment.TickCount * 3.5d;
26 | MoLangRuntime runtime = new MoLangRuntime();
27 |
28 | runtime.Environment.Structs.TryAdd(
29 | "query", new InteropStruct(new TestClass(expected)));
30 |
31 | var result = runtime.Execute(expression);
32 | Assert.AreEqual(expected, result.AsDouble());
33 | }
34 |
35 | [TestMethod]
36 | public void PropertyWrite()
37 | {
38 | var expression = MoLangParser.Parse("query.life_time = 5");
39 |
40 | MoLangRuntime runtime = new MoLangRuntime();
41 |
42 | var testStruct = new TestClass(Environment.TickCount);
43 | runtime.Environment.Structs.TryAdd(
44 | "query", new InteropStruct(testStruct));
45 |
46 | runtime.Execute(expression);
47 | Assert.AreEqual(5d, testStruct.Lifetime);
48 | }
49 |
50 | public class TestClass
51 | {
52 | private double _value;
53 |
54 | public TestClass(double value)
55 | {
56 | _value = value;
57 | }
58 |
59 | [MoProperty("life_time")]
60 | public double Lifetime
61 | {
62 | get
63 | {
64 | return _value;
65 | }
66 | set
67 | {
68 | _value = value;
69 | }
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/MathOptimizationVisitorTest.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser;
2 | using ConcreteMC.MolangSharp.Parser.Expressions;
3 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
4 | using ConcreteMC.MolangSharp.Parser.Visitors;
5 | using ConcreteMC.MolangSharp.Runtime;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace ConcreteMC.MolangSharp.Tests;
9 |
10 | [TestClass]
11 | public class MathOptimizationVisitorTest
12 | {
13 | [TestMethod]
14 | public void Constants()
15 | {
16 | MoLangParser parser = new MoLangParser(new TokenIterator("7 + 2 * (6 + 3) / 3 - 7"));
17 | parser.ExpressionTraverser.Visitors.Add(new MathOptimizationVisitor());
18 |
19 | var expr = parser.Parse();
20 | Assert.IsInstanceOfType(expr, typeof(NumberExpression));
21 |
22 | MoLangRuntime runtime = new MoLangRuntime();
23 | var result = runtime.Execute(expr);
24 |
25 | Assert.AreEqual(6, result.AsDouble());
26 | }
27 |
28 | [TestMethod]
29 | public void MathFunctions()
30 | {
31 | MoLangParser parser = new MoLangParser(new TokenIterator("math.floor(10.1 + 20.1)"));
32 | parser.ExpressionTraverser.Visitors.Add(new MathOptimizationVisitor());
33 |
34 | var expr = parser.Parse();
35 | Assert.IsInstanceOfType(expr, typeof(NumberExpression));
36 |
37 | MoLangRuntime runtime = new MoLangRuntime();
38 | var result = runtime.Execute(expr);
39 |
40 | Assert.AreEqual(30, result.AsDouble());
41 | }
42 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/MathTest.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using ConcreteMC.MolangSharp.Parser;
3 | using ConcreteMC.MolangSharp.Runtime;
4 | using ConcreteMC.MolangSharp.Runtime.Struct;
5 | using ConcreteMC.MolangSharp.Runtime.Value;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace ConcreteMC.MolangSharp.Tests;
9 |
10 | [TestClass]
11 | public class MathTest
12 | {
13 | [TestInitialize]
14 | public void Init()
15 | {
16 | //Init static
17 | var a = MoLangMath.Library;
18 | }
19 |
20 | private MoLangRuntime Setup(double a, double b)
21 | {
22 | MoLangRuntime runtime = new MoLangRuntime();
23 |
24 | runtime.Environment.Structs["variable"] = new VariableStruct(
25 | new List>()
26 | {
27 | new KeyValuePair("a", new DoubleValue(a)),
28 | new KeyValuePair("b", new DoubleValue(b))
29 | });
30 |
31 | return runtime;
32 | }
33 |
34 | [TestMethod]
35 | public void ArithmeticsAdding()
36 | {
37 | const int a = 1200;
38 | const int b = 800;
39 | const double expectedResult = a + b;
40 |
41 | var expression = MoLangParser.Parse("v.a + v.b");
42 | var runtime = Setup(a, b);
43 |
44 | var result = runtime.Execute(expression);
45 | Assert.AreEqual(expectedResult, result.AsDouble());
46 | }
47 |
48 | [TestMethod]
49 | public void ArithmeticsSubtracting()
50 | {
51 | const double a = 1200;
52 | const double b = 800;
53 | const double expectedResult = a - b;
54 |
55 | var expression = MoLangParser.Parse("v.a - v.b");
56 | var runtime = Setup(a, b);
57 |
58 | var result = runtime.Execute(expression);
59 | Assert.AreEqual(expectedResult, result.AsDouble());
60 | }
61 |
62 | [TestMethod]
63 | public void ArithmeticsMultiplication()
64 | {
65 | const double a = 1200;
66 | const double b = 800;
67 | const double expectedResult = a * b;
68 |
69 | var expression = MoLangParser.Parse("v.a * v.b");
70 | var runtime = Setup(a, b);
71 |
72 | var result = runtime.Execute(expression);
73 | Assert.AreEqual(expectedResult, result.AsDouble());
74 | }
75 |
76 | [TestMethod]
77 | public void ArithmeticsDivision()
78 | {
79 | const double a = 1200;
80 | const double b = 800;
81 | const double expectedResult = a / b;
82 |
83 | var expression = MoLangParser.Parse("v.a / v.b");
84 | var runtime = Setup(a, b);
85 |
86 | var result = runtime.Execute(expression);
87 | Assert.AreEqual( expectedResult, result.AsDouble());
88 | }
89 |
90 | [TestMethod]
91 | public void OrderOfOperations()
92 | {
93 | var runtime = Setup(10, 20);
94 |
95 | var expr = MoLangParser.Parse("v.b + (7 + 2 * (6 + 3) / 3 - 7) + v.a");
96 | var result = runtime.Execute(expr);
97 | Assert.AreEqual(36, result.AsDouble());
98 |
99 | result = runtime.Execute(MoLangParser.Parse("10 * 2 - (7 + 9)"));
100 | Assert.AreEqual(4, result.AsDouble());
101 |
102 | result = runtime.Execute(MoLangParser.Parse("12 + 2 * 44"));
103 | Assert.AreEqual(100, result.AsDouble());
104 | }
105 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/MolangSharp.Tests.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | net6.0
5 | enable
6 |
7 | false
8 |
9 | ConcreteMC.MolangSharp.Tests
10 |
11 | ConcreteMC.MolangSharp.Tests
12 |
13 |
14 |
15 |
16 |
17 |
18 |
19 |
20 |
21 |
22 |
23 |
24 |
25 |
26 |
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/PerformanceTest.cs:
--------------------------------------------------------------------------------
1 | using System.Diagnostics;
2 | using ConcreteMC.MolangSharp.Parser;
3 | using ConcreteMC.MolangSharp.Runtime;
4 | using ConcreteMC.MolangSharp.Runtime.Value;
5 | using ConcreteMC.MolangSharp.Utils;
6 | using Microsoft.VisualStudio.TestTools.UnitTesting;
7 |
8 | namespace ConcreteMC.MolangSharp.Tests;
9 |
10 | [TestClass]
11 | public class PerformanceTest
12 | {
13 | private Stopwatch _sw;
14 | private MoLangEnvironment _environment;
15 | private MoLangRuntime _runtime;
16 |
17 | [TestInitialize]
18 | public void Init()
19 | {
20 | _sw = new Stopwatch();
21 | _environment = new MoLangEnvironment();
22 | _runtime = new MoLangRuntime(_environment);
23 |
24 | _environment.SetValue(new MoPath("variable.test"), DoubleValue.One);
25 | _environment.SetValue(new MoPath("variable.life_time"), DoubleValue.Zero);
26 |
27 | MoLangRuntimeConfiguration.UseDummyValuesInsteadOfExceptions = false;
28 | MoLangRuntimeConfiguration.UseMoLangStackTrace = true;
29 | }
30 |
31 | [TestCleanup]
32 | public void Cleanup()
33 | {
34 | MoLangRuntimeConfiguration.UseMoLangStackTrace = true;
35 | MoLangRuntimeConfiguration.UseDummyValuesInsteadOfExceptions = false;
36 | }
37 |
38 | [TestMethod]
39 | public void TestVariableReadingMath()
40 | {
41 | const int iterations = 5000000;
42 | long total = 0;
43 |
44 | var expression = MoLangParser.Parse("variable.test * 20");
45 | for (int i = 0; i < iterations; i++)
46 | {
47 | _sw.Restart();
48 | var a = _runtime.Execute(expression);
49 | total += _sw.ElapsedMilliseconds;
50 | Assert.AreEqual(20, a.AsDouble());
51 | }
52 |
53 | Debug.WriteLine($"Average: {((double)total / iterations):N10}ms");
54 | }
55 |
56 | [TestMethod]
57 | public void TestVariableReading()
58 | {
59 | const int iterations = 5000000;
60 | long total = 0;
61 |
62 | var expression = MoLangParser.Parse("variable.test");
63 | for (int i = 0; i < iterations; i++)
64 | {
65 | _sw.Restart();
66 | var a = _runtime.Execute(expression);
67 | total += _sw.ElapsedMilliseconds;
68 | Assert.AreEqual(1, a.AsDouble());
69 | }
70 |
71 | Debug.WriteLine($"Average: {((double)total / iterations):N10}ms");
72 | }
73 |
74 | [TestMethod]
75 | public void TestVariableWriting()
76 | {
77 | const int iterations = 5000000;
78 | long total = 0;
79 |
80 | var expression = MoLangParser.Parse("variable.test = 20");
81 | for (int i = 0; i < iterations; i++)
82 | {
83 | _sw.Restart();
84 | _runtime.Execute(expression);
85 | total += _sw.ElapsedMilliseconds;
86 | }
87 |
88 | Debug.WriteLine($"Average: {((double)total / iterations):N10}ms");
89 | }
90 |
91 | [TestMethod]
92 | public void TestInvalidPathPerformance()
93 | {
94 | const int iterations = 50000;
95 | long total = 0;
96 |
97 | var expression = MoLangParser.Parse("fr.test");
98 | for (int i = 0; i < iterations; i++)
99 | {
100 | _sw.Restart();
101 |
102 | try
103 | {
104 | _runtime.Execute(expression);
105 | }
106 | catch
107 | {
108 |
109 | }
110 | total += _sw.ElapsedMilliseconds;
111 | }
112 |
113 | Debug.WriteLine($"Average: {((double)total / iterations):N10}ms");
114 | }
115 |
116 | [TestMethod]
117 | public void TestDummyValuesConfiguration()
118 | {
119 | var expression = MoLangParser.Parse("return fr.test");
120 | MoLangRuntimeConfiguration.UseDummyValuesInsteadOfExceptions = true;
121 | var result = _runtime.Execute(expression);
122 | Assert.AreEqual(0d, result.AsDouble());
123 | }
124 |
125 | [TestMethod]
126 | public void RawPerformanceTest()
127 | {
128 | var parsed = MoLangParser.Parse("math.cos(v.life_time * 60) * -45.0");
129 |
130 | RunPerformanceTestAndOutput(parsed);
131 | }
132 |
133 | [TestMethod]
134 | public void InvalidPathPerformanceTest()
135 | {
136 | var parsed = MoLangParser.Parse("math.cos(a.life_time * 60) * -45.0");
137 |
138 | RunPerformanceTestAndOutput(parsed);
139 | }
140 |
141 | [TestMethod]
142 | public void InvalidPathPerformanceWithoutExceptionThrowingTest()
143 | {
144 | MoLangRuntimeConfiguration.UseDummyValuesInsteadOfExceptions = true;
145 | var parsed = MoLangParser.Parse("math.cos(a.life_time * 60) * -45.0");
146 |
147 | RunPerformanceTestAndOutput(parsed);
148 | }
149 |
150 | [TestMethod]
151 | public void InvalidPathPerformanceWithoutStackTraceThrowingTest()
152 | {
153 | MoLangRuntimeConfiguration.UseMoLangStackTrace = false;
154 | var parsed = MoLangParser.Parse("math.cos(a.life_time * 60) * -45.0");
155 |
156 | RunPerformanceTestAndOutput(parsed);
157 | }
158 |
159 |
160 | private void LogOutput(long iterations, long timespent)
161 | {
162 | Debug.WriteLine($"Iterations: {iterations}. Elapsed: {timespent}ms Avg: {timespent / (double)iterations}ms");
163 | }
164 |
165 | private void RunPerformanceTestAndOutput(IExpression expression)
166 | {
167 | var result = RunPerformanceTest(expression);
168 | LogOutput(result.iterations, result.timeSpent);
169 | }
170 |
171 | private (long iterations, long timeSpent) RunPerformanceTest(IExpression expression)
172 | {
173 | var iterations = 0L;
174 | var sw = Stopwatch.StartNew();
175 | while (sw.ElapsedMilliseconds < 1000)
176 | {
177 | try
178 | {
179 | var e = _runtime.Execute(expression);
180 | }
181 | catch
182 | {
183 |
184 | }
185 |
186 | iterations++;
187 | }
188 | sw.Stop();
189 |
190 | return (iterations, sw.ElapsedMilliseconds);
191 | }
192 | }
--------------------------------------------------------------------------------
/src/MolangSharp.Tests/ScriptTest.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Diagnostics;
3 | using ConcreteMC.MolangSharp.Attributes;
4 | using ConcreteMC.MolangSharp.Parser;
5 | using ConcreteMC.MolangSharp.Runtime;
6 | using ConcreteMC.MolangSharp.Runtime.Struct;
7 | using Microsoft.VisualStudio.TestTools.UnitTesting;
8 |
9 | namespace ConcreteMC.MolangSharp.Tests;
10 |
11 | [TestClass]
12 | public class ScriptTest
13 | {
14 | private Stopwatch _sw;
15 | private MoLangRuntime _runtime;
16 | [TestInitialize]
17 | public void Setup()
18 | {
19 | _sw = new Stopwatch();
20 | _runtime = new MoLangRuntime();
21 | _runtime.Environment.Structs.TryAdd("query", new InteropStruct(new TestClass(_sw)) { });
22 | }
23 |
24 | [TestMethod("Script Execution")]
25 | public void ScriptRun()
26 | {
27 | _sw.Start();
28 | var parsed = MoLangParser.Parse(@"
29 | t.a = 213 + 2 / 0.5 + 5 + 2 * 3;
30 |
31 | query.debug_output(1 + 2 * 3);
32 |
33 | array.test.0 = 100;
34 | array.test[1] = 200;
35 | array.test[2] = 10.5;
36 |
37 | query.debug_output(array.test[1]);
38 |
39 | t.b = 3;
40 |
41 | loop(10, {
42 | array.test[t.b] = array.test[t.b - 1] + 2;
43 | t.b = t.b + 1;
44 | });
45 |
46 | for_each(v.r, array.test, {
47 | t.a = t.a + v.r;
48 | query.debug_output('hello1', t.a, v.r);
49 | });
50 |
51 | t.b = 0;
52 |
53 | loop(100, {
54 | t.b = t.b + 1;
55 | t.a = t.a + math.cos((Math.PI / 180.0f) * 270) + t.b;
56 | query.debug_output(array.test[t.b]);
57 | query.debug_output('hello', 'test', t.a, array.test[2], t.b);
58 | });
59 |
60 | query.debug_output(query.life_time());
61 | return t.a;
62 | ");
63 | _sw.Stop();
64 | var timeElapsedOnParsing = _sw.Elapsed;
65 |
66 | Assert.IsNotNull(parsed);
67 |
68 | Console.WriteLine($"Parser completed in {timeElapsedOnParsing.TotalMilliseconds}ms");
69 |
70 | const int runs = 1000;
71 | const int warmupRuns = 10;
72 |
73 | TimeSpan totalElapsed = TimeSpan.Zero;
74 | TimeSpan max = TimeSpan.Zero;
75 | TimeSpan min = TimeSpan.MaxValue;
76 |
77 | for (int i = 0; i < runs + warmupRuns; i++)
78 | {
79 | _sw.Restart();
80 | _runtime.Execute(parsed);
81 | _sw.Stop();
82 |
83 | if (i >= warmupRuns)
84 | {
85 | totalElapsed += _sw.Elapsed;
86 |
87 | if (_sw.Elapsed < min)
88 | min = _sw.Elapsed;
89 |
90 | if (_sw.Elapsed > max)
91 | max = _sw.Elapsed;
92 | }
93 | }
94 |
95 | Console.WriteLine($"Executed {runs} runs. Total={totalElapsed.TotalMilliseconds}ms Avg={totalElapsed.TotalMilliseconds / runs}ms Max={max.TotalMilliseconds}ms Min={min.TotalMilliseconds}ms");
96 | }
97 |
98 | public class TestClass
99 | {
100 | private Stopwatch _sw;
101 | public TestClass(Stopwatch sw)
102 | {
103 | _sw = sw;
104 | }
105 |
106 | [MoProperty("life_time")]
107 | public double Lifetime
108 | {
109 | get
110 | {
111 | return _sw.Elapsed.TotalSeconds;
112 | }
113 | }
114 |
115 | [MoFunction("debug_output")]
116 | public void DebugOutput(MoParams mo)
117 | {
118 | // var str = string.Join(" ", mo.GetParams().Select(x => x?.AsString()));
119 | // Console.WriteLine(str);
120 | }
121 | }
122 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Attributes/MoFunctionAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ConcreteMC.MolangSharp.Attributes
4 | {
5 | ///
6 | /// Identifies a method as a MoLang Accessible function
7 | ///
8 | [AttributeUsage(AttributeTargets.Method)]
9 | public class MoFunctionAttribute : Attribute
10 | {
11 | ///
12 | /// The names this method is exposed via
13 | ///
14 | public string[] Name { get; }
15 |
16 | ///
17 | /// Identifies a method as a MoLang Accessible function
18 | ///
19 | /// The names this function is callable by in a MoLang expression
20 | public MoFunctionAttribute(params string[] functionNames)
21 | {
22 | Name = functionNames;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Attributes/MoObservableAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ConcreteMC.MolangSharp.Attributes
4 | {
5 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field)]
6 | public class MoObservableAttribute : Attribute { }
7 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Attributes/MoPropertyAttribute.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ConcreteMC.MolangSharp.Attributes
4 | {
5 | ///
6 | /// Identifies a class property/field as MoLang Accessible
7 | ///
8 | [AttributeUsage(AttributeTargets.Property | AttributeTargets.Field, AllowMultiple = true)]
9 | public class MoPropertyAttribute : Attribute
10 | {
11 | ///
12 | /// The name of this property as used in a MoLang expression
13 | ///
14 | public string Name { get; }
15 |
16 | ///
17 | /// Identifies a class property/field as MoLang Accessible
18 | ///
19 | /// The name used for this property.
20 | public MoPropertyAttribute(string name)
21 | {
22 | Name = name;
23 | }
24 | }
25 | }
--------------------------------------------------------------------------------
/src/MolangSharp/MolangSharp.csproj:
--------------------------------------------------------------------------------
1 |
2 |
3 |
4 | Debug;Release
5 | AnyCPU;x64
6 | true
7 | 1.0.3
8 | true
9 | netstandard2.1; netcoreapp6.0
10 | https://github.com/ConcreteMC/MolangSharp
11 | https://github.com/ConcreteMC/MolangSharp.git
12 | MPL-2.0
13 | A library implementing the MoLang expression language
14 | Kenny van Vulpen
15 | Kenny van Vulpen
16 | Copyright Kenny van Vulpen 2019-2022
17 | Minecraft Molang MCPE MoLang bedrock mojang alex
18 |
19 | - Fixed an issue with struct accessor
20 |
21 |
22 | ConcreteMC.MolangSharp
23 | ConcreteMC.MolangSharp
24 | 1.0.3
25 | ConcreteMC.MolangSharp
26 | git
27 | ConcreteMC.MolangSharp
28 | Alex.MoLang
29 |
30 |
31 |
32 | bin\x64\Debug\netstandard2.1\Alex.MoLang.xml
33 |
34 |
35 |
36 | bin\x64\Release\netstandard2.1\Alex.MoLang.xml
37 |
38 |
39 |
40 |
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Exceptions/MoLangParserException.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser.Exceptions
4 | {
5 | public class MoLangParserException : Exception
6 | {
7 | public MoLangParserException(string message) : base(message) { }
8 |
9 | public MoLangParserException(string message, Exception innerException) : base(message, innerException) { }
10 | }
11 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Value;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser
6 | {
7 | ///
8 | /// An abstract base class for all Expressions
9 | ///
10 | public abstract class Expression : IExpression
11 | {
12 | ///
13 | /// The parameters used by this expression
14 | ///
15 | public IExpression[] Parameters { get; set; }
16 |
17 | ///
18 | public ExpressionMeta Meta { get; } = new ExpressionMeta();
19 |
20 | ///
21 | /// Create a new instance of the class
22 | ///
23 | ///
24 | /// The parameters used by this expression
25 | ///
26 | protected Expression(params IExpression[] parameters)
27 | {
28 | Parameters = parameters;
29 | }
30 |
31 | ///
32 | public abstract IMoValue Evaluate(MoScope scope, MoLangEnvironment environment);
33 |
34 | ///
35 | public virtual void Assign(MoScope scope, MoLangEnvironment environment, IMoValue value)
36 | {
37 | throw new Exception("Cannot assign a value to " + this.GetType());
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/ExpressionMeta.cs:
--------------------------------------------------------------------------------
1 | using System.Text;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser
5 | {
6 | ///
7 | /// Contains metadata about an expression
8 | ///
9 | public class ExpressionMeta
10 | {
11 | ///
12 | /// The token
13 | ///
14 | public Token Token { get; set; }
15 |
16 | ///
17 | /// The parent expression
18 | ///
19 | public IExpression Parent { get; set; }
20 |
21 | ///
22 | /// The previous expression
23 | ///
24 | public IExpression Previous { get; set; }
25 |
26 | ///
27 | /// The next expression
28 | ///
29 | public IExpression Next { get; set; }
30 |
31 | public override string ToString()
32 | {
33 | StringBuilder sb = new StringBuilder(255);
34 | bool includeFileInfoIfAvailable;
35 |
36 | if (Token != null)
37 | {
38 | sb.Append(Token.Text);
39 | includeFileInfoIfAvailable = true;
40 | }
41 | else
42 | {
43 | includeFileInfoIfAvailable = false;
44 | }
45 |
46 | if (includeFileInfoIfAvailable)
47 | {
48 | // sb.Append(" at offset ");
49 |
50 | // if (_nativeOffset == OFFSET_UNKNOWN)
51 | // sb.Append("");
52 | // else
53 | // sb.Append(_nativeOffset);
54 |
55 | sb.Append(" in file:line:column ");
56 | sb.Append("");
57 | sb.Append(':');
58 | sb.Append(Token.Position.LineNumber);
59 | sb.Append(':');
60 | sb.Append(Token.Position.Index);
61 | }
62 | else
63 | {
64 | sb.Append("");
65 | }
66 |
67 | sb.AppendLine();
68 |
69 | return sb.ToString();
70 | }
71 | }
72 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/ExpressionTraverser.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Concurrent;
3 | using System.Collections.Generic;
4 | using System.Linq;
5 | using System.Reflection;
6 | using ConcreteMC.MolangSharp.Runtime.Exceptions;
7 |
8 | namespace ConcreteMC.MolangSharp.Parser
9 | {
10 | ///
11 | /// Traverses arrays of with 's
12 | ///
13 | public class ExpressionTraverser
14 | {
15 | ///
16 | /// The list of that will visit the traversed expressions
17 | ///
18 | public readonly List Visitors = new List();
19 |
20 | private bool _stop = false;
21 |
22 | ///
23 | /// Traverse an array of expressions.
24 | ///
25 | /// The array of expressions to visit
26 | /// The traversed array of expressions
27 | public IExpression[] Traverse(IExpression[] expressions)
28 | {
29 | TraverseArray(expressions);
30 |
31 | return expressions.Where(x => x != null).ToArray();
32 | }
33 |
34 | private void TraverseArray(IExpression[] expressions)
35 | {
36 | foreach (IExpressionVisitor visitor in Visitors)
37 | {
38 | visitor.BeforeTraverse(expressions);
39 | }
40 |
41 | for (var index = 0; index < expressions.Length; index++)
42 | {
43 | IExpression expression = expressions[index];
44 |
45 | if (expression == null)
46 | throw new MoLangRuntimeException("Expression was null", null);
47 |
48 | expressions[index] = TraverseExpr(expression, null);
49 |
50 | if (_stop)
51 | {
52 | break;
53 | }
54 | }
55 |
56 | foreach (IExpressionVisitor visitor in Visitors)
57 | {
58 | visitor.AfterTraverse(expressions);
59 | }
60 | }
61 |
62 | private IExpression TraverseExpr(IExpression expression, IExpression parent)
63 | {
64 | expression = Visit(expression);
65 | expression.Meta.Parent = parent;
66 |
67 | var parameters = expression.Parameters;
68 |
69 | for (var index = 0; index < parameters.Length; index++)
70 | {
71 | parameters[index] = TraverseExpr(parameters[index], expression);
72 |
73 | if (_stop)
74 | {
75 | break;
76 | }
77 | }
78 |
79 | expression.Parameters = parameters;
80 |
81 | OnLeave(expression);
82 |
83 | return expression;
84 | }
85 |
86 | private IExpression Visit(IExpression expression)
87 | {
88 | foreach (var visitor in Visitors)
89 | {
90 | expression = visitor.OnVisit(this, expression);
91 | }
92 |
93 | return expression;
94 | }
95 |
96 | private void OnLeave(IExpression expression)
97 | {
98 | foreach (var visitor in Visitors)
99 | {
100 | visitor.OnLeave(expression);
101 | }
102 | }
103 |
104 | public void Stop()
105 | {
106 | _stop = true;
107 | }
108 |
109 | private static ConcurrentDictionary _cachedProperties =
110 | new ConcurrentDictionary();
111 |
112 | private static PropertyInfo[] GetAllProperties(Type type)
113 | {
114 | return _cachedProperties.GetOrAdd(
115 | type, t => t.GetProperties(BindingFlags.Public | BindingFlags.Instance).ToArray());
116 | }
117 |
118 | private object GetFieldValue(PropertyInfo field, object obj)
119 | {
120 | return field.GetValue(obj);
121 | }
122 |
123 | private void SetFieldValue(PropertyInfo field, object obj, object value)
124 | {
125 | field.SetValue(obj, value);
126 | }
127 |
128 | [Flags]
129 | public enum VisitationResult
130 | {
131 | None,
132 |
133 | RemoveCurrent = 0x01,
134 | StopTraversal = 0x02,
135 | DontTraverseChildren = 0x04,
136 | DontTraverseCurrent = 0x08,
137 | DontTraverseCurrentAndChildren = DontTraverseCurrent | DontTraverseChildren
138 | }
139 | }
140 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/ExpressionVisitor.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser
2 | {
3 | ///
4 | /// An abstract class that can be used as a base for any ExpressionVisitor
5 | ///
6 | public abstract class ExpressionVisitor : IExpressionVisitor
7 | {
8 | ///
9 | public virtual void BeforeTraverse(IExpression[] expressions) { }
10 |
11 | ///
12 | public abstract IExpression OnVisit(ExpressionTraverser traverser, IExpression expression);
13 |
14 | ///
15 | public virtual void OnLeave(IExpression expression) { }
16 |
17 | ///
18 | public virtual void AfterTraverse(IExpression[] expressions) { }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ArrayAccessExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Struct;
3 | using ConcreteMC.MolangSharp.Runtime.Value;
4 | using ConcreteMC.MolangSharp.Utils;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Expressions
7 | {
8 | public class ArrayAccessExpression : Expression
9 | {
10 | public IExpression Array => Parameters[0];
11 | public IExpression Index => Parameters[1];
12 |
13 | public ArrayAccessExpression(IExpression array, IExpression index) : base(array, index) { }
14 |
15 | ///
16 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
17 | {
18 | var index = (int) Index.Evaluate(scope, environment).AsDouble();
19 | MoPath path;
20 |
21 | if (Array is NameExpression nameExpression)
22 | {
23 | var p = nameExpression.Name;
24 | path = p;
25 | }
26 | else
27 | {
28 | var eval = Array.Evaluate(scope, environment);
29 | path = new MoPath($"{eval.AsString()}");
30 | }
31 |
32 | var array = environment.GetValue(path);
33 |
34 | if (array is ArrayStruct asArray)
35 | return asArray[index];
36 |
37 | return environment.GetValue(path);
38 | }
39 |
40 | ///
41 | public override void Assign(MoScope scope, MoLangEnvironment environment, IMoValue value)
42 | {
43 | var index = (int) Index.Evaluate(scope, environment).AsDouble();
44 |
45 | MoPath path;
46 |
47 | if (Array is NameExpression nameExpression)
48 | {
49 | var p = nameExpression.Name;
50 | path = p;
51 | }
52 | else
53 | {
54 | var eval = Array.Evaluate(scope, environment);
55 | path = new MoPath($"{eval.AsString()}");
56 | }
57 |
58 | var array = environment.GetValue(path);
59 |
60 | if (array is ArrayStruct asArray)
61 | {
62 | asArray[index] = value;
63 | }
64 | }
65 | }
66 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/AssignExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class AssignExpression : Expression
7 | {
8 | public IExpression Variable => Parameters[0];
9 | public IExpression Expression => Parameters[1];
10 |
11 | public AssignExpression(IExpression variable, IExpression expr) : base(variable, expr) { }
12 |
13 | ///
14 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
15 | {
16 | Variable.Assign(scope, environment, Expression.Evaluate(scope, environment));
17 |
18 | return DoubleValue.Zero;
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/ArrowExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class ArrowExpression : BinaryOpExpression
7 | {
8 | public ArrowExpression(IExpression left, IExpression right) : base(left, right) { }
9 |
10 | ///
11 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
12 | {
13 | var leftEnv = Left.Evaluate(scope, environment);
14 |
15 | if (leftEnv is MoLangEnvironment leftMolangEnvironment)
16 | {
17 | return Right.Evaluate(scope, leftMolangEnvironment);
18 | }
19 |
20 | return null;
21 | }
22 |
23 | ///
24 | public override string GetSigil()
25 | {
26 | return "->";
27 | }
28 | }
29 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/BooleanAndExpressio.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class BooleanAndExpression : BinaryOpExpression
7 | {
8 | ///
9 | public BooleanAndExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsBool() && Right.Evaluate(scope, environment).AsBool());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "&&";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/BooleanOrExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class BooleanOrExpression : BinaryOpExpression
7 | {
8 | ///
9 | public BooleanOrExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsBool() || Right.Evaluate(scope, environment).AsBool());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "||";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/CoalesceExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 | using ConcreteMC.MolangSharp.Utils;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
6 | {
7 | public class CoalesceExpression : BinaryOpExpression
8 | {
9 | ///
10 | public CoalesceExpression(IExpression l, IExpression r) : base(l, r) { }
11 |
12 | ///
13 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
14 | {
15 | IMoValue evalLeft = Left.Evaluate(scope, environment);
16 |
17 | //IMoValue value = environment.GetValue(new MoPath(evalLeft.AsString()));
18 |
19 | if (evalLeft == null || !evalLeft.AsBool())
20 | {
21 | return Right.Evaluate(scope, environment);
22 | }
23 | else
24 | {
25 | return evalLeft;
26 | }
27 | }
28 |
29 | ///
30 | public override string GetSigil()
31 | {
32 | return "??";
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/DivideExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Exceptions;
4 | using ConcreteMC.MolangSharp.Runtime.Value;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
7 | {
8 | public class DivideExpression : BinaryOpExpression
9 | {
10 | ///
11 | public DivideExpression(IExpression l, IExpression r) : base(l, r) { }
12 |
13 | ///
14 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
15 | {
16 | try
17 | {
18 | return new DoubleValue(
19 | Left.Evaluate(scope, environment).AsDouble() / Right.Evaluate(scope, environment).AsDouble());
20 | }
21 | catch (Exception ex)
22 | {
23 | throw new MoLangRuntimeException("An unexpected error occured.", ex);
24 | }
25 | }
26 |
27 | ///
28 | public override string GetSigil()
29 | {
30 | return "/";
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/EqualExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class EqualExpression : BinaryOpExpression
7 | {
8 | ///
9 | public EqualExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | var left = Left.Evaluate(scope, environment);
15 | var right = Right.Evaluate(scope, environment);
16 |
17 | return new DoubleValue(left.Equals(right));
18 | }
19 |
20 | ///
21 | public override string GetSigil()
22 | {
23 | return "==";
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/GreaterExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class GreaterExpression : BinaryOpExpression
7 | {
8 | ///
9 | public GreaterExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() > Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return ">";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/GreaterOrEqualExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class GreaterOrEqualExpression : BinaryOpExpression
7 | {
8 | ///
9 | public GreaterOrEqualExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() >= Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return ">=";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/MinusExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class MinusExpression : BinaryOpExpression
7 | {
8 | ///
9 | public MinusExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() - Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "-";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/NotEqualExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class NotEqualExpression : BinaryOpExpression
7 | {
8 | ///
9 | public NotEqualExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | var left = Left.Evaluate(scope, environment);
15 | var right = Right.Evaluate(scope, environment);
16 |
17 | return new DoubleValue(!left.Equals(right));
18 | }
19 |
20 | ///
21 | public override string GetSigil()
22 | {
23 | return "!=";
24 | }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/PlusExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Exceptions;
4 | using ConcreteMC.MolangSharp.Runtime.Value;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
7 | {
8 | public class PlusExpression : BinaryOpExpression
9 | {
10 | ///
11 | public PlusExpression(IExpression l, IExpression r) : base(l, r) { }
12 |
13 | ///
14 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
15 | {
16 | try
17 | {
18 | return new DoubleValue(
19 | Left.Evaluate(scope, environment).AsDouble() + Right.Evaluate(scope, environment).AsDouble());
20 | }
21 | catch (Exception ex)
22 | {
23 | throw new MoLangRuntimeException(this, "An unexpected error occured.", ex);
24 | }
25 | }
26 |
27 | ///
28 | public override string GetSigil()
29 | {
30 | return "+";
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/PowExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class PowExpression : BinaryOpExpression
7 | {
8 | ///
9 | public PowExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() * Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "*";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/SmallerExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class SmallerExpression : BinaryOpExpression
7 | {
8 | ///
9 | public SmallerExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() < Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "<";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOp/SmallerOrEqualExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp
5 | {
6 | public class SmallerOrEqualExpression : BinaryOpExpression
7 | {
8 | ///
9 | public SmallerOrEqualExpression(IExpression l, IExpression r) : base(l, r) { }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return new DoubleValue(
15 | Left.Evaluate(scope, environment).AsDouble() <= Right.Evaluate(scope, environment).AsDouble());
16 | }
17 |
18 | ///
19 | public override string GetSigil()
20 | {
21 | return "<=";
22 | }
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BinaryOpExpression.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser.Expressions
2 | {
3 | public abstract class BinaryOpExpression : Expression
4 | {
5 | public IExpression Left
6 | {
7 | get { return Parameters[0]; }
8 | set
9 | {
10 | Parameters[0] = value;
11 | }
12 | }
13 |
14 | public IExpression Right
15 | {
16 | get { return Parameters[1]; }
17 | set { Parameters[1] = value; }
18 | }
19 |
20 | protected BinaryOpExpression(IExpression l, IExpression r) : base(l, r) { }
21 |
22 | public abstract string GetSigil();
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BooleanExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class BooleanExpression : Expression
7 | {
8 | private readonly IMoValue _value;
9 |
10 | public BooleanExpression(bool value) : base()
11 | {
12 | _value = value ? DoubleValue.One : DoubleValue.Zero;
13 | }
14 |
15 | ///
16 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
17 | {
18 | return _value;
19 | }
20 | }
21 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BooleanNotExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class BooleanNotExpression : Expression
7 | {
8 | public BooleanNotExpression(IExpression value) : base(value)
9 | {
10 | //Value = value;
11 | }
12 |
13 | ///
14 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
15 | {
16 | return Parameters[0].Evaluate(scope, environment).AsBool() ? DoubleValue.Zero :
17 | DoubleValue.One; // .Equals(DoubleValue.One) ? DoubleValue.Zero : DoubleValue.One;
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/BreakExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class BreakExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | scope.IsBreak = true;
12 |
13 | return DoubleValue.Zero;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ContinueExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class ContinueExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | scope.IsContinue = true;
12 |
13 | return DoubleValue.Zero;
14 | }
15 | }
16 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ForEachExpression.cs:
--------------------------------------------------------------------------------
1 | using System.Linq;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Struct;
4 | using ConcreteMC.MolangSharp.Runtime.Value;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Expressions
7 | {
8 | public class ForEachExpression : Expression
9 | {
10 | public IExpression Variable => Parameters[0];
11 | public IExpression Array => Parameters[1];
12 | public IExpression Body => Parameters[2];
13 |
14 | public ForEachExpression(IExpression variable, IExpression array, IExpression body) : base(
15 | variable, array, body) { }
16 |
17 | ///
18 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
19 | {
20 | IMoValue array = Array.Evaluate(scope, environment);
21 |
22 | if (array is VariableStruct vs)
23 | {
24 | MoScope subScope = new MoScope(scope.Runtime);
25 |
26 | foreach (IMoValue value in vs.Map.Values)
27 | {
28 | subScope.IsContinue = false;
29 | subScope.IsBreak = false;
30 |
31 | Variable.Assign(
32 | subScope, environment, value is VariableStruct vss ? vss.Map.FirstOrDefault().Value : value);
33 |
34 | Body.Evaluate(subScope, environment);
35 |
36 | if (subScope.ReturnValue != null)
37 | {
38 | return subScope.ReturnValue;
39 | }
40 | else if (subScope.IsBreak)
41 | {
42 | break;
43 | }
44 | }
45 | }
46 |
47 | return DoubleValue.Zero;
48 | }
49 | }
50 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/FuncCallExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 | using ConcreteMC.MolangSharp.Utils;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Expressions
6 | {
7 | public class FuncCallExpression : Expression
8 | {
9 | public MoPath Name { get; set; }
10 |
11 | public FuncCallExpression(MoPath name, IExpression[] args) : base(args)
12 | {
13 | Name = name;
14 | }
15 |
16 | ///
17 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
18 | {
19 | //List p = Args.ToList();
20 | MoPath name = Name; /* Name is NameExpression expression ? expression.Name :
21 | new MoPath(Name.Evaluate(scope, environment).ToString());*/
22 |
23 | IMoValue[] arguments = new IMoValue[Parameters.Length];
24 |
25 | for (int i = 0; i < arguments.Length; i++)
26 | {
27 | arguments[i] = Parameters[i].Evaluate(scope, environment);
28 | }
29 |
30 | return environment.GetValue(name, new MoParams(arguments));
31 | }
32 | }
33 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/LoopExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class LoopExpression : Expression
7 | {
8 | public IExpression Count => Parameters[0];
9 | public IExpression Body => Parameters[1];
10 |
11 | public LoopExpression(IExpression count, IExpression body) : base(count, body) { }
12 |
13 | ///
14 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
15 | {
16 | int loop = (int) Count.Evaluate(scope, environment).AsDouble();
17 | MoScope subScope = new MoScope(scope.Runtime) {Runtime = scope.Runtime};
18 |
19 | while (loop > 0)
20 | {
21 | subScope.IsContinue = false;
22 | subScope.IsBreak = false;
23 |
24 | Body.Evaluate(subScope, environment);
25 | loop--;
26 |
27 | if (subScope.ReturnValue != null)
28 | {
29 | return subScope.ReturnValue;
30 | }
31 | else if (subScope.IsBreak)
32 | {
33 | break;
34 | }
35 | }
36 |
37 | return DoubleValue.Zero;
38 | }
39 | }
40 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/NameExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 | using ConcreteMC.MolangSharp.Utils;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Expressions
6 | {
7 | public class NameExpression : Expression
8 | {
9 | public MoPath Name { get; set; }
10 |
11 | ///
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | return environment.GetValue(Name);
15 | }
16 |
17 | ///
18 | public override void Assign(MoScope scope, MoLangEnvironment environment, IMoValue value)
19 | {
20 | environment.SetValue(Name, value);
21 | }
22 |
23 | ///
24 | public NameExpression(string value)
25 | {
26 | Name = new MoPath(value);
27 | }
28 |
29 | public NameExpression(MoPath path)
30 | {
31 | Name = path;
32 | }
33 | }
34 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/NumberExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class NumberExpression : Expression
7 | {
8 | private readonly IMoValue _value;
9 |
10 | ///
11 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
12 | {
13 | return _value;
14 | }
15 |
16 | ///
17 | public NumberExpression(double value) : base()
18 | {
19 | _value = new DoubleValue(value);
20 | }
21 |
22 | public NumberExpression(IMoValue value) : base()
23 | {
24 | _value = value;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ReturnExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class ReturnExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | IMoValue eval = Parameters[0].Evaluate(scope, environment);
12 | scope.ReturnValue = eval;
13 |
14 | return eval;
15 | }
16 |
17 | ///
18 | public ReturnExpression(IExpression value) : base(value) { }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ScriptExpression.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Runtime;
3 | using ConcreteMC.MolangSharp.Runtime.Exceptions;
4 | using ConcreteMC.MolangSharp.Runtime.Value;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Expressions
7 | {
8 | public class ScriptExpression : Expression
9 | {
10 | public ScriptExpression(IExpression[] expressions) : base(expressions) { }
11 |
12 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
13 | {
14 | IMoValue result = DoubleValue.Zero;
15 | // MoScope scope = new MoScope(this);
16 |
17 | foreach (IExpression expression in Parameters)
18 | {
19 | if (expression == null)
20 | continue;
21 |
22 | try
23 | {
24 | result = expression.Evaluate(scope, environment);
25 |
26 | if (scope.ReturnValue != null)
27 | {
28 | result = scope.ReturnValue;
29 |
30 | break;
31 | }
32 | }
33 | catch (Exception ex)
34 | {
35 | throw new MoLangRuntimeException(
36 | expression, "An error occured while evaluating the expression", ex);
37 | }
38 | }
39 |
40 | return result;
41 | }
42 | }
43 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/StatementExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class StatementExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | foreach (IExpression expression in Parameters)
12 | {
13 | expression.Evaluate(scope, environment);
14 |
15 | if (scope.ReturnValue != null)
16 | {
17 | return scope.ReturnValue;
18 | }
19 | else if (scope.IsBreak || scope.IsContinue)
20 | {
21 | break;
22 | }
23 | }
24 |
25 | return DoubleValue.Zero;
26 | }
27 |
28 | ///
29 | public StatementExpression(IExpression[] value) : base(value) { }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/StringExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class StringExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | return new StringValue(_value);
12 | }
13 |
14 | private string _value;
15 |
16 | ///
17 | public StringExpression(string value) : base()
18 | {
19 | _value = value;
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/TernaryExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class TernaryExpression : Expression
7 | {
8 | public IExpression Condition => Parameters[0];
9 | public IExpression ThenExpr => Parameters[1];
10 | public IExpression ElseExpr => Parameters[2];
11 |
12 | public TernaryExpression(IExpression condition, IExpression thenExpr, IExpression elseExpr) : base(
13 | condition, thenExpr, elseExpr) { }
14 |
15 | ///
16 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
17 | {
18 | if (Condition.Evaluate(scope, environment).Equals(DoubleValue.One))
19 | {
20 | return ThenExpr == null ? Condition.Evaluate(scope, environment) :
21 | ThenExpr.Evaluate(scope, environment);
22 | }
23 | else if (ElseExpr != null)
24 | {
25 | return ElseExpr.Evaluate(scope, environment);
26 | }
27 |
28 | return DoubleValue.Zero;
29 | }
30 | }
31 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/ThisExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class ThisExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | return environment.ThisVariable; // environment.GetValue(_this);
12 | }
13 |
14 | ///
15 | public ThisExpression() { }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/UnaryMinusExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class UnaryMinusExpression : Expression
7 | {
8 | ///
9 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
10 | {
11 | return new DoubleValue(-(Parameters[0].Evaluate(scope, environment).AsDouble()));
12 | }
13 |
14 | ///
15 | public UnaryMinusExpression(IExpression value) : base(value) { }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Expressions/UnaryPlusExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Expressions
5 | {
6 | public class UnaryPlusExpression : Expression
7 | {
8 | ///
9 | public UnaryPlusExpression(IExpression value) : base(value)
10 | {
11 | //_value = value;
12 | }
13 |
14 | ///
15 | public override IMoValue Evaluate(MoScope scope, MoLangEnvironment environment)
16 | {
17 | return new DoubleValue(+(Parameters[0].Evaluate(scope, environment).AsDouble()));
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/IExpression.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Runtime;
2 | using ConcreteMC.MolangSharp.Runtime.Value;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser
5 | {
6 | ///
7 | /// The interface for all expressions to implement
8 | ///
9 | public interface IExpression
10 | {
11 | ///
12 | /// Contains metadata about this expression
13 | ///
14 | ExpressionMeta Meta { get; }
15 |
16 | ///
17 | /// Evaluate the expression
18 | ///
19 | /// The current scope
20 | /// The environment provided by the
21 | /// The value returned by the expression
22 | IMoValue Evaluate(MoScope scope, MoLangEnvironment environment);
23 |
24 | ///
25 | /// Invoked when trying to assign a value to a property/field
26 | ///
27 | /// The current scope
28 | /// The environment provided by the
29 | /// The value to assign
30 | void Assign(MoScope scope, MoLangEnvironment environment, IMoValue value);
31 |
32 | ///
33 | /// The parameters used by this expression
34 | ///
35 | IExpression[] Parameters { get; set; }
36 | }
37 |
38 | public abstract class Expression : Expression
39 | {
40 | protected Expression(T value) : base()
41 | {
42 | Value = value;
43 | }
44 |
45 | public T Value { get; set; }
46 | }
47 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/IExpressionVisitor.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser
2 | {
3 | ///
4 | /// The base interface for expression visitors.
5 | ///
6 | ///
7 | /// Expression visitors are mainly used to optimize arrays of
8 | /// One such example is the
9 | ///
10 | public interface IExpressionVisitor
11 | {
12 | ///
13 | /// Invoked before any ExpressionVisitor has traversed expression array
14 | ///
15 | /// The expressions to be traversed
16 | void BeforeTraverse(IExpression[] expressions);
17 |
18 | ///
19 | /// Invoked once for every
20 | ///
21 | /// The that invoked the visitor
22 | /// The expressions to visit
23 | /// The visited expression
24 | IExpression OnVisit(ExpressionTraverser traverser, IExpression expression);
25 |
26 | ///
27 | /// Invoked when all ExpressionVisitors have visited an expression
28 | ///
29 | /// The expressions that has been visited
30 | void OnLeave(IExpression expression);
31 |
32 | ///
33 | /// Invoked after all of the ExpressionVisitors have traversed an expression array
34 | ///
35 | /// The visited expression array
36 | void AfterTraverse(IExpression[] expressions);
37 | }
38 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/InfixParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser
4 | {
5 | public abstract class InfixParselet
6 | {
7 | public Precedence Precedence { get; protected set; }
8 |
9 | public InfixParselet(Precedence precedence)
10 | {
11 | Precedence = precedence;
12 | }
13 |
14 | public abstract IExpression Parse(MoLangParser parser, Token token, IExpression leftExpr);
15 | }
16 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/ArrayAccessParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the indexer/array accessor parser
8 | ///
9 | ///
10 | /// Parses expressions such as "array[0]"
11 | ///
12 | public class ArrayAccessParselet : InfixParselet
13 | {
14 | ///
15 | public override IExpression Parse(MoLangParser parser, Token token, IExpression leftExpr)
16 | {
17 | IExpression index = parser.ParseExpression(Precedence);
18 | parser.ConsumeToken(TokenType.ArrayRight);
19 |
20 | return new ArrayAccessExpression(leftExpr, index);
21 | }
22 |
23 | ///
24 | public ArrayAccessParselet() : base(Precedence.ArrayAccess) { }
25 | }
26 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/AssignParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "=" parselet
8 | ///
9 | public class AssignParselet : InfixParselet
10 | {
11 | ///
12 | public AssignParselet() : base(Precedence.Assignment) { }
13 |
14 | ///
15 | public override IExpression Parse(MoLangParser parser, Token token, IExpression leftExpr)
16 | {
17 | return new AssignExpression(leftExpr, parser.ParseExpression(Precedence));
18 | }
19 | }
20 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/BooleanNotParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "!=" parselet
8 | ///
9 | public class BooleanNotParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new BooleanNotExpression(parser.ParseExpression(Precedence.Prefix));
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/BooleanParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the boolean parselet
8 | ///
9 | public class BooleanParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new BooleanExpression(bool.Parse(token.Text));
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/BracketScopeParselet.cs:
--------------------------------------------------------------------------------
1 | using System.Collections.Generic;
2 | using ConcreteMC.MolangSharp.Parser.Expressions;
3 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Parselet
6 | {
7 | ///
8 | /// Implements the scope parselet
9 | ///
10 | public class BracketScopeParselet : PrefixParselet
11 | {
12 | ///
13 | public override IExpression Parse(MoLangParser parser, Token token)
14 | {
15 | List exprs = new List();
16 |
17 | if (!parser.MatchToken(TokenType.CurlyBracketRight))
18 | {
19 | do
20 | {
21 | if (parser.MatchToken(TokenType.CurlyBracketRight, false))
22 | {
23 | break;
24 | }
25 |
26 | exprs.Add(parser.ParseExpression(Precedence.Scope));
27 | } while (parser.MatchToken(TokenType.Semicolon));
28 |
29 | parser.ConsumeToken(TokenType.CurlyBracketRight);
30 | }
31 |
32 | return new StatementExpression(exprs.ToArray());
33 | }
34 | }
35 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/BreakParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "break" instruction parser
8 | ///
9 | public class BreakParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new BreakExpression();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/ContinueParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "continue" instruction parser
8 | ///
9 | public class ContinueParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new ContinueExpression();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/FloatParselet.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using ConcreteMC.MolangSharp.Parser.Exceptions;
3 | using ConcreteMC.MolangSharp.Parser.Expressions;
4 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Parselet
7 | {
8 | ///
9 | /// Implements Float parsing
10 | ///
11 | public class FloatParselet : PrefixParselet
12 | {
13 | private const NumberStyles NumberStyle = System.Globalization.NumberStyles.AllowDecimalPoint;
14 | private static readonly CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
15 |
16 | ///
17 | public override IExpression Parse(MoLangParser parser, Token token)
18 | {
19 | if (float.TryParse(token.Text, NumberStyle, Culture, out var result))
20 | {
21 | return new NumberExpression(result);
22 | }
23 |
24 | throw new MoLangParserException($"Could not parse \'{token.Text.ToString()}\' as float");
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/ForEachParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Exceptions;
2 | using ConcreteMC.MolangSharp.Parser.Expressions;
3 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Parselet
6 | {
7 | ///
8 | /// Implements the "foreach" instruction parser
9 | ///
10 | public class ForEachParselet : PrefixParselet
11 | {
12 | ///
13 | public override IExpression Parse(MoLangParser parser, Token token)
14 | {
15 | if (!parser.TryParseArgs(out var expressions) || expressions.Length != 3)
16 | throw new MoLangParserException(
17 | $"ForEach: Expected 3 argument, {(expressions?.Length ?? 0)} argument given");
18 |
19 | return new ForEachExpression(expressions[0], expressions[1], expressions[2]);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/GenericBinaryOpParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions.BinaryOp;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Generic binary operator parselet
8 | ///
9 | public class GenericBinaryOpParselet : InfixParselet
10 | {
11 | ///
12 | public GenericBinaryOpParselet(Precedence precedence) : base(precedence) { }
13 |
14 | ///
15 | public override IExpression Parse(MoLangParser parser, Token token, IExpression leftExpr)
16 | {
17 | IExpression rightExpr = parser.ParseExpression(Precedence);
18 |
19 | if (token.Type.Equals(TokenType.Arrow))
20 | return new ArrowExpression(leftExpr, rightExpr);
21 |
22 | if (token.Type.Equals(TokenType.And))
23 | return new BooleanAndExpression(leftExpr, rightExpr);
24 |
25 | if (token.Type.Equals(TokenType.Or))
26 | return new BooleanOrExpression(leftExpr, rightExpr);
27 |
28 | if (token.Type.Equals(TokenType.Coalesce))
29 | return new CoalesceExpression(leftExpr, rightExpr);
30 |
31 | if (token.Type.Equals(TokenType.Slash))
32 | return new DivideExpression(leftExpr, rightExpr);
33 |
34 | if (token.Type.Equals(TokenType.EqualsEquals))
35 | return new EqualExpression(leftExpr, rightExpr);
36 |
37 | if (token.Type.Equals(TokenType.Greater))
38 | return new GreaterExpression(leftExpr, rightExpr);
39 |
40 | if (token.Type.Equals(TokenType.GreaterOrEquals))
41 | return new GreaterOrEqualExpression(leftExpr, rightExpr);
42 |
43 | if (token.Type.Equals(TokenType.Minus))
44 | return new MinusExpression(leftExpr, rightExpr);
45 |
46 | if (token.Type.Equals(TokenType.NotEquals))
47 | return new NotEqualExpression(leftExpr, rightExpr);
48 |
49 | if (token.Type.Equals(TokenType.Plus))
50 | return new PlusExpression(leftExpr, rightExpr);
51 |
52 | if (token.Type.Equals(TokenType.Asterisk))
53 | return new PowExpression(leftExpr, rightExpr);
54 |
55 | if (token.Type.Equals(TokenType.Smaller))
56 | return new SmallerExpression(leftExpr, rightExpr);
57 |
58 | if (token.Type.Equals(TokenType.SmallerOrEquals))
59 | return new SmallerOrEqualExpression(leftExpr, rightExpr);
60 |
61 | return null;
62 | }
63 | }
64 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/GroupParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser.Parselet
4 | {
5 | ///
6 | /// Implements the "group" parselet
7 | ///
8 | public class GroupParselet : PrefixParselet
9 | {
10 | ///
11 | public override IExpression Parse(MoLangParser parser, Token token)
12 | {
13 | IExpression expr = parser.ParseExpression();
14 | var result = parser.ConsumeToken(TokenType.BracketRight);
15 |
16 | return expr;
17 | }
18 | }
19 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/LoopParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Exceptions;
2 | using ConcreteMC.MolangSharp.Parser.Expressions;
3 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Parselet
6 | {
7 | ///
8 | /// Implements the "loop" instruction parser
9 | ///
10 | public class LoopParselet : PrefixParselet
11 | {
12 | ///
13 | public override IExpression Parse(MoLangParser parser, Token token)
14 | {
15 | if (!parser.TryParseArgs(out var expressions) || expressions.Length != 2)
16 | throw new MoLangParserException(
17 | $"Loop: Expected 2 argument, {(expressions?.Length ?? 0)} argument given");
18 |
19 | return new LoopExpression(expressions[0], expressions[1]);
20 | }
21 | }
22 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/NameParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 | using ConcreteMC.MolangSharp.Utils;
4 |
5 | namespace ConcreteMC.MolangSharp.Parser.Parselet
6 | {
7 | ///
8 | /// Implements the "name" parser
9 | ///
10 | ///
11 | /// Used to parse function calls or property accessors.
12 | /// For example: "query.frame_time" or "math.min(10, 20)"
13 | ///
14 | public class NameParselet : PrefixParselet
15 | {
16 | ///
17 | public override IExpression Parse(MoLangParser parser, Token token)
18 | {
19 | var path = parser.FixNameShortcut(new MoPath(token.Text));
20 |
21 | if (parser.TryParseArgs(out var expressions))
22 | return new FuncCallExpression(path, expressions);
23 |
24 | return new NameExpression(path);
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/NumberParselet.cs:
--------------------------------------------------------------------------------
1 | using System.Globalization;
2 | using ConcreteMC.MolangSharp.Parser.Exceptions;
3 | using ConcreteMC.MolangSharp.Parser.Expressions;
4 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
5 |
6 | namespace ConcreteMC.MolangSharp.Parser.Parselet
7 | {
8 | ///
9 | /// Implements number parsing
10 | ///
11 | public class NumberParselet : PrefixParselet
12 | {
13 | private const NumberStyles NumberStyle = System.Globalization.NumberStyles.AllowDecimalPoint;
14 | private static readonly CultureInfo Culture = System.Globalization.CultureInfo.InvariantCulture;
15 |
16 | ///
17 | public override IExpression Parse(MoLangParser parser, Token token)
18 | {
19 | if (double.TryParse(token.Text, NumberStyle, Culture, out var result))
20 | {
21 | return new NumberExpression(result);
22 | }
23 |
24 | throw new MoLangParserException($"Could not parse \'{token.Text.ToString()}\' as a double");
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/ReturnParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "return" instruction parser
8 | ///
9 | public class ReturnParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new ReturnExpression(parser.ParseExpression());
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/StringParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the string parser
8 | ///
9 | public class StringParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new StringExpression(token.Text);
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/TernaryParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the Ternary expression parser
8 | ///
9 | public class TernaryParselet : InfixParselet
10 | {
11 | ///
12 | public TernaryParselet() : base(Precedence.Conditional) { }
13 |
14 | ///
15 | public override IExpression Parse(MoLangParser parser, Token token, IExpression leftExpr)
16 | {
17 | if (parser.MatchToken(TokenType.Colon))
18 | {
19 | return new TernaryExpression(leftExpr, null, parser.ParseExpression(Precedence));
20 | }
21 | else
22 | {
23 | IExpression thenExpr = parser.ParseExpression(Precedence);
24 |
25 | if (!parser.MatchToken(TokenType.Colon))
26 | {
27 | return new TernaryExpression(leftExpr, thenExpr, null);
28 | }
29 | else
30 | {
31 | return new TernaryExpression(leftExpr, thenExpr, parser.ParseExpression(Precedence));
32 | }
33 | }
34 | }
35 | }
36 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/ThisParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the "this" instruction parser
8 | ///
9 | public class ThisParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new ThisExpression();
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/UnaryMinusParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the unary minus parser
8 | ///
9 | public class UnaryMinusParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new UnaryMinusExpression(parser.ParseExpression(Precedence.Prefix));
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Parselet/UnaryPlusParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Expressions;
2 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Parselet
5 | {
6 | ///
7 | /// Implements the unary plus parser
8 | ///
9 | public class UnaryPlusParselet : PrefixParselet
10 | {
11 | ///
12 | public override IExpression Parse(MoLangParser parser, Token token)
13 | {
14 | return new UnaryPlusExpression(parser.ParseExpression(Precedence.Prefix));
15 | }
16 | }
17 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Precedence.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser
2 | {
3 | public enum Precedence
4 | {
5 | Anything,
6 | Scope,
7 |
8 | Assignment,
9 | Conditional,
10 | ArrayAccess,
11 |
12 | Coalesce,
13 |
14 | And,
15 | Or,
16 |
17 | Compare,
18 |
19 | Sum,
20 | Product,
21 | Prefix,
22 | Arrow
23 | }
24 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/PrefixParselet.cs:
--------------------------------------------------------------------------------
1 | using ConcreteMC.MolangSharp.Parser.Tokenizer;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser
4 | {
5 | public abstract class PrefixParselet
6 | {
7 | public abstract IExpression Parse(MoLangParser parser, Token token);
8 | }
9 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Tokenizer/ITokenIterator.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser.Tokenizer
2 | {
3 | public interface ITokenIterator
4 | {
5 | Token Next();
6 |
7 | void Step();
8 | }
9 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Tokenizer/Token.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser.Tokenizer
2 | {
3 | ///
4 | /// A token is a piece of code in an expression
5 | ///
6 | public class Token
7 | {
8 | ///
9 | /// The type of this token
10 | ///
11 | public TokenType Type { get; }
12 |
13 | ///
14 | /// The piece of code defining this token
15 | ///
16 | public string Text { get; }
17 |
18 | ///
19 | /// The position in the source expression that this token was found at
20 | ///
21 | public TokenPosition Position { get; }
22 |
23 | ///
24 | /// Initializes a new token
25 | ///
26 | ///
27 | ///
28 | public Token(TokenType tokenType, TokenPosition position)
29 | {
30 | this.Type = tokenType;
31 | this.Text = tokenType.Symbol;
32 | this.Position = position;
33 | }
34 |
35 | ///
36 | /// Initializes a new token
37 | ///
38 | ///
39 | ///
40 | ///
41 | public Token(TokenType tokenType, string text, TokenPosition position)
42 | {
43 | this.Type = tokenType;
44 | this.Text = text;
45 | this.Position = position;
46 | }
47 | }
48 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Tokenizer/TokenIterator.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using ConcreteMC.MolangSharp.Parser.Exceptions;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Tokenizer
5 | {
6 | public class TokenIterator : ITokenIterator
7 | {
8 | private readonly string _code;
9 |
10 | private int _index = 0;
11 | private int _currentLine = 0;
12 | private int _lastStep = 0;
13 | private int _lastStepLine = 0;
14 |
15 | public TokenIterator(string code)
16 | {
17 | this._code = code;
18 | }
19 |
20 | public Token Next()
21 | {
22 | while (_index < _code.Length)
23 | {
24 | if (_code.Length > _index + 1)
25 | {
26 | // check tokens with double chars
27 | TokenType token = TokenType.BySymbol(_code.Substring(_index, 2));
28 |
29 | if (token != null)
30 | {
31 | _index += 2;
32 |
33 | return new Token(token, GetPosition());
34 | }
35 | }
36 |
37 | var expr = GetCharacterAt(_index);
38 | TokenType tokenType = TokenType.BySymbol(expr);
39 |
40 | if (tokenType != null)
41 | {
42 | _index++;
43 |
44 | return new Token(tokenType, GetPosition());
45 | }
46 | else
47 | {
48 | if (expr.Equals('\''))
49 | {
50 | int stringStart = _index + 1;
51 | int stringLength = 0;
52 |
53 | while (stringStart + stringLength < _code.Length
54 | && !GetCharacterAt(stringStart + stringLength).Equals('\''))
55 | {
56 | stringLength++;
57 | }
58 |
59 | stringLength++;
60 | _index = stringStart + stringLength;
61 |
62 | return new Token(
63 | TokenType.String, _code.Substring(stringStart, stringLength - 1), GetPosition());
64 | }
65 |
66 | if (char.IsLetter(expr))
67 | {
68 | var nameStart = _index;
69 | int nameLength = 1;
70 |
71 | while (nameStart + nameLength < _code.Length
72 | && (char.IsLetterOrDigit(GetCharacterAt(nameStart + nameLength))
73 | || GetCharacterAt(nameStart + nameLength).Equals('_')
74 | || GetCharacterAt(nameStart + nameLength).Equals('.')))
75 | {
76 | nameLength++;
77 | }
78 |
79 | string value = _code.Substring(_index, nameLength);
80 | TokenType token = TokenType.BySymbol(value);
81 |
82 | if (token == null)
83 | {
84 | token = TokenType.Name;
85 | }
86 |
87 | _index = nameStart + nameLength;
88 |
89 | return new Token(token, value, GetPosition());
90 | }
91 |
92 | if (char.IsDigit(expr))
93 | {
94 | int numStart = _index;
95 | int numLength = 1;
96 | bool hasDecimal = false;
97 | bool isFloat = false;
98 |
99 |
100 | while (numStart + numLength < _code.Length)
101 | {
102 | var character = GetCharacterAt(numStart + numLength);
103 |
104 | if (!char.IsDigit(character))
105 | {
106 | if (character == 'f' && !isFloat)
107 | {
108 | isFloat = true;
109 | }
110 | else if (character == '.' && !hasDecimal)
111 | {
112 | hasDecimal = true;
113 | }
114 | else
115 | {
116 | break;
117 | }
118 | }
119 |
120 | numLength++;
121 |
122 | if (isFloat)
123 | break;
124 | }
125 |
126 | _index = numStart + numLength;
127 |
128 | if (isFloat)
129 | return new Token(
130 | TokenType.FloatingPointNumber, _code.Substring(numStart, numLength - 1), GetPosition());
131 |
132 | return new Token(TokenType.Number, _code.Substring(numStart, numLength), GetPosition());
133 | }
134 |
135 | if (expr.Equals('\n') || expr.Equals('\r'))
136 | {
137 | _currentLine++;
138 | }
139 | }
140 |
141 | _index++;
142 | }
143 |
144 | return new Token(TokenType.Eof, GetPosition());
145 | }
146 |
147 | public void Step()
148 | {
149 | _lastStep = _index;
150 | _lastStepLine = _currentLine;
151 | }
152 |
153 | private TokenPosition GetPosition()
154 | {
155 | return new TokenPosition(_lastStepLine, _currentLine, _lastStep, _index);
156 | }
157 |
158 | private char GetCharacterAt(int index)
159 | {
160 | if (index > _code.Length - 1)
161 | throw new MoLangParserException(
162 | $"Value '{index + 1}' is outside of range Min: 0, Max:{_code.Length - 1}",
163 | new IndexOutOfRangeException(nameof(index)));
164 |
165 | return _code[index]; //.Substring(index, 1)[0];
166 | }
167 | }
168 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Tokenizer/TokenPosition.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser.Tokenizer
2 | {
3 | ///
4 | /// Describes the position of a
5 | ///
6 | public class TokenPosition
7 | {
8 | // public int StartLineNumber;
9 | //public int EndLineNumber;
10 | //public int StartColumn;
11 | // public int EndColumn;
12 | ///
13 | /// The linenumber this token was found at
14 | ///
15 | public int LineNumber { get; }
16 |
17 | ///
18 | /// The character index of this token
19 | ///
20 | public int Index { get; }
21 |
22 | public TokenPosition(int lastStepLine, int currentLine, int lastStep, int index)
23 | {
24 | LineNumber = currentLine;
25 | Index = index;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Tokenizer/TokenType.cs:
--------------------------------------------------------------------------------
1 | using System.Threading;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser.Tokenizer
4 | {
5 | public sealed class TokenType
6 | {
7 | public static readonly TokenType EqualsEquals = new TokenType("==", "EqualsEquals");
8 | public static readonly TokenType NotEquals = new TokenType("!=", "Not Equals");
9 | public static readonly TokenType Coalesce = new TokenType("??", "Coalesce");
10 | public static readonly TokenType And = new TokenType("&&", "AndAnd");
11 | public static readonly TokenType Or = new TokenType("||", "Or");
12 | public static readonly TokenType GreaterOrEquals = new TokenType(">=", "Greater or equal to");
13 | public static readonly TokenType SmallerOrEquals = new TokenType("<=", "Smaller or equal to");
14 | public static readonly TokenType Arrow = new TokenType("->", "Arrow");
15 |
16 | public static readonly TokenType Greater = new TokenType(">", "Bigger");
17 | public static readonly TokenType Smaller = new TokenType("<", "Smaller");
18 | public static readonly TokenType BracketLeft = new TokenType("(", "Bracket Left");
19 | public static readonly TokenType BracketRight = new TokenType(")", "Bracket Right");
20 | public static readonly TokenType ArrayLeft = new TokenType("[", "Array Left");
21 | public static readonly TokenType ArrayRight = new TokenType("]", "Array Right");
22 | public static readonly TokenType CurlyBracketLeft = new TokenType("{", "Curly Bracket Left");
23 | public static readonly TokenType CurlyBracketRight = new TokenType("}", "Curly Bracket Right");
24 | public static readonly TokenType Comma = new TokenType(",", "Comma");
25 | public static readonly TokenType Assign = new TokenType("=", "Assign");
26 | public static readonly TokenType Plus = new TokenType("+", "Plus");
27 | public static readonly TokenType Minus = new TokenType("-", "Minus");
28 | public static readonly TokenType Asterisk = new TokenType("*", "Asterisk");
29 | public static readonly TokenType Slash = new TokenType("/", "Slash");
30 | public static readonly TokenType Question = new TokenType("?", "Question");
31 | public static readonly TokenType Colon = new TokenType(":", "Colon");
32 | public static readonly TokenType Semicolon = new TokenType(";", "Semicolon");
33 | public static readonly TokenType Bang = new TokenType("!", "Bang");
34 |
35 | public static readonly TokenType Return = new TokenType("return", "Return");
36 | public static readonly TokenType Continue = new TokenType("continue", "Continue");
37 | public static readonly TokenType Break = new TokenType("break", "Break");
38 | public static readonly TokenType ForEach = new TokenType("for_each", "ForEach");
39 | public static readonly TokenType Loop = new TokenType("loop", "Loop");
40 | public static readonly TokenType This = new TokenType("this", "Reference");
41 | public static readonly TokenType True = new TokenType("true", "bool");
42 | public static readonly TokenType False = new TokenType("false", "bool");
43 | public static readonly TokenType String = new TokenType("", "string");
44 | public static readonly TokenType Number = new TokenType("", "number");
45 | public static readonly TokenType FloatingPointNumber = new TokenType("", "floating point number");
46 | public static readonly TokenType Name = new TokenType("", "name");
47 | public static readonly TokenType Eof = new TokenType("", "EndOfFile");
48 |
49 | private static int _typeCounter = 0;
50 |
51 | ///
52 | /// A string "identifying" this tokentype
53 | ///
54 | public string Symbol { get; }
55 |
56 | ///
57 | /// A human readable identifier for this tokentype
58 | ///
59 | public string TypeName { get; }
60 |
61 | private readonly int _typeId;
62 |
63 | private TokenType(string symbol, string typename = "")
64 | {
65 | Symbol = symbol;
66 | TypeName = typename;
67 |
68 | _typeId = Interlocked.Increment(ref _typeCounter);
69 | }
70 |
71 | private static readonly TokenType[] Values = new TokenType[]
72 | {
73 | EqualsEquals, NotEquals, Coalesce, And, Or, GreaterOrEquals, SmallerOrEquals, Arrow, Greater, Smaller,
74 | BracketLeft, BracketRight, ArrayLeft, ArrayRight, CurlyBracketLeft, CurlyBracketRight, Comma, Assign,
75 | Plus, Minus, Asterisk, Slash, Question, Colon, Semicolon, Bang, Return, Continue, Break, ForEach, Loop,
76 | This, True, False, String, Number, Name, Eof
77 | };
78 |
79 | ///
80 | /// Finds the TokenType by symbol
81 | ///
82 | /// The symbol to lookup
83 | /// The resulting TokenType or null if no match has been found
84 | public static TokenType BySymbol(string symbol)
85 | {
86 | foreach (TokenType tokenType in TokenType.Values)
87 | {
88 | if (tokenType.Symbol.Equals(symbol))
89 | {
90 | return tokenType;
91 | }
92 | }
93 |
94 | return null;
95 | }
96 |
97 | ///
98 | /// Finds the TokenType by symbol
99 | ///
100 | /// The symbol to lookup
101 | /// The resulting TokenType or null if no match has been found
102 | public static TokenType BySymbol(char symbol)
103 | {
104 | return BySymbol(symbol.ToString());
105 | }
106 |
107 | ///
108 | /// Checks if this tokentype is equal to
109 | ///
110 | ///
111 | ///
112 | public bool Equals(TokenType other)
113 | {
114 | return _typeId == other._typeId;
115 | }
116 | }
117 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Visitors/ExpressionConnectingVisitor.cs:
--------------------------------------------------------------------------------
1 | namespace ConcreteMC.MolangSharp.Parser.Visitors
2 | {
3 | public class ExpressionConnectingVisitor : ExpressionVisitor
4 | {
5 | //private LinkedList Stack { get; set; } = new LinkedList();
6 |
7 | // private LinkedList _previousStack = null;
8 |
9 | private IExpression _last = null;
10 |
11 | ///
12 | public override void BeforeTraverse(IExpression[] expressions)
13 | {
14 | _last = null;
15 | // _previousStack = Stack;
16 | // Stack = new LinkedList();
17 | }
18 |
19 | ///
20 | public override IExpression OnVisit(ExpressionTraverser traverser, IExpression expression)
21 | {
22 | var previous = _last;
23 | expression.Meta.Previous = previous;
24 |
25 | if (previous != null && previous != expression.Meta.Parent)
26 | {
27 | previous.Meta.Next = expression;
28 | }
29 |
30 | //Stack.AddLast(expression);
31 |
32 | return expression;
33 | }
34 |
35 | ///
36 | public override void OnLeave(IExpression expression)
37 | {
38 | _last = expression;
39 | //Stack.RemoveLast();
40 | }
41 |
42 | ///
43 | public override void AfterTraverse(IExpression[] expressions)
44 | {
45 | base.AfterTraverse(expressions);
46 | //Stack = _previousStack;
47 | }
48 | }
49 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Visitors/FindingVisitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Collections.Generic;
3 |
4 | namespace ConcreteMC.MolangSharp.Parser.Visitors
5 | {
6 | public class FindingVisitor : ExpressionVisitor
7 | {
8 | private Predicate _predicate;
9 | public List FoundExpressions = new List();
10 |
11 | public FindingVisitor(Predicate predicate)
12 | {
13 | _predicate = predicate;
14 | }
15 |
16 | ///
17 | public override IExpression OnVisit(ExpressionTraverser traverser, IExpression expression)
18 | {
19 | if (_predicate(expression))
20 | {
21 | FoundExpressions.Add(expression);
22 | }
23 |
24 | return expression;
25 | }
26 | }
27 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Visitors/FirstFindingVisitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 |
3 | namespace ConcreteMC.MolangSharp.Parser.Visitors
4 | {
5 | public class FirstFindingVisitor : ExpressionVisitor
6 | {
7 | private Predicate _predicate;
8 | public IExpression Found = null;
9 |
10 | public FirstFindingVisitor(Predicate predicate)
11 | {
12 | _predicate = predicate;
13 | }
14 |
15 | ///
16 | public override IExpression OnVisit(ExpressionTraverser traverser, IExpression expression)
17 | {
18 | if (_predicate(expression))
19 | {
20 | Found = expression;
21 |
22 | traverser.Stop();
23 | }
24 |
25 | return expression;
26 | }
27 | }
28 | }
--------------------------------------------------------------------------------
/src/MolangSharp/Parser/Visitors/InteropOptimization/InteropOptimizationVisitor.cs:
--------------------------------------------------------------------------------
1 | using System;
2 | using System.Linq;
3 | using ConcreteMC.MolangSharp.Parser.Expressions;
4 | using ConcreteMC.MolangSharp.Runtime;
5 | using ConcreteMC.MolangSharp.Runtime.Struct.Interop;
6 | using ConcreteMC.MolangSharp.Runtime.Value;
7 | using ConcreteMC.MolangSharp.Utils;
8 |
9 | namespace ConcreteMC.MolangSharp.Parser.Visitors.InteropOptimization
10 | {
11 | ///
12 | /// Optimizes interop calls to call the methods or properties directly instead of going through the MoLang query system.
13 | ///
14 | ///
15 | /// This is a very simple optimization that can be done to improve performance, it does come with some limitations however.
16 | /// These limitations are:
17 | /// - You need to pass in the object instance to the visitor options, this is because the visitor cannot know what object you are trying to access.
18 | /// - You cannot access properties or functions that are not directly on the object, for example: query.myThing.blabla will not work, but query.blabla will work.
19 | ///
20 | public class InteropOptimizationVisitor : ExpressionVisitor
21 | {
22 | private readonly InteropOptimizationVisitorOptions _options;
23 |
24 | public InteropOptimizationVisitor(InteropOptimizationVisitorOptions options)
25 | {
26 | options.Validate();
27 |
28 | _options = options;
29 | }
30 |
31 | ///
32 | public override IExpression OnVisit(ExpressionTraverser traverser, IExpression expression)
33 | {
34 | switch (expression)
35 | {
36 | case FuncCallExpression functionCall:
37 | return _options.OptimizeFunctionCalls ? TryOptimizeFunctionCall(functionCall) : functionCall;
38 |
39 | case NameExpression nameExpression:
40 | return _options.OptimizeVariableAccess ? TryOptimizeNameExpression(nameExpression) : nameExpression;
41 |
42 | case AssignExpression assignExpression:
43 | return _options.OptimizeVariableAssignment ? TryOptimizeAssignExpression(assignExpression) : assignExpression;
44 |
45 | default:
46 | return expression;
47 | }
48 | }
49 |
50 | private IExpression TryOptimizeAssignExpression(AssignExpression expression)
51 | {
52 | //Optimize variable assignment to call the method directly.
53 | var variableToAccess = expression.Variable;
54 |
55 | if (variableToAccess is NameExpression nameExpression)
56 | {
57 | var name = nameExpression.Name.Value;
58 | var interopEntry = _options.InteropEntries.FirstOrDefault(x => x.Name == name);
59 |
60 | if (interopEntry == null)
61 | return expression;
62 |
63 | if (TryGetProperty(interopEntry.Cache, nameExpression.Name.Next, out var valueAccessor))
64 | {
65 | return new OptimizedAssignExpression(interopEntry.Instance, valueAccessor, expression.Expression);
66 | }
67 | }
68 |
69 | return expression;
70 | }
71 |
72 | private IExpression TryOptimizeNameExpression(NameExpression expression)
73 | {
74 | //Optimize variable access to call the method directly.
75 |
76 | var name = expression.Name.Value;
77 | var interopEntry = _options.InteropEntries.FirstOrDefault(x => x.Name == name);
78 |
79 | if (interopEntry == null)
80 | return expression;
81 |
82 | if (TryGetProperty(interopEntry.Cache, expression.Name.Next, out var valueAccessor))
83 | return new OptimizedNameExpression(interopEntry.Instance, valueAccessor);
84 |
85 | return expression;
86 | }
87 |
88 | private IExpression TryOptimizeFunctionCall(FuncCallExpression expression)
89 | {
90 | //Optimize function call to call the method directly.
91 | var name = expression.Name.Value;
92 | var interopEntry = _options.InteropEntries.FirstOrDefault(x => x.Name == name);
93 |
94 | if (interopEntry == null)
95 | return expression;
96 |
97 | if (TryGetFunction(interopEntry.Cache, expression.Name.Next, out var function))
98 | return new OptimizedFunctionCallExpression(interopEntry.Instance, function, expression.Parameters);
99 |
100 | return expression;
101 | }
102 |
103 | private bool TryGetFunction(PropertyCache cache, MoPath path, out Func