port from perforce

This commit is contained in:
2026-04-18 22:31:51 +02:00
commit 8d0ab5b7cc
8409 changed files with 3972376 additions and 0 deletions

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("BooleanLiteral", Namespace = _namespace)]
public sealed class BooleanLiteralModel : LiteralModelBase<bool>
{
public override CodeGenNodeViewModel CreateViewModel()
{
return new BooleanLiteralNode();
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class BooleanLiteralNode : CodeGenNodeViewModel
{
static BooleanLiteralNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<BooleanLiteralNode>));
}
public BooleanLiteralNode() : base(NodeType.Literal)
{
Name = "Boolean";
Output = new CodeGenOutputViewModel<ITypedExpression<bool>>(EPortType.Boolean)
{
Name = "Value",
Editor = ValueEditor,
Value = ValueEditor.ValueChanged.Select(v => new BooleanLiteralValue { Value = v })
};
Outputs.Add(Output);
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Output.CurrentValue)
.Where(v => v != null)
.Subscribe(_ => stringPreview.Value = Output.CurrentValue.PreviewValue ?? "False");
}
public BooleanValueEditorViewModel ValueEditor { get; } = new();
public ValueNodeOutputViewModel<ITypedExpression<bool>> Output { get; }
public override NodeModelBase CreateModel()
{
return new BooleanLiteralModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var booleanLiteral = (BooleanLiteralModel)model;
ValueEditor.Value = booleanLiteral.Value;
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var booleanLiteral = (BooleanLiteralModel)model;
booleanLiteral.Value = ValueEditor.Value;
}
}
}

View File

@@ -0,0 +1,6 @@
namespace Intromat.Nodes.Code
{
public class BooleanLiteralValue : LiteralValueBase<bool>
{
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("FloatLiteral", Namespace = _namespace)]
public sealed class FloatLiteralModel : LiteralModelBase<float>
{
public override CodeGenNodeViewModel CreateViewModel()
{
return new FloatLiteralNode();
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class FloatLiteralNode : CodeGenNodeViewModel
{
static FloatLiteralNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<FloatLiteralNode>));
}
public FloatLiteralNode() : base(NodeType.Literal)
{
Name = "Float";
Output = new CodeGenOutputViewModel<ITypedExpression<float>>(EPortType.Float)
{
Name = "Value",
Editor = ValueEditor,
Value = ValueEditor.ValueChanged.Select(v => new FloatLiteralValue { Value = v })
};
Outputs.Add(Output);
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Output.CurrentValue)
.Where(v => v != null)
.Subscribe(_ => stringPreview.Value = Output.CurrentValue.PreviewValue ?? "0.0");
}
public FloatValueEditorViewModel ValueEditor { get; } = new();
public ValueNodeOutputViewModel<ITypedExpression<float>> Output { get; }
public override NodeModelBase CreateModel()
{
return new FloatLiteralModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var floatLiteral = (FloatLiteralModel)model;
ValueEditor.Value = floatLiteral.Value;
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var floatLiteral = (FloatLiteralModel)model;
floatLiteral.Value = ValueEditor.Value;
}
}
}

View File

@@ -0,0 +1,9 @@
using System.Globalization;
namespace Intromat.Nodes.Code
{
public class FloatLiteralValue : LiteralValueBase<float>
{
public override string? PreviewValue => Value.ToString(CultureInfo.InvariantCulture);
}
}

View File

@@ -0,0 +1,19 @@
using System.Xml.Serialization;
using Intromat.PersistentModel;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("ForLoop", Namespace = _namespace)]
public sealed class ForLoopModel : NodeModelBase
{
public IntLiteralModel FirstIndex { get; set; } = null!;
public IntLiteralModel LastIndex { get; set; } = null!;
public override CodeGenNodeViewModel CreateViewModel()
{
return new ForLoopNode();
}
}
}

View File

