Neuron®
The Neuron® is the basis for the creation of open and secure federated networks for smart societies.
Loading...
Searching...
No Matches
Variables.cs
1using System;
2using System.IO;
3using System.Collections.Generic;
4using System.Threading;
6using System.Collections;
7using System.Threading.Tasks;
9using Waher.Events;
10
11namespace Waher.Script
12{
19 public delegate Task<string> ValuePrinter(object Value, Variables Variables);
20
24 public class Variables : IEnumerable<Variable>, IContextVariables
25 {
29 protected Dictionary<string, Variable> variables = new Dictionary<string, Variable>();
30 private Stack<Dictionary<string, Variable>> stack = null;
31 private TextWriter consoleOut = null;
32 private IContextVariables contextVariables = null;
33 private readonly SemaphoreSlim semaphore = new SemaphoreSlim(1);
34 private volatile bool active = true;
35 private ValuePrinter printer = null;
36
40 public Variables(params Variable[] Variables)
41 {
42 foreach (Variable Variable in Variables)
43 this.variables[Variable.Name] = Variable;
44 }
45
52 public virtual bool TryGetVariable(string Name, out Variable Variable)
53 {
54 if (this.active)
55 {
56 lock (this.variables)
57 {
58 if (this.variables.TryGetValue(Name, out Variable))
59 return true;
60 }
61
62 if (!(this.contextVariables is null))
63 return this.contextVariables.TryGetVariable(Name, out Variable);
64
65 return false;
66 }
67 else
68 throw new ScriptAbortedException();
69 }
70
76 public virtual bool ContainsVariable(string Name)
77 {
78 if (this.active)
79 {
80 lock (this.variables)
81 {
82 if (this.variables.ContainsKey(Name))
83 return true;
84 }
85
86 if (!(this.contextVariables is null))
87 return this.contextVariables.ContainsVariable(Name);
88
89 return false;
90 }
91 else
92 throw new ScriptAbortedException();
93 }
94
100 public object this[string Name]
101 {
102 get
103 {
104 if (this.TryGetVariable(Name, out Variable v))
105 return v.ValueObject;
106 else
107 return null;
108 }
109
110 set
111 {
112 this.Add(Name, value);
113 }
114 }
115
122 public virtual Variable Add(string Name, object Value)
123 {
124 Variable Result;
125
126 if (this.active)
127 {
128 lock (this.variables)
129 {
130 if (this.variables.TryGetValue(Name, out Result))
131 Result.SetValue(Value);
132 else
133 this.variables[Name] = Result = new Variable(Name, Value);
134 }
135 }
136 else
137 throw new ScriptAbortedException();
138
139 return Result;
140 }
141
147 public virtual bool Remove(string VariableName)
148 {
149 if (this.active)
150 {
151 lock (this.variables)
152 {
153 return this.variables.Remove(VariableName);
154 }
155 }
156 else
157 throw new ScriptAbortedException();
158 }
159
163 public virtual void Clear()
164 {
165 if (this.active)
166 {
167 lock (this.variables)
168 {
169 this.variables.Clear();
170 }
171 }
172 else
173 throw new ScriptAbortedException();
174 }
175
180 public virtual void Push()
181 {
182 if (this.active)
183 {
184 if (this.stack is null)
185 this.stack = new Stack<Dictionary<string, Variable>>();
186
187 this.stack.Push(this.variables);
188
189 Dictionary<string, Variable> Clone = new Dictionary<string, Variable>();
190 foreach (KeyValuePair<string, Variable> P in this.variables)
191 Clone[P.Key] = new Variable(P.Key, P.Value.ValueElement);
192
193 this.variables = Clone;
194 }
195 else
196 throw new ScriptAbortedException();
197 }
198
202 public virtual void Pop()
203 {
204 if (this.active)
205 {
206 if (this.stack is null)
207 throw new ScriptException("Stack is empty.");
208
209 this.variables = this.stack.Pop();
210 }
211 else
212 throw new ScriptAbortedException();
213 }
214
218 public TextWriter ConsoleOut
219 {
220 get => this.consoleOut;
221 set => this.consoleOut = value;
222 }
223
228 {
229 get => this.contextVariables;
230 set => this.contextVariables = value;
231 }
232
238 {
239 get => this.printer;
240 set => this.printer = value;
241 }
242
251 [Obsolete("Use the LockAsync method for better performance of processing asynchronous tasks.")]
252 public void Lock()
253 {
254 this.Lock(30000);
255 }
256
265 public Task LockAsync()
266 {
267 return this.LockAsync(30000);
268 }
269
279 [Obsolete("Use the LockAsync method for better performance of processing asynchronous tasks.")]
280 public void Lock(int Timeout)
281 {
282 this.LockAsync(Timeout).Wait();
283 }
284
294 public async Task LockAsync(int Timeout)
295 {
296 if (this.active)
297 {
298 if (!await this.semaphore.WaitAsync(Timeout))
299 throw new TimeoutException("Unique access to variables connection was not granted.");
300 }
301 else
302 throw new ScriptAbortedException();
303 }
304
308 public void Release()
309 {
310 this.semaphore.Release();
311 }
312
317 {
318 get
319 {
320 if (this.active)
321 {
323
324 lock (this.variables)
325 {
326 Variables = new Variable[this.variables.Count];
327 this.variables.Values.CopyTo(Variables, 0);
328 }
329
330 return Variables;
331 }
332 else
333 throw new ScriptAbortedException();
334 }
335 }
336
341 public IEnumerator<Variable> GetEnumerator()
342 {
343 return new VariableEnumerator(this.AvailableVariables);
344 }
345
346 private class VariableEnumerator : IEnumerator<Variable>
347 {
348 private readonly Variable[] variables;
349 private int pos = -1;
350
351 internal VariableEnumerator(Variable[] Variables)
352 {
353 this.variables = Variables;
354 }
355
356 public Variable Current
357 {
358 get
359 {
360 return this.variables[this.pos];
361 }
362 }
363
364 object IEnumerator.Current
365 {
366 get
367 {
368 return this.variables[this.pos];
369 }
370 }
371
372 public void Dispose()
373 {
374 }
375
376 public bool MoveNext()
377 {
378 return ++this.pos < this.variables.Length;
379 }
380
381 public void Reset()
382 {
383 this.pos = -1;
384 }
385 }
386
391 IEnumerator IEnumerable.GetEnumerator()
392 {
393 return this.AvailableVariables.GetEnumerator();
394 }
395
401 {
402 Variable[] VariablesToCopy = this.AvailableVariables;
403 Dictionary<string, Variable> Recipient = Variables.variables;
404
405 lock (Recipient)
406 {
407 foreach (Variable Variable in VariablesToCopy)
408 Recipient[Variable.Name] = Variable;
409 }
410 }
411
415 public void Abort()
416 {
417 this.active = false;
418 }
419
423 public void CancelAbort()
424 {
425 this.active = true;
426 }
427
432
436 public bool HandlesPreview
437 {
438 get
439 {
440 if (!(this.OnPreview is null))
441 return true;
442
443 if (this.contextVariables is Variables v)
444 return v.HandlesPreview;
445 else
446 return false;
447 }
448 }
449
456 {
458
459 if (!(h is null))
460 {
461 try
462 {
463 h(this, new PreviewEventArgs(Expression, this, Result));
464 }
465 catch (Exception ex)
466 {
467 Log.Exception(ex);
468 }
469 }
470
471 if (this.contextVariables is Variables v)
472 v.Preview(Expression, Result);
473 }
474
475
481 public void Status(Expression Expression, string Result)
482 {
484 if (!(h is null))
485 {
486 try
487 {
488 h(this, new StatusEventArgs(Expression, this, Result));
489 }
490 catch (Exception ex)
491 {
492 Log.Exception(ex);
493 }
494 }
495 }
496
500 public bool HandlesStatus
501 {
502 get { return !(this.OnStatus is null); }
503 }
504
508 public event StatusEventHandler OnStatus = null;
509
510 }
511}
Static class managing the application event log. Applications and services log events on this static ...
Definition: Log.cs:13
static void Exception(Exception Exception, string Object, string Actor, string EventId, EventLevel Level, string Facility, string Module, params KeyValuePair< string, object >[] Tags)
Logs an exception. Event type will be determined by the severity of the exception.
Definition: Log.cs:1647
Exception thrown when a script has been aborted.
Base class for script exceptions.
Class managing a script expression.
Definition: Expression.cs:39
Event arguments for preview events.
Event arguments for status events.
Contains information about a variable.
Definition: Variable.cs:10
void SetValue(object Value)
Sets the value of the variable.
Definition: Variable.cs:70
string Name
Name of variable.
Definition: Variable.cs:78
Collection of variables.
Definition: Variables.cs:25
TextWriter ConsoleOut
Console out interface. Can be used by functions and script to output data to the console.
Definition: Variables.cs:219
virtual void Push()
Pushes the current set of variables to the stack. This state is restored by calling Pop....
Definition: Variables.cs:180
virtual void Pop()
Pops a previously stored set of variables from the stack. Variables are stored on the stack by callin...
Definition: Variables.cs:202
IContextVariables ContextVariables
Variables available during the current context.
Definition: Variables.cs:228
void Preview(Expression Expression, IElement Result)
Reports a preview of the final result.
Definition: Variables.cs:455
bool HandlesPreview
If previews are desired.
Definition: Variables.cs:437
bool HandlesStatus
If status messages are desired.
Definition: Variables.cs:501
void Status(Expression Expression, string Result)
Reports current status of execution.
Definition: Variables.cs:481
void CopyTo(Variables Variables)
Copies available variables to another variable collection.
Definition: Variables.cs:400
void CancelAbort()
Allows new script to be evaluated using this collection of variables.
Definition: Variables.cs:423
virtual Variable Add(string Name, object Value)
Adds a variable to the collection.
Definition: Variables.cs:122
Task LockAsync()
Locks the collection. The collection is by default thread safe. But if longer transactions require un...
Definition: Variables.cs:265
async Task LockAsync(int Timeout)
Locks the collection. The collection is by default thread safe. But if longer transactions require un...
Definition: Variables.cs:294
virtual void Clear()
Removes all variables from the collection.
Definition: Variables.cs:163
ValuePrinter Printer
Delegate that converts values to strings for (implicit) printing. Default is null,...
Definition: Variables.cs:238
virtual bool ContainsVariable(string Name)
If the collection contains a variable with a given name.
Definition: Variables.cs:76
Dictionary< string, Variable > variables
Internal set of variables.
Definition: Variables.cs:29
Variables(params Variable[] Variables)
Collection of variables.
Definition: Variables.cs:40
Variable[] AvailableVariables
Returns an array of available variables.
Definition: Variables.cs:317
void Release()
Releases the collection, previously locked through a call to Lock().
Definition: Variables.cs:308
PreviewEventHandler OnPreview
Event raised when there is a new value to preview.
Definition: Variables.cs:431
virtual bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
Definition: Variables.cs:52
void Lock()
Locks the collection. The collection is by default thread safe. But if longer transactions require un...
Definition: Variables.cs:252
StatusEventHandler OnStatus
Event raised when a status message has been reported.
Definition: Variables.cs:508
virtual bool Remove(string VariableName)
Removes a varaiable from the collection.
Definition: Variables.cs:147
void Lock(int Timeout)
Locks the collection. The collection is by default thread safe. But if longer transactions require un...
Definition: Variables.cs:280
void Abort()
Aborts the execution of script using this collection of variables.
Definition: Variables.cs:415
IEnumerator< Variable > GetEnumerator()
Returns an enumerator that iterates through a collection.
Definition: Variables.cs:341
Basic interface for all types of elements.
Definition: IElement.cs:20
Variables available in a specific context.
bool TryGetVariable(string Name, out Variable Variable)
Tries to get a variable object, given its name.
bool ContainsVariable(string Name)
If the collection contains a variable with a given name.
delegate Task PreviewEventHandler(object Sender, PreviewEventArgs e)
Delegate for preview events.
delegate Task< string > ValuePrinter(object Value, Variables Variables)
Converts a value to a printable string.
delegate Task StatusEventHandler(object Sender, StatusEventArgs e)
Delegate for status events.