From ef16003971f43b918dfceca0693a5017a1d096a8 Mon Sep 17 00:00:00 2001 From: Michael Schimmel Date: Fri, 19 Sep 2025 09:03:02 +0200 Subject: [PATCH] Refactoring --- Src/AST/Myc.Ast.Evaluator.pas | 30 ++++++++-------- Src/Data/Myc.Data.Scalar.pas | 67 ++++++++++++++++++++++++++++++++++- Test/MycTests.dpr | 11 +----- Test/MycTests.dproj | 9 ----- 4 files changed, 83 insertions(+), 34 deletions(-) diff --git a/Src/AST/Myc.Ast.Evaluator.pas b/Src/AST/Myc.Ast.Evaluator.pas index e55d3cd..3354b65 100644 --- a/Src/AST/Myc.Ast.Evaluator.pas +++ b/Src/AST/Myc.Ast.Evaluator.pas @@ -126,8 +126,6 @@ var i: Integer; sourceAddresses: TArray; closureScope: IExecutionScope; - [weak] - closure: TDataValue.TFunc; visitorFactory: TVisitorFactory; begin sourceAddresses := Node.Upvalues; @@ -146,7 +144,9 @@ begin var scopeDescriptor := Node.ScopeDescriptor; var params := Node.Parameters; - // weak reference to break cyclic referencing + // declare closure as weak to break cyclic referencing when it is captured by itself + var [weak] closure: TDataValue.TFunc; + closure := TDataValue.TFunc( function(const ArgValues: TArray): TDataValue @@ -182,35 +182,37 @@ begin end ); - Result := TDataValue(closure); + Result := closure; end; function TEvaluatorVisitor.VisitFunctionCall(const Node: IFunctionCallNode): TDataValue; var calleeValue: TDataValue; + [weak] + callee: TDataValue.TFunc; begin calleeValue := Node.Callee.Accept(Self); - if calleeValue.Kind <> vkMethod then + case calleeValue.Kind of + vkMethod: callee := calleeValue.AsMethod(); + else raise EArgumentException.Create('Expression is not invokable in this context.'); + end; var argNodes := Node.Arguments; case Length(argNodes) of - 0: Result := (calleeValue.AsMethod)([]); - 1: Result := (calleeValue.AsMethod)([argNodes[0].Accept(Self)]); - 2: Result := (calleeValue.AsMethod)([argNodes[0].Accept(Self), argNodes[1].Accept(Self)]); - 3: Result := (calleeValue.AsMethod)([argNodes[0].Accept(Self), argNodes[1].Accept(Self), argNodes[2].Accept(Self)]); - 4: - Result := - (calleeValue.AsMethod) - ([argNodes[0].Accept(Self), argNodes[1].Accept(Self), argNodes[2].Accept(Self), argNodes[3].Accept(Self)]); + 0: Result := callee([]); + 1: Result := callee([argNodes[0].Accept(Self)]); + 2: Result := callee([argNodes[0].Accept(Self), argNodes[1].Accept(Self)]); + 3: Result := callee([argNodes[0].Accept(Self), argNodes[1].Accept(Self), argNodes[2].Accept(Self)]); + 4: Result := callee([argNodes[0].Accept(Self), argNodes[1].Accept(Self), argNodes[2].Accept(Self), argNodes[3].Accept(Self)]); else var argValues: TArray; SetLength(argValues, Length(argNodes)); for var i := 0 to High(argNodes) do argValues[i] := argNodes[i].Accept(Self); - Result := (calleeValue.AsMethod)(argValues); + Result := callee(argValues); end; end; diff --git a/Src/Data/Myc.Data.Scalar.pas b/Src/Data/Myc.Data.Scalar.pas index d172b09..ca2f9df 100644 --- a/Src/Data/Myc.Data.Scalar.pas +++ b/Src/Data/Myc.Data.Scalar.pas @@ -78,7 +78,7 @@ type // Creates a new scalar from a kind and a value. constructor Create(AKind: TScalarKind; const AValue: TScalarValue); - // Factory methods for specific scalar types. + // Factory methods for specific scalar types (do not use anymore, these may become deprecated in the future) class function FromInteger(AValue: Integer): TScalar; static; inline; class function FromInt64(AValue: Int64): TScalar; static; inline; class function FromUInt64(AValue: UInt64): TScalar; static; inline; @@ -93,6 +93,17 @@ type class function FromBytes(const AValue: TScalarBytes): TScalar; static; inline; class function FromDecimal(const AValue: TDecimal): TScalar; static; inline; + // Implicit casts from primitive types to TScalar. + class operator Implicit(AValue: Integer): TScalar; overload; inline; + class operator Implicit(AValue: Int64): TScalar; overload; inline; + class operator Implicit(AValue: UInt64): TScalar; overload; inline; + class operator Implicit(AValue: Single): TScalar; overload; inline; + class operator Implicit(AValue: Double): TScalar; overload; inline; + class operator Implicit(AValue: TDateTime): TScalar; overload; inline; + class operator Implicit(AValue: Boolean): TScalar; overload; inline; + class operator Implicit(AValue: Char): TScalar; overload; inline; + class operator Implicit(const AValue: TDecimal): TScalar; overload; inline; + class function StringToKind(const AName: string): TScalarKind; static; function ToString: String; @@ -405,6 +416,60 @@ begin Result.Value := TScalarValue.FromDouble(AValue); end; +class operator TScalar.Implicit(AValue: Boolean): TScalar; +begin + Result.Kind := skBoolean; + Result.Value := TScalarValue.FromBoolean(AValue); +end; + +class operator TScalar.Implicit(AValue: Char): TScalar; +begin + Result.Kind := skChar; + Result.Value := TScalarValue.FromChar(AValue); +end; + +class operator TScalar.Implicit(AValue: TDateTime): TScalar; +begin + Result.Kind := skDateTime; + Result.Value := TScalarValue.FromDateTime(AValue); +end; + +class operator TScalar.Implicit(const AValue: TDecimal): TScalar; +begin + Result.Kind := skDecimal; + Result.Value := TScalarValue.FromDecimal(AValue); +end; + +class operator TScalar.Implicit(AValue: Double): TScalar; +begin + Result.Kind := skDouble; + Result.Value := TScalarValue.FromDouble(AValue); +end; + +class operator TScalar.Implicit(AValue: Int64): TScalar; +begin + Result.Kind := skInt64; + Result.Value := TScalarValue.FromInt64(AValue); +end; + +class operator TScalar.Implicit(AValue: Integer): TScalar; +begin + Result.Kind := skInteger; + Result.Value := TScalarValue.FromInteger(AValue); +end; + +class operator TScalar.Implicit(AValue: Single): TScalar; +begin + Result.Kind := skSingle; + Result.Value := TScalarValue.FromSingle(AValue); +end; + +class operator TScalar.Implicit(AValue: UInt64): TScalar; +begin + Result.Kind := skUInt64; + Result.Value := TScalarValue.FromUInt64(AValue); +end; + class function TScalar.FromInt64(AValue: Int64): TScalar; begin Result.Kind := skInt64; diff --git a/Test/MycTests.dpr b/Test/MycTests.dpr index bb7fe9d..e4bcd38 100644 --- a/Test/MycTests.dpr +++ b/Test/MycTests.dpr @@ -15,7 +15,7 @@ uses {$ENDIF } DUnitX.TestFramework, TestNotifier in 'TestNotifier.pas', - TestNotifier_Threading in 'TestNotifier_Threading.pas' {/TestNotifier_ChaosStress in 'TestNotifier_ChaosStress.pas',}, + TestNotifier_Threading in 'TestNotifier_Threading.pas', TestNotifier_ChaosStress in 'TestNotifier_ChaosStress.pas', TestTasks in 'TestTasks.pas', TestCoreFutures in 'TestCoreFutures.pas', @@ -25,17 +25,8 @@ uses Myc.Test.Signals.Dirty in '..\Src\Myc.Test.Signals.Dirty.pas', Test.Core.Mutable in 'Test.Core.Mutable.pas', TestDataArray in 'TestDataArray.pas', - Myc.Data.Types in '..\Src\Myc.Data.Types.pas', - Myc.Data.Types.Ordinal in 'Myc.Data.Types.Ordinal.pas', - Myc.Data.Types.Records in 'Myc.Data.Types.Records.pas', - Myc.Data.Types.Float in 'Myc.Data.Types.Float.pas', - Myc.Data.Types.Arrays in 'Myc.Data.Types.Arrays.pas', TestDataTypes in '..\Src\Data\TestDataTypes.pas', - Myc.Data.Types.Method in '..\Src\Data\Myc.Data.Types.Method.pas', - Myc.Data.Types.Void in '..\Src\Data\Myc.Data.Types.Void.pas', - Myc.Data.Types.Decimal in '..\Src\Data\Myc.Data.Types.Decimal.pas', Myc.Ast in '..\Src\AST\Myc.Ast.pas', - Myc.Data.Types.JSON in '..\Src\Data\Myc.Data.Types.JSON.pas', TestDataTypes.JSON in '..\Src\Data\TestDataTypes.JSON.pas', Myc.Data.POD in '..\Src\Data\Myc.Data.Scalar.pas', Myc.Data.Decimal in '..\Src\Data\Myc.Data.Decimal.pas', diff --git a/Test/MycTests.dproj b/Test/MycTests.dproj index f6d8b1b..245c89b 100644 --- a/Test/MycTests.dproj +++ b/Test/MycTests.dproj @@ -126,17 +126,8 @@ $(PreBuildEvent)]]> - - - - - - - - - Myc.Data.POD