@@ -0,0 +1,114 @@
using System;
using System.Reactive;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using NodeNetwork.ViewModels;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class ForLoopNode : ExecutionNodeBase
{
static ForLoopNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<ForLoopNode>));
}
public ForLoopNode() : base(NodeType.Code)
{
var boundsGroup = new EndpointGroup("Bounds");
Name = "For Loop";
LoopBodyFlow = new CodeGenInputViewModel<IStatement>(EPortType.Execution)
{
Name = "Loop Body",
Group = _executionFlowGroup
};
Inputs.Add(LoopBodyFlow);
FirstIndex = new CodeGenInputViewModel<ITypedExpression<int>>(EPortType.Integer)
{
Name = "First Index",
Group = boundsGroup,
Editor = FirstIndexEditor
};
Inputs.Add(FirstIndex);
LastIndex = new CodeGenInputViewModel<ITypedExpression<int>>(EPortType.Integer)
{
Name = "Last Index",
Group = boundsGroup,
Editor = LastIndexEditor
};
Inputs.Add(LastIndex);
var loopBodyChanged = LoopBodyFlow.ValueChanged.Select(_ => Unit.Default).StartWith(Unit.Default);
FlowIn.Value = loopBodyChanged
.CombineLatest(FlowOutChanged, FirstIndex.ValueChanged, LastIndex.ValueChanged, (bodyChange, endChange, firstI, lastI) => (BodyChange: bodyChange, EndChange: endChange, FirstI: firstI, LastI: lastI))
.Select(v => new ForLoopValue
{
LoopBody = LoopBodyFlow.Value,
FlowOut = FlowOut.Value,
LowerBound = v.FirstI,
UpperBound = v.LastI
});
CurrentIndex = new CodeGenOutputViewModel<ITypedExpression<int>>(EPortType.Integer)
{
Name = "Current Index",
Value = FlowIn.Value.Select(v => new VariableReference<int> { LocalVariable = ((ForLoopValue)v).CurrentIndex })
};
Outputs.Add(CurrentIndex);
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
FlowIn.Value.Subscribe(v =>
{
var forLoop = (ForLoopValue)v;
stringPreview.Value = $"[{forLoop.LowerBound?.PreviewValue ?? "0"}..{forLoop.UpperBound?.PreviewValue ?? "0"}]";
});
}
public ValueNodeInputViewModel<IStatement> LoopBodyFlow { get; }
public IntegerExpressionEditorViewModel FirstIndexEditor { get; } = new();
public ValueNodeInputViewModel<ITypedExpression<int>> FirstIndex { get; }
public IntegerExpressionEditorViewModel LastIndexEditor { get; } = new();
public ValueNodeInputViewModel<ITypedExpression<int>> LastIndex { get; }
public ValueNodeOutputViewModel<ITypedExpression<int>> CurrentIndex { get; }
public override NodeModelBase CreateModel()
{
return new ForLoopModel();
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var forLoop = (ForLoopModel)model;
forLoop.FirstIndex = FirstIndexEditor.CreateModel();
forLoop.LastIndex = LastIndexEditor.CreateModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var forLoop = (ForLoopModel)model;
FirstIndexEditor.LoadModel(forLoop.FirstIndex);
LastIndexEditor.LoadModel(forLoop.LastIndex);
}
}
}

View File

@@ -0,0 +1,48 @@
using System.Diagnostics;
using System.Text;
using Intromat.Model;
using Intromat.Model.Compiler;
namespace Intromat.Nodes.Code
{
public class ForLoopValue : ExecutionValueBase
{
public IStatement? LoopBody { get; set; }
public ITypedExpression<int>? LowerBound { get; set; }
public ITypedExpression<int>? UpperBound { get; set; }
public InlineVariableDefinition<int> CurrentIndex { get; } = new();
public override void Compile(CompilerContext context, StringBuilder sb)
{
Debug.Assert(UpperBound != null, nameof(UpperBound) + " != null");
context.EnterNewScope("For loop");
CurrentIndex.Value = LowerBound;
sb.Append("for (");
CurrentIndex.Compile(context, sb);
sb.Append("; ");
sb.Append(CurrentIndex.VariableName);
sb.Append(" <= ");
UpperBound.Compile(context, sb);
sb.Append("; ++");
sb.Append(CurrentIndex.VariableName);
sb.Append(")\n{\n");
LoopBody?.Compile(context, sb);
sb.Append("\n}\n");
context.LeaveScope();
base.Compile(context, sb);
}
public override void CompileHeader(CompilerContext context, StringBuilder sb)
{
LoopBody?.CompileHeader(context, sb);
base.CompileHeader(context, sb);
}
}
}

View File

