Ast Schema

This commit is contained in:
Michael Schimmel
2026-01-06 14:48:22 +01:00
parent 7313848538
commit 74a5c30ae0
4 changed files with 116 additions and 110 deletions
+14 -12
View File
@@ -15,7 +15,7 @@ uses
type
TAstSchema = class
public
// Generates the TypeScript definition by scanning classes via RTTI
// Generates the TypeScript definition by scanning INTERFACES via RTTI
class function GenerateTypeScriptDefinition: string;
// Static rules for the format
@@ -29,7 +29,6 @@ implementation
type
// Helper structure to collect fields per type
// Moved here to avoid scope issues with generics
TFieldInfo = record
Idx: Integer;
Def: string;
@@ -42,6 +41,7 @@ var
ctx: TRttiContext;
types: TArray<TRttiType>;
typ: TRttiType;
prop: TRttiProperty;
attr: TCustomAttribute;
fieldAttr: AstFieldAttribute;
nodeDefs: TDictionary<string, TList<TFieldInfo>>;
@@ -50,7 +50,6 @@ var
sb: TStringBuilder;
tag: string;
fieldInfo: TFieldInfo;
f: TRttiField;
i: Integer;
function GetTsType(Kind: TFieldKind): string;
@@ -74,15 +73,16 @@ begin
sb := TStringBuilder.Create;
try
// 1. Scan all types in the application context
// 1. Scan all types (looking for INTERFACES now)
types := ctx.GetTypes;
for typ in types do
begin
if not typ.IsInstance then
// CHANGE: We now look for Interfaces, not Classes
if typ.TypeKind <> tkInterface then
Continue;
// Check for [AstTag] attribute on the class
// Check for [AstTag] attribute on the interface
tag := '';
for attr in typ.GetAttributes do
if attr is AstTagAttribute then
@@ -102,10 +102,10 @@ begin
fieldsList := nodeDefs[tag];
// Scan Fields (Variables) of the class
for f in typ.AsInstance.GetFields do
// CHANGE: Scan Properties of the interface
for prop in typ.GetProperties do
begin
for attr in f.GetAttributes do
for attr in prop.GetAttributes do
if attr is AstFieldAttribute then
begin
fieldAttr := AstFieldAttribute(attr);
@@ -119,7 +119,7 @@ begin
end;
// 2. Build the output
sb.AppendLine('// AST Schema Definition (Auto-Generated via RTTI)');
sb.AppendLine('// AST Schema Definition (Auto-Generated via RTTI from Interfaces)');
sb.AppendLine('// Format: Compact JSON Arrays [Tag, Arg1, Arg2, ...]');
sb.AppendLine;
@@ -136,13 +136,15 @@ begin
sb.AppendLine(';');
sb.AppendLine;
// Special Handling for Tuple (it's recursive array structure)
sb.AppendLine('type Tuple = ["Tuple", AstNode[]];');
sb.AppendLine;
// Node Definitions
for tag in unionTypes do
begin
// Tuple is special base type
// Skip Tuple in automatic generation as we defined it manually above
// to represent the array structure correctly in TypeScript
if tag = 'Tuple' then
Continue;
@@ -202,7 +204,7 @@ class function TAstSchema.GenerateFullSystemPrompt: string;
begin
// Combine everything
Result :=
'You are a compiler frontend for the "Myc" scripting language.'
'You are a compiler frontend for a scripting language.'
+ sLineBreak
+ 'Your task is to generate a valid Abstract Syntax Tree (AST) in a specific Compact JSON format.'
+ sLineBreak
+99 -97
View File
@@ -1,6 +1,3 @@
//==================================================================================================
//== FULL UNIT START: Myc.Ast.Nodes (from Myc.Ast.Nodes.pas)
//==================================================================================================
unit Myc.Ast.Nodes;
interface
@@ -14,7 +11,7 @@ uses
Myc.Ast.Scope,
Myc.Ast.Types,
Myc.Ast.Identities,
Myc.Ast.Attributes; // Hinzugefügt für [AstTag] und [AstField]
Myc.Ast.Attributes;
type
// --- Forward Declarations ---
@@ -81,16 +78,12 @@ type
IAstVisitor = interface;
IAstTypedNode = interface;
// Core Nodes
// Forward Declarations of specific nodes
IConstantNode = interface;
IIdentifierNode = interface;
IKeywordNode = interface;
// Structure
ITupleNode = interface;
IRecordFieldNode = interface;
// Control Flow & Structure
IIfExpressionNode = interface;
ICondExpressionNode = interface;
ILambdaExpressionNode = interface;
@@ -111,8 +104,6 @@ type
ISeriesLengthNode = interface;
IRecurNode = interface;
INopNode = interface;
// Pipes
IPipeNode = interface;
// Node Kinds & Helpers
@@ -121,8 +112,8 @@ type
akIdentifier,
akKeyword,
// Containers
akTuple, // The universal list (replaces ArgList, ParamList, ExprList, FieldList)
akRecordField, // Single key-value pair
akTuple,
akRecordField,
// Control Flow
akIfExpression,
akCondExpression,
@@ -153,7 +144,6 @@ type
function ToString: string;
end;
// Represents a single branch in a Cond expression (Condition -> Branch)
TCondPair = record
Condition: IAstNode;
Branch: IAstNode;
@@ -215,18 +205,21 @@ type
property StaticType: IStaticType read GetStaticType;
end;
[AstTag('Field')]
IRecordFieldNode = interface(IAstNode)
{$region 'private'}
function GetKey: IKeywordNode;
function GetValue: IAstNode;
{$endregion}
[AstField(0, 'key', fkNode)]
property Key: IKeywordNode read GetKey;
[AstField(1, 'value', fkNode)]
property Value: IAstNode read GetValue;
end;
// --- Node Interfaces (Definitions) ---
// Function Definition (Lambda)
IFunctionDefinition = interface(IAstTypedNode)
{$region 'private'}
function GetBody: IAstNode;
@@ -238,59 +231,80 @@ type
property IsPure: Boolean read GetIsPure;
end;
[AstTag('Nop')]
INopNode = interface(IAstTypedNode)
end;
[AstTag('Const')]
IConstantNode = interface(IAstTypedNode)
{$region 'private'}
function GetValue: TDataValue;
{$endregion}
[AstField(0, 'value', fkValue)]
property Value: TDataValue read GetValue;
end;
[AstTag('Id')]
IIdentifierNode = interface(IAstTypedNode)
{$region 'private'}
function GetAddress: TResolvedAddress;
function GetName: string;
{$endregion}
property Address: TResolvedAddress read GetAddress;
[AstField(0, 'name', fkString)]
property Name: string read GetName;
end;
[AstTag('Key')]
IKeywordNode = interface(IAstTypedNode)
{$region 'private'}
function GetValue: IKeyword;
{$endregion}
[AstField(0, 'name', fkString)]
property Value: IKeyword read GetValue;
end;
[AstTag('Tuple')]
ITupleNode = interface(IAstTypedNode)
{$region 'private'}
function GetElements: TArray<IAstNode>;
{$endregion}
[AstField(0, 'elements', fkNode)]
property Elements: TArray<IAstNode> read GetElements;
end;
[AstTag('If')]
IIfExpressionNode = interface(IAstTypedNode)
{$region 'private'}
function GetCondition: IAstNode;
function GetThenBranch: IAstNode;
function GetElseBranch: IAstNode;
{$endregion}
[AstField(0, 'cond', fkNode)]
property Condition: IAstNode read GetCondition;
[AstField(1, 'then', fkNode)]
property ThenBranch: IAstNode read GetThenBranch;
[AstField(2, 'else', fkNullableNode)]
property ElseBranch: IAstNode read GetElseBranch;
end;
[AstTag('Cond')]
ICondExpressionNode = interface(IAstTypedNode)
{$region 'private'}
function GetPairs: TArray<TCondPair>;
function GetElseBranch: IAstNode;
{$endregion}
[AstField(0, 'pairs', fkArrayOfPairs)]
property Pairs: TArray<TCondPair> read GetPairs;
[AstField(1, 'else', fkNullableNode)]
property ElseBranch: IAstNode read GetElseBranch;
end;
[AstTag('Fn')]
ILambdaExpressionNode = interface(IFunctionDefinition)
{$region 'private'}
function GetLayout: IScopeLayout;
@@ -302,8 +316,16 @@ type
property Descriptor: IScopeDescriptor read GetDescriptor;
property Upvalues: TArray<TResolvedAddress> read GetUpvalues;
property HasNestedLambdas: Boolean read GetHasNestedLambdas;
// Annotated properties from base interface (for schema generation)
[AstField(0, 'params', fkTuple)]
property Parameters: ITupleNode read GetParameters;
[AstField(1, 'body', fkNode)]
property Body: IAstNode read GetBody;
end;
[AstTag('Call')]
IFunctionCallNode = interface(IAstTypedNode)
{$region 'private'}
function GetCallee: IAstNode;
@@ -312,8 +334,12 @@ type
function GetStaticTarget: TDataValue.TFunc;
function GetIsTargetPure: Boolean;
{$endregion}
[AstField(0, 'callee', fkNode)]
property Callee: IAstNode read GetCallee;
[AstField(1, 'args', fkTuple)]
property Arguments: ITupleNode read GetArguments;
property IsTailCall: Boolean read GetIsTailCall;
property StaticTarget: TDataValue.TFunc read GetStaticTarget;
property IsTargetPure: Boolean read GetIsTargetPure;
@@ -328,135 +354,186 @@ type
property ExpandedBody: IAstNode read GetExpandedBody;
end;
[AstTag('Recur')]
IRecurNode = interface(IAstTypedNode)
{$region 'private'}
function GetArguments: ITupleNode;
{$endregion}
[AstField(0, 'args', fkTuple)]
property Arguments: ITupleNode read GetArguments;
end;
[AstTag('Block')]
IBlockExpressionNode = interface(IAstTypedNode)
{$region 'private'}
function GetExpressions: ITupleNode;
{$endregion}
[AstField(0, 'expressions', fkTuple)]
property Expressions: ITupleNode read GetExpressions;
end;
[AstTag('Var')]
IVariableDeclarationNode = interface(IAstTypedNode)
{$region 'private'}
function GetTarget: IAstNode;
function GetInitializer: IAstNode;
function GetIsBoxed: Boolean;
{$endregion}
[AstField(0, 'target', fkNode)]
property Target: IAstNode read GetTarget;
[AstField(1, 'init', fkNullableNode)]
property Initializer: IAstNode read GetInitializer;
property IsBoxed: Boolean read GetIsBoxed;
end;
[AstTag('Assign')]
IAssignmentNode = interface(IAstTypedNode)
{$region 'private'}
function GetTarget: IAstNode;
function GetValue: IAstNode;
{$endregion}
[AstField(0, 'target', fkNode)]
property Target: IAstNode read GetTarget;
[AstField(1, 'value', fkNode)]
property Value: IAstNode read GetValue;
end;
[AstTag('Macro')]
IMacroDefinitionNode = interface(IAstTypedNode)
{$region 'private'}
function GetName: IIdentifierNode;
function GetParameters: ITupleNode;
function GetBody: IAstNode;
{$endregion}
[AstField(0, 'name', fkNode)]
property Name: IIdentifierNode read GetName;
[AstField(1, 'params', fkTuple)]
property Parameters: ITupleNode read GetParameters;
[AstField(2, 'body', fkNode)]
property Body: IAstNode read GetBody;
end;
[AstTag('Quote')]
IQuasiquoteNode = interface(IAstNode)
{$region 'private'}
function GetExpression: IAstNode;
{$endregion}
[AstField(0, 'expr', fkNode)]
property Expression: IAstNode read GetExpression;
end;
[AstTag('Unquote')]
IUnquoteNode = interface(IAstNode)
{$region 'private'}
function GetExpression: IAstNode;
{$endregion}
[AstField(0, 'expr', fkNode)]
property Expression: IAstNode read GetExpression;
end;
[AstTag('Splice')]
IUnquoteSplicingNode = interface(IAstNode)
{$region 'private'}
function GetExpression: IQuasiquoteNode;
{$endregion}
[AstField(0, 'expr', fkNode)]
property Expression: IQuasiquoteNode read GetExpression;
end;
[AstTag('Index')]
IIndexerNode = interface(IAstTypedNode)
{$region 'private'}
function GetBase: IAstNode;
function GetIndex: IAstNode;
{$endregion}
[AstField(0, 'base', fkNode)]
property Base: IAstNode read GetBase;
[AstField(1, 'index', fkNode)]
property Index: IAstNode read GetIndex;
end;
[AstTag('Member')]
IMemberAccessNode = interface(IAstTypedNode)
{$region 'private'}
function GetBase: IAstNode;
function GetMember: IKeywordNode;
{$endregion}
[AstField(0, 'base', fkNode)]
property Base: IAstNode read GetBase;
[AstField(1, 'member', fkNode)]
property Member: IKeywordNode read GetMember;
end;
[AstTag('Record')]
IRecordLiteralNode = interface(IAstTypedNode)
{$region 'private'}
function GetFields: ITupleNode;
function GetGenericDefinition: IGenericRecordDefinition;
function GetScalarDefinition: IScalarRecordDefinition;
{$endregion}
[AstField(0, 'fields', fkTuple)]
property Fields: ITupleNode read GetFields;
property GenericDefinition: IGenericRecordDefinition read GetGenericDefinition;
property ScalarDefinition: IScalarRecordDefinition read GetScalarDefinition;
end;
[AstTag('Series')]
ICreateSeriesNode = interface(IAstTypedNode)
{$region 'private'}
function GetDefinitionNode: IAstNode;
function GetRecordDefinition: IScalarRecordDefinition;
{$endregion}
[AstField(0, 'definition', fkNode)]
property DefinitionNode: IAstNode read GetDefinitionNode;
property RecordDefinition: IScalarRecordDefinition read GetRecordDefinition;
end;
[AstTag('Add')]
IAddSeriesItemNode = interface(IAstTypedNode)
{$region 'private'}
function GetSeries: IIdentifierNode;
function GetValue: IAstNode;
function GetLookback: IAstNode;
{$endregion}
[AstField(0, 'series', fkNode)]
property Series: IIdentifierNode read GetSeries;
[AstField(1, 'value', fkNode)]
property Value: IAstNode read GetValue;
[AstField(2, 'lookback', fkNullableNode)]
property Lookback: IAstNode read GetLookback;
end;
[AstTag('Count')]
ISeriesLengthNode = interface(IAstTypedNode)
{$region 'private'}
function GetSeries: IIdentifierNode;
{$endregion}
[AstField(0, 'series', fkNode)]
property Series: IIdentifierNode read GetSeries;
end;
// The main pipe definition: (pipe [[source [:sel]]...] (fn ...))
[AstTag('Pipe')]
IPipeNode = interface(IAstTypedNode)
{$region 'private'}
function GetInputs: ITupleNode;
function GetTransformation: ILambdaExpressionNode;
{$endregion}
[AstField(0, 'inputs', fkTuple)]
property Inputs: ITupleNode read GetInputs;
[AstField(1, 'transform', fkNode)]
property Transformation: ILambdaExpressionNode read GetTransformation;
end;
@@ -531,12 +608,9 @@ type
property StaticType: IStaticType read GetStaticType;
end;
[AstTag('Field')]
TRecordFieldNode = class(TAstNode, IRecordFieldNode)
private
[AstField(0, 'key', fkNode)]
FKey: IKeywordNode;
[AstField(1, 'value', fkNode)]
FValue: IAstNode;
function GetKey: IKeywordNode;
function GetValue: IAstNode;
@@ -549,10 +623,8 @@ type
// --- Core Nodes Implementations ---
[AstTag('Const')]
TConstantNode = class(TAstTypedNode, IConstantNode)
private
[AstField(0, 'value', fkValue)]
FConstIdentity: IConstantIdentity; // Typed reference for fast access
function GetValue: TDataValue;
protected
@@ -562,10 +634,8 @@ type
function AsConstant: IConstantNode; override;
end;
[AstTag('Id')]
TIdentifierNode = class(TAstTypedNode, IIdentifierNode)
private
[AstField(0, 'name', fkString)]
FNamedIdentity: INamedIdentity; // Typed reference for fast access
FAddress: TResolvedAddress;
function GetAddress: TResolvedAddress;
@@ -577,10 +647,8 @@ type
function AsIdentifier: IIdentifierNode; override;
end;
[AstTag('Key')]
TKeywordNode = class(TAstTypedNode, IKeywordNode)
private
[AstField(0, 'name', fkString)]
FKeywordIdentity: IKeywordIdentity;
function GetValue: IKeyword;
protected
@@ -590,10 +658,8 @@ type
function AsKeyword: IKeywordNode; override;
end;
[AstTag('Tuple')]
TTupleNode = class(TAstTypedNode, ITupleNode)
private
[AstField(0, 'elements', fkNode)] // Represents array
FElements: TArray<IAstNode>;
function GetElements: TArray<IAstNode>;
protected
@@ -603,10 +669,8 @@ type
function AsTuple: ITupleNode; override;
end;
[AstTag('Series')]
TCreateSeriesNode = class(TAstTypedNode, ICreateSeriesNode)
private
[AstField(0, 'definition', fkNode)]
FDefinitionNode: IAstNode;
FRecordDefinition: IScalarRecordDefinition;
function GetDefinitionNode: IAstNode;
@@ -623,17 +687,9 @@ type
function AsCreateSeries: ICreateSeriesNode; override;
end;
// --- Structural Nodes (Identity only for location) ---
[AstTag('If')]
TIfExpressionNode = class(TAstTypedNode, IIfExpressionNode)
private
[AstField(0, 'cond', fkNode)]
FCondition: IAstNode;
[AstField(1, 'then', fkNode)]
FThenBranch: IAstNode;
[AstField(2, 'else', fkNullableNode)]
FElseBranch: IAstNode;
FCondition, FThenBranch, FElseBranch: IAstNode;
function GetCondition: IAstNode;
function GetThenBranch: IAstNode;
function GetElseBranch: IAstNode;
@@ -648,12 +704,9 @@ type
function AsIfExpression: IIfExpressionNode; override;
end;
[AstTag('Cond')]
TCondExpressionNode = class(TAstTypedNode, ICondExpressionNode)
private
[AstField(0, 'pairs', fkArrayOfPairs)]
FPairs: TArray<TCondPair>;
[AstField(1, 'else', fkNullableNode)]
FElseBranch: IAstNode;
function GetPairs: TArray<TCondPair>;
function GetElseBranch: IAstNode;
@@ -669,12 +722,9 @@ type
function AsCondExpression: ICondExpressionNode; override;
end;
[AstTag('Fn')]
TLambdaExpressionNode = class(TAstTypedNode, ILambdaExpressionNode, IFunctionDefinition)
private
[AstField(0, 'params', fkTuple)]
FParameters: ITupleNode;
[AstField(1, 'body', fkNode)]
FBody: IAstNode;
FLayout: IScopeLayout;
FDescriptor: IScopeDescriptor;
@@ -703,12 +753,9 @@ type
function AsLambdaExpression: ILambdaExpressionNode; override;
end;
[AstTag('Call')]
TFunctionCallNode = class(TAstTypedNode, IFunctionCallNode)
private
[AstField(0, 'callee', fkNode)]
FCallee: IAstNode;
[AstField(1, 'args', fkTuple)]
FArguments: ITupleNode;
FIsTailCall: Boolean;
FStaticTarget: TDataValue.TFunc;
@@ -733,14 +780,10 @@ type
function AsFunctionCall: IFunctionCallNode; override;
end;
[AstTag('Macro')]
TMacroDefinitionNode = class(TAstTypedNode, IMacroDefinitionNode)
private
[AstField(0, 'name', fkNode)]
FName: IIdentifierNode;
[AstField(1, 'params', fkTuple)]
FParameters: ITupleNode;
[AstField(2, 'body', fkNode)]
FBody: IAstNode;
function GetName: IIdentifierNode;
function GetParameters: ITupleNode;
@@ -770,10 +813,8 @@ type
function AsMacroExpansion: IMacroExpansionNode; override;
end;
[AstTag('Quote')]
TQuasiquoteNode = class(TAstNode, IQuasiquoteNode)
private
[AstField(0, 'expr', fkNode)]
FExpression: IAstNode;
function GetExpression: IAstNode;
protected
@@ -783,10 +824,8 @@ type
function AsQuasiquote: IQuasiquoteNode; override;
end;
[AstTag('Unquote')]
TUnquoteNode = class(TAstNode, IUnquoteNode)
private
[AstField(0, 'expr', fkNode)]
FExpression: IAstNode;
function GetExpression: IAstNode;
protected
@@ -796,10 +835,8 @@ type
function AsUnquote: IUnquoteNode; override;
end;
[AstTag('Splice')]
TUnquoteSplicingNode = class(TAstNode, IUnquoteSplicingNode)
private
[AstField(0, 'expr', fkNode)]
FExpression: IQuasiquoteNode;
function GetExpression: IQuasiquoteNode;
protected
@@ -809,10 +846,8 @@ type
function AsUnquoteSplicing: IUnquoteSplicingNode; override;
end;
[AstTag('Recur')]
TRecurNode = class(TAstTypedNode, IRecurNode)
private
[AstField(0, 'args', fkTuple)]
FArguments: ITupleNode;
function GetArguments: ITupleNode;
protected
@@ -822,10 +857,8 @@ type
function AsRecur: IRecurNode; override;
end;
[AstTag('Block')]
TBlockExpressionNode = class(TAstTypedNode, IBlockExpressionNode)
private
[AstField(0, 'expressions', fkTuple)]
FExpressions: ITupleNode;
function GetExpressions: ITupleNode;
protected
@@ -835,13 +868,9 @@ type
function AsBlockExpression: IBlockExpressionNode; override;
end;
[AstTag('Var')]
TVariableDeclarationNode = class(TAstTypedNode, IVariableDeclarationNode)
private
[AstField(0, 'target', fkNode)]
FTarget: IAstNode;
[AstField(1, 'init', fkNullableNode)]
FInitializer: IAstNode;
FTarget, FInitializer: IAstNode;
FIsBoxed: Boolean;
function GetTarget: IAstNode;
function GetInitializer: IAstNode;
@@ -859,13 +888,9 @@ type
function AsVariableDeclaration: IVariableDeclarationNode; override;
end;
[AstTag('Assign')]
TAssignmentNode = class(TAstTypedNode, IAssignmentNode)
private
[AstField(0, 'target', fkNode)]
FTarget: IAstNode;
[AstField(1, 'value', fkNode)]
FValue: IAstNode;
FTarget, FValue: IAstNode;
function GetTarget: IAstNode;
function GetValue: IAstNode;
protected
@@ -875,13 +900,9 @@ type
function AsAssignment: IAssignmentNode; override;
end;
[AstTag('Index')]
TIndexerNode = class(TAstTypedNode, IIndexerNode)
private
[AstField(0, 'base', fkNode)]
FBase: IAstNode;
[AstField(1, 'index', fkNode)]
FIndex: IAstNode;
FBase, FIndex: IAstNode;
function GetBase: IAstNode;
function GetIndex: IAstNode;
protected
@@ -891,12 +912,9 @@ type
function AsIndexer: IIndexerNode; override;
end;
[AstTag('Member')]
TMemberAccessNode = class(TAstTypedNode, IMemberAccessNode)
private
[AstField(0, 'base', fkNode)]
FBase: IAstNode;
[AstField(1, 'member', fkNode)]
FMember: IKeywordNode;
function GetBase: IAstNode;
function GetMember: IKeywordNode;
@@ -912,10 +930,8 @@ type
function AsMemberAccess: IMemberAccessNode; override;
end;
[AstTag('Record')]
TRecordLiteralNode = class(TAstTypedNode, IRecordLiteralNode)
private
[AstField(0, 'fields', fkTuple)]
FFields: ITupleNode;
FScalarDef: IScalarRecordDefinition;
FGenericDef: IGenericRecordDefinition;
@@ -935,15 +951,10 @@ type
function AsRecordLiteral: IRecordLiteralNode; override;
end;
[AstTag('Add')]
TAddSeriesItemNode = class(TAstTypedNode, IAddSeriesItemNode)
private
[AstField(0, 'series', fkNode)]
FSeries: IIdentifierNode;
[AstField(1, 'value', fkNode)]
FValue: IAstNode;
[AstField(2, 'lookback', fkNullableNode)]
FLookback: IAstNode;
FValue, FLookback: IAstNode;
function GetSeries: IIdentifierNode;
function GetValue: IAstNode;
function GetLookback: IAstNode;
@@ -959,10 +970,8 @@ type
function AsAddSeriesItem: IAddSeriesItemNode; override;
end;
[AstTag('Count')]
TSeriesLengthNode = class(TAstTypedNode, ISeriesLengthNode)
private
[AstField(0, 'series', fkNode)]
FSeries: IIdentifierNode;
function GetSeries: IIdentifierNode;
protected
@@ -972,7 +981,6 @@ type
function AsSeriesLength: ISeriesLengthNode; override;
end;
[AstTag('Nop')]
TNopNode = class(TAstTypedNode, INopNode)
protected
function GetKind: TAstNodeKind; override;
@@ -981,12 +989,9 @@ type
function AsNop: INopNode; override;
end;
[AstTag('Pipe')]
TPipeNode = class(TAstTypedNode, IPipeNode)
private
[AstField(0, 'inputs', fkTuple)]
FInputs: ITupleNode;
[AstField(1, 'transform', fkNode)]
FTransformation: ILambdaExpressionNode;
function GetInputs: ITupleNode;
function GetTransformation: ILambdaExpressionNode;
@@ -1006,9 +1011,9 @@ implementation
uses
System.Classes,
System.TypInfo,
System.Rtti,
System.StrUtils;
System.StrUtils,
System.TypInfo; // Added for GetEnumName
{ TCompiledFunction }
@@ -2129,6 +2134,3 @@ begin
end;
end.
//==================================================================================================
//== FULL UNIT END: Myc.Ast.Nodes
//==================================================================================================
+2
View File
@@ -193,6 +193,8 @@ begin
FWorkspace.SetFocus;
var WorldP := FWorkspace.ScreenToWorld(FWorkspace.LocalToScreen(TPointF.Create(X, Y)));
if not Assigned(FWorkspace.RootNode) then
exit;
var Hit := FWorkspace.RootNode.HitTest(WorldP);
if (Button = TMouseButton.mbLeft) and (Hit is TAstViewNode) then