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-46: support qualified `new`, `is`, `~` (type cast) and static calls

The existing object creation fallback mechanism did not support qualified paths (`new a.b.c`) and retro-fitting it into that mechanism was not realistic. Mostly because it is highly context-dependent (which symbols are actually defined) and because back-tracking isn't really an option with the way both symbol resolution _and_ the parser generator are designed.

The solution is to start representing the "type operations" (creation, type check, type cast, static call) within the value universe of Prexonite (as ordinary Prexonite symbols). As we have dedicated byte code instructions and AST nodes, we don't want to implement these as commands. Instead, we have "built-in" macro commands that are parameterized and instantiated multiple times (once for each built-in type).

A consequence of this is that the `AstTypecheck`, `AstTypecast`, `AstGetSetStatic` and `AstObjectCreation` no longer show up directly in the AST. They only exist temporarily between macro expansion and code generation. This could be fixed with an earlier lowering pass, but such a thing needs to be considered carefully.

An alternative would have been to encode these operations directly in the symbol table (4 new `Symbol` sub-types), but that solution seemed to push _more_ logic into the compiler core as opposed to less.

Breaking changes:
- `AstTypecheck`: replace file-line-column constructor with `ISourcePosition` constructor. This means Prexonite code using `psr\macro` needs to construct instances using `ast3` instead of `ast`.
- `AstGetSetStatic`: replace file-line-column constructor with `ISourcePosition` constructor. This means Prexonite code using `psr\macro` needs to construct instances using `ast3` instead of `ast`.
- `AstConstant`: constant is now `readonly`
- `AstTypecheck` not longer has an `IsInverted` property. As a result, AST factory `UnaryOperation` no longer automatically handles partial application of `? is not T`. There is no replacement.
- In Prexonite Script 2, object creation, type checks, type casts and static calls require the import of `sys.*` (or `sys.rt.builtin.*` or `prx.core.rt.builtin.*`)
- Removed the concept of type expressions from the language. This means you can no longer pass e.g., `~String`, i.e. the concept of the type String, as a type parameter to another type. This feature has not been used at all since the inception of Prexonite. Constant and dynamic _value_ parameters are still supported.
- built-in types (or any registered PTypes) are no longer privileged over "fallback" functions. That means a locally defined `is_String` function will supersede the built-in `is String` implementation. (Previously, custom type operations were only used as a fallback if the type isn't registered)
- Type operations need to be declared at compile-time. For Prexonite 1, the loader automatically will declare symbols for each registered type. For Prexonite 2, symbols will have to be declared (e.g., by providing a companion module).

Miscellaneous Fixes:
- Delta left and right (`<|` and `|>`) are now supported in a `ModifyingAssignment` (AST Factory).
- Remove custom overrides of `CheckForPlaceholders`. Implementation based on `IAstPartiallyApplicable`.
- Allow multiple namespace transfers in export clauses even if the `()` of the subject namespace is not there.
- Bump version to 1.98

Follow-up: PRX-56 to resolve the confusing error message about missing `create_`, `is_`, `to_`, `static_call_` symbols.

Christian Klauser (Sep 3, 2021, 8:17 PM +0200) 43d818fe d88018f5

+1053 -255
+1 -1
Prexonite/Commands/List/CreateEnumerator.cs
··· 42 42 43 43 #endregion 44 44 45 - public const string Alias = Loader.ObjectCreationFallbackPrefix + "enumerator"; 45 + public const string Alias = Loader.ObjectCreationPrefix + "enumerator"; 46 46 47 47 #region Overrides of PCommand 48 48
-6
Prexonite/Compiler/AST/AstCoalescence.cs
··· 160 160 } 161 161 } 162 162 163 - public override bool CheckForPlaceholders() 164 - { 165 - return base.CheckForPlaceholders() || 166 - Expressions.Any(AstPartiallyApplicable.IsPlaceholder); 167 - } 168 - 169 163 public NodeApplicationState CheckNodeApplicationState() 170 164 { 171 165 var hasSplices = Expressions.Any(x => x is AstArgumentSplice);
+4 -10
Prexonite/Compiler/AST/AstConstant.cs
··· 24 24 // WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 25 25 // IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 26 26 using System; 27 + using System.Text; 27 28 using Prexonite.Modular; 28 29 using Prexonite.Types; 29 30 ··· 31 32 { 32 33 public class AstConstant : AstExpr 33 34 { 34 - public object Constant; 35 + public readonly object Constant; 35 36 36 37 internal AstConstant(Parser p, object constant) 37 38 : this(p.scanner.File, p.t.line, p.t.col, constant) ··· 53 54 expr = null; 54 55 if (value.Type is ObjectPType) 55 56 target.Loader.Options.ParentEngine.CreateNativePValue(value.Value); 56 - if (value.Type is IntPType 57 - || value.Type is RealPType 58 - || value.Type is BoolPType 59 - || value.Type is StringPType 60 - || value.Type is NullPType 61 - || _isModuleName(value)) 57 + if (value.Type is IntPType or RealPType or BoolPType or StringPType or NullPType || _isModuleName(value)) 62 58 expr = new AstConstant(position.File, position.Line, position.Column, value.Value); 63 59 else //Cannot represent value in a constant instruction 64 60 return false; ··· 104 100 target.EmitConstant(Position, (string) Constant); 105 101 break; 106 102 default: 107 - var moduleName = Constant as ModuleName; 108 - 109 - if (moduleName != null) 103 + if (Constant is ModuleName moduleName) 110 104 { 111 105 target.EmitConstant(Position, moduleName); 112 106 }
+9 -4
Prexonite/Compiler/AST/AstDynamicTypeExpression.cs
··· 33 33 public class AstDynamicTypeExpression : AstTypeExpr, 34 34 IAstHasExpressions 35 35 { 36 - public List<AstExpr> Arguments = new(); 37 - public string TypeId; 36 + public List<AstExpr> Arguments { get; } = new(); 37 + public string TypeId { get; } 38 38 39 39 public AstDynamicTypeExpression(string file, int line, int column, string typeId) 40 - : base(file, line, column) 40 + : this(new SourcePosition(file, line, column), typeId) 41 + { 42 + } 43 + 44 + public AstDynamicTypeExpression(ISourcePosition position, string typeId) 45 + :base(position) 41 46 { 42 47 TypeId = typeId ?? throw new ArgumentNullException(nameof(typeId)); 43 48 } 44 49 45 50 internal AstDynamicTypeExpression(Parser p, string typeId) 46 - : this(p.scanner.File, p.t.line, p.t.col, typeId) 51 + : this(p.GetPosition(), typeId) 47 52 { 48 53 } 49 54
+7 -1
Prexonite/Compiler/AST/AstExpand.cs
··· 30 30 31 31 namespace Prexonite.Compiler.Ast 32 32 { 33 - public class AstExpand : AstGetSetImplBase 33 + public class AstExpand : AstGetSetImplBase, IAstPartiallyApplicable 34 34 { 35 35 public AstExpand(ISourcePosition position, EntityRef entity, PCall call) : base(position, call) 36 36 { ··· 71 71 if (session != null) 72 72 target.ReleaseMacroSession(session); 73 73 } 74 + } 75 + 76 + void IAstPartiallyApplicable.DoEmitPartialApplicationCode(CompilerTarget target) 77 + { 78 + // This may fail if the macro implementation does not support partial application. 79 + DoEmitCode(target, StackSemantics.Value); 74 80 } 75 81 76 82 public override bool TryOptimize(CompilerTarget target, out AstExpr expr)
+17 -45
Prexonite/Compiler/AST/AstFactoryBase.cs
··· 153 153 154 154 public AstTypeExpr DynamicType(ISourcePosition position, string typeId, IEnumerable<AstExpr> arguments) 155 155 { 156 - var t = new AstDynamicTypeExpression(position.File, position.Line,position.Column, typeId); 156 + var t = new AstDynamicTypeExpression(position, typeId); 157 157 t.Arguments.AddRange(arguments); 158 158 return t; 159 159 } ··· 469 469 switch (op) 470 470 { 471 471 case UnaryOperator.LogicalNot: 472 - { 473 - if (operand is AstTypecheck typecheck && typecheck.CheckForPlaceholders() && typecheck.IsInverted) 474 - { 475 - // Special handling of "? is not Y", where typecheck.IsInverted is set to true. 476 - // Note that "not (? is Y)" is not the same thing. 477 - 478 - var thenCmd = this.Call(position, EntityRef.Command.Create(Engine.ThenAlias)); 479 - 480 - // Create "not ?" 481 - var notId = OperatorNames.Prexonite.GetName(UnaryOperator.LogicalNot); 482 - var notOp = CurrentBlock.Symbols.TryGet(notId, out var notSymbol) 483 - ? ExprFor(position, notSymbol) 484 - : new AstUnresolved(position, notId); 485 - if (!(notOp is AstGetSet notCall)) 486 - { 487 - ReportMessage( 488 - Message.Error( 489 - Resources.AstFactoryBase_UnaryOperation_NotOperatorForTypecheckRequiresLValue, 490 - position, MessageClasses.LValueExpected)); 491 - notCall = CreateNullNode(position); 492 - } 493 - 494 - notCall.Arguments.Add(Placeholder(position,0)); 495 - 496 - // Create "? is T" 497 - var partialTypecheck = Typecheck(position, typecheck.Subject, typecheck.Type); 498 - 499 - // Assemble "(? is T) then (not ?)" 500 - thenCmd.Arguments.Add(partialTypecheck); 501 - thenCmd.Arguments.Add(notCall); 502 - 503 - return thenCmd; 504 - } 505 - else 506 - { 507 - goto case UnaryOperator.UnaryNegation; 508 - } 509 - } 510 472 case UnaryOperator.UnaryNegation: 511 473 case UnaryOperator.OnesComplement: 512 474 case UnaryOperator.PostDeltaLeft: ··· 633 595 getVariation.Call = PCall.Get; 634 596 getVariation.Arguments.RemoveAt(getVariation.Arguments.Count - 1); 635 597 636 - if (!(assignment.Arguments[^1] is AstTypeExpr T)) 598 + if (assignment.Arguments[^1] is AstTypeExpr T) 599 + { 600 + assignment.Arguments[^1] = Typecast(position, getVariation, T); 601 + } 602 + else if (assignment.Arguments[^1] is AstGetSet castExpr) 603 + { 604 + castExpr.Arguments.Add(getVariation); 605 + } 606 + else 637 607 { 638 608 ReportMessage(Message.Error(Resources.AstFactoryBase_ModifyingAssignment_TypeExpressionExpected,position, MessageClasses.TypeExpressionExpected)); 639 609 T = ConstantType(position, NullPType.Literal); 610 + assignment.Arguments[^1] = Typecast(position, getVariation, T); 640 611 } 641 612 642 - assignment.Arguments[^1] = Typecast(position, getVariation, T); 643 613 return assignment; 644 614 } 645 615 case BinaryOperator.Addition: ··· 657 627 case BinaryOperator.GreaterThanOrEqual: 658 628 case BinaryOperator.LessThan: 659 629 case BinaryOperator.LessThanOrEqual: 630 + case BinaryOperator.DeltaLeft: 631 + case BinaryOperator.DeltaRight: 660 632 { 661 633 if (assignPrototype.Arguments.Count < 1) 662 634 { ··· 786 758 787 759 public AstObjectCreation CreateObject(ISourcePosition position, AstTypeExpr type) 788 760 { 789 - return new(position.File, position.Line, position.Column, type); 761 + return new(position, type); 790 762 } 791 763 792 764 public AstExpr Typecheck(ISourcePosition position, AstExpr operand, AstTypeExpr type) 793 765 { 794 - return new AstTypecheck(position.File, position.Line, position.Column,operand,type); 766 + return new AstTypecheck(position, operand, type); 795 767 } 796 768 797 769 public AstExpr Typecast(ISourcePosition position, AstExpr operand, AstTypeExpr type) 798 770 { 799 - return new AstTypecast(position.File, position.Line, position.Column,operand,type); 771 + return new AstTypecast(position, operand, type); 800 772 } 801 773 802 774 public AstExpr Reference(ISourcePosition position, EntityRef entity) ··· 811 783 812 784 public AstGetSet StaticMemberAccess(ISourcePosition position, AstTypeExpr typeExpr, string memberId, PCall call = PCall.Get) 813 785 { 814 - return new AstGetSetStatic(position.File, position.Line, position.Column,call,typeExpr,memberId); 786 + return new AstGetSetStatic(position,call,typeExpr,memberId); 815 787 } 816 788 817 789 public AstGetSet IndirectCall(ISourcePosition position, AstExpr receiver, PCall call = PCall.Get)
+2
Prexonite/Compiler/AST/AstFactoryBridge.cs
··· 453 453 node = _takeOptionalArguments(sctx, args, i, complex); 454 454 break; 455 455 } 456 + case "getsetstatic": 457 + throw new PrexoniteException("Cannot construct \"GetSetStatic\" node. Did you mean \"StaticMemberAccess\"?"); 456 458 case "staticmemberaccess": 457 459 { 458 460 const string sig = "StaticMemberAccess(position, typeExpr~AstTypeExpr, memberId~String, call~PCall, args~List<AstExpr> = [])";
-6
Prexonite/Compiler/AST/AstGetSet.cs
··· 156 156 target.Arguments.AddRange(Arguments); 157 157 } 158 158 159 - public override bool CheckForPlaceholders() 160 - { 161 - return this is IAstPartiallyApplicable && 162 - (base.CheckForPlaceholders() || Arguments.Any(AstPartiallyApplicable.IsPlaceholder)); 163 - } 164 - 165 159 public virtual NodeApplicationState CheckNodeApplicationState() 166 160 { 167 161 return new(
+4 -4
Prexonite/Compiler/AST/AstGetSetStatic.cs
··· 36 36 37 37 [DebuggerStepThrough] 38 38 public AstGetSetStatic( 39 - string file, int line, int col, PCall call, AstTypeExpr typeExpr, string memberId) 40 - : base(file, line, col, call) 39 + ISourcePosition position, PCall call, AstTypeExpr typeExpr, string memberId) 40 + : base(position, call) 41 41 { 42 42 TypeExpr = typeExpr ?? throw new ArgumentNullException(nameof(typeExpr)); 43 43 MemberId = memberId ?? throw new ArgumentNullException(nameof(memberId)); ··· 45 45 46 46 [DebuggerStepThrough] 47 47 internal AstGetSetStatic(Parser p, PCall call, AstTypeExpr typeExpr, string memberId) 48 - : this(p.scanner.File, p.t.line, p.t.col, call, typeExpr, memberId) 48 + : this(p.GetPosition(), call, typeExpr, memberId) 49 49 { 50 50 } 51 51 ··· 116 116 117 117 public override AstGetSet GetCopy() 118 118 { 119 - var copy = new AstGetSetStatic(File, Line, Column, Call, TypeExpr, MemberId); 119 + var copy = new AstGetSetStatic(Position, Call, TypeExpr, MemberId); 120 120 CopyBaseMembers(copy); 121 121 return copy; 122 122 }
+2 -4
Prexonite/Compiler/AST/AstLazyLogical.cs
··· 331 331 var constExpr = CreatePrefix(Position, Conditions.Take(Conditions.Count - 1)); 332 332 //var identityFunc = new AstGetSetSymbol(File, Line, Column, PCall.Get, Commands.Core.Id.Alias, SymbolInterpretations.Command); 333 333 //identityFunc.Arguments.Add(new AstPlaceholder(File, Line, Column, placeholder.Index)); 334 - var identityFunc = new AstTypecast(File, Line, Column, 335 - placeholder.GetCopy(), 334 + var identityFunc = new AstTypecast(Position, placeholder.GetCopy(), 336 335 new AstConstantTypeExpression(File, Line, Column, PType.Bool.ToString())); 337 336 var conditional = new AstConditionalExpression(File, Line, Column, constExpr, 338 337 ShortcircuitValue) ··· 415 414 { 416 415 var primaryExpr = Conditions.First.Value; 417 416 expr = _GetOptimizedNode(target, 418 - new AstTypecast(primaryExpr.File, primaryExpr.Line, primaryExpr.Column, 419 - primaryExpr, 417 + new AstTypecast(primaryExpr.Position, primaryExpr, 420 418 new AstConstantTypeExpression(primaryExpr.File, 421 419 primaryExpr.Line, 422 420 primaryExpr.Column,
+2 -5
Prexonite/Compiler/AST/AstNode.cs
··· 106 106 /// cref = "IAstPartiallyApplicable.CheckForPlaceholders" />, if implemented in derived types. 107 107 /// </summary> 108 108 /// <returns>True if this node has placeholders; false otherwise</returns> 109 - public virtual bool CheckForPlaceholders() 110 - { 111 - var partiallyApplicable = this as IAstPartiallyApplicable; 112 - return partiallyApplicable?.CheckNodeApplicationState().HasPlaceholders ?? false; 113 - } 109 + public bool CheckForPlaceholders() => 110 + this is IAstPartiallyApplicable pa && pa.CheckNodeApplicationState().HasPlaceholders; 114 111 115 112 [NotNull] 116 113 internal static AstExpr _GetOptimizedNode(
+10 -10
Prexonite/Compiler/AST/AstObjectCreation.cs
··· 48 48 49 49 private readonly List<AstExpr> _arguments = new(); 50 50 51 + public AstObjectCreation(ISourcePosition position, AstTypeExpr type) 52 + : base(position) 53 + { 54 + TypeExpr = type ?? throw new ArgumentNullException(nameof(type)); 55 + Arguments = new(_arguments); 56 + } 57 + 58 + [Obsolete] 51 59 [DebuggerStepThrough] 52 60 public AstObjectCreation(string file, int line, int col, AstTypeExpr type) 53 - : base(file, line, col) 61 + : this(new SourcePosition(file, line, col), type) 54 62 { 55 - TypeExpr = type ?? throw new ArgumentNullException(nameof(type)); 56 - Arguments = new ArgumentsProxy(_arguments); 57 63 } 58 64 59 65 [DebuggerStepThrough] 60 66 internal AstObjectCreation(Parser p, AstTypeExpr type) 61 - : this(p.scanner.File, p.t.line, p.t.col, type) 67 + : this(p.GetPosition(), type) 62 68 { 63 69 } 64 70 ··· 107 113 #endregion 108 114 109 115 #region Implementation of IAstPartiallyApplicable 110 - 111 - public override bool CheckForPlaceholders() 112 - { 113 - return base.CheckForPlaceholders() || 114 - Arguments.Any(AstPartiallyApplicable.IsPlaceholder); 115 - } 116 116 117 117 public NodeApplicationState CheckNodeApplicationState() 118 118 {
+4 -4
Prexonite/Compiler/AST/AstTypeCast.cs
··· 35 35 public AstExpr Subject { get; private set; } 36 36 public AstTypeExpr Type { get; private set; } 37 37 38 - public AstTypecast(string file, int line, int column, AstExpr subject, AstTypeExpr type) 39 - : base(file, line, column) 38 + public AstTypecast(ISourcePosition position, AstExpr subject, AstTypeExpr type) 39 + :base(position) 40 40 { 41 41 Subject = subject ?? throw new ArgumentNullException(nameof(subject)); 42 - Type = type ?? throw new ArgumentNullException(nameof(type)); 42 + Type = type ?? throw new ArgumentNullException(nameof(type)); 43 43 } 44 44 45 45 internal AstTypecast(Parser p, AstExpr subject, AstTypeExpr type) 46 - : this(p.scanner.File, p.t.line, p.t.col, subject, type) 46 + : this(p.GetPosition(), subject, type) 47 47 { 48 48 } 49 49
+2 -20
Prexonite/Compiler/AST/AstTypecheck.cs
··· 34 34 { 35 35 private AstExpr _subject; 36 36 37 - /// <summary> 38 - /// Indicates whether this typecheck is inverted (X is not Y). 39 - /// Does not, however, change the behaviour of AstTypecheck itself. 40 - /// It is used to distinguish between 41 - /// not (X is Y) 42 - /// and 43 - /// X is not Y 44 - /// 45 - /// Both times, the typecheck is wrapped in a unary not, but the flag 46 - /// is only set in the second case. 47 - /// </summary> 48 - public bool IsInverted { get; set; } 49 - 50 37 public AstTypecheck( 51 - string file, int line, int column, AstExpr subject, AstTypeExpr type) 52 - : base(file, line, column) 38 + ISourcePosition position, AstExpr subject, AstTypeExpr type) 39 + : base(position) 53 40 { 54 41 _subject = subject ?? throw new ArgumentNullException(nameof(subject)); 55 42 Type = type ?? throw new ArgumentNullException(nameof(type)); 56 - } 57 - 58 - internal AstTypecheck(Parser p, AstExpr subject, AstTypeExpr type) 59 - : this(p.scanner.File, p.t.line, p.t.col, subject, type) 60 - { 61 43 } 62 44 63 45 #region IAstHasExpressions Members
+4 -1
Prexonite/Compiler/AST/IAstPartiallyApplicable.cs
··· 47 47 /// This method mainly exists for backwards compatibility with script code.</para> 48 48 /// <returns>True if this node has placeholders; false otherwise</returns> 49 49 [Obsolete("Use CheckNodeApplicationState instead")] 50 - bool CheckForPlaceholders(); 50 + bool CheckForPlaceholders() 51 + { 52 + return CheckNodeApplicationState().HasPlaceholders; 53 + } 51 54 52 55 /// <summary> 53 56 /// Checks the node's immediate child nodes for <see cref="AstPlaceholder"/>s and
+1
Prexonite/Compiler/Grammar/Header.atg
··· 33 33 using Prexonite.Compiler.Symbolic; 34 34 using Prexonite.Compiler.Symbolic.Internal; 35 35 using Prexonite.Compiler.Symbolic.Compatibility; 36 + using Prexonite.Compiler.Macro.Commands; 36 37 using Prexonite.Properties; 37 38 38 39 COMPILER Prexonite
+121 -38
Prexonite/Compiler/Grammar/Parser.Expression.atg
··· 197 197 . 198 198 199 199 AssignExpr<out AstExpr expr> (. AstGetSet assignment; BinaryOperator setModifier = BinaryOperator.None; 200 - AstTypeExpr typeExpr; 200 + AstGetSet typeExpr; 201 201 ISourcePosition position; 202 202 .) 203 203 = (. position = GetPosition(); .) ··· 225 225 | deltaright assign (. setModifier = BinaryOperator.DeltaRight; .) 226 226 ) Expr<out expr> //(. expr = expr; .) 227 227 228 - | ( tilde assign (. setModifier = BinaryOperator.Cast; .) 229 - )TypeExpr<out typeExpr> (. expr = typeExpr; .) 228 + | tilde assign (. setModifier = BinaryOperator.Cast; .) 229 + TypeExpr<out typeExpr, _conversionShift> 230 + (. expr = typeExpr; .) 230 231 ) 231 232 (. assignment.Arguments.Add(expr); 232 233 if(setModifier == BinaryOperator.None) ··· 238 239 . 239 240 240 241 PostfixUnaryExpr<out AstExpr expr> 241 - (. AstTypeExpr type; AstGetSet extension; bool isInverted = false; .) 242 + (. AstGetSet type; AstGetSet extension; bool isInverted = false; 243 + ISourcePosition notPosition = GetPosition(); 244 + .) 242 245 = 243 246 PrefixUnaryExpr<out expr> (. var position = GetPosition(); .) 244 - { tilde TypeExpr<out type> (. expr = new AstTypecast(this, expr, type); .) 247 + { tilde TypeExpr<out type, _conversionShift> 248 + (. type.Arguments.Add(expr); 249 + expr = type; 250 + .) 245 251 | is 246 - [ not (. isInverted = true; .) 252 + [ not (. isInverted = true; notPosition = GetPosition(); .) 247 253 ] 248 - TypeExpr<out type> (. expr = new AstTypecheck(this, expr, type); 249 - if(isInverted) 250 - { 251 - ((AstTypecheck)expr).IsInverted = true; 252 - expr = Create.UnaryOperation(position, UnaryOperator.LogicalNot, expr); 253 - } 254 + TypeExpr<out type, _typeCheckShift> 255 + (. type.Arguments.Add(expr); 256 + expr = isInverted 257 + ? (type.CheckForPlaceholders() 258 + // Special handling of "? is not Y" as that's not the same thing 259 + // as "not (? is Y)" when placeholders are involved. 260 + ? _createPartialInvertedTypeCheck(position, type) 261 + : Create.UnaryOperation(position, UnaryOperator.LogicalNot, type) 262 + ) 263 + : type; 254 264 .) 255 265 | inc (. expr = Create.UnaryOperation(position, UnaryOperator.PostIncrement, expr); .) 256 266 | dec (. expr = Create.UnaryOperation(position, UnaryOperator.PostDecrement, expr); .) ··· 391 401 392 402 393 403 ObjectCreation<out AstExpr expr> 394 - (. AstTypeExpr type; 395 - ArgumentsProxy args; 404 + (. AstGetSet type; 396 405 .) 397 406 = 398 - new TypeExpr<out type> (. _fallbackObjectCreation(type, out expr, out args); .) 399 - Arguments<args> 407 + new TypeExpr<out type, _objectCreationShift> 408 + (. expr = type; .) 409 + Arguments<type.Arguments> 400 410 . 401 411 402 412 CoroutineCreation<out AstExpr expr> ··· 513 523 this (. Loader.ReportMessage(Message.Error("Illegal use of reserved keyword `this`.",position,MessageClasses.ThisReserved)); .) 514 524 . 515 525 516 - ExplicitTypeExpr<out AstTypeExpr type> (. type = null; .) 526 + ExplicitTypeExpr<out AstGetSet type, [NotNull]SymbolShift shift> 527 + (. type = null; .) 517 528 = 518 - tilde PrexoniteTypeExpr<out type> 519 - | ClrTypeExpr<out type> 529 + tilde PrexoniteTypeExpr<out type, shift> 530 + | ClrTypeExpr<out type, shift> 520 531 . 521 532 522 - TypeExpr<out AstTypeExpr type> (. type = null; .) 533 + TypeExpr<out AstGetSet type, [NotNull]SymbolShift shift> 534 + (. type = null; .) 523 535 = 524 - PrexoniteTypeExpr<out type> 525 - | ClrTypeExpr<out type> 536 + PrexoniteTypeExpr<out type, shift> 537 + | ClrTypeExpr<out type, shift> 526 538 . 527 539 528 - ClrTypeExpr<out AstTypeExpr type> 529 - (. string id; .) 540 + ClrTypeExpr<out AstGetSet type, [NotNull]SymbolShift shift> 541 + (. string id; ISourcePosition position = GetPosition(); .) 530 542 = 531 543 (. StringBuilder typeId = new StringBuilder(); .) 532 544 ( doublecolon ··· 535 547 { ns (. typeId.Append(t.val); typeId.Append('.'); .) 536 548 } 537 549 Id<out id> (. typeId.Append(id); 538 - type = new AstConstantTypeExpression(this, 539 - "Object(\"" + StringPType.Escape(typeId.ToString()) + "\")"); 550 + type = _useSymbol(Symbols, shift(ObjectPType.Literal), position); 551 + // arity of PType Object = 1 552 + type.Arguments.Add(Create.Constant(position, 1)); 553 + // CLR type name 554 + type.Arguments.Add(Create.Constant(position, typeId.ToString())); 540 555 .) 541 556 . 542 557 543 - PrexoniteTypeExpr<out AstTypeExpr type> 544 - (. string id = null; .) 545 - = 546 - ( Id<out id> | null (. id = NullPType.Literal; .) 558 + PrexoniteTypeExpr<out AstGetSet type, [NotNull]SymbolShift shift> 559 + (. AstGetSet expr = null; 560 + string id = "<unknownId>"; 561 + string shiftedId = "<unknownShiftedId>"; 562 + ISourcePosition position; 563 + AstNamespaceUsage lastNs; 564 + bool shiftUsed = false; 565 + ISourcePosition argPos; 566 + .) 567 + = (. position = GetPosition(); .) 568 + ( Id<out id> (. 569 + shiftedId = shift(id); 570 + if(Symbols.TryGet(shiftedId, out _)) 571 + { 572 + expr = _useSymbol(Symbols, shiftedId, position); 573 + shiftUsed = true; 574 + } 575 + else 576 + { 577 + expr = _useSymbol(Symbols, id, position); 578 + } 579 + .) 580 + { IF(!shiftUsed && expr is AstNamespaceUsage ns) 581 + (. position = GetPosition(); lastNs = ns; .) 582 + dot 583 + DotId<out id> (. 584 + shiftedId = shift(id); 585 + if(ns.Namespace.TryGet(shiftedId, out _)) 586 + { 587 + expr = _useSymbolFromNamespace(ns, shiftedId, position); 588 + shiftUsed = true; 589 + } 590 + else 591 + { 592 + expr = _useSymbolFromNamespace(ns, id, position); 593 + } 594 + .) 595 + } 596 + | null (. shiftedId = shift(NullPType.Literal); 597 + id = NullPType.Literal; 598 + expr = _useSymbol(Symbols, shiftedId, position); 599 + shiftUsed = true; 600 + .) 547 601 ) 548 - (. AstDynamicTypeExpression dType = new AstDynamicTypeExpression(this, id); .) 602 + (. if(!shiftUsed) { 603 + Loader.ReportMessage(Message.Error( 604 + string.Format("Cannot find {0} in scope.", shiftedId), 605 + position, 606 + MessageClasses.ShiftedSymbolRequired)); 607 + expr = _NullNode(position); 608 + } 609 + if(expr == null) { 610 + Loader.ReportMessage(Message.Error( 611 + "Internal parser error: expression in prexonite type expression should not be null.", 612 + position, 613 + MessageClasses.ParserInternal)); 614 + expr = _NullNode(position); 615 + } 616 + argPos = GetPosition(); 617 + var supportsTypeArguments = 618 + BuiltInTypeCommandBase.SupportsTypeArguments(Loader, expr); 619 + var typeArgs = new List<AstExpr>(); 620 + .) 549 621 [ lt 550 - [ TypeExprElement<dType.Arguments> 551 - { comma TypeExprElement<dType.Arguments> } 622 + [ (. argPos = GetPosition(); .) 623 + TypeExprElement<typeArgs> 624 + { comma TypeExprElement<typeArgs> } 552 625 ] 553 626 gt 554 - ] 555 - (. type = dType; .) 627 + ] (. if(supportsTypeArguments) { 628 + expr.Arguments.Add(Create.Constant(argPos, typeArgs.Count)); 629 + expr.Arguments.AddRange(typeArgs); 630 + } 631 + else if(typeArgs.Count > 0 && !supportsTypeArguments) { 632 + Loader.ReportMessage(Message.Error( 633 + string.Format("The type {0} does not support type arguments.", id), 634 + position, 635 + MessageClasses.TypeArgumentsNotSupported 636 + )); 637 + } 638 + type = expr; 639 + .) 556 640 . 557 641 558 - TypeExprElement<. List<AstExpr> args .> 559 - (. AstExpr expr; AstTypeExpr type; .) 642 + TypeExprElement<. IList<AstExpr> args .> 643 + (. AstExpr expr; .) 560 644 = 561 645 Constant<out expr> (. args.Add(expr); .) 562 - | ExplicitTypeExpr<out type> (. args.Add(type); .) 563 646 | lpar Expr<out expr> rpar (. args.Add(expr); .) 564 647 .
+3
Prexonite/Compiler/Grammar/Parser.GlobalScope.atg
··· 1182 1182 semicolon 1183 1183 ] 1184 1184 | NsTransferSpec<exportBuilder> 1185 + { comma 1186 + NsTransferSpec<exportBuilder> 1187 + } 1185 1188 semicolon 1186 1189 ) (. _popLexerState(); .) 1187 1190 | (. // In the absence of an export spec, we export
+12 -16
Prexonite/Compiler/Grammar/Parser.Statement.atg
··· 146 146 else 147 147 { 148 148 // Namespace lookup 149 - extension = _useSymbol(ns.Namespace, id, GetPosition()); 150 - // write down qualified path 151 - AstNamespaceUsage subns = extension as AstNamespaceUsage; 152 - if(subns != null && subns.ReferencePath == null) 153 - { 154 - subns.ReferencePath = ns.ReferencePath + new QualifiedId(id); 155 - } 149 + extension = _useSymbolFromNamespace(ns, id, GetPosition()); 156 150 } 157 151 .) 158 152 Arguments<extension.Arguments> ··· 171 165 GetInitiator<out AstExpr complex> 172 166 (. complex = null; 173 167 AstGetSet actualComplex = null; 174 - AstGetSetStatic staticCall = null; 168 + AstGetSet staticCall = null; 175 169 AstGetSet member = null; 176 170 AstExpr expr; 177 171 List<AstExpr> args = new List<AstExpr>(); ··· 314 308 Arguments<complex.Arguments> 315 309 . 316 310 317 - StaticCall<out AstGetSetStatic staticCall> 318 - (. AstTypeExpr typeExpr; 319 - string memberId; 311 + StaticCall<out AstGetSet staticCall> 312 + (. string memberId; 313 + ISourcePosition idPosition; 320 314 .) 321 315 = 322 - ExplicitTypeExpr<out typeExpr> 323 - dot DotId<out memberId> (. staticCall = new AstGetSetStatic(this, PCall.Get, typeExpr, memberId); .) 316 + ExplicitTypeExpr<out staticCall, _staticCallShift> 317 + dot (. idPosition = GetPosition(); .) 318 + DotId<out memberId> (. staticCall.Arguments.Add(Create.Constant(idPosition, memberId)); .) 324 319 Arguments<staticCall.Arguments> 325 320 . 326 321 //Fallback in case of a syntax error to avoid NullReferenceExceptions ··· 340 335 Assignment<AstGetSet lvalue, out AstNode node> 341 336 (. AstExpr expr = null; 342 337 BinaryOperator setModifier = BinaryOperator.None; 343 - AstTypeExpr typeExpr; 338 + AstGetSet typeExpr; 344 339 node = lvalue; 345 340 ISourcePosition position; 346 341 .) ··· 356 351 | coalescence assign (. setModifier = BinaryOperator.Coalescence; .) 357 352 ) Expr<out expr> //(. expr = expr; .) 358 353 359 - | ( tilde assign (. setModifier = BinaryOperator.Cast; .) 360 - ) TypeExpr<out typeExpr> (. expr = typeExpr; .) 354 + | tilde assign (. setModifier = BinaryOperator.Cast; .) 355 + TypeExpr<out typeExpr, _conversionShift> 356 + (. expr = typeExpr; .) 361 357 ) 362 358 (. if(expr == null) 363 359 {
+4
Prexonite/Compiler/Internal/SymbolShift.cs
··· 1 + namespace Prexonite.Compiler.Internal 2 + { 3 + public delegate string SymbolShift(string id); 4 + }
+18 -4
Prexonite/Compiler/Loader.cs
··· 102 102 103 103 private void _imprintCommandInfo() 104 104 { 105 - foreach (var buildCommand in BuildCommands) 106 - ParentEngine.Commands.ProvideFallbackInfo(buildCommand.Key, 107 - buildCommand.Value.ToCommandInfo()); 105 + foreach (var (alias, command) in BuildCommands) 106 + ParentEngine.Commands.ProvideFallbackInfo(alias, command.ToCommandInfo()); 108 107 } 109 108 110 109 public void RegisterExistingCommands() ··· 586 585 _addMacroCommand(Call_Tail.Instance.Partial); 587 586 _addMacroCommand(CallAsync.Instance.Partial); 588 587 _addCallMacro(); 588 + 589 + // Type conversions / type checks / static calls on built-ins 590 + foreach (var (typeId, _) in ParentEngine.PTypeRegistry) 591 + { 592 + _addMacroCommand(new ConvertToBuiltIn(typeId)); 593 + _addMacroCommand(new CheckIsBuiltIn(typeId)); 594 + _addMacroCommand(new StaticCallBuiltIn(typeId)); 595 + _addMacroCommand(new CreateBuiltIn(typeId)); 596 + } 589 597 } 590 598 591 599 private void _addCallMacro() ··· 1386 1394 [SuppressMessage("Microsoft.Naming", "CA1704:IdentifiersShouldBeSpelledCorrectly", 1387 1395 MessageId = "Cil")] public const string CilHintsKey = "cilhints"; 1388 1396 1389 - public const string ObjectCreationFallbackPrefix = "create_"; 1397 + [Obsolete("Use ObjectCreationPrefix instead")] 1398 + [PublicAPI] 1399 + public const string ObjectCreationFallbackPrefix = ObjectCreationPrefix; 1400 + public const string ObjectCreationPrefix = "create_"; 1401 + public const string ConversionPrefix = "to_"; 1402 + public const string TypeCheckPrefix = "is_"; 1403 + public const string StaticCallPrefix = "static_call_"; 1390 1404 private const string DirectorySeparatorKey = @"\directory_separator"; 1391 1405 } 1392 1406 }
+108
Prexonite/Compiler/Macro/Commands/BuiltInTypeCommandBase.cs
··· 1 + using System.Collections.Generic; 2 + using System.Linq; 3 + using JetBrains.Annotations; 4 + using Prexonite.Compiler.Ast; 5 + using Prexonite.Properties; 6 + 7 + namespace Prexonite.Compiler.Macro.Commands 8 + { 9 + public abstract class BuiltInTypeCommandBase : PartialMacroCommand 10 + { 11 + protected abstract int NumAdditionalArguments { get; } 12 + protected abstract string IncompleteMessageClass { get; } 13 + protected abstract string OperationName { get; } 14 + public string RegistryId { get; } 15 + 16 + protected BuiltInTypeCommandBase(string id, string registryId) : base(id) 17 + { 18 + RegistryId = registryId; 19 + } 20 + 21 + [PublicAPI] 22 + public const string SupportsTypeArgumentsId = @"pxs\supportsTypeArguments"; 23 + 24 + protected static bool SupportsFeature<T>(Loader ldr, AstNode node, string metaSwitchId) where T: MacroCommand 25 + { 26 + if (node is AstExpand {Entity: {} entityRef}) 27 + { 28 + if (entityRef.TryGetMacroCommand(out var mCmdRef) 29 + && mCmdRef.TryGetEntity(ldr, out var entity) 30 + && entity is { Value: MacroCommand mCmd }) 31 + { 32 + return mCmd is T; 33 + } 34 + else if (entityRef.TryGetFunction(out var funcRef) 35 + && funcRef.TryGetEntity(ldr, out var funcValue) 36 + && funcValue is {Value: PFunction func}) 37 + { 38 + return func.Meta[metaSwitchId].Switch; 39 + } 40 + else 41 + { 42 + return false; 43 + } 44 + } 45 + else if (node is AstIndirectCall {Subject: AstReference {Entity: { } callRef}}) 46 + { 47 + if (callRef.TryGetFunction(out var funcRef) 48 + && funcRef.TryGetEntity(ldr, out var funcValue) 49 + && funcValue is {Value: PFunction func}) 50 + { 51 + return func.Meta[metaSwitchId].Switch; 52 + } 53 + else 54 + { 55 + return false; 56 + } 57 + } 58 + else 59 + { 60 + return false; 61 + } 62 + } 63 + 64 + public static bool SupportsTypeArguments(Loader ldr, AstNode node) => 65 + SupportsFeature<BuiltInTypeCommandBase>(ldr, node, SupportsTypeArgumentsId); 66 + 67 + protected sealed override void DoExpand(MacroContext context) 68 + { 69 + if (context.Invocation.Arguments.Count < NumAdditionalArguments + 1) 70 + { 71 + var message = string.Format( 72 + Resources.BuiltInTypeCommandBase_DoExpand_0_for_type_1_requires_at_least_2_arguments, 73 + OperationName, 74 + RegistryId, 75 + NumAdditionalArguments + 1, 76 + context.Invocation.Arguments.Count 77 + ); 78 + context.ReportMessage(Message.Error(message, context.Invocation.Position, IncompleteMessageClass)); 79 + return; 80 + } 81 + 82 + if (context.GetOptimizedNode(context.Invocation.Arguments[0]) is not AstConstant {Constant: int arity}) 83 + { 84 + context.ReportMessage(Message.Error(string.Format(Resources.BuiltInTypeCommandBase_DoExpand_0_for_type_1_requires_an_arity_integer_as_the_first_argument, "Static call", RegistryId), context.Invocation.Position, MessageClasses.IncompleteBuiltinStaticCall)); 85 + return; 86 + } 87 + 88 + var typeArguments = context.Invocation.Arguments.Skip(1).Take(arity); 89 + var typeExpr = new AstDynamicTypeExpression(context.Invocation.Position, RegistryId); 90 + typeExpr.Arguments.AddRange(typeArguments); 91 + 92 + Instantiate(context, typeExpr, 93 + context.Invocation.Arguments.Skip(1 + arity).Take(NumAdditionalArguments), 94 + context.Invocation.Arguments.Skip(1 + arity + NumAdditionalArguments)); 95 + } 96 + 97 + protected abstract void Instantiate(MacroContext context, 98 + AstDynamicTypeExpression typeExpr, 99 + IEnumerable<AstExpr> additionalArguments, 100 + IEnumerable<AstExpr> operationArguments); 101 + 102 + protected override bool DoExpandPartialApplication(MacroContext context) 103 + { 104 + DoExpand(context); 105 + return true; 106 + } 107 + } 108 + }
+1 -1
Prexonite/Compiler/Macro/Commands/CallSubInterpret.cs
··· 163 163 var getRetVar = 164 164 context.CreateGetSetMember(context.CreateCall(EntityRef.Variable.Local.Create(resultV)), PCall.Get, 165 165 "Key"); 166 - var asInt = new AstTypecast(inv.File, inv.Line, inv.Column, getRetVar, intT); 166 + var asInt = new AstTypecast(inv.Position, getRetVar, intT); 167 167 var setRetVar = context.CreateCall(EntityRef.Variable.Local.Create(retVarV), PCall.Set, asInt); 168 168 context.Block.Add(setRetVar); 169 169 }
+26
Prexonite/Compiler/Macro/Commands/CheckIsBuiltIn.cs
··· 1 + using System.Collections.Generic; 2 + using System.Linq; 3 + using Prexonite.Compiler.Ast; 4 + using Prexonite.Properties; 5 + 6 + namespace Prexonite.Compiler.Macro.Commands 7 + { 8 + public class CheckIsBuiltIn : BuiltInTypeCommandBase 9 + { 10 + public CheckIsBuiltIn(string registryId) : base($"{Loader.TypeCheckPrefix}{registryId}", registryId) 11 + { 12 + } 13 + 14 + protected override int NumAdditionalArguments => 0; 15 + protected override string IncompleteMessageClass => MessageClasses.IncompleteBuiltinTypeCheck; 16 + protected override string OperationName => "Type check"; 17 + 18 + protected override void Instantiate(MacroContext context, AstDynamicTypeExpression typeExpr, IEnumerable<AstExpr> additionalArguments, 19 + IEnumerable<AstExpr> operationArguments) 20 + { 21 + var subject = operationArguments.First(); 22 + var check = new AstTypecheck(context.Invocation.Position, subject, typeExpr); 23 + context.Block.Expression = check; 24 + } 25 + } 26 + }
+27
Prexonite/Compiler/Macro/Commands/ConvertToBuiltIn.cs
··· 1 + using System.Collections.Generic; 2 + using System.Linq; 3 + using Prexonite.Compiler.Ast; 4 + using Prexonite.Properties; 5 + 6 + namespace Prexonite.Compiler.Macro.Commands 7 + { 8 + public class ConvertToBuiltIn : BuiltInTypeCommandBase 9 + { 10 + 11 + public ConvertToBuiltIn(string registryId) : base($"{Loader.ConversionPrefix}{registryId}", registryId) 12 + { 13 + } 14 + 15 + protected override int NumAdditionalArguments => 0; 16 + protected override string IncompleteMessageClass => MessageClasses.IncompleteBuiltinConversion; 17 + protected override string OperationName => "Type cast"; 18 + 19 + protected override void Instantiate(MacroContext context, AstDynamicTypeExpression typeExpr, IEnumerable<AstExpr> additionalArguments, 20 + IEnumerable<AstExpr> operationArguments) 21 + { 22 + var subject = operationArguments.First(); 23 + var cast = new AstTypecast(context.Invocation.Position, subject, typeExpr); 24 + context.Block.Expression = cast; 25 + } 26 + } 27 + }
+27
Prexonite/Compiler/Macro/Commands/CreateBuiltIn.cs
··· 1 + using System.Collections.Generic; 2 + using System.Linq; 3 + using Prexonite.Compiler.Ast; 4 + using Prexonite.Properties; 5 + 6 + namespace Prexonite.Compiler.Macro.Commands 7 + { 8 + public class CreateBuiltIn : BuiltInTypeCommandBase 9 + { 10 + 11 + public CreateBuiltIn(string registryId) : base($"{Loader.ObjectCreationPrefix}{registryId}", registryId) 12 + { 13 + } 14 + 15 + protected override int NumAdditionalArguments => 0; 16 + protected override string IncompleteMessageClass => MessageClasses.IncompleteBuiltinObjectCreation; 17 + protected override string OperationName => "Value creation"; 18 + 19 + protected override void Instantiate(MacroContext context, AstDynamicTypeExpression typeExpr, IEnumerable<AstExpr> additionalArguments, 20 + IEnumerable<AstExpr> operationArguments) 21 + { 22 + var creation = new AstObjectCreation(context.Invocation.Position, typeExpr); 23 + creation.Arguments.AddRange(operationArguments); 24 + context.Block.Expression = creation; 25 + } 26 + } 27 + }
+37
Prexonite/Compiler/Macro/Commands/StaticCallBuiltIn.cs
··· 1 + using System.Collections.Generic; 2 + using System.Linq; 3 + using Prexonite.Compiler.Ast; 4 + using Prexonite.Properties; 5 + 6 + namespace Prexonite.Compiler.Macro.Commands 7 + { 8 + public class StaticCallBuiltIn : BuiltInTypeCommandBase 9 + { 10 + public StaticCallBuiltIn(string registryId) : base($"{Loader.StaticCallPrefix}{registryId}", registryId) 11 + { 12 + } 13 + 14 + protected override int NumAdditionalArguments => 1; 15 + protected override string IncompleteMessageClass => MessageClasses.IncompleteBuiltinStaticCall; 16 + protected override string OperationName => "Static call"; 17 + 18 + protected override void Instantiate(MacroContext context, AstDynamicTypeExpression typeExpr, IEnumerable<AstExpr> additionalArguments, 19 + IEnumerable<AstExpr> operationArguments) 20 + { 21 + var methodNameExpr = additionalArguments.First(); 22 + if (context.GetOptimizedNode(methodNameExpr) is not AstConstant { Constant: string methodName }) 23 + { 24 + var message = Resources.StaticCallBuiltIn_DoExpand_Static_call_requires_a_constant_method_name; 25 + context.ReportMessage(Message.Error( 26 + message, 27 + methodNameExpr.Position, 28 + MessageClasses.IncompleteBuiltinStaticCall)); 29 + return; 30 + } 31 + 32 + var cast = new AstGetSetStatic(context.Invocation.Position, context.Call, typeExpr, methodName); 33 + cast.Arguments.AddRange(operationArguments); 34 + context.Block.Expression = cast; 35 + } 36 + } 37 + }
+1 -2
Prexonite/Compiler/Macro/MacroContextExtensions.cs
··· 81 81 position.Line, 82 82 position.Column, 83 83 PType.Object[typeof (T)].ToString()); 84 - return new AstGetSetStatic(position.File, position.Line, 85 - position.Column, PCall.Get, pcallT, member); 84 + return new AstGetSetStatic(position, PCall.Get, pcallT, member); 86 85 } 87 86 88 87 /// <summary>
+1 -2
Prexonite/Compiler/Macro/MacroSession.cs
··· 50 50 private readonly SymbolCollection _allocationList = new(); 51 51 52 52 [NotNull] 53 - private readonly HashSet<AstGetSet> _invocations = 54 - new(); 53 + private readonly HashSet<AstGetSet> _invocations = new(); 55 54 56 55 [NotNull] 57 56 private readonly object _buildCommandToken;
+6
Prexonite/Compiler/MessageClasses.cs
··· 64 64 public const string NonTopLevelNamespaceImport = "P.NonTopLevelNamespaceImport"; 65 65 public const string UnexpectedDoubleColonInNamespaceName = "P.UnexpectedDoubleColonInNamespaceName"; 66 66 public const string IncompleteBinaryOperation = "P.IncompleteBinaryOperation"; 67 + public const string ShiftedSymbolRequired = "P.ShiftedSymbolRequired"; 68 + public const string TypeArgumentsNotSupported = "P.TypeArgumentsNotSupported"; 67 69 68 70 #endregion 69 71 ··· 80 82 public const string TypeExpressionExpected = "C.TypeExpressionExpected"; 81 83 public const string ExpectedEntityFoundNamespace = "C.NamespaceInEntityPosition"; 82 84 public const string ArgumentSpliceNotSupported = "C.ArgumentSpliceNotSupported"; 85 + public const string IncompleteBuiltinConversion = "C.IncompleteBuiltinConversion"; 86 + public const string IncompleteBuiltinTypeCheck = "C.IncompleteBuiltinTypeCheck"; 87 + public const string IncompleteBuiltinStaticCall = "C.IncompleteBuiltinStaticCall"; 88 + public const string IncompleteBuiltinObjectCreation = "C.IncompleteBuiltinObjectCreation"; 83 89 84 90 #endregion 85 91
+69 -55
Prexonite/Compiler/Parser.Code.cs
··· 244 244 } 245 245 } 246 246 247 - if (localNs.Prefix == null) 248 - { 249 - localNs.Prefix = nextPrefix.ToString().Replace('.', '\\'); 250 - } 247 + localNs.Prefix ??= nextPrefix.ToString().Replace('.', '\\'); 251 248 } 252 249 253 250 [CanBeNull] ··· 257 254 { 258 255 scope.TryGet(qualifiedId[0], out var sym); 259 256 var expr = Create.ExprFor(qualifiedIdPosition, sym); 260 - if (!(expr is AstNamespaceUsage nsUsage)) 257 + if (expr is not AstNamespaceUsage nsUsage) 261 258 { 262 259 Create.ReportMessage( 263 260 Message.Error(string.Format(Resources.Parser_NamespaceExpected, qualifiedId[0], sym == null ? "not defined" : sym.ToString()), ··· 825 822 return sym; 826 823 } 827 824 825 + /// <summary> 826 + /// Resolve a symbol into an expression. Will emit error messages as a side-effect. 827 + /// Use with unqualified references. For qualified references, use <see cref="_useSymbolFromNamespace"/> instead. 828 + /// </summary> 829 + /// <param name="scope">The scope to resolve the symbol in. Usually just <see cref="Symbols"/>.</param> 830 + /// <param name="id">The ID to resolve.</param> 831 + /// <param name="position">The position to use for error messages.</param> 832 + /// <returns>The expression that this symbol resolves to.</returns> 828 833 [NotNull] 829 834 private AstGetSet _useSymbol([NotNull] ISymbolView<Symbol> scope, [NotNull] string id, [NotNull] ISourcePosition position) 830 835 { ··· 836 841 // If we have a namespace usage at hand, record the id used to access it 837 842 // (namespaces are otherwise anonymous, they have no physical name) 838 843 // Note: similar code is located in the GetSetExtension parser production 839 - // for subnamespaces 844 + // for sub namespaces 840 845 if (complex is AstNamespaceUsage {ReferencePath: null} nsu) 841 846 { 842 847 nsu.ReferencePath = new QualifiedId(id); ··· 847 852 complex = _NullNode(position); 848 853 return complex; 849 854 } 855 + 856 + /// <summary> 857 + /// Resolve a symbol into an expression. Will emit error messages as a side-effect. 858 + /// Use with qualified references. For unqualified references, use <see cref="_useSymbol"/> instead. 859 + /// </summary> 860 + /// <param name="ns">The namespace usage that serves as the scope for this resolution.</param> 861 + /// <param name="id">The ID to resolve within the base namespace.</param> 862 + /// <param name="position">The position to use for error messages.</param> 863 + /// <returns>The expression that this symbol resolves to.</returns> 864 + [NotNull] 865 + private AstGetSet _useSymbolFromNamespace([NotNull] AstNamespaceUsage ns, [NotNull] string id, [NotNull] ISourcePosition position) 866 + { 867 + var expr = _useSymbol(ns.Namespace, id, position); 868 + // write down qualified path 869 + if(expr is AstNamespaceUsage {ReferencePath: null} subNs) 870 + { 871 + subNs.ReferencePath = ns.ReferencePath + new QualifiedId(id); 872 + } 873 + 874 + return expr; 875 + } 850 876 851 877 private Symbol _parseSymbol(MExpr expr) 852 878 { ··· 882 908 [DebuggerStepThrough] 883 909 private static bool isGlobalId(Token c) 884 910 { 885 - return c.kind == _id || c.kind == _anyId; 911 + return c.kind is _id or _anyId; 886 912 } 887 913 888 914 private bool _isNotNewDecl() ··· 1029 1055 } 1030 1056 } 1031 1057 1032 - private class EnsureInScopeHandler : TransformHandler<Parser> 1058 + private static readonly SymbolShift _objectCreationShift = static id => Compiler.Loader.ObjectCreationPrefix + id; 1059 + private static readonly SymbolShift _conversionShift = static id => Compiler.Loader.ConversionPrefix + id; 1060 + private static readonly SymbolShift _typeCheckShift = static id => Compiler.Loader.TypeCheckPrefix + id; 1061 + private static readonly SymbolShift _staticCallShift = static id => Compiler.Loader.StaticCallPrefix + id; 1062 + 1063 + /// <summary> 1064 + /// Given the partial application of a type check <c>(? is T)</c>, this method will construct the 1065 + /// negated partial application <c>(? is not T)</c> by chaining the negation with <c>then</c>: 1066 + /// <c>(? is T) then (not ?)</c>. 1067 + /// </summary> 1068 + /// <param name="position">The position of the overall expression.</param> 1069 + /// <param name="check">The (non-inverted) type check.</param> 1070 + /// <returns>The partial application of an inverted type check.</returns> 1071 + [NotNull] 1072 + private AstExpr _createPartialInvertedTypeCheck([NotNull] ISourcePosition position, [NotNull] AstExpr check) 1033 1073 { 1034 - public override Symbol HandleReference(ReferenceSymbol self, Parser argument) 1074 + // Special handling of "? is not Y" as that's not the same thing as "not (? is Y)" 1075 + // when placeholders are involved. 1076 + Debug.Assert(check.CheckForPlaceholders(), "check is expected to have placeholders"); 1077 + 1078 + // Create "not ?" 1079 + var notId = OperatorNames.Prexonite.GetName(UnaryOperator.LogicalNot); 1080 + var notOp = CurrentBlock.Symbols.TryGet(notId, out var notSymbol) 1081 + ? Create.ExprFor(position, notSymbol) 1082 + : new AstUnresolved(position, notId); 1083 + if (notOp is not AstGetSet notCall) 1035 1084 { 1036 - if(self.Entity.TryGetLocalVariable(out var local) 1037 - && argument.isOuterVariable(local.Id)) 1038 - argument.target.RequireOuterVariable(local.Id); 1039 - return self; 1085 + Loader.ReportMessage( 1086 + Message.Error( 1087 + Resources.AstFactoryBase_UnaryOperation_NotOperatorForTypecheckRequiresLValue, 1088 + position, MessageClasses.LValueExpected)); 1089 + notCall = _NullNode(position); 1040 1090 } 1041 - } 1042 - private static readonly EnsureInScopeHandler _ensureInScope = new(); 1043 1091 1044 - public void EnsureInScope(Symbol symbol) 1045 - { 1046 - symbol.HandleWith(_ensureInScope, this); 1047 - } 1092 + notCall.Arguments.Add(Create.Placeholder(position,0)); 1048 1093 1049 - private void _fallbackObjectCreation(AstTypeExpr type, out AstExpr expr, 1050 - out ArgumentsProxy args) 1051 - { 1052 - if ( 1053 - //is a type expression we understand (Parser currently only generates dynamic type expressions) 1054 - // constant type expressions are recognized during optimization 1055 - type is AstDynamicTypeExpression {TypeId: { }} typeExpr && typeExpr.Arguments.Count == 0 && !ParentEngine.PTypeRegistry.Contains(typeExpr.TypeId) && target.Symbols.TryGet( 1056 - Loader.ObjectCreationFallbackPrefix + typeExpr.TypeId, 1057 - out var fallbackSymbol)) 1058 - { 1059 - EnsureInScope(fallbackSymbol); 1094 + // Assemble "(? is T) then (not ?)" 1095 + var thenCmd = Create.Call(position, EntityRef.Command.Create(Engine.ThenAlias)); 1096 + thenCmd.Arguments.Add(check); 1097 + thenCmd.Arguments.Add(notCall); 1060 1098 1061 - var e = Create.ExprFor(type.Position,fallbackSymbol); 1062 - if (!(e is AstGetSet call)) 1063 - { 1064 - var pos = GetPosition(); 1065 - call = Create.IndirectCall(pos, Create.Null(pos)); 1066 - Loader.ReportMessage(Message.Create(MessageSeverity.Error, 1067 - string.Format(Resources.Parser__CannotUseExpressionAsAConstructor, 1068 - e), pos, 1069 - MessageClasses.CannotUseExpressionAsConstructor)); 1070 - } 1071 - expr = call; 1072 - args = call.Arguments; 1073 - } 1074 - else if (type != null) 1075 - { 1076 - var creation = new AstObjectCreation(this, type); 1077 - expr = creation; 1078 - args = creation.Arguments; 1079 - } 1080 - else 1081 - { 1082 - Loader.ReportMessage(Message.Error(Resources.Parser__fallbackObjectCreation_Failed,GetPosition(),MessageClasses.ObjectCreationSyntax)); 1083 - expr = new AstNull(this); 1084 - args = new ArgumentsProxy(new List<AstExpr>()); 1085 - } 1099 + return thenCmd; 1086 1100 } 1087 1101 1088 1102 private AstExpr _createUnknownExpr()
+2 -1
Prexonite/Prexonite.csproj
··· 8 8 9 9 <PropertyGroup> 10 10 <IsPackable>true</IsPackable> 11 - <Version>1.95</Version> 11 + <Version>1.98</Version> 12 12 <Title>Prexonite Scripting Language</Title> 13 13 <PackageDescription>An embeddable scripting language with a focus on meta programming and domain specific languages.</PackageDescription> 14 14 <Description>$(PackageDescription)</Description> ··· 78 78 <Compile Include="$(ProjectDir)\Internal\Parser.cs" /> 79 79 <Compile Include="$(ProjectDir)\Internal\Scanner.cs" /> 80 80 <Compile Include="Commands\Core\Operators\Operators.cs" /> 81 + <None Remove="Compiler\Lexer.cs~" /> 81 82 </ItemGroup> 82 83 <ItemGroup> 83 84 <Grammar Include="PTypeExpression.atg" />
+21
Prexonite/Properties/Resources.resx
··· 445 445 <data name="Parser_BinaryOperandMissing_Right" xml:space="preserve"> 446 446 <value>Right-hand side of {0} operation is missing.</value> 447 447 </data> 448 + <data name="ConvertToBuiltIn_DoExpand_Missing_expression_to_convert_built_in_type" xml:space="preserve"> 449 + <value>Missing expression to convert built-in type {0}.</value> 450 + </data> 451 + <data name="StaticCallBuiltIn_DoExpand_Missing_type_arguments_or_method_name_for_static_method_call_" xml:space="preserve"> 452 + <value>Missing type arguments or method name for static method call.</value> 453 + </data> 454 + <data name="CheckIsBuiltIn_DoExpand_Missing_expression_to_check_against_built_in_type" xml:space="preserve"> 455 + <value>Missing inversion flag or expression to check against built-in type {0}.</value> 456 + </data> 457 + <data name="StaticCallBuiltIn_DoExpand_Static_call_requires_a_constant_method_name" xml:space="preserve"> 458 + <value>Static call requires a constant method name.</value> 459 + </data> 460 + <data name="CreateToBuiltIn_DoExpand_Missing_type_arguments_value_creation" xml:space="preserve"> 461 + <value>Missing type arguments for value creation.</value> 462 + </data> 463 + <data name="BuiltInTypeCommandBase_DoExpand_0_for_type_1_requires_at_least_2_arguments" xml:space="preserve"> 464 + <value>{0} for type {1} requires at least {2} arguments. Got {3} instead.</value> 465 + </data> 466 + <data name="BuiltInTypeCommandBase_DoExpand_0_for_type_1_requires_an_arity_integer_as_the_first_argument" xml:space="preserve"> 467 + <value>{0} for type {1} requires an arity (integer) as the first argument.</value> 468 + </data> 448 469 </root>
+50 -1
Prexonite/prxlib/prx.core.pxs
··· 25 25 26 26 namespace rt 27 27 { 28 - 28 + namespace builtin 29 + { 30 + 31 + } 32 + export(*),prx.prim( 33 + // constructor (new T) 34 + create_Bool, 35 + create_Char, 36 + create_Hash, 37 + create_Int, 38 + create_List, 39 + create_Null, 40 + create_Object, 41 + create_Real, 42 + create_String, 43 + create_Structure, 44 + // type check (is T) 45 + is_Bool, 46 + is_Char, 47 + is_Hash, 48 + is_Int, 49 + is_List, 50 + is_Null, 51 + is_Object, 52 + is_Real, 53 + is_String, 54 + is_Structure, 55 + // type cast (~T) 56 + to_Bool, 57 + to_Char, 58 + to_Hash, 59 + to_Int, 60 + // don't map to_list; will use `prx.core.seq.to_list` instead 61 + to_Null, 62 + to_Object, 63 + to_Real, 64 + to_String, 65 + to_Structure, 66 + // static call (~T.method) 67 + static_call_Bool, 68 + static_call_Char, 69 + static_call_Hash, 70 + static_call_Int, 71 + static_call_List, 72 + static_call_Null, 73 + static_call_Object, 74 + static_call_Real, 75 + static_call_String, 76 + static_call_Structure 77 + ),seq(to_list); 29 78 } 30 79 export(*),prx.prim(caller,LoadAssembly => load_assembly,debug, CompileToCil => compile_to_cil,boxed); 31 80
+45 -1
Prexonite/prxlib/prx.prim.pxs
··· 123 123 call\star = expand macro command "call\\star", 124 124 entityref_to = expand macro command "entityref_to", 125 125 call\macro = expand macro command "call\\macro", 126 - call\macro\impl = expand macro command "call\\macro\\impl" 126 + call\macro\impl = expand macro command "call\\macro\\impl", 127 + // constructor (new T) 128 + create_Bool = expand macro command "create_Bool", 129 + create_Char = expand macro command "create_Char", 130 + create_Hash = expand macro command "create_Hash", 131 + create_Int = expand macro command "create_Int", 132 + create_List = expand macro command "create_List", 133 + create_Null = expand macro command "create_Null", 134 + create_Object = expand macro command "create_Object", 135 + create_Real = expand macro command "create_Real", 136 + create_String = expand macro command "create_String", 137 + create_Structure = expand macro command "create_Structure", 138 + // type check (is T) 139 + is_Bool = expand macro command "is_Bool", 140 + is_Char = expand macro command "is_Char", 141 + is_Hash = expand macro command "is_Hash", 142 + is_Int = expand macro command "is_Int", 143 + is_List = expand macro command "is_List", 144 + is_Null = expand macro command "is_Null", 145 + is_Object = expand macro command "is_Object", 146 + is_Real = expand macro command "is_Real", 147 + is_String = expand macro command "is_String", 148 + is_Structure = expand macro command "is_Structure", 149 + // type cast (~T) 150 + to_Bool = expand macro command "to_Bool", 151 + to_Char = expand macro command "to_Char", 152 + to_Hash = expand macro command "to_Hash", 153 + to_Int = expand macro command "to_Int", 154 + to_List = expand macro command "to_List", 155 + to_Null = expand macro command "to_Null", 156 + to_Object = expand macro command "to_Object", 157 + to_Real = expand macro command "to_Real", 158 + to_String = expand macro command "to_String", 159 + to_Structure = expand macro command "to_Structure", 160 + // static call (~T.method) 161 + static_call_Bool = expand macro command "static_call_Bool", 162 + static_call_Char = expand macro command "static_call_Char", 163 + static_call_Hash = expand macro command "static_call_Hash", 164 + static_call_Int = expand macro command "static_call_Int", 165 + static_call_List = expand macro command "static_call_List", 166 + static_call_Null = expand macro command "static_call_Null", 167 + static_call_Object = expand macro command "static_call_Object", 168 + static_call_Real = expand macro command "static_call_Real", 169 + static_call_String = expand macro command "static_call_String", 170 + static_call_Structure = expand macro command "static_call_Structure" 127 171 ); 128 172 }
+45 -1
Prexonite/prxlib/prx.v1.prelude.pxs
··· 129 129 call\star, 130 130 call\macro, 131 131 call\macro\impl, 132 - entityref_to 132 + entityref_to, 133 + // constructor (new T) 134 + create_Bool, 135 + create_Char, 136 + create_Hash, 137 + create_Int, 138 + create_List, 139 + create_Null, 140 + create_Object, 141 + create_Real, 142 + create_String, 143 + create_Structure, 144 + // type check (is T) 145 + is_Bool, 146 + is_Char, 147 + is_Hash, 148 + is_Int, 149 + is_List, 150 + is_Null, 151 + is_Object, 152 + is_Real, 153 + is_String, 154 + is_Structure, 155 + // type cast (~T) 156 + to_Bool, 157 + to_Char, 158 + to_Hash, 159 + to_Int, 160 + to_List, 161 + to_Null, 162 + to_Object, 163 + to_Real, 164 + to_String, 165 + to_Structure, 166 + // static call (~T.method) 167 + static_call_Bool, 168 + static_call_Char, 169 + static_call_Hash, 170 + static_call_Int, 171 + static_call_List, 172 + static_call_Null, 173 + static_call_Object, 174 + static_call_Real, 175 + static_call_String, 176 + static_call_Structure 133 177 };
+45 -1
Prexonite/prxlib/prx.v1.pxs
··· 126 126 call\star, 127 127 call\macro, 128 128 call\macro\impl, 129 - entityref_to 129 + entityref_to, 130 + // constructor (new T) 131 + create_Bool, 132 + create_Char, 133 + create_Hash, 134 + create_Int, 135 + create_List, 136 + create_Null, 137 + create_Object, 138 + create_Real, 139 + create_String, 140 + create_Structure, 141 + // type check (is T) 142 + is_Bool, 143 + is_Char, 144 + is_Hash, 145 + is_Int, 146 + is_List, 147 + is_Null, 148 + is_Object, 149 + is_Real, 150 + is_String, 151 + is_Structure, 152 + // type cast (~T) 153 + to_Bool, 154 + to_Char, 155 + to_Hash, 156 + to_Int, 157 + to_List, 158 + to_Null, 159 + to_Object, 160 + to_Real, 161 + to_String, 162 + to_Structure, 163 + // static call (~T.method) 164 + static_call_Bool, 165 + static_call_Char, 166 + static_call_Hash, 167 + static_call_Int, 168 + static_call_List, 169 + static_call_Null, 170 + static_call_Object, 171 + static_call_Real, 172 + static_call_String, 173 + static_call_Structure 130 174 }; 131 175 132 176 }
+1 -1
Prexonite/prxlib/sys.pxs
··· 18 18 // behavior while prx.core would move forward 19 19 // Adventurous users can depend directly on prx.prim to be on the bleeding edge. 20 20 namespace sys {} 21 - export prx.core.*; 21 + export prx.core.*, prx.core.rt.builtin.*; 22 22 23 23 // We deliberately re-export this 'as-is' as part of the standard library. 24 24 // Things in here are too experimental for use inside the standard library
+205 -2
PrexoniteTests/Tests/Compiler.Parser.cs
··· 375 375 } 376 376 377 377 [Test] 378 + public void StaticCallAssign() 379 + { 380 + _compile(@" 381 + function test\static_assign 382 + { 383 + ::System::Console.WriteLine = ""Hi""; 384 + } 385 + "); 386 + Expect(@"test\static_assign", @" 387 + ldc.string ""Hi"" 388 + dup 1 389 + sset.1 ""Object(\""System.Console\"")::WriteLine"" 390 + ret.value 391 + "); 392 + } 393 + 394 + [Test] 378 395 public void StaticCalls() 379 396 { 380 397 _compile( ··· 3052 3069 } 3053 3070 3054 3071 [Test] 3072 + public void CastAssignSingle() 3073 + { 3074 + _compile(@" 3075 + function main(a, b) 3076 + { 3077 + var x = b; 3078 + x ~ = Object<""System.Version"">; 3079 + return x; 3080 + } 3081 + "); 3082 + 3083 + Expect(@" 3084 + var a,b,x 3085 + 3086 + ldloc b 3087 + stloc x 3088 + 3089 + ldloc x 3090 + cast.const ""Object(\""System.Version\"")"" 3091 + stloc x 3092 + 3093 + ldloc x 3094 + ret 3095 + "); 3096 + } 3097 + 3098 + [Test] 3055 3099 public void SimpleAssignExpr() 3056 3100 { 3057 3101 _compile(@" ··· 3119 3163 { 3120 3164 var a; 3121 3165 var b = a *= 5; 3122 - var c ~= T; 3166 + var c ~= String; 3123 3167 var d = b ??= a; 3124 3168 3125 3169 return null; ··· 3136 3180 stloc b 3137 3181 3138 3182 ldloc c 3139 - cast.const ""T"" 3183 + cast.const ""String"" 3140 3184 stloc c 3141 3185 3142 3186 ldloc b ··· 3657 3701 ldloc y 3658 3702 func.2 make_foo 3659 3703 ret 3704 + "); 3705 + } 3706 + 3707 + [Test] 3708 + public void ObjectCreationFallbackWithTypeArgs() 3709 + { 3710 + _compile(@" 3711 + declare function make_foo as create_foo; 3712 + function make_foo()[pxs\supportsTypeArguments]{} 3713 + function main(x,y) 3714 + { 3715 + return new foo<1,""a"">(x,y); 3716 + } 3717 + 3718 + 3719 + "); 3720 + Expect(@" 3721 + ldc.int 2 3722 + ldc.int 1 3723 + ldc.string ""a"" 3724 + ldloc x 3725 + ldloc y 3726 + func.5 make_foo 3727 + ret 3728 + "); 3729 + } 3730 + 3731 + [Test] 3732 + public void CustomTypeConversion() 3733 + { 3734 + _compile(@" 3735 + function convert_to_foo as to_foo(){}; 3736 + function main(x) { 3737 + return x~foo; 3738 + } 3739 + "); 3740 + Expect(@" 3741 + ldloc x 3742 + func.1 convert_to_foo 3743 + ret.value 3744 + "); 3745 + } 3746 + 3747 + [Test] 3748 + public void CustomTypeConversionWithTypeArgs() 3749 + { 3750 + _compile(@" 3751 + function convert_to_foo as to_foo()[pxs\supportsTypeArguments]{}; 3752 + function main(x) { 3753 + return x~foo<1, ""a"">; 3754 + } 3755 + "); 3756 + Expect(@" 3757 + ldc.int 2 3758 + ldc.int 1 3759 + ldc.string ""a"" 3760 + ldloc x 3761 + func.4 convert_to_foo 3762 + ret.value 3763 + "); 3764 + } 3765 + 3766 + [Test] 3767 + public void CustomTypeCheck() 3768 + { 3769 + _compile(@" 3770 + function check_foo as is_foo(){} 3771 + function main(x) { 3772 + println(x is not foo); 3773 + return x is foo; 3774 + } 3775 + "); 3776 + Expect(@" 3777 + ldloc x 3778 + func.1 check_foo 3779 + not 3780 + @cmd.1 println 3781 + ldloc x 3782 + func.1 check_foo 3783 + ret.value 3784 + "); 3785 + } 3786 + 3787 + [Test] 3788 + public void CustomTypeCheckWithTypeArgs() 3789 + { 3790 + _compile(@" 3791 + function check_foo as is_foo()[pxs\supportsTypeArguments]{} 3792 + function main(x) { 3793 + println(x is not foo<3, ""a"">); 3794 + return x is foo<1, ""b"">; 3795 + } 3796 + "); 3797 + Expect(@" 3798 + ldc.int 2 3799 + ldc.int 3 3800 + ldc.string ""a"" 3801 + ldloc x 3802 + func.4 check_foo 3803 + not 3804 + @cmd.1 println 3805 + ldc.int 2 3806 + ldc.int 1 3807 + ldc.string ""b"" 3808 + ldloc x 3809 + func.4 check_foo 3810 + ret.value 3811 + "); 3812 + } 3813 + 3814 + [Test] 3815 + public void CustomTypeStaticCall() 3816 + { 3817 + _compile(@" 3818 + function static_foo as static_call_foo(){} 3819 + function main(x,y) { 3820 + ~foo.the_property = x; 3821 + return ~foo.the_method(x,y); 3822 + } 3823 + "); 3824 + Expect(@" 3825 + ldc.string ""the_property"" 3826 + ldloc x 3827 + @func.2 static_foo 3828 + 3829 + ldc.string ""the_method"" 3830 + ldloc x 3831 + ldloc y 3832 + func.3 static_foo 3833 + ret.value 3834 + "); 3835 + } 3836 + 3837 + [Test] 3838 + public void CustomTypeStaticCallWithTypeArgs() 3839 + { 3840 + _compile(@" 3841 + function static_foo as static_call_foo()[pxs\supportsTypeArguments]{} 3842 + function main(x,y) { 3843 + ~foo<1, ""a"">.the_property = x; 3844 + return ~foo<3, ""b"">.the_method(x,y); 3845 + } 3846 + "); 3847 + Expect(@" 3848 + ldc.int 2 3849 + ldc.int 1 3850 + ldc.string a 3851 + ldc.string ""the_property"" 3852 + ldloc x 3853 + @func.5 static_foo 3854 + 3855 + ldc.int 2 3856 + ldc.int 3 3857 + ldc.string b 3858 + ldc.string ""the_method"" 3859 + ldloc x 3860 + ldloc y 3861 + func.6 static_foo 3862 + ret.value 3660 3863 "); 3661 3864 } 3662 3865
+2
PrexoniteTests/Tests/Configurations/UnitTestConfiguration.cs
··· 144 144 container.OneTimeSetupLog.WriteLine("Warning: {0}", warning); 145 145 foreach (var info in target.Messages.Where(m => m.Severity == MessageSeverity.Info)) 146 146 container.OneTimeSetupLog.WriteLine("Info: {0}", info); 147 + 148 + TestContext.WriteLine(container.OneTimeSetupLog); 147 149 Assert.Fail("The target {0} failed to build. Working directory: {1}", target.Name, Environment.CurrentDirectory); 148 150 } 149 151
+97
PrexoniteTests/Tests/Translation.cs
··· 1473 1473 } 1474 1474 1475 1475 [Test] 1476 + public void CustomTypeFunctionsInNamespaces() 1477 + { 1478 + Compile(@" 1479 + namespace a.b.c { 1480 + function create_pot(x) = ""pot($x)""; 1481 + function static_call_pot(m, arg) = ""pot.$m($arg)""; 1482 + function to_pot(x) = ""$x~pot""; 1483 + function is_pot(x) = x is String and x.Contains(""pot""); 1484 + } 1485 + 1486 + function main(x,y) { 1487 + var p1 = new a.b.c.pot(x); 1488 + var p2 = y~a.b.c.pot; 1489 + var z = ~a.b.c.pot.heat(x); 1490 + return [p1, p2, z, p1 is a.b.c.pot, 5 is not a.b.c.pot, ""fire"" is not a.b.c.pot]; 1491 + } 1492 + "); 1493 + Expect(new List<PValue> 1494 + { 1495 + "pot(X)", 1496 + "Y~pot", 1497 + "pot.heat(X)", 1498 + true, 1499 + true, 1500 + true 1501 + }, "X", "Y"); 1502 + } 1503 + 1504 + [Test] 1505 + public void CustomTypeFunctionsWithDotSuffix() 1506 + { 1507 + Compile(@" 1508 + namespace a.b.c { 1509 + function create_pot() = ""pot()""; 1510 + function static_call_pot(m) = ""pot.$m""; 1511 + function to_pot(x) = ""$x~pot""; 1512 + function is_pot(x) = x is String and x.Contains(""pot""); 1513 + } 1514 + function main(y) { 1515 + var p1 = new a.b.c.pot.ToString; 1516 + var p2 = y~a.b.c.pot.ToString; 1517 + var z = ~a.b.c.pot.heat.ToString; 1518 + return [p1, p2, z, p1 is a.b.c.pot.ToString, 5 is not a.b.c.pot.ToString, ""fire"" is not a.b.c.pot.ToString]; 1519 + } 1520 + "); 1521 + Expect(new List<PValue> 1522 + { 1523 + "pot()", 1524 + "Y~pot", 1525 + "pot.heat", 1526 + "True", 1527 + "True", 1528 + "True" 1529 + 1530 + },"Y"); 1531 + } 1532 + 1533 + [Test] 1534 + public void CustomTypeFunctionsInNamespacesWithTypeArgs() 1535 + { 1536 + Compile(@" 1537 + namespace a.b.c { 1538 + function create_pot(nT, T1, T2, x)[pxs\supportsTypeArguments] = ""pot`$nT<$T1,$T2>($x)""; 1539 + function static_call_pot(nT, T1, T2, m, arg)[pxs\supportsTypeArguments] = ""pot`$nT<$T1,$T2>.$m($arg)""; 1540 + function to_pot(nT, T1, T2, x)[pxs\supportsTypeArguments] = ""$x~pot`$nT<$T1,$T2>""; 1541 + function is_pot(nT, T1, T2, x)[pxs\supportsTypeArguments] = x is String 1542 + and x.Contains(""pot"") 1543 + and x.Contains(T1) 1544 + and x.Contains(T2); 1545 + } 1546 + 1547 + function main(x,y) { 1548 + var p1 = new a.b.c.pot<""a"", ""b"">(x); 1549 + var p2 = y~a.b.c.pot<""c"", ""d"">; 1550 + var z = ~a.b.c.pot<""e"", ""f"">.heat(x); 1551 + return [p1, p2, z, 1552 + // should match 1553 + p1 is a.b.c.pot<""a"", ""b"">, 1554 + // should not match => eval to true 1555 + p2 is not a.b.c.pot<""c"", ""zz"">, 1556 + // should not match => eval to true 1557 + ""fire"" is not a.b.c.pot 1558 + ]; 1559 + } 1560 + "); 1561 + Expect(new List<PValue> 1562 + { 1563 + "pot`2<a,b>(X)", 1564 + "Y~pot`2<c,d>", 1565 + "pot`2<e,f>.heat(X)", 1566 + true, 1567 + true, 1568 + true 1569 + }, "X", "Y"); 1570 + } 1571 + 1572 + [Test] 1476 1573 public void QuestionMarkSpliceIsInvalid() 1477 1574 { 1478 1575 var ldr = CompileInvalid(@"
+1 -1
Prx/Prx.csproj
··· 9 9 <TargetFramework>net5.0</TargetFramework> 10 10 <AppConfig>config/app.$(Configuration).config</AppConfig> 11 11 <LangVersion>9</LangVersion> 12 - <Version>1.95</Version> 12 + <Version>1.98</Version> 13 13 <Title>Prexonite CLI</Title> 14 14 <Description>Prexonite command line interpreter and compiler.</Description> 15 15 <Copyright>Christian Klauser © 2020</Copyright>
+2
Prx/psr/_2/psr/test.pxs
··· 3 3 prx/1.0 4 4 }; 5 5 6 + namespace import sys.rt.builtin.create_Object; 7 + 6 8 namespace psr.test.v1 7 9 import prx.v1(*) 8 10 {
+5 -5
Prx/psr/impl/macro.pxs
··· 286 286 { 287 287 var getContext = macro\get_context; 288 288 var parseMessageSeverity_t = ast("ConstantTypeExpression", "Object(\"Prexonite.Compiler.MessageSeverity\")"); 289 - var getSeverity = ast("GetSetStatic", SI.get, parseMessageSeverity_t, severity); 289 + var getSeverity = ast3("StaticMemberAccess", parseMessageSeverity_t, severity, SI.get); 290 290 var getInvocation = ast("GetSetMemberAccess", SI.get, getContext, "Invocation"); 291 291 var position = ast("GetSetMemberAccess",SI.get,getInvocation,"Position"); 292 292 var reportMessage = ast("GetSetMemberAccess", SI.get, getContext, "ReportMessage"); ··· 553 553 var set_arg_pt = new arg_pt(SI.set); 554 554 set_arg_pt.Arguments.Add(ast("GetSetMemberAccess", box_node_arg, "Type")); 555 555 556 - var obj_type_check = ast("TypeCheck",set_arg_pt,ast("ConstantTypeExpression", 556 + var obj_type_check = ast3("Typecheck",set_arg_pt,ast("ConstantTypeExpression", 557 557 "Object(\"Prexonite.Types.ObjectPType\")")); 558 558 559 559 var cond = ast3("Condition",obj_type_check,true); ··· 565 565 566 566 // static var node_t ??= System::Type.GetType(node_t_name); 567 567 { 568 - var node_t_null_check = ast("TypeCheck", new node_t, ast("ConstantTypeExpression","Null")); 568 + var node_t_null_check = ast3("Typecheck", new node_t, ast("ConstantTypeExpression","Null")); 569 569 var cond = ast3("Condition", node_t_null_check,false); 570 - var type_getType = ast("GetSetStatic", SI.get, 571 - ast("ConstantTypeExpression", "Object(\"System.Type\")"), "GetType"); 570 + var type_getType = ast3("StaticMemberAccess", 571 + ast("ConstantTypeExpression", "Object(\"System.Type\")"), "GetType", SI.get); 572 572 type_getType.Arguments.Add(node_t_name); 573 573 var set_node_t = new node_t(SI.set); 574 574 set_node_t.Arguments.Add(type_getType);
+1 -1
Prx/psr/impl/prop.pxs
··· 72 72 73 73 var prop_arg = ast\lvar(parameters[dummyArgs]); 74 74 75 - var nullCheck = ast("Typecheck",prop_arg,ast("ConstantTypeExpression",::NullPType.Literal)); 75 + var nullCheck = ast3("Typecheck",prop_arg,ast("ConstantTypeExpression",::NullPType.Literal)); 76 76 var varargsId = ::PFunction.ArgumentListId; 77 77 var getArgs = ast\lvar(varargsId); 78 78 if(not context.Function.Variables.Contains(varargsId))
+1 -1
Prx/src/prx_interactive.pxs
··· 131 131 //Compile some standard code into the interactive application 132 132 buffer.AppendLine("var prompt = null;"); 133 133 if(Not app.Functions.Contains("exit")) 134 - buffer.AppendLine("function exit(c) does System::Environment.Exit(c ?? 0);"); 134 + buffer.AppendLine("function exit(c) namespace import sys.* does System::Environment.Exit(c ?? 0);"); 135 135 buffer.AppendLine("declare exit as quit;"); 136 136 137 137 // Top-level namespace import for common standard library functions and