Prexonite, a .NET hosted scripting language with a focus on meta-programming and embedded DSLs
0

Configure Feed

Select the types of activity you want to include in your feed.

PRX-30: Add v2 variants of psr.pattern,psr.struct,psr.misc

Also:
- properly abort preflight parsing by injecting an EOF token
- also consider dependencies when resolving modules
- remove a debug println in prop.pxs
- add app.config

Christian Klauser (Dec 28, 2020, 9:54 PM +0100) ab4b75d4 5424d478

+335 -20
+51 -10
Prexonite/Compiler/Build/Internal/SelfAssemblingPlan.cs
··· 284 284 // requires refSpec.ModuleName != null || refSpec.Source != null || refSpec.rawPath != null || refSpec.ResolvedPath != null 285 285 // ensures result == refSpec && (TargetDescriptions.Contains(result) || refSpec.ErrorMessage != null) 286 286 { 287 - if (refSpec.ErrorMessage != null) 287 + if (!refSpec.IsValid) 288 288 return refSpec; 289 289 290 290 var pathCandidateCount = 0; ··· 312 312 refSpec.ResolvedPath = candidate; 313 313 var result = await _orderPreflight(refSpec, token); 314 314 315 - if (result.ErrorMessage != null) 315 + if (!result.IsValid) 316 316 { 317 317 _trace.TraceEvent(TraceEventType.Verbose, 0, 318 318 "Rejected {0} as a candidate for {1} because there were errors during preflight: {2}", ··· 344 344 candidateSequence?.Dispose(); 345 345 } 346 346 347 - Debug.Assert(refSpec.ErrorMessage != null || TargetDescriptions.Contains(refSpec.ModuleName)); 347 + Debug.Assert(!refSpec.IsValid || TargetDescriptions.Contains(refSpec.ModuleName)); 348 348 return refSpec; 349 349 } 350 350 ··· 360 360 return await _performCreateTargetDescription(result, src, actualToken, mode); 361 361 }, token); 362 362 } 363 - 363 + 364 364 private async Task<ITargetDescription> _performCreateTargetDescription(PreflightResult result, ISource source, CancellationToken token, SelfAssemblyMode mode) 365 365 { 366 - Debug.Assert(result.ErrorMessage == null, "TargetDescription ordered despite the preflight result containing errors."); 367 - Debug.Assert(result.References.All(r => r.ErrorMessage == null), "TargetDescription ordered despite the preflight result containing errors."); 366 + Debug.Assert(result.IsValid, "TargetDescription ordered despite the preflight result (or its dependencies) containing errors.", "PreflightResult {0} is not valid.", result.RenderDebugState()); 368 367 369 368 RefSpec[] refSpecs; 370 369 switch (mode) ··· 384 383 throw new ArgumentOutOfRangeException(nameof(mode), mode, Resources.SelfAssemblingPlan_performCreateTargetDescription_mode); 385 384 } 386 385 387 - var buildMessages = refSpecs.Where(t => t.ErrorMessage != null).Select( 386 + var buildMessages = refSpecs.Where(t => !t.IsValid).Select( 388 387 s => 389 388 { 390 - Debug.Assert(s.ErrorMessage != null); 389 + Debug.Assert(!s.IsValid); 391 390 // ReSharper disable PossibleNullReferenceException,AssignNullToNotNullAttribute 392 391 var refPosition = new SourcePosition( 393 392 s.ResolvedPath != null ? s.ResolvedPath.ToString() ··· 537 536 public volatile bool SuppressStandardLibrary; 538 537 539 538 public bool IsValid => ErrorMessage == null && References.All(x => x.IsValid); 539 + 540 + internal string RenderDebugState() 541 + { 542 + var sb = new StringBuilder(); 543 + _renderDebugState(sb); 544 + return sb.ToString(); 545 + } 546 + 547 + private void _renderDebugState(StringBuilder builder) 548 + { 549 + builder.Append(ModuleName); 550 + builder.Append('('); 551 + if (Path != null) 552 + { 553 + builder.AppendFormat("path: \"{0}\" ", Path); 554 + } 555 + if (ErrorMessage != null) 556 + { 557 + builder.AppendFormat("error: \"{0}\" ", ErrorMessage); 558 + } 559 + 560 + if (References.Count > 0) 561 + { 562 + builder.Append("references: "); 563 + var commaRequired = false; 564 + foreach (var reference in References) 565 + { 566 + if (commaRequired) 567 + { 568 + builder.Append(','); 569 + } 570 + 571 + commaRequired = true; 572 + reference.Render(builder); 573 + } 574 + } 575 + builder.Append(')'); 576 + } 540 577 } 541 578 542 579 internal class RefSpec ··· 556 593 public override string ToString() 557 594 { 558 595 var sb = new StringBuilder(); 596 + Render(sb); 597 + return sb.ToString(); 598 + } 599 + 600 + internal void Render(StringBuilder sb) 601 + { 559 602 if (ModuleName != null) 560 603 sb.Append(ModuleName); 561 604 if (ResolvedPath != null) ··· 570 613 571 614 if (ErrorMessage != null) 572 615 sb.AppendFormat(" error: {0}", ErrorMessage); 573 - 574 - return sb.ToString(); 575 616 } 576 617 } 577 618 }
+6 -1
Prexonite/Compiler/Build/ManualPlan.cs
··· 159 159 return tcs.Task; 160 160 } 161 161 else 162 + { 162 163 // Note how the lambda expression doesn't actually depend on the result (directly) 163 164 // the continue all makes sure that we're not wasting a thread that blocks on Task.Result 164 165 // GetBuildEnvironment can access the results via the taskMap. 166 + Plan.Trace.TraceEvent(TraceEventType.Verbose, 0,"{0} is waiting for its dependencies to be built: {1}", 167 + description.Name, description.Dependencies.ToListString()); 165 168 return Task.Factory.ContinueWhenAll(description.Dependencies.Select(d => taskMap[d].Value).ToArray(), 166 - _ => GetBuildEnvironment(taskMap, description, token)); 169 + _ => GetBuildEnvironment(taskMap, description, token)); 170 + } 167 171 } 168 172 169 173 protected virtual IBuildEnvironment GetBuildEnvironment(TaskMap<ModuleName, ITarget> taskMap, ITargetDescription description, CancellationToken token) ··· 216 220 _linkDependencies(taskMap, instance, targetDescription, token); 217 221 token.ThrowIfCancellationRequested(); 218 222 var target = await BuildTargetAsync(bet, desc, depMap, token); 223 + Plan.Trace.TraceEvent(TraceEventType.Verbose, 0, "Finished BuildTargetAsync({0})", desc.Name); 219 224 return target; 220 225 } 221 226 finally
+1
Prexonite/Compiler/Parser.Code.cs
··· 432 432 public void ViolentlyAbortParse() 433 433 { 434 434 scanner.Abort(); 435 + la = new Token {kind = _EOF, pos = la.pos, line = la.pos, col = la.col, val = ""}; 435 436 } 436 437 437 438 #region Helper
+1 -1
PrexoniteTests/psr-tests/_2/macro.test.pxs
··· 1 - name psr::macro::test; 1 + name psr::macro::test/2.0; 2 2 references { 3 3 psr::test, 4 4 psr::test::meta_macro,
+69
PrexoniteTests/psr-tests/_2/pattern.test.pxs
··· 1 + 2 + name psr::pattern::test/2.0; 3 + references { 4 + psr::test, 5 + psr::pattern 6 + }; 7 + 8 + namespace import 9 + sys.*, 10 + sys.seq.*, 11 + psr.test.assertions.*, 12 + psr.pattern.*, 13 + sys.rt(boxed) 14 + ; 15 + 16 + function test_con[test] 17 + { 18 + var a = 11; 19 + var b = 13; 20 + 21 + var x = kvp(a,b); 22 + assert(x is Prexonite::Types::PValueKeyValuePair,"$(boxed(x)) is not a PValueKeyValuePair"); 23 + assert_eq(x.Key,a,"Key of $(boxed(x)) doesn't match"); 24 + assert_eq(x.Value,b,"Value of $(boxed(x)) doesn't match"); 25 + 26 + //nested 27 + var c = 17; 28 + var d = 19; 29 + var x = kvp(kvp(a,b),kvp(c,d)); 30 + assert(x is Prexonite::Types::PValueKeyValuePair,"$(boxed(x)) is not a PValueKeyValuePair (nested)"); 31 + var xa = x.Key; 32 + assert(xa is Prexonite::Types::PValueKeyValuePair,"$(boxed(xa)) should be PValueKeyValuePair (key of nested)"); 33 + assert_eq(xa.Key,a,"Key of $(boxed(xa)) doesn't match"); 34 + assert_eq(xa.Value,b,"Value of $(boxed(xa)) doesn't match"); 35 + var xb = x.Value; 36 + assert(xb is Prexonite::Types::PValueKeyValuePair,"$(boxed(xb)) should be PValueKeyValuePair (key of nested)"); 37 + assert_eq(xb.Key,c,"Key of $(boxed(xb)) doesn't match"); 38 + assert_eq(xb.Value,d,"Value of $(boxed(xb)) doesn't match"); 39 + } 40 + 41 + function test_dcon[test] 42 + { 43 + var a = 11; 44 + var b = 13; 45 + 46 + var p = a:b; 47 + kvp(var x,var y) = p; 48 + assert_eq(x,a,"Key doesn't match"); 49 + assert_eq(y,b,"Value doesn't match"); 50 + 51 + var c = 17; 52 + var s = new Structure; 53 + var mem_called = false; 54 + s.\\("mem") = (self,z) => { 55 + assert_eq(mem_called,false,"s.mem already called"); 56 + mem_called = true; 57 + assert_eq(z,c,"mem arg doesn't match"); 58 + }; 59 + 60 + var q = p:c; 61 + 62 + var x = y = null; 63 + kvp(kvp(var x, var y),s.mem) = q; 64 + 65 + assert_eq(x,a,"Key doesn't match #2"); 66 + assert_eq(y,b,"Value doesn't match #2"); 67 + assert(mem_called,"s.mem has not been called"); 68 + 69 + }
+106
PrexoniteTests/psr-tests/_2/prop.test.pxs
··· 1 + name psr::prop::test/2.0; 2 + references { 3 + psr::test, 4 + psr::prop, 5 + psr::ast, 6 + psr::$macro 7 + }; 8 + 9 + namespace import 10 + sys.*, 11 + psr.test.assertions.*, 12 + psr.prop.*, 13 + psr.ast, 14 + psr.ast.SI, 15 + psr.$macro.ast, 16 + sys.ct.entityref_to, 17 + sys.rt.boxed; 18 + 19 + function test_prop_simple[test] 20 + { 21 + function p = prop; 22 + 23 + assert(p is null,"Property p should be initialized to null."); 24 + var a = 13; 25 + p(a); 26 + assert_eq(p,a,"Assignment to p failed."); 27 + p(null); 28 + assert(p is null,"Cannot assign null"); 29 + } 30 + 31 + var test_prop_capset\store; 32 + 33 + function test_prop_capset\impl(isset,x) 34 + { 35 + var old = test_prop_capset\store; 36 + test_prop_capset\store = isset.ToString + x; 37 + return old; 38 + } 39 + 40 + macro test_prop_capset 41 + { 42 + var fc = ast.call(context.Call, entityref_to(test_prop_capset\impl)); 43 + fc.Arguments.Add(ast.const(SI.eq(context.Call,SI.set))); 44 + fc.Arguments.AddRange(var args); 45 + context.Block.Expression = fc; 46 + } 47 + 48 + function test_prop_proxy[test] 49 + { 50 + function p = prop(test_prop_capset); 51 + 52 + assert(p is null,"Property p should be initialized to null."); 53 + var a = 13; 54 + p(a); 55 + assert_eq(p,"True13"); 56 + assert_eq(p,"False"); 57 + p(null); 58 + assert_eq(p,"True"); 59 + assert_eq(p,"False"); 60 + } 61 + 62 + function test_prop_complex[test] 63 + { 64 + var assert_flag = null; 65 + var a = 11; 66 + function p = prop(() => 67 + { 68 + if(assert_flag is null) 69 + { 70 + return null; 71 + } 72 + else 73 + { 74 + assert(assert_flag,"Unexpected call to getter"); 75 + assert_flag = false; 76 + return a; 77 + } 78 + }, 79 + value => 80 + { 81 + assert(not assert_flag~Bool,"Unexpected call to setter with $(boxed(value))"); 82 + assert_eq(value,a,"Unexpected value"); 83 + assert_flag = true; 84 + }); 85 + 86 + assert(p is null,"Property p should be initialized to null"); 87 + p(a); 88 + assert_eq(p,a); 89 + a += 2; 90 + p = a; 91 + assert_eq(p,a); 92 + } 93 + 94 + function test_prop_glob = prop; 95 + 96 + function test_prop_simple_glob[test] 97 + { 98 + declare test_prop_glob as p; 99 + 100 + assert(p is null,"Property p should be initialized to null."); 101 + var a = 13; 102 + p(a); 103 + assert_eq(p,a,"Assignment to p failed."); 104 + p(null); 105 + assert(p is null,"Cannot assign null"); 106 + }
+14 -4
PrexoniteTests/psr-tests/_2/run_tests.pxs
··· 30 30 } else { 31 31 // taskMap~Dictionary<ModuleName, Task<Tuple<Application, ITarget>>> 32 32 var taskMap = host.self_assembling_build_plan.LoadAsync(names, no_cancellation); 33 - System::Threading::Tasks::Task.WaitAll(taskMap.Values >> map(?~Object<"System.Threading.Tasks.Task`1[System.Tuple`2[Prexonite.Application,Prexonite.Compiler.Build.ITarget]]">) >> to_list); 33 + var taskArray = ( 34 + taskMap.Values 35 + >> map(?~Object<"System.Threading.Tasks.Task`1[System.Tuple`2[Prexonite.Application,Prexonite.Compiler.Build.ITarget]]">) 36 + >> to_list 37 + )~Object<"System.Threading.Tasks.Task[]">; 38 + until(System::Threading::Tasks::Task.WaitAll(taskArray, 1000)) { 39 + print("."); 40 + } 34 41 var resultMap = new Object<"System.Collections.Generic.Dictionary`2[Prexonite.Modular.ModuleName,System.Tuple`2[Prexonite.Application,Prexonite.Compiler.Build.ITarget]]">; 35 42 foreach(var entry in taskMap) { 36 43 resultMap[entry.Key] = entry.Value.Result; ··· 48 55 var src = new source_file(file_path); 49 56 targetDescriptionTasks[] = host.self_assembling_build_plan.AssembleAsync(src, no_cancellation); 50 57 } 51 - System::Threading::Tasks::Task.WaitAll(targetDescriptionTasks~Object<"System.Threading.Tasks.Task[]">); 58 + var targetTaskArray = targetDescriptionTasks~Object<"System.Threading.Tasks.Task[]">; 59 + until(System::Threading::Tasks::Task.WaitAll(targetTaskArray, 1000)) { 60 + print("."); 61 + } 52 62 timer.stop; 53 63 var totalCompTime = timer.elapsed; 54 - println("done."); 64 + println(" done."); 55 65 timer.reset; 56 66 57 67 print("Compiling $(targetDescriptionTasks.Count) test modules (and their dependencies)..."); ··· 59 69 var testSuiteMap = load_from_descriptions(targetDescriptionTasks, var args >> exists(?.Contains("cil"))); 60 70 timer.stop; 61 71 totalCompTime += timer.elapsed; 62 - println("done."); 72 + println(" done."); 63 73 timer.reset; 64 74 65 75 // Check for compile errors
+3
PrexoniteTests/psr-tests/_2/testconfig.txt
··· 1 1 .\ast.test.pxs>|compiler_is_loaded|test_ast_withpos_null|test_ast_withpos_memcall|test_ast_simple_memcall|test_ast_memcall|test_unique_id_counter|test_is_member_access|test_local_meta|test_si_fields|test_si_is_star|test_si_make_star|test_si_m_is_star|test_sub_blocks 2 + .\macro.test.pxs>|test_file|test_pos|test_is_in_macro|test_establish_macro_context|test_reports|test_ast_is_expression|test_ast_is_effect|test_ast_is_partially_applicable|test_ast_is_partial_application|test_ast_is_CreateClosure|test_ast_is_node|test_temp|test_optimize|test_read|test_macro_internal_id_static|test_macro_internal_id|test_macro_entity_static|test_expand_macro|test_ast_symbol|test_ast_member|test_ast_const|test_ast_ret|test_ast_with_args|test_ast_new|test_ast_null 3 + .\pattern.test.pxs>|test_con|test_dcon 4 + .\prop.test.pxs>|test_prop_simple|test_prop_proxy|test_prop_complex|test_prop_simple_glob
+2 -1
Prx/Prx.csproj
··· 5 5 </ItemGroup> 6 6 7 7 <PropertyGroup> 8 - <OutputType>Exe</OutputType> 8 + <OutputType>exe</OutputType> 9 9 <TargetFramework>netcoreapp3.1</TargetFramework> 10 + <AppConfig>config/app.$(Configuration).config</AppConfig> 10 11 <LangVersion>8</LangVersion> 11 12 <Version>1.91</Version> 12 13 <Title>Prexonite CLI</Title>
+34
Prx/psr/_2/psr/misc.pxs
··· 1 + name psr::ast; 2 + references { 3 + prx/1.0 4 + psr::struct, 5 + psr::ast, 6 + psr::$macro 7 + }; 8 + 9 + namespace psr.misc.v1 10 + import 11 + prx.v1.*, 12 + psr.struct, 13 + psr.ast.v1.*, 14 + psr.macro.v1.* 15 + { 16 + build does add("../../impl/misc.pxs"); 17 + } 18 + 19 + namespace psr.misc {} export psr.misc.v1( 20 + cmp, 21 + cmp_values, 22 + cmp_keys, 23 + cmp_with, 24 + cmp_then, 25 + cmpr, 26 + ieq, 27 + ieq_any, 28 + ieq_all, 29 + refeq, 30 + nrefeq, 31 + on, 32 + create_terminator, 33 + swap 34 + );
+28
Prx/psr/_2/psr/pattern.pxs
··· 1 + name psr::pattern; 2 + references { 3 + prx/1.0, 4 + psr::ast, 5 + psr::$macro, 6 + psr::struct, 7 + psr::prop 8 + }; 9 + 10 + namespace psr.pattern.v1 11 + import 12 + prx.v1.*, 13 + psr.ast.v1.*, 14 + psr.macro.v1.*, 15 + psr.struct, 16 + psr.prop.v1.* 17 + { 18 + build does add("../../impl/pattern.pxs"); 19 + } 20 + 21 + namespace psr.misc {} export psr.pattern.v1(zip,repeatable); 22 + 23 + namespace psr.pattern {} export psr.pattern.v1(kvp); 24 + 25 + namespace psr.pattern.impl {} export psr.pattern.v1( 26 + create_pat_desc, 27 + pattern\gen => generate 28 + );
+17
Prx/psr/_2/psr/struct.pxs
··· 1 + name psr::struct; 2 + references { 3 + prx/1.0, 4 + psr::ast, 5 + psr::$macro 6 + }; 7 + 8 + namespace psr.struct.v1 9 + import 10 + prx.v1.*, 11 + psr.ast.v1.*, 12 + psr.macro.v1.* 13 + { 14 + build does add("../../impl/struct.pxs"); 15 + } 16 + 17 + namespace psr {} export psr.struct.v1.struct;
+1 -1
Prx/psr/_2/psr/test.pxs
··· 2 2 references { 3 3 prx/1.0 4 4 }; 5 - test\version "0.2"; 6 5 7 6 namespace psr.test.v1 8 7 import prx.v1(*) ··· 10 9 // NOTE: test is not split up into impl and dependencies because it must not 11 10 // have any dependencies. 12 11 build does add("../../test.pxs"); 12 + test\version "2.0"; 13 13 } 14 14 15 15 namespace psr.test {} export psr.test.v1(
+2 -2
Prx/psr/impl/prop.pxs
··· 84 84 85 85 prop_set.Arguments.Add(prop_arg); 86 86 87 - println("prop\\macro\\assemble($dummyArgs,$prop_get,$prop_set)"); 87 + //println("prop\\macro\\assemble($dummyArgs,$prop_get,$prop_set)"); 88 88 check.IfExpression = prop_get; 89 89 check.ElseExpression = prop_set; 90 90 ··· 144 144 return; 145 145 } 146 146 147 - println("prop\\macro\\proxy($dummyArgs,$prop_get)"); 147 + //println("prop\\macro\\proxy($dummyArgs,$prop_get)"); 148 148 var prop_set = prop_get.GetCopy(); 149 149 prop_set.Call = SI.set; 150 150