Difference between revisions of "Parsed Expressions"

(19 intermediate revisions by 2 users not shown)
Line 1: Line 1:
''New to Analytica 4.3''
+
[[Category:Expressions]]
 +
[[Category:Data Type Functions]]
  
When you enter a valid expression into the definition of an object, Analytica parses the expression and stored a parsed representation of the expression in an attributed named '''FixedDef'''.  Analytica internally utilizes these parsed expressions elsewhere also, such as in '''FixedCheck'''.
 
  
Users and modelers almost never need to, or should want to, utilize Analytica's internal parsed representations directly.  However, it is conceivable that in some very rare cases, very advanced users might want to accessed these parsed representations for certain types of [[Meta-Inference]] Algorithms.  The parse-tree uses special internal data structures, so access to the internals of a parse tree require the use of special built-in functions, namely:
+
__TOC__
  
* [[#TypeOf(expr)|TypeOf]]
+
When you enter a valid expression into the definition of an object, Analytica parses the expression and stores a parsed representation of the expression in an attributed named '''FixedDef'''. Analytica internally utilizes these parsed expressions elsewhere also, such as in '''FixedCheck'''.
* [[#ParsedExprFunction(expr)|ParsedExprFunction]]
 
* [[#ParsedExprLength(expr)|ParsedExprLength]]
 
* [[##ParsedExprParameter.28expr.2Cparam.29|ParsedExprParameter]]
 
* [[IsNotSpecified]]
 
  
== [[TypeOf]](expr) ==
+
Users and modelers almost never need to, or should want to, utilize Analytica's internal parsed representations directly.  However, it is conceivable that in some very rare cases, very advanced users might want to accessed these parsed representations for certain types of [[Meta-Inference]] Algorithms.  The parse-tree uses special internal data structures, so access to the internals of a parse tree require the use of special built-in functions, namely [[#TypeOf(expr)|TypeOf]], [[#ParsedExprFunction(expr)|ParsedExprFunction]] and  [[##ParsedExprParameters.28expr.29|ParsedExprParameters]].
  
The general function of the [[TypeOf]] function is described at [[TypeOf]].  Here I discuss its application only as relevant to parsed expressions.
+
== TypeOf(expr) ==
 +
 
 +
The general function of the [[TypeOf]] function is described at [[TypeOf]].  Here we discuss its application only as relevant to parsed expressions.
  
 
The representation of a parsed expression may be one of several types:
 
The representation of a parsed expression may be one of several types:
Line 19: Line 17:
 
* A literal text
 
* A literal text
 
* An identifier (which will be a [[handle]] to the object in the parsed expression)
 
* An identifier (which will be a [[handle]] to the object in the parsed expression)
* A literal list, such as <code>[1,2,3]</code>
+
* A literal list, such as <code>[1, 2, 3]</code>
* An operator, such as <code>X+Y</code>, or <code>X<Y</code>.
+
* An operator, such as <code>X + Y</code>, or <code>X < Y</code>.
 
* A function call
 
* A function call
  
 
The [[TypeOf]] function tells you the type of the parsed expression.  Note that the parameter is evaluated, so you can compute the parsed expression.  Normally in the case discussed here, the parameter will be something like
 
The [[TypeOf]] function tells you the type of the parsed expression.  Note that the parameter is evaluated, so you can compute the parsed expression.  Normally in the case discussed here, the parameter will be something like
[[TypeOf]](fixedDef of X)
+
:<code>TypeOf(fixedDef of X)</code>
  
 
[[TypeOf]] returns a textual name of the type -- for a parsed expression, you may see: "Number", "Integer", "FixedPointReal", "Text", "Handle", "Expression", or "FunctionCall".
 
[[TypeOf]] returns a textual name of the type -- for a parsed expression, you may see: "Number", "Integer", "FixedPointReal", "Text", "Handle", "Expression", or "FunctionCall".
  
Detecting the case in which the parsed expression contains a literal list, such as <code>[1,2,3]</code>, is tricky, because [[TypeOf]] will array abstract over the elements and give you a list of the types of the elements.  To detect a list, you need to use the following expression:
+
Detecting the case in which the parsed expression contains a literal list, such as <code>[1, 2, 3]</code>, is tricky, because [[TypeOf]] will array abstract over the elements and give you a list of the types of the elements.  To detect a list at the top level of a parse tree, use:
[[ParsedExprLength]](expr)<>[[Null]] [[And]] [[ParsedExprFunction]](expr)==[[Null]]
+
 
 +
:<code>Size(IndexesOf(expr)) = 1 and Slice(IndexesOf(expr), 1) = Null</code>
 +
 
 +
Once you are recursing down the parse tree, detecting a literal list becomes less tricky since [[ParsedExprParameters]] will return a reference to an indexed list, so for sub-trees, you can simply test for [[IsReference]](expr).
  
 
== ParsedExprFunction(expr) ==
 
== ParsedExprFunction(expr) ==
 
 
Once you've determined that your parsed expression is either a "FunctionCall" or "Expression" (aka operation), you may then want to determine which function is called, or which operation is performed.
 
Once you've determined that your parsed expression is either a "FunctionCall" or "Expression" (aka operation), you may then want to determine which function is called, or which operation is performed.
  
In the case of a function call, ''ParsedExprFunction''(expr) returns the handle to the function object.  Note that «expr» is evaluated, so the parsed expression needs to be the result of evaluating «expr».  Suppose we have the following variable defined in our model:
+
In the case of a function call, [[ParsedExprFunction]](expr) returns the [[handle]] to the function object.  Note that «expr» is evaluated, so the parsed expression needs to be the result of evaluating «expr».  Suppose we have the following variable defined in our model:
 
+
:<code>Variable The_Npv := Npv(8%, Cash_flow, Time)</code>
Variable The_Npv := [[Npv]](8%,Cash_flow,Time)
 
  
 
Then:
 
Then:
 
+
:<code>ParsedExprFunction(fixedDef of The_Npv) &rarr; Npv      { A handle to the Npv function object }</code>
ParsedExprFunction(fixedDef of The_Npv) &rarr; [[Npv]]     { A handle to the [[Npv]] function object }
 
  
 
You could test whether [[Npv]] is being called using:
 
You could test whether [[Npv]] is being called using:
 +
:<code>ParsedExprFunction'''(fixedDef of The_Npv) = Handle(Npv)  &rarr; 1</code>
  
'''ParsedExprFunction'''(fixedDef of The_Npv) = [[Handle]](Npv)  &rarr; 1
+
== ParsedExprParameters(expr) ==
 
+
When «expr» contains a parsed function call or parsed operator expression, this returns the parsed parameters to the function call or operator as a 1-D arrayThe result is indexed by a local index with the name .Parameter, containing function parameter names (in the case of a function) or numbers (in the case of an operator).
 
 
== ParsedExprLength(expr) ==
 
 
 
Once you've determined that the parsed expression is either a "FunctionCall" or "Expression" (aka operation), then you may want to know how many parameters that function or operation can have (particularly if you plan to scan the parameters by position in a generic fashion).  Function [[ParsedExprLength]](expr) returns the largest parameter number for the function or operator in «expr».   
 
 
 
When «expr» is a function call to a function containing optional parameters, the length may be more than the number of parameters actually specified. It may be less than the total number of parameters actually accepted by a function if the final parameters are not specified, but it will be greater than or equal to the position of the largest parameter number specified.  For example:
 
 
 
Function F(x,y ; a,b,c,d : optional)
 
Variable V := F(5,6,c:7)
 
&nbsp;
 
ParsedExprLength(fixedDef of V) &rarr; 5
 
 
 
In the above example, only three parameters are specified, but the last parameter, «c» was the 5th parameter of F, so internally the parse tree contains slots for five parameters.  The function actually accepts up to 6 parameters.  Analytica's parser may or may not leave extra room for these final parameters, depending a numerous internal factors.
 
 
 
When the function being called contains a repeated (ellipsis) parameter, the number returned by [[ParsedExprLength]] may be less than the number of parameters actually passed to the function.  A repeated parameter is counted as a single parameter by [[ParsedExprLength]], since it is declared as one parameter.  The corresponding parameter value will be returned as a list.  Example:
 
 
 
Function G(x:... Number)
 
Variable W := G(1,2,3,4,5)
 
&nbsp;
 
ParsedExprLength(fixedDef of W) &rarr; 1
 
 
 
In this example, the first parameter passed to G is the list [1,2,3,4,5].
 
 
 
When «expr» evaluates a literal list (such as <code>[1,2,3]</code>), '''ParsedExprLength'' returns the length of the list.
 
 
 
When «expr» is an expression (an operation), '''ParsedExprLength'' returns the number of parameters used by the operation.  For example, operations like +, -, /, *, &, <, =, >, <=, >=, <>, [[And]], and [[Or]] will report 2 parameters. Operations like [[If]], [[IfOnly]], [[IfAll]] report 3 parameters.  And operations like [[Using References|\\]], [[Using References|#]], [[Index Position Operator::@|@]] and unary - report 1.
 
 
 
Note also that «expr» is evaluated.
 
 
 
== ParsedExprParameter(expr,''param'') ==
 
  
When «expr» contains a parsed function call or parsed expression, you can access the individual parameters using Function ''ParsedExprParameter''.   
+
If an explicit list is passed to a parameter, or for any repeated parameter, a reference to an unindex list is returnedThis is to ensure that every parameter returned is atomic.
  
You specify which parameter you are interested in using the parameter «param», and can specify either a number (the position of the parameter in the function declaration) or the textual parameter name.  
+
The parameter «expr» is evaluated, so you are retrieving information on the parsed expression that is the result of evaluating «expr».  This means that in most cases, «expr» will be of the form <code>fixedDef of obj</code>.
  
When a literal list is passed as the value to a parameter, or when the parameter is a repeated (ellipsis) parameter, a handle to an unindexed list is returned.  The extra reference is introduced so that any value returned by this function is atomic, which makes it convenient to combine parameters.  Use the function [[IsReference]] to test for this case.
+
=== Examples: ===
 +
:<code>Function H(u, v: number; w: ...; x, y, z: optional)</code>
 +
:<code>Variable X1 := H(3, 2 + 2, 5, 6)</code>
 +
:<code>Variable X2 := H(z: [1, 2, 3], v: 2, w: 3, 4, u: 8)</code>
  
Examples:
+
:<code>ParsedExprParameters(fixedDef of X1) &rarr;</code>
 +
:{| class="wikitable"
 +
!  colspan=3|.Parameter &#9654;
 +
|-
 +
! u
 +
! v
 +
! w
 +
|-
 +
| 3
 +
| (2 + 2)
 +
| \[5, 6]
 +
|}
  
Function H(u,v : number ; w : ... ; x,y,z : optional)
+
:<code>ParsedExprParameters(fixedDef of X2) &rarr;</code>
Variable X1 := H(3,2+2,5,6)
+
:{| class="wikitable"
Variable X2 := H(z:1,v:2,w:3,4,u:8)
+
! colspan=4|.Parameter &#9660;
&nbsp;
+
|-
ParsedExprParameter(fixedDef of X1,1) &rarr; 3
+
! u  
ParsedExprParameter(fixedDef of X1,2) &rarr; (2+2)          { an expression, which is treated as atomic }
+
! v
ParsedExprParameter(fixedDef of X1,3) &rarr; \[5,6]          { The actual expression is a list, but a [[Using References|reference]] to a list is returned}
+
! w
ParsedExprParameter(fixedDef of X1,4) &rarr; [[Undefined]]  { Use [[IsNotSpecified]] to detect }
+
! z
ParsedExprParameter(fixedDef of X1,'u') &rarr; 3
+
|-
ParsedExprParameter(fixedDef of X2,1) &rarr; 8
+
|8
ParsedExprParameter(fixedDef of X2,6) &rarr; 1
+
|2
ParsedExprParameter(fixedDef of X2,'v') &rarr; 2
+
|\[3,4]
ParsedExprParameter(fixedDef of X2,'w') &rarr; \[3,4]
+
|\[1,2,3]
 +
|}
  
You may also omit the second parameter to [[ParsedExprParameter]], causing all parameters to be returned. The result is a 1-D array with a local index named .Parameter containing as its labels the names of each parameter, and containing as its cells the parsed value for each parameter.  Again, when a literal list is passed to a parameter, or a parameter is declared as repeated (ellipsis) a reference to the list is returned to ensure that the result is 1-D.
+
==History==
 +
Parsed expressions were introduced in Analytica 4.3.
  
Some optional parameters may not be specified in a particular function call.  Thus, you should use the function [[IsNotSpecified]](p) on each parameter returned by [[ParsedExprParameter]] to test for this.  The actual value returned for an omitted parameter is an internal valued called [[Undefined]], which as a user of Analytica you will normally not encounter.  This special value is distinct from the special value [[Null]], which could be returned when the literal [[Null|«null»]] is passed as the parameter of a function.
+
== See Also ==
 +
* [[Expressions]]
 +
* [[Expression Syntax]]
 +
* [[Expression Assist]]
 +
* [[The Expression popup menu]]
 +
* [[Expressions that don't array-abstract]]
 +
* [[TypeOf]]
 +
* [[Size]]
 +
* [[Using References]]
 +
* [[IsReference]]

Revision as of 00:17, 1 June 2016


When you enter a valid expression into the definition of an object, Analytica parses the expression and stores a parsed representation of the expression in an attributed named FixedDef. Analytica internally utilizes these parsed expressions elsewhere also, such as in FixedCheck.

Users and modelers almost never need to, or should want to, utilize Analytica's internal parsed representations directly. However, it is conceivable that in some very rare cases, very advanced users might want to accessed these parsed representations for certain types of Meta-Inference Algorithms. The parse-tree uses special internal data structures, so access to the internals of a parse tree require the use of special built-in functions, namely TypeOf, ParsedExprFunction and ParsedExprParameters.

TypeOf(expr)

The general function of the TypeOf function is described at TypeOf. Here we discuss its application only as relevant to parsed expressions.

The representation of a parsed expression may be one of several types:

  • A literal number
  • A literal text
  • An identifier (which will be a handle to the object in the parsed expression)
  • A literal list, such as [1, 2, 3]
  • An operator, such as X + Y, or X < Y.
  • A function call

The TypeOf function tells you the type of the parsed expression. Note that the parameter is evaluated, so you can compute the parsed expression. Normally in the case discussed here, the parameter will be something like

TypeOf(fixedDef of X)

TypeOf returns a textual name of the type -- for a parsed expression, you may see: "Number", "Integer", "FixedPointReal", "Text", "Handle", "Expression", or "FunctionCall".

Detecting the case in which the parsed expression contains a literal list, such as [1, 2, 3], is tricky, because TypeOf will array abstract over the elements and give you a list of the types of the elements. To detect a list at the top level of a parse tree, use:

Size(IndexesOf(expr)) = 1 and Slice(IndexesOf(expr), 1) = Null

Once you are recursing down the parse tree, detecting a literal list becomes less tricky since ParsedExprParameters will return a reference to an indexed list, so for sub-trees, you can simply test for IsReference(expr).

ParsedExprFunction(expr)

Once you've determined that your parsed expression is either a "FunctionCall" or "Expression" (aka operation), you may then want to determine which function is called, or which operation is performed.

In the case of a function call, ParsedExprFunction(expr) returns the handle to the function object. Note that «expr» is evaluated, so the parsed expression needs to be the result of evaluating «expr». Suppose we have the following variable defined in our model:

Variable The_Npv := Npv(8%, Cash_flow, Time)

Then:

ParsedExprFunction(fixedDef of The_Npv) → Npv { A handle to the Npv function object }

You could test whether Npv is being called using:

ParsedExprFunction(fixedDef of The_Npv) = Handle(Npv) → 1

ParsedExprParameters(expr)

When «expr» contains a parsed function call or parsed operator expression, this returns the parsed parameters to the function call or operator as a 1-D array. The result is indexed by a local index with the name .Parameter, containing function parameter names (in the case of a function) or numbers (in the case of an operator).

If an explicit list is passed to a parameter, or for any repeated parameter, a reference to an unindex list is returned. This is to ensure that every parameter returned is atomic.

The parameter «expr» is evaluated, so you are retrieving information on the parsed expression that is the result of evaluating «expr». This means that in most cases, «expr» will be of the form fixedDef of obj.

Examples:

Function H(u, v: number; w: ...; x, y, z: optional)
Variable X1 := H(3, 2 + 2, 5, 6)
Variable X2 := H(z: [1, 2, 3], v: 2, w: 3, 4, u: 8)
ParsedExprParameters(fixedDef of X1) →
.Parameter ▶
u v w
3 (2 + 2) \[5, 6]
ParsedExprParameters(fixedDef of X2) →
.Parameter ▼
u v w z
8 2 \[3,4] \[1,2,3]

History

Parsed expressions were introduced in Analytica 4.3.

See Also

Comments


You are not allowed to post comments.