@@ -0,0 +1,31 @@
using System.Collections.Generic;
using System.Diagnostics;
using System.Text;
using Intromat.Model.Compiler;
namespace Intromat.Nodes.Code
{
public class FunctionCall : ExecutionValueBase
{
public string? FunctionName { get; set; }
public List<IExpression> Parameters { get; } = new();
public override void Compile(CompilerContext context, StringBuilder sb)
{
Debug.Assert(FunctionName != null, nameof(FunctionName) + " != null");
sb.Append($"{FunctionName}(");
for (int i = 0, n = Parameters.Count; i < n; ++i)
{
var p = Parameters[i];
p.Compile(context, sb);
if (i != n - 1)
sb.Append(", ");
}
sb.Append(")\n");
base.Compile(context, sb);
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("IntLiteral", Namespace = _namespace)]
public sealed class IntLiteralModel : LiteralModelBase<int>
{
public override CodeGenNodeViewModel CreateViewModel()
{
return new IntLiteralNode();
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class IntLiteralNode : CodeGenNodeViewModel
{
static IntLiteralNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<IntLiteralNode>));
}
public IntLiteralNode() : base(NodeType.Literal)
{
Name = "Integer";
Output = new CodeGenOutputViewModel<ITypedExpression<int>>(EPortType.Integer)
{
Name = "Value",
Editor = ValueEditor,
Value = ValueEditor.ValueChanged.Select(v => new IntLiteralValue { Value = v })
};
Outputs.Add(Output);
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Output.CurrentValue)
.Where(v => v != null)
.Subscribe(_ => stringPreview.Value = Output.CurrentValue.PreviewValue ?? "0");
}
public IntegerValueEditorViewModel ValueEditor { get; } = new();
public ValueNodeOutputViewModel<ITypedExpression<int>> Output { get; }
public override NodeModelBase CreateModel()
{
return new IntLiteralModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var intLiteral = (IntLiteralModel)model;
ValueEditor.Value = intLiteral.Value;
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var intLiteral = (IntLiteralModel)model;
intLiteral.Value = ValueEditor.Value;
}
}
}

View File

@@ -0,0 +1,25 @@
using System;
namespace Intromat.Nodes.Code
{
public class IntLiteralValue : LiteralValueBase<int>
{
public int EvaluateDimension()
{
var relativeDimension = RelativeSource switch
{
ERelativeSource.Parent => 1 << ParentValue,
ERelativeSource.Input => InputValue,
_ => 1
};
var result = Value switch
{
< 0 => relativeDimension >> -Value,
> 0 => relativeDimension << Value,
_ => relativeDimension
};
return Math.Max(1, Math.Min(8192, result));
}
}
}

View File

@@ -0,0 +1,34 @@
using System.Xml.Serialization;
using Intromat.Nodes.Textures;
using Intromat.PersistentModel;
namespace Intromat.Nodes.Code
{
public enum ERelativeSource
{
Custom,
Parent,
Input
}
[XmlInclude(typeof(IntLiteralModel))]
[XmlInclude(typeof(StringLiteralModel))]
[XmlInclude(typeof(FloatLiteralModel))]
[XmlInclude(typeof(BooleanLiteralModel))]
[XmlInclude(typeof(SamplerLiteralModel))]
public abstract class LiteralModelBase : NodeModelBase
{
public ERelativeSource RelativeSource { get; set; }
}
public class LiteralModelEntry
{
public string Key { get; set; } = null!;
public LiteralModelBase Literal { get; set; } = null!;
}
public abstract class LiteralModelBase<T> : LiteralModelBase
{
public T Value { get; set; } = default!;
}
}

View File

@@ -0,0 +1,28 @@
using System.Text;
using Intromat.Model.Compiler;
namespace Intromat.Nodes.Code
{
public abstract class LiteralValueBase<T> : ITypedExpression<T>
{
public virtual string? PreviewValue => Value?.ToString();
public T ParentValue { get; set; } = default!;
public T InputValue { get; set; } = default!;
public T Value { get; set; } = default!;
public ERelativeSource RelativeSource { get; set; }
public virtual void Compile(CompilerContext context, StringBuilder sb)
{
sb.Append(Value);
}
public virtual T Evaluate()
{
return Value;
}
}
}

View File

@@ -0,0 +1,17 @@
using System.Xml.Serialization;
using Intromat.PersistentModel;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("Print", Namespace = _namespace)]
public sealed class PrintModel : NodeModelBase
{
public string? Text { get; set; }
public override CodeGenNodeViewModel CreateViewModel()
{
return new PrintNode();
}
}
}

