zeoslib  UNKNOWN
 All Files
ZExpression.pas
Go to the documentation of this file.
1 {*********************************************************}
2 { }
3 { Zeos Database Objects }
4 { Expression classes and interfaces }
5 { }
6 { Originally written by Sergey Seroukhov }
7 { }
8 {*********************************************************}
9 
10 {@********************************************************}
11 { Copyright (c) 1999-2012 Zeos Development Group }
12 { }
13 { License Agreement: }
14 { }
15 { This library is distributed in the hope that it will be }
16 { useful, but WITHOUT ANY WARRANTY; without even the }
17 { implied warranty of MERCHANTABILITY or FITNESS FOR }
18 { A PARTICULAR PURPOSE. See the GNU Lesser General }
19 { Public License for more details. }
20 { }
21 { The source code of the ZEOS Libraries and packages are }
22 { distributed under the Library GNU General Public }
23 { License (see the file COPYING / COPYING.ZEOS) }
24 { with the following modification: }
25 { As a special exception, the copyright holders of this }
26 { library give you permission to link this library with }
27 { independent modules to produce an executable, }
28 { regardless of the license terms of these independent }
29 { modules, and to copy and distribute the resulting }
30 { executable under terms of your choice, provided that }
31 { you also meet, for each linked independent module, }
32 { the terms and conditions of the license of that module. }
33 { An independent module is a module which is not derived }
34 { from or based on this library. If you modify this }
35 { library, you may extend this exception to your version }
36 { of the library, but you are not obligated to do so. }
37 { If you do not wish to do so, delete this exception }
38 { statement from your version. }
39 { }
40 { }
41 { The project web site is located on: }
42 { http://zeos.firmos.at (FORUM) }
43 { http://sourceforge.net/p/zeoslib/tickets/ (BUGTRACKER)}
44 { svn://svn.code.sf.net/p/zeoslib/code-0/trunk (SVN) }
45 { }
46 { http://www.sourceforge.net/projects/zeoslib. }
47 { }
48 { }
49 { Zeos Development Group. }
50 {********************************************************@}
51 
52 unit ZExpression;
53 
54 interface
55 
56 {$I ZCore.inc}
57 
58 uses SysUtils, Classes, {$IFDEF WITH_TOBJECTLIST_INLINE}System.Contnrs, {$ENDIF}
59  ZClasses, ZCompatibility, ZVariant, ZTokenizer, ZExprParser;
60 
61 type
62  {** Defines an expression exception. }
63  TZExpressionError = class (Exception);
64 
65  {** Defines an execution stack object. }
66  TZExecutionStack = class (TObject)
67  private
68  FValues: TZVariantDynArray;
69  FCount: Integer;
70  FCapacity: Integer;
71 
72  function GetValue(Index: Integer): TZVariant;
73  public
74  constructor Create;
75 
76  procedure DecStackPointer(const Value : integer);
77  function Pop: TZVariant;
78  function Peek: TZVariant;
79  procedure Push(Value: TZVariant);
80  function GetParameter(Index: Integer): TZVariant;
81  procedure Swap;
82 
83  procedure Clear;
84 
85  property Count: Integer read FCount;
86  property Values[Index: Integer]: TZVariant read GetValue;
87  end;
88 
89  {** Defines a list of variables. }
90  IZVariablesList = interface (IZInterface)
91  ['{F4347F46-32F3-4021-B6DB-7A39BF171275}']
92 
93  function GetCount: Integer;
94  function GetName(Index: Integer): string;
95  function GetValue(Index: Integer): TZVariant;
96  procedure SetValue(Index: Integer; const Value: TZVariant);
97  function GetValueByName(const Name: string): TZVariant;
98  procedure SetValueByName(const Name: string; const Value: TZVariant);
99 
100  procedure Add(const Name: string; const Value: TZVariant);
101  procedure Remove(const Name: string);
102  function FindByName(const Name: string): Integer;
103 
104  procedure ClearValues;
105  procedure Clear;
106 
107  property Count: Integer read GetCount;
108  property Names[Index: Integer]: string read GetName;
109  property Values[Index: Integer]: TZVariant read GetValue write SetValue;
110  property NamedValues[const Index: string]: TZVariant read GetValueByName
111  write SetValueByName;
112  end;
113 
114  {** Defines a function interface. }
115  IZFunction = interface (IZInterface)
116  ['{E9B3AFF9-6CD9-49C8-AB66-C8CF60ED8686}']
117 
118  function GetName: string;
119 
120  function Execute(Stack: TZExecutionStack;
121  VariantManager: IZVariantManager): TZVariant;
122 
123  property Name: string read GetName;
124  end;
125 
126  {** Defines a list of functions. }
127  IZFunctionsList = interface (IZInterface)
128  ['{54453054-F012-475B-84C3-7E5C46187FDB}']
129 
130  function GetCount: Integer;
131  function GetName(Index: Integer): string;
132  function GetFunction(Index: Integer): IZFunction;
133 
134  procedure Add(Func: IZFunction);
135  procedure Remove(const Name: string);
136  function FindByName(const Name: string): Integer;
137  procedure Clear;
138 
139  property Count: Integer read GetCount;
140  property Names[Index: Integer]: string read GetName;
141  property Functions[Index: Integer]: IZFunction read GetFunction;
142  end;
143 
144  {** Defines an interface to expression calculator. }
145  IZExpression = interface (IZInterface)
146  ['{26F9D379-5618-446C-8999-D50FBB2F8560}']
147 
148  function GetTokenizer: IZTokenizer;
149  procedure SetTokenizer(Value: IZTokenizer);
150  function GetExpression: string;
151  procedure SetExpression(const Value: string);
152  function GetVariantManager: IZVariantManager;
153  procedure SetVariantManager(Value: IZVariantManager);
154  function GetDefaultVariables: IZVariablesList;
155  procedure SetDefaultVariables(Value: IZVariablesList);
156  function GetDefaultFunctions: IZFunctionsList;
157  procedure SetDefaultFunctions(Value: IZFunctionsList);
158  function GetAutoVariables: Boolean;
159  procedure SetAutoVariables(Value: Boolean);
160 
161  function Evaluate: TZVariant;
162  function Evaluate2(Variables: IZVariablesList): TZVariant;
163  function Evaluate3(Variables: IZVariablesList;
164  Functions: IZFunctionsList): TZVariant;
165  function Evaluate4(Variables: IZVariablesList;
166  Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
167 
168  procedure CreateVariables(Variables: IZVariablesList);
169  procedure Clear;
170 
171  property Tokenizer: IZTokenizer read GetTokenizer write SetTokenizer;
172  property Expression: string read GetExpression write SetExpression;
173  property VariantManager: IZVariantManager read GetVariantManager
174  write SetVariantManager;
175  property DefaultVariables: IZVariablesList read GetDefaultVariables
176  write SetDefaultVariables;
177  property DefaultFunctions: IZFunctionsList read GetDefaultFunctions
178  write SetDefaultFunctions;
179  property AutoVariables: Boolean read GetAutoVariables
180  write SetAutoVariables;
181  end;
182 
183  {** Implements an expression calculator class. }
184  TZExpression = class (TInterfacedObject, IZExpression)
185  private
186  FTokenizer: IZTokenizer;
187  FDefaultVariables: IZVariablesList;
188  FDefaultFunctions: IZFunctionsList;
189  FVariantManager: IZVariantManager;
190  FParser: TZExpressionParser;
191  FAutoVariables: Boolean;
192 
193  function GetTokenizer: IZTokenizer;
194  procedure SetTokenizer(Value: IZTokenizer);
195  function GetExpression: string;
196  procedure SetExpression(const Value: string);
197  function GetVariantManager: IZVariantManager;
198  procedure SetVariantManager(Value: IZVariantManager);
199  function GetDefaultVariables: IZVariablesList;
200  procedure SetDefaultVariables(Value: IZVariablesList);
201  function GetDefaultFunctions: IZFunctionsList;
202  procedure SetDefaultFunctions(Value: IZFunctionsList);
203  function GetAutoVariables: Boolean;
204  procedure SetAutoVariables(Value: Boolean);
205  public
206  constructor Create;
207  constructor CreateWithExpression(const Expression: string);
208  destructor Destroy; override;
209 
210  function Evaluate: TZVariant;
211  function Evaluate2(Variables: IZVariablesList): TZVariant;
212  function Evaluate3(Variables: IZVariablesList;
213  Functions: IZFunctionsList): TZVariant;
214  function Evaluate4(Variables: IZVariablesList;
215  Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
216 
217  procedure CreateVariables(Variables: IZVariablesList);
218  procedure Clear;
219 
220  property Expression: string read GetExpression write SetExpression;
221  property VariantManager: IZVariantManager read GetVariantManager
222  write SetVariantManager;
223  property DefaultVariables: IZVariablesList read GetDefaultVariables
224  write SetDefaultVariables;
225  property DefaultFunctions: IZFunctionsList read GetDefaultFunctions
226  write SetDefaultFunctions;
227  property AutoVariables: Boolean read GetAutoVariables
228  write SetAutoVariables;
229  end;
230 
231 implementation
232 
233 uses
234  ZMessages, ZExprToken, ZVariables, ZFunctions, ZMatchPattern;
235 
236 { TZExecutionStack }
237 
238 {**
239  Creates this object.
240 }
241 constructor TZExecutionStack.Create;
242 begin
243  FCapacity := 100;
244  SetLength(FValues, FCapacity);
245  FCount := 0;
246 end;
247 
248 {**
249  Gets a value from absolute position in the stack.
250  @param Index a value index.
251  @returns a variant value from requested position.
252 }
253 function TZExecutionStack.GetValue(Index: Integer): TZVariant;
254 begin
255  Result := FValues[Index];
256 end;
257 
258 {**
259  Gets a value from the top of the stack without removing it.
260  @returns a value from the top.
261 }
262 function TZExecutionStack.Peek: TZVariant;
263 begin
264  if FCount > 0 then
265  Result := FValues[FCount - 1]
266  else Result := NullVariant;
267 end;
268 
269 {**
270  Gets a function parameter by index.
271  @param a function parameter index. O is used for parameter count.
272  @returns a parameter value.
273 }
274 function TZExecutionStack.GetParameter(Index: Integer): TZVariant;
275 begin
276  if FCount <= Index then
277  raise TZExpressionError.Create(SStackIsEmpty);
278  Result := FValues[FCount - Index - 1];
279 end;
280 
281 procedure TZExecutionStack.DecStackPointer(const Value : integer);
282 begin
283  Dec(FCount, Value);
284  if FCount < 0 then
285  begin
286  FCount := 0;
287  raise TZExpressionError.Create(SStackIsEmpty);
288  end;
289 end;
290 
291 {**
292  Gets a value from the top and removes it from the stack.
293  @returns a value from the top.
294 }
295 function TZExecutionStack.Pop: TZVariant;
296 begin
297  Result := NullVariant;
298  if FCount <= 0 then
299  raise TZExpressionError.Create(SStackIsEmpty);
300  Dec(FCount);
301  Result := FValues[FCount];
302 end;
303 
304 {**
305  Puts a value to the top of the stack.
306 }
307 procedure TZExecutionStack.Push(Value: TZVariant);
308 begin
309  if FCapacity = FCount then
310  begin
311  Inc(FCapacity, 64);
312  SetLength(FValues, FCapacity);
313  end;
314  DefVarManager.Assign(Value, FValues[FCount]);
315  Inc(FCount);
316 end;
317 
318 {**
319  Swaps two values on the top of the stack.
320 }
321 procedure TZExecutionStack.Swap;
322 var
323  Temp: TZVariant;
324 begin
325  if FCount <= 1 then
326  raise TZExpressionError.Create(SStackIsEmpty);
327 
328  Temp := FValues[FCount - 1];
329  FValues[FCount - 1] := FValues[FCount - 2];
330  FValues[FCount - 2] := Temp;
331 end;
332 
333 {**
334  Clears this stack.
335 }
336 procedure TZExecutionStack.Clear;
337 begin
338  FCount := 0;
339 end;
340 
341 { TZExpression }
342 
343 {**
344  Creates this expression calculator object.
345 }
346 constructor TZExpression.Create;
347 begin
348  FTokenizer := TZExpressionTokenizer.Create;
349  FDefaultVariables := TZVariablesList.Create;
350  FDefaultFunctions := TZDefaultFunctionsList.Create;
351  FVariantManager := TZSoftVariantManager.Create;
352  FParser := TZExpressionParser.Create(FTokenizer);
353  FAutoVariables := True;
354 end;
355 
356 {**
357  Creates this expression calculator and assignes expression string.
358  @param Expression an expression string.
359 }
360 constructor TZExpression.CreateWithExpression(const Expression: string);
361 begin
362  Create;
363  SetExpression(Expression);
364 end;
365 
366 {**
367  Destroys this object and cleanups the memory.
368 }
369 destructor TZExpression.Destroy;
370 begin
371  FTokenizer := nil;
372  FDefaultVariables := nil;
373  FDefaultFunctions := nil;
374  FVariantManager := nil;
375  FParser.Free;
376 
377  inherited Destroy;
378 end;
379 
380 {**
381  Gets the current auto variables create flag.
382  @returns the auto variables create flag.
383 }
384 function TZExpression.GetAutoVariables: Boolean;
385 begin
386  Result := FAutoVariables;
387 end;
388 
389 {**
390  Sets a new auto variables create flag.
391  @param value a new auto variables create flag.
392 }
393 procedure TZExpression.SetAutoVariables(Value: Boolean);
394 begin
395  FAutoVariables := Value;
396 end;
397 
398 {**
399  Gets a list of default functions.
400  @returns a list of default functions.
401 }
402 function TZExpression.GetDefaultFunctions: IZFunctionsList;
403 begin
404  Result := FDefaultFunctions;
405 end;
406 
407 {**
408  Sets a new list of functions.
409  @param Value a new list of functions.
410 }
411 procedure TZExpression.SetDefaultFunctions(Value: IZFunctionsList);
412 begin
413  FDefaultFunctions := Value;
414 end;
415 
416 {**
417  Gets a list of default variables.
418  @returns a list of default variables.
419 }
420 function TZExpression.GetDefaultVariables: IZVariablesList;
421 begin
422  Result := FDefaultVariables;
423 end;
424 
425 {**
426  Sets a new list of variables.
427  @param Value a new list of variables.
428 }
429 procedure TZExpression.SetDefaultVariables(Value: IZVariablesList);
430 begin
431  FDefaultVariables := Value;
432 end;
433 
434 {**
435  Gets the current set expression string.
436  @returns the current expression string.
437 }
438 function TZExpression.GetExpression: string;
439 begin
440  Result := FParser.Expression;
441 end;
442 
443 {**
444  Sets a new expression string.
445  @param Value a new expression string.
446 }
447 procedure TZExpression.SetExpression(const Value: string);
448 begin
449  FParser.Expression := Value;
450  if FAutoVariables then
451  CreateVariables(FDefaultVariables);
452 end;
453 
454 {**
455  Gets a reference to the current variant manager.
456  @returns a reference to the current variant manager.
457 }
458 function TZExpression.GetVariantManager: IZVariantManager;
459 begin
460  Result := FVariantManager;
461 end;
462 
463 {**
464  Sets a new variant manager.
465  @param Value a new variant manager.
466 }
467 procedure TZExpression.SetVariantManager(Value: IZVariantManager);
468 begin
469  FVariantManager := Value;
470 end;
471 
472 {**
473  Gets the current expression tokenizer.
474  @returns the current expression tokenizer.
475 }
476 function TZExpression.GetTokenizer: IZTokenizer;
477 begin
478  Result := FTokenizer;
479 end;
480 
481 {**
482  Sets a new expression tokenizer.
483  @param Value a new expression tokenizer.
484 }
485 procedure TZExpression.SetTokenizer(Value: IZTokenizer);
486 begin
487  FTokenizer := Value;
488  FParser.Tokenizer := Value;
489 end;
490 
491 {**
492  Clears this class from all data.
493 }
494 procedure TZExpression.Clear;
495 begin
496  FParser.Clear;
497  FDefaultVariables.Clear;
498 end;
499 
500 {**
501  Creates an empty variables.
502  @param Variables a list of variables.
503 }
504 procedure TZExpression.CreateVariables(Variables: IZVariablesList);
505 var
506  I: Integer;
507  Name: string;
508 begin
509  for I := 0 to FParser.Variables.Count - 1 do
510  begin
511  Name := FParser.Variables[I];
512  if Variables.FindByName(Name) < 0 then
513  Variables.Add(Name, NullVariant);
514  end;
515 end;
516 
517 {**
518  Evaluates this expression.
519  @returns an evaluated expression value.
520 }
521 function TZExpression.Evaluate: TZVariant;
522 begin
523  Result := Evaluate3(FDefaultVariables, FDefaultFunctions);
524 end;
525 
526 {**
527  Evaluates this expression.
528  @param Variables a list of variables.
529  @returns an evaluated expression value.
530 }
531 function TZExpression.Evaluate2(Variables: IZVariablesList): TZVariant;
532 begin
533  Result := Evaluate3(Variables, FDefaultFunctions);
534 end;
535 
536 {**
537  Evaluates this expression.
538  @param Variables a list of variables.
539  @param Functions a list of functions.
540  @returns an evaluated expression value.
541 }
542 function TZExpression.Evaluate3(Variables: IZVariablesList;
543  Functions: IZFunctionsList): TZVariant;
544 var
545  Stack: TZExecutionStack;
546 begin
547  Stack := TZExecutionStack.Create;
548  try
549  Result := Evaluate4(Variables, Functions, Stack);
550  finally
551  Stack.Free;
552  end;
553 end;
554 
555 {**
556  Evaluates this expression.
557  @param Variables a list of variables.
558  @param Functions a list of functions.
559  @param Stack an execution stack.
560  @returns an evaluated expression value.
561 }
562 function TZExpression.Evaluate4(Variables: IZVariablesList;
563  Functions: IZFunctionsList; Stack: TZExecutionStack): TZVariant;
564 var
565  I, Index, ParamsCount: Integer;
566  Current: TZExpressionToken;
567  Value1, Value2: TZVariant;
568 begin
569  Stack.Clear;
570 
571  for I := 0 to FParser.ResultTokens.Count - 1 do
572  begin
573  Current := TZExpressionToken(FParser.ResultTokens[I]);
574  case Current.TokenType of
575  ttConstant:
576  Stack.Push(Current.Value);
577 { ttVariable:
578  begin
579  Index := Variables.FindByName(DefVarManager.GetAsString(Current.Value));
580  if Index < 0 then
581  begin
582  raise TZExpressionError.Create(
583  Format(SVariableWasNotFound, [DefVarManager.GetAsString(Current.Value)]));
584  end;
585  Value1 := Variables.Values[Index];
586  Stack.Push(Value1)
587  end;
588 } ttVariable:
589  begin
590  if Current.Value.VType = vtString then
591  begin
592  Index := Variables.FindByName(Current.Value.VString);
593  if Index < 0 then
594  begin
595  raise TZExpressionError.Create(
596  Format(SVariableWasNotFound, [Current.Value.VString]));
597  end;
598  Current.Value := EncodeInteger(Index);
599  end;
600  if Current.Value.VType = vtInteger then
601  Stack.Push(Variables.Values[Current.Value.VInteger])
602  else
603  raise TZExpressionError.Create(
604  Format(SSyntaxErrorNear, [SoftVarManager.GetAsString(Current.Value)]));
605  end;
606 { ttFunction:
607  begin
608  Index := Functions.FindByName(DefVarManager.GetAsString(Current.Value));
609  if Index < 0 then
610  begin
611  raise TZExpressionError.Create(
612  Format(SFunctionWasNotFound, [DefVarManager.GetAsString(Current.Value)]));
613  end;
614  Value1 := Functions.Functions[Index].Execute(Stack, FVariantManager);
615  ParamsCount := DefVarManager.GetAsInteger(Stack.Pop);
616  while ParamsCount > 0 do
617  begin
618  Stack.Pop;
619  Dec(ParamsCount);
620  end;
621  Stack.Push(Value1);
622  end;
623 } ttFunction:
624  begin
625  if Current.Value.VType = vtString then
626  begin
627  Index := Functions.FindByName(Current.Value.VString);
628  if Index < 0 then
629  begin
630  raise TZExpressionError.Create(
631  Format(SFunctionWasNotFound, [Current.Value.VString]));
632  end;
633  Current.Value := EncodeInterface(Functions.Functions[Index]);
634  end;
635  if Current.Value.VType = vtInterface then
636  begin
637  Value1 := IZFunction(Current.Value.VInterface).Execute(Stack, FVariantManager);
638  ParamsCount := DefVarManager.GetAsInteger(Stack.Pop);
639  Stack.DecStackPointer(ParamsCount);
640  Stack.Push(Value1);
641  end
642  else
643  raise TZExpressionError.Create(
644  Format(SSyntaxErrorNear, [SoftVarManager.GetAsString(Current.Value)]));
645  end;
646  ttAnd:
647  begin
648  Value2 := Stack.Pop;
649  Value1 := Stack.Pop;
650  Stack.Push(FVariantManager.OpAnd(Value1, Value2));
651  end;
652  ttOr:
653  begin
654  Value2 := Stack.Pop;
655  Value1 := Stack.Pop;
656  Stack.Push(FVariantManager.OpOr(Value1, Value2));
657  end;
658  ttXor:
659  begin
660  Value2 := Stack.Pop;
661  Value1 := Stack.Pop;
662  Stack.Push(FVariantManager.OpXor(Value1, Value2));
663  end;
664  ttNot:
665  Stack.Push(FVariantManager.OpNot(Stack.Pop));
666  ttPlus:
667  begin
668  Value2 := Stack.Pop;
669  Value1 := Stack.Pop;
670  Stack.Push(FVariantManager.OpAdd(Value1, Value2));
671  end;
672  ttMinus:
673  begin
674  Value2 := Stack.Pop;
675  Value1 := Stack.Pop;
676  Stack.Push(FVariantManager.OpSub(Value1, Value2));
677  end;
678  ttStar:
679  begin
680  Value2 := Stack.Pop;
681  Value1 := Stack.Pop;
682  Stack.Push(FVariantManager.OpMul(Value1, Value2));
683  end;
684  ttSlash:
685  begin
686  Value2 := Stack.Pop;
687  Value1 := Stack.Pop;
688  Stack.Push(FVariantManager.OpDiv(Value1, Value2));
689  end;
690  ttProcent:
691  begin
692  Value2 := Stack.Pop;
693  Value1 := Stack.Pop;
694  Stack.Push(FVariantManager.OpMod(Value1, Value2));
695  end;
696  ttEqual:
697  begin
698  Value2 := Stack.Pop;
699  Value1 := Stack.Pop;
700  Stack.Push(FVariantManager.OpEqual(Value1, Value2));
701  end;
702  ttNotEqual:
703  begin
704  Value2 := Stack.Pop;
705  Value1 := Stack.Pop;
706  Stack.Push(FVariantManager.OpNotEqual(Value1, Value2));
707  end;
708  ttMore:
709  begin
710  Value2 := Stack.Pop;
711  Value1 := Stack.Pop;
712  Stack.Push(FVariantManager.OpMore(Value1, Value2));
713  end;
714  ttLess:
715  begin
716  Value2 := Stack.Pop;
717  Value1 := Stack.Pop;
718  Stack.Push(FVariantManager.OpLess(Value1, Value2));
719  end;
720  ttEqualMore:
721  begin
722  Value2 := Stack.Pop;
723  Value1 := Stack.Pop;
724  Stack.Push(FVariantManager.OpMoreEqual(Value1, Value2));
725  end;
726  ttEqualLess:
727  begin
728  Value2 := Stack.Pop;
729  Value1 := Stack.Pop;
730  Stack.Push(FVariantManager.OpLessEqual(Value1, Value2));
731  end;
732  ttPower:
733  begin
734  Value2 := Stack.Pop;
735  Value1 := Stack.Pop;
736  Stack.Push(FVariantManager.OpPow(Value1, Value2));
737  end;
738  ttUnary:
739  Stack.Push(FVariantManager.OpNegative(Stack.Pop));
740  ttLike:
741  begin
742  Value2 := Stack.Pop;
743  Value1 := Stack.Pop;
744  Stack.Push(EncodeBoolean(
745  IsMatch(FVariantManager.GetAsString(Value2),
746  FVariantManager.GetAsString(Value1))));
747  end;
748  ttNotLike:
749  begin
750  Value2 := Stack.Pop;
751  Value1 := Stack.Pop;
752  Stack.Push(EncodeBoolean(
753  not IsMatch(FVariantManager.GetAsString(Value2),
754  FVariantManager.GetAsString(Value1))));
755  end;
756  ttIsNull:
757  begin
758  Value1 := Stack.Pop;
759  Stack.Push(EncodeBoolean(FVariantManager.IsNull(Value1)));
760  end;
761  ttIsNotNull:
762  begin
763  Value1 := Stack.Pop;
764  Stack.Push(EncodeBoolean(not FVariantManager.IsNull(Value1)));
765  end;
766  else
767  raise TZExpressionError.Create(SInternalError);
768  end;
769  end;
770 
771  if Stack.Count <> 1 then
772  raise TZExpressionError.Create(SInternalError);
773  Result := Stack.Pop;
774 end;
775 
776 end.