PML2
Training Notes
What’s New in PML2 Objects and Object methods Form names are now preceded with !! i.e.
setup form _fred
followed by : setup form !!fred results in an error because !!fred was already defined in the previous assignment Forms are now loaded dynamically return error noalert allows an error to be returned without any messages
What to avoid in PML2 Commands with dollars in $m $m+ $W25 Numbered variables $v1120 The var command var !x name var !x read Synonyms Global variables
What to avoid in forms and menus Dots in gadget names selector gadgets Userdata Pixmap views
Alert gadgets Radiogroups Simple Textin gadgets Numbers at the beginning of gadget names Waiton to show forms Do list/pane/sel
What’s not changed in PML2 In theory, all old PML should work in PDMS11.1. Very little of the old appware has been converted because this would be a waste of resources. Cadcentre policy on converting appware to use new facilities is to only upgrade appware when modifications are being made in that area. The only exception to this, is where new facilities in core code supersede or improve functionality and it is necessary to write new code to use the extra functionality.
New Environment Variables PMLLIB
/DIRECTORYNAME
This is a directory which is searched when the system looks for functions and forms
PMLTRACE
ON/OFF
When set to ON, PMLTRACE will display a trace of all macros called in the unix command shell. This can also be switched on or off on the command line, so it is probably better to set the variable to off and use commands to control trace as before. The command in PDMS is PML TRACE ON/OFF PMLCOMPILE ON/OFF Environment variable PMLDEBUG ON will write a trace file
Available variable types
2
$v1 !a
old style not recommended Named variables both global and local !!global !local
NOTE: !a is evaluated as text automatically by using $!A (early evaluation) Named variables are now typed variables as one of the following STRING REAL
‘Text in quotes or vertical bars up to a Max of 254? char’ Any number
BOOLEAN ARRAY
TRUE,FALSE These are not text i.e. ‘TRUE’,’FALSE’ Any type including arrays of arrays of anything
OBJECTS
A collection of different variables under a user defined type
Variables can be predefined as a particular type or revert to type when they are set There are two ways of setting variables Var !a (25)
!a is a string
!a = 25
!a is a real
!a = ‘xyz’
!a is a string
!a[1] = 75
!a[1] is a real element of array !a Note: other elements in the same array can be of any type
!a = TRUE
!a is BOOLEAN
Beware Pre version 11 the var command was used to set all variables and it produced a string. Now we don’t use var apart from collections. Variables may also be created before they are used using Methods !!Answer = real() !textline = String() !test = boolean() !squares = array() All of the above have the value ‘unset’
3
There are various ways of testing whether a variable exists or is set: If(undefined(!x))then If(defined(!x))then If(unset(!x))then If(!x.unset())then If(set(!x))then If(!x.set())then To make a variable undefined i.e. empty it. !x.delete() var !x delete
Arrays arrays may be sparse i.e. you can set in index order Negative subscripts are not permitted A subscript of zero can be used but is not advised do loop from and to variables can now include expressions and even functions
Array methods !arraysize = !arraything.size()
Replaces var !arraysisze (arraysize(!arraything))
Sets the variable arraysize to the number of elements in the array !testarray.clear()
Deletes all elements from !testarray
!test.removefrom(5, 20)
Removes 20 elements from element number 5
!new = !test.removefrom(5,20)
Removes 20 elements as above and creates a new array with the 20 elements inside.
!myarray.append(!newdata)
acts like var !array append ‘fhjffj’
!myarray.[27].delete()
Deletes element 27 of the array the array still exists 4
!myarray.delete()
Deletes the array entirely
!line = ‘ this is a line of text with some funny spaces ‘ !line = !line.trim(‘lrm’) trims the spaces from the variable called !line !line = ‘ this is a line of text with some funny spaces ‘ !lines = !line.split(!line) Splits the string !line into an array of strings called !lines. Note: we could not use the same variable name because it is a different type !a = !lines.size() !a = !lines.width()
gives the number of elements in the array gives the number of characters in the longest word of the array
No result methods. !lines.sort() !lines.invert()
sorts the array !lines and returns the array in its sorted form inverts the array order first to last etc. These methods work only on the original array. Attempts to set another array results in an error.
i.e. !new = !lines.sort() Gives an error The old method. !ind = !lines.sortedindices() Produces a sorted index without changing the original array. This can be used to sort parallel arrays in the same way as before. !lines = !lines.relindex(!ind)
Reorders an array according to the order of array !ind If applied to the original array, it would have the same effect as a simple sort, its use is to sort parallel arrays.
The Current Element variable
5
There is one global variable which is always set by the system to be the element you are positioned at in the database this is called !!CE. !!CE is an object of type DBREF. Its attributes are described as members of the object. e.g. !tem = !!ce 1 q var !tem
$* creates a variable which is a copy of !!ce $* Queries the attributes of the DBREF pointed to by !item
=8196/8 NAME > <STRING> ‘DA/2000’ TYPE > <STRING> ‘SITE’ LOCK > FALSE OWNER > =8196/0 DESC > <STRING> ‘MAIN REACTOR AREA’ FUNC > <STRING> ‘’ PURP > <STRING> ‘’ NUMB > 0 AREA > 0 POS > E 0mm N 0mm U 0mm WRT /* ORI > Y is N AND Z is U WRT /* MODU > <STRING> ‘’ ORRF > Unset STMF > Unset :MATERIAL > <STRING> ‘Carbon Steel’ q var !item /DA/2000
$* gives $* without all of the other stuff
!item
$* as a command, does nothing
$!item
$* navigates to /DA/2000
Querying attributes q var !item.pos
$* gives
6
E 0mm N 0mm U 0mm WRT /* ORIGIN =8196/0 UP 0 EAST 0 NORTH 0 q var !item.e 0
$*query the east position
q var !item.pos.origin q var !item.pos.origin.lock
$* gives all of the attributes of =8196/0 $* gives the lock of =8196/0
q var !item.pos.wrt(=8196/32)
$* uses the method WRT(DBREF) to extract a $*position relative to some other database $*reference
METHODS/FUNCTIONS Different data types in pml have associated built in ‘methods’ which may be used to convert or read data in a particular way. Some methods are similar to the built in functions pre version 11.1 as in the example below: !NCHARS = !MYSTRING.LENGTH()
$* THIS IS A METHOD
!NCHARS = LENGTH(!MYSTRING)
$* THIS IS A FUNCTION CALL
The pre version 11.1 syntax for the function call would have been as follows: VAR !NCHARS LENGTH(|$!MYSTRING|)
$* THIS IS A 10.5 FUNCTION CALL
The difference between the 10.5 example and the 11.1 example is that version 11 now returns a typed variable (REAL) where version 10.5 would have returned a string. Methods are built in for various data types and are listed in appendix A of the Customisation guide.
7
Block evaluation of arrays Block evaluation is a method of stepping through each element of an array and performing some action. In effect, it is like a single command do loop. To perform block evaluation, there are two stages: First you need to define the expression which will operate on the array elements Second, you need to apply the expression to an array The expression is stored in a variable and is defined as follows: !EXPRESSIONVAR = OBJECT BLOCK (‘!!ARRAYNAME[!EVALINDEX] * 2’) the !!arrayname[!evalindex] bit is effectively the name of the variable being operated on by the expression. In the example above, the result would be to multiply all of the numbers in the input array by 2. The variable !evalindex is a special variable used in block evaluation. Any other variable name will not work! To apply the expression is as follows: !!newarray = !!arrayname.evaluate(!expressionvar) This creates an array called !!newarray containing the numbers of the original array multiplied by 2. The original array can also be modified using this method: !!arrayname = !!arrayname.evaluate(!expressionvar) Here are some simple examples !text = 'this is a line of text' !myarray = !text.split() This creates an array called !!myarray with six elements !myarray[1] = ‘this’ !myarray[2] = ‘is’ !myarray[3] = ‘a’ !myarray[4] = ‘line’
8
!myarray[5] = ‘of’ !myarray[6] = ‘text’ Now we can define some blocks !extractchar1 = object block ('subs(!myarray[!evalindex],1,1)') !new = !myarray.evaluate(!extractchar1) This extracts the first character of each word into and array called !new giving the following: !new[1] = ‘t’ !new[2] = ‘i’ !new[3] = ‘a’ !new[4] = ‘l’ !new[5] = ‘o’ !new[6] = ‘t’ !extractchar1 = object block ('upcase(subs(!myarray[!evalindex],1,1))') !new = ! myarray.evaluate(!!extractchar1) This does the same as before, but also changes the letters to upper case !new[1] = ‘T’ !new[2] = ‘I’ !new[3] = ‘A’ !new[4] = ‘L’ !new[5] = ‘O’ !new[6] = ‘T’ !extractchar1 = object block ('upcase(subs(!myarray[!evalindex],1,1)) & |fred|') !new = !myarray.evaluate(!extractchar1) This does as before, but uses the & character to append the string fred to the result !new[1] = ‘Tfred’ !new[2] = ‘Ifred’ !new[3] = ‘Afred’ !new[4] = ‘Lfred’
9
!new[5] = ‘Ofred’ !new[6] = ‘Tfred’ !extractchar1 = object block ('!!testfunc(!myarray[!evalindex])') !myarray.evaluate(!extractchar1) This example passes the evaluation into a function called !!testfunc, resulting in the function being run on each element of the array. More on functions later!
10
Objects define object COMPONENT member .detail is string member .material is string member .bore is real member .position is position endobject To use this object !x = object COMPONENT() !x.detail = !!ce.dtxr !x.material = !!ce.mtxx !x.bore = !!ce.pbor1 !.pos = !ce.pos
External Functions The new environment variable PMLLIB points to an area where both forms and functions(macros) can be dynamically loaded according to name. PML functions are macros which may or may not return a value. They must be named with a suffix of “.pmlfrm” , “pmlobj” & “pmlfnc” and they are called as follows: Officially: call !!functionname() Unofficially: !!functionname() e.g a function definition define function !!dir_to_next(!comp is dbref) $!comp go to component passed dir to next next if (!!ce.type eq ‘ELBO’)then 11
back dir to next endif next forw return
To run this function on the current element, type: !!dir_to_next or call !!dir_to_next This would result in the system searching for a file called “dir_to_next.pmlfnc” and if found, running it as a macro. To get all of the text of the selected elements in a list would require a simple function as follows: Function to get all selected text items in a list gadget Pass the name of the list gadget is the input parameter define function !!textlist(!input is gadget)is array !selected = !input.val !expression = object block(‘!input.rtext[!selected[!evalindex]]’) !x = !selected.evaluate(!expression) return !x endfunction to run this !!text = !!textlist(!!myform.members)
Alert Views Alert views are slightly different to pre version 11. They are treated as functions and called in the same way
12
!!Alert.Error(‘This is an error message’) !!Alert.warning(‘This is a warning message’) !!Alert.Message(‘This is a message’) !answer = !!Alert.confirm(‘Do you want to savework’) This returns ‘YES’ or ‘NO’ !answer = !!alert.question(‘ok to delete world’) This returns ‘YES’ ‘NO’ or ‘CANCEL’
Forms and Menus setup form !!myform Paragraph .message text ‘Press goodbye button to close’ button .goodbye ok exit !!myform.show() by convention, all form definition macros have the extension .frm to load the form type $m/myform.frm In the above example the button has no display text. In fact the display text is taken from the name and made upper case. The method !!myform.show() is the equivalent of show _myform Querying the form q var !!myform would give something like the following:
13