View File

@@ -0,0 +1,75 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class PrintNode : ExecutionNodeBase
{
static PrintNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<PrintNode>));
}
public PrintNode() : base(NodeType.Code)
{
Name = "Print";
Text = new CodeGenInputViewModel<ITypedExpression<string>>(EPortType.String)
{
Name = "Text",
Editor = TextEditor
};
Inputs.Add(Text);
FlowIn.Value = FlowOutChanged
.CombineLatest(Text.ValueChanged, (flowOutChanged, textValueChanged) => (FlowOutChanged: flowOutChanged, StringExpression: textValueChanged))
.Select(v => new FunctionCall
{
FunctionName = "print",
FlowOut = FlowOut.Value,
Parameters = { v.StringExpression ?? new StringLiteralValue { Value = "" } }
});
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Text.Value)
.Where(v => v != null)
.Subscribe(_ => stringPreview.Value = Text.Value.PreviewValue ?? string.Empty);
}
public StringExpressionEditorViewModel TextEditor { get; } = new();
public ValueNodeInputViewModel<ITypedExpression<string>> Text { get; }
public override NodeModelBase CreateModel()
{
return new PrintModel();
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var print = (PrintModel)model;
print.Text = TextEditor.Value is StringLiteralValue text ? text.Value : null;
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var print = (PrintModel)model;
if (print.Text != null)
TextEditor.Value = new StringLiteralValue { Value = print.Text };
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("StringFile", Namespace = _namespace)]
public sealed class StringFileModel : LiteralModelBase<string?>
{
public override CodeGenNodeViewModel CreateViewModel()
{
return new StringFileNode();
}
}
}

View File

@@ -0,0 +1,121 @@
using System;
using System.IO;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using NodeNetwork.Utilities;
using ReactiveUI;
using RxFileSystemWatcher;
using Splat;
namespace Intromat.Nodes.Code
{
public class StringFileNode : CodeGenNodeViewModel
{
private readonly ObservableAsPropertyHelper<ObservableFileSystemWatcher> _fileWatcher;
private readonly ObservableAsPropertyHelper<string> _fullPath;
static StringFileNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<StringFileNode>));
}
public StringFileNode()
: base(NodeType.Literal)
{
Name = "String (file)";
Path = new CodeGenInputViewModel<string?>(EPortType.String)
{
Name = "Path",
Editor = PathEditor,
};
Inputs.Add(Path);
Contents = new CodeGenOutputViewModel<ITypedExpression<string?>>(EPortType.String)
{
Name = "Contents",
};
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Parent, vm => vm.Path.Value)
.Where(pair => pair.Item1 != null && pair.Item2 != null)
.Select(pair => System.IO.Path.Combine(((CodeGenNetworkViewModel)pair.Item1).Document.Parent.FullPath, pair.Item2!))
.StartWith(string.Empty)
.ToProperty(this, vm => vm.FullPath, out _fullPath);
this.WhenAnyValue(vm => vm.FullPath)
.Where(File.Exists)
.Select(path => new ObservableFileSystemWatcher(c =>
{
c.Path = System.IO.Path.GetDirectoryName(path)!;
}))
.ToProperty(this, vm => vm.FileWatcher, out _fileWatcher);
Contents.Value = this.WhenAnyValue(vm => vm.FileWatcher)
.PairWithPreviousValue()
.Select(pair =>
{
var oldWatcher = pair.OldValue;
var newWatcher = pair.NewValue;
oldWatcher?.Dispose();
if (newWatcher != null)
{
stringPreview.Value = Path.Value!;
var result =
newWatcher.Renamed.Where(e => e.FullPath == FullPath)
.Merge(newWatcher.Changed.Where(e => e.FullPath == FullPath))
.Throttle(TimeSpan.FromMilliseconds(100))
.Select(_ => new StringLiteralValue() { Value = File.ReadAllText(FullPath) })
.StartWith(new StringLiteralValue() { Value = File.ReadAllText(FullPath) });
newWatcher.Start();
return result;
}
stringPreview.Value = string.Empty;
return Observable.Empty<StringLiteralValue>();
})
.Switch();
Outputs.Add(Contents);
}
public ObservableFileSystemWatcher FileWatcher => _fileWatcher.Value;
public string FullPath => _fullPath.Value;
public StringValueEditorViewModel PathEditor { get; } = new();
public ValueNodeInputViewModel<string?> Path { get; }
public ValueNodeOutputViewModel<ITypedExpression<string?>> Contents { get; }
public override NodeModelBase CreateModel()
{
return new StringFileModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var fileModel = (StringFileModel)model;
PathEditor.Value = fileModel.Value;
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var fileModel = (StringFileModel)model;
fileModel.Value = PathEditor.Value;
}
}
}

View File

@@ -0,0 +1,14 @@
using System.Xml.Serialization;
using Intromat.ViewModels;
namespace Intromat.Nodes.Code
{
[XmlRoot("StringLiteral", Namespace = _namespace)]
public sealed class StringLiteralModel : LiteralModelBase<string?>
{
public override CodeGenNodeViewModel CreateViewModel()
{
return new StringLiteralNode();
}
}
}

View File

@@ -0,0 +1,66 @@
using System;
using System.Reactive.Linq;
using DynamicData;
using Intromat.Model.Compiler;
using Intromat.PersistentModel;
using Intromat.ViewModels;
using Intromat.ViewModels.Editors;
using Intromat.ViewModels.Previews;
using Intromat.Views;
using NodeNetwork.Toolkit.ValueNode;
using ReactiveUI;
using Splat;
namespace Intromat.Nodes.Code
{
public class StringLiteralNode : CodeGenNodeViewModel
{
static StringLiteralNode()
{
Locator.CurrentMutable.Register(() => new CodeGenNodeView(), typeof(IViewFor<StringLiteralNode>));
}
public StringLiteralNode() : base(NodeType.Literal)
{
Name = "String";
Output = new CodeGenOutputViewModel<ITypedExpression<string?>>(EPortType.String)
{
Name = "Value",
Editor = ValueEditor,
Value = ValueEditor.ValueChanged.Select(v => new StringLiteralValue { Value = v })
};
Outputs.Add(Output);
var stringPreview = new StringPreviewViewModel();
Preview = stringPreview;
this.WhenAnyValue(vm => vm.Output.CurrentValue)
.Where(v => v != null)
.Subscribe(_ => stringPreview.Value = ((StringLiteralValue)Output.CurrentValue).Value ?? string.Empty);
}
public StringValueEditorViewModel ValueEditor { get; } = new();
public ValueNodeOutputViewModel<ITypedExpression<string?>> Output { get; }
public override NodeModelBase CreateModel()
{
return new StringLiteralModel();
}
public override void LoadModel(NodeModelBase model)
{
base.LoadModel(model);
var textLiteral = (StringLiteralModel)model;
ValueEditor.Value = textLiteral.Value;
}
public override void SaveModel(NodeModelBase model)
{
base.SaveModel(model);
var textLiteral = (StringLiteralModel)model;
textLiteral.Value = ValueEditor.Value;
}
}
}

View File

@@ -0,0 +1,21 @@
using System.Diagnostics;
using System.Text;
using Intromat.Model.Compiler;
namespace Intromat.Nodes.Code
{
public class StringLiteralValue : LiteralValueBase<string?>
{
public override string? PreviewValue => Value;
public override void Compile(CompilerContext context, StringBuilder sb)
{
sb.Append($"\"{Value}\"");
}
public override string Evaluate()
{
return Value ?? string.Empty;
}
}
}

View File

@@ -0,0 +1,32 @@
using System;
using System.Diagnostics;
using System.Text;
using Intromat.Model;
using Intromat.Model.Compiler;
using Intromat.Model.Compiler.Error;
namespace Intromat.Nodes.Code
{
public class VariableReference<T> : ITypedExpression<T>
{
public string? PreviewValue => LocalVariable?.VariableName;
public ITypedVariableDefinition<T>? LocalVariable { get; set; }
public void Compile(CompilerContext context, StringBuilder sb)
{
var localVariable = LocalVariable;
Debug.Assert(localVariable != null, nameof(localVariable) + " != null");
Debug.Assert(localVariable.VariableName != null, $"{nameof(localVariable)}.{nameof(localVariable.VariableName)} != null");
if (!context.IsInScope(localVariable))
throw new VariableOutOfScopeException(localVariable.VariableName);
sb.Append(localVariable.VariableName);
}
public T Evaluate()
{
throw new NotImplementedException();
}
}
}