Skill 语言用户手册---第一章--5、6节

本文由 shirdon 于 2014-6-17 9:19 发布在  Skill 语言中文版    

    第五节 流程控制

    这部分介绍:

    Relational Operators: <, <=, >, >=, ==, !=  关系运算符

    Logical Operators: !, &&, ||      逻辑运算符

    Branching: if, when, unless      条件(分支)运算符

    Multi-way Branching: case        多路分支运算符

    Iteration: for, foreach              循环(迭代)

    Iteration refers to repeatedly executing a collection of SKILL expressions by changing - usually incrementing or decrementing - the value of one or more loop variables.    

    循环涉及重复执行一个SKILL语句集---通过一个活多个递增或递减的循环变量。


    1.关系运算符

    Use the following operators to compare data values. SKILL generates an error if the data types are inappropriate. These operators all return t or nil.

    使用下面的操作符来比较数据值。如果数据类型不恰当,SKILL会生成一个错误。这些操作符都返回 t  或者 nil

    It is helpful to know the function name because error messages mention the function (greaterp below) instead of the operator ( > ).

    知道函数名是非常有用的,因为错误信息涉及函数名(greaterp )代替操作符(>)

1 > "abc" 
Message: *Error* greaterp: can't handle (1 > "abc")

    2.逻辑运算符

    SKILL considers nil as FALSE and any other value as TRUE. The and (&&) and or (||) operators only evaluate their second argument if they need to determine the return result.

    SKILL指定 nil 作为 FLASE ,其他值为 TRUE。 与(&&)和或(||)操作符如果需要确定返回结果,仅需评估其第二个参数。

 

        Sample Logical Operators

Operator

Arguments

Function

Example

Return Value

&&

general

and

3 && 5
5 && 3
t && nil
nil && t

5
3
nil
nil

||

general

or

3 || 5
5 || 3
t || nil
nil || t

3
5
t
t

    The && and || operators return the value last computed. Consequently, both && and || operators can be used to avoid cumbersome if or when expressions.

    与(&&)和或(||)操作符返回最后计算的值,所以与和或操作符可以用来避免繁琐的if 或者when表达式

    使用与(&&)

    When SKILL creates a variable, it gives the variable a value of unbound to indicate that the variable has not been initialized yet. Use the boundp function to determine whether a variable is bound. The boundp function

    当SKILL创建一个变量,它给变量一个自由的值来说明变量还没有被声明(初始化),使用boundp函数来确定变量是否是限定的(bound)。

    Returns t if the variable is bound to a value. 

    Returns nil if it is not bound to a value.

    Suppose you want to return the value of a variable trMessages. If trMessages is unbound, retrieving the value causes an error. Instead, use the expression

    假设您想返回变量trMessages 的值,如果trMessages 自由的(unbound,则获取值时将促使一个错误。用下面的表达式代替:

boundp( 'trMessages ) && trMessages 

    使用或(||)

    Suppose you have a default name, such as noName. Suppose you have a variable, such as userName. To use the default name if userName is nil, use the following expression

    假设您有一个默认的名字,例如 'noname',假设您有一个变量,例如 username,如果username为nil使用默认名,则使用下面的表达式

userName || "noName"


    3. IF函数

    Use the if function to selectively evaluate two groups of one or more expressions. The condition in an if expression evaluates to nil or non-nil. The return value of the if expression is the value last computed.

    使用IF函数选择性地评估两组中的一或多个表达式。一个if表达式中的条件判断为nil (假或 非nil(真)。if表达式的返回值为最后计算的值。

if( shapeType == "rect" 
      then 
            println( "Shape is a rectangle" ) 
            ++rectCount 
      else
            println( "Shape is not a rectangle" ) 
            ++miscCount 
      ) 

    SKILL does most of its error checking during execution. Error messages involving if expressions can be obscure. Be sure to

    SKILL在执行期间,做大部分的错误检查。错误信息表明if表达式可能是模糊的。确定:

    Be aware of the placement of the parentheses: if( ... then ... else ... ).注意圆括号的放置

    Avoid white space immediately after the if keyword. if关键字后避免空格  “if(”正确,“if (”错误

    Use then and else when appropriate to your logic.  使用 then 和 else 来符合您的逻辑

    Consider the error message when you accidentally put white space after the if keyword.如果if关键字后不小心输入空格将产生错误信息

shapeType = "rect" 
if ( shapeType == "rect" 
      then 
            println( "Shape is a rectangle" ) 
            ++rectCount 
      else 
            println( "Shape is not a rectangle" ) 
            ++miscCount 
      )

Message: *Error* if: too few arguments (at least 2 expected, 1 given)...     

    Consider the error message when you accidentally drop the then keyword, but include an else keyword, and the condition returns nil.

    如果您不小心丢掉 then 关键字但包含else关键字,将产生错误信息,且条件将返回 nil

shapeType = "label" 
if( shapeType == "rect" 
            println( "Shape is a rectangle" ) 
            ++rectCount 
      else 
            println( "Shape is not a rectangle" ) 
            ++miscCount 
      ) 

Message: *Error* if: too many arguments ... 

    3.  when 和 unless 函数

    当您只有then表达式时,使用when 函数 (只有一个条件--个人理解)

when( shapeType == "rect"
            println( "Shape is a rectangle" )
            ++rectCount 
      ) ; when

when( shapeType == "ellipse"
      println( "Shape is an ellipse" )
      ++ellipseCount 
      ) ; when 

    Use the unless function to avoid negating a condition. Some users find this less confusing.

    使用unless函数避免否定一个条件。有些用户发现这个很少疑惑

unless( shapeType == "rect" || shapeType == "line"
      println( "Shape is miscellaneous" )
      ++miscCount 
      ) ; unless

    The when and unless functions both return the last value evaluated within their body or nil.

    when和unless函数都返回其体内运算的最后的值 或者 nil.



    4. case 函数

    The case function offers branching based on a numeric or string value.

    case函数基于一个数值的或字符串的值提供分支。

case( shapeType 
      ( "rect" 
            ++rectCount 
            println( "Shape is a rectangle" ) 
            ) 
      ( "line"
            ++lineCount 
            println( "Shape is a line" ) 
            ) 
      ( "label" 
            ++labelCount 
            println( "Shape is a label" ) 
            ) 
      ( t 
            ++miscCount 
            println( "Shape is miscellaneous" ) 
            ) 
      ) ; case 

    The optional value t acts as a catch-all and should be handled last. The case function returns the value of the last expression evaluated. In this example:

    可选的t 充当所有其他的条件,应该被最后处理。case函数返回最后赋值表达式的值。在这个例子里: 

  • The value of the variable shapeType is compared against the values rect, line, and label. If SKILL finds a match, the several expressions in that arm are evaluated. 变量shapeType的值跟值rect, line, and label比较,SKILL发现匹配的值,执行匹配分支的表达式

  • If no match is found, the final arm is evaluated. 如果没有匹配的,最后的分支被执行。

  • When an arm's target value is actually a list, SKILL searches the list for the candidate value. If SKILL finds the candidate value, all the expressions in the arm are evaluated.

    一个手臂的目标值实际上是一个列表,技巧搜索列表中候选值如果SKILL发现候选值在分支所有表达式被执行

    case( shapeType 
          ( "rect" 
                ++rectCount 
                println( "Shape is a rectangle" ) 
                ) 
          ( ( "label" "line" ) 
                ++labelOrLineCount 
                println( "Shape is a line or a label" ) 
                ) 
          ( t 
                ++miscCount 
                println( "Shape is miscellaneous" ) 
                ) 
          ) ; case 


    5. for 函数

    The index in a for expression is saved before the for loop and is restored to its saved value after the for loop is exited. SKILL does most of its error checking during execution. Error messages involving for expressions can be obscure. Be sure to

    for循环表达式的索引在for循环之前被存储且在for循环结束后返回一个已保存的值SKILL在执行期间,做大部分的错误检查。错误信息表明for表达式可能是模糊的。确定:

  • Be aware of the placement of the parentheses: for( ... ). 注意圆括号的放置

  • Avoid white space immediately after the for keyword. 避免for关键字后存在空格

    The example below adds the integers from one to five to an intermediate sum. i is a variable used as a counter for the loop and as the value to add to sum. Counting begins with one and ends with the completion of the fifth loop. i increases by one for each iteration through the loop.

    下面的例子将整数从1加到5相加,结果存入中间变量sum。 i是循环一个计数器,同时其值被加到sum这个变量。计数从1到5. i每循环一次增加1
for( i 1 5
      sum = sum + i
      println( sum )
      )
=> t

    SKILL prints the value of sum with a carriage return for each pass through the loop:

1
3
6
10
15

    The for function always returns t. for 循环总返回 t



    6. foreach函数

    The foreach function is very useful for performing operations on each element in a list. Use the foreach function to evaluate one or more expressions for each element of a list of values.

    foreach函数对于操作list中放入每个元素是非常有用的。 使用foreach函数计算一个活多个表达式来获得list中每个元素的值

rectCount = lineCount = polygonCount = 0 
shapeTypeList = '( "rect" "polygon" "rect" "line" ) 
foreach( shapeType shapeTypeList 
      case( shapeType 
            ( "rect"             ++rectCount ) 
            ( "line"             ++lineCount ) 
            ( "polygon"          ++polygonCount ) 
            ( t                  ++miscCount ) 
            ) ;case 
      ) ; foreach 
=> ( "rect" "polygon" "rect" "line" )

    When evaluating a foreach expression, SKILL determines the list of values and repeatedly assigns successive elements to the index variable, evaluating each expression in the foreach body. The foreach expression returns the list of values over which it iterates.

    当执行一个foreach表达式,SKILL确定列表的值,在foreach循环内,重复将连续的元素赋值给索引变量。foreach返回循环的list

    In the example: 在这个例中:

     
  • The variable shapeType is the index variable. Before entering the foreach loop, SKILL saves the current value of shapeType. SKILL restores the saved value after completing the foreach loop.变量shapeType是索引变量,在输入foreach前,SKILL保存shapeType的当前值,在完成循环后则返回保存后的值

  • The variable shapeTypeList contains the list of values. SKILL successively assigns the values in shapeTypeList to shapeType, evaluating the body of the foreach loop once for each separate value. 变量shapeTypeList包含一些值的list。SKILL连续将shapeTypeList值给shapeType,每个单独的值都将做一次循环

  • The body of the foreach loop is a single case expression. foreach循环体是一个单一条件的表达式

  • The return value of the foreach loop is the list contained in variable shapeTypeList. foreach循环的返回值是一个包含在变量shapeTypeListlist

    If you have executed the example above, you can examine the effect of the iterations by typing the name of the counter:

    如果您已执行上面的例子可以通过输入计数器的名称检查循环的效果

rectCount        => 2
lineCount        => 1
polygonCount     => 1


    第六节 开发一个SKILL函数

    Developing a SKILL function includes the following tasks. 开发一个SKILL函数包含以下任务: 

  • Grouping several SKILL statements into a single SKILL statement 将几个SKILL语句组合进一个单一的SKILL语句。

  • Declaring a SKILL function with the procedure function procedure 声明一个函数

  • Defining function parameters 定义函数参数

  • Maintaining your source code 维护您的源代码

  • Loading your SKILL source code  加载您的SKILL源代码

  • Redefining a SKILL function  重定义一个SKILL函数



    1. 群组SKILL语句

    Sometimes it is convenient to group several SKILL statements into a single SKILL statement. Use braces { and } to group a collection of SKILL statements into a single SKILL statement. The return value of the single statement is the return value of the last SKILL statement in the group. You can assign this return value to a variable.

    有时将几个语句群组进一个语句是很方便的。使用大括号{}实现群组一个SKILL语句集。单一语句的返回值为群组中最后的SKILL语句的返回值。您可以将返回值赋值给一个变量。

    This example computes the pixel height of bBox and assigns it to the bBoxHeight variable:

    这个例子计算bBox像素高度,且将其赋值给变量bBoxHeight

bBoxHeight = { 
      bBox = list( 100:150 250:400)
      ll = car( bBox )
      ur = cadr( bBox )
      lly = yCoord( ll )
      ury = yCoord( ur )
      ury - lly }
     
  • The ll and ur variables hold the lower-left and upper-right coordinates of the bounding box. ll 和 ur 变量抓取边界框左下角和右上角坐标

  • The xCoord and yCoord functions return the x and y coordinate of a point.xCoord 和 yCoord 函数返回一个点的x和y坐标

  • The ury - lly expression computes the height. This last statement in the group determines the return value of the group.ury - lly 计算高度,最后的语句确定群组的返回结果。

  • The return value is assigned to the bBoxHeight variable. 返回值赋值给变量bBoxHeight

    You can declare the variables ll, ur, ury, and lly to be local variables. Use the prog or let functions to define a collection of local variables for a group of several statements. However, defining local variables is not recommended for novices.

    您可以将ll, ur, ury, 和 lly声明为局部变量。使用prog 或 let 给群组的几个语句定义一个局部变量集。不过不建议初学者定义局部变量。



    2. 声明SKILL函数

    To refer to the group of statements by name, use the procedure declaration to associate a name with the group. The group of statements and the name make up a SKILL function. 

    群组语句通过名字引用,使用procedure函数声明与一个群组关联到一个名字,将群组语句和名字组成一个SKILL函数

  • The name is known as the function name. 群组的名字被作为函数命名。

  • The group of statements is the function body. 群组语句是函数体

  • To execute the group of statements, mention the function name followed immediately by ( ). 执行群组相当于函数名后紧跟着括号()

    The ComputeBBoxHeight function example below computes the pixel height of bBox.

    下面例子ComputeBBoxHeight 函数计算 bBox 的像素高度

procedure( ComputeBBoxHeight( ) 
      bBox = list( 100:150 250:400)
      ll       = car( bBox )
      ur       = cadr( bBox )
      lly      = yCoord( ll )
      ury      = yCoord( ur )
      ury - lly 
      ) ; procedure

bBoxHeight = ComputeBBoxHeight()


    3. 定义函数参数

    To make your function more versatile, you can identify certain variables in the function body as formal parameters.

    When you invoke your function, you supply a parameter value for each formal parameter.

    In the following example, the bBox is the parameter.

    为了使您的函数更加灵活,您可以在函数体内确定某些变量作为形式参数(形参
    当您调用函数时,您需要提供的参数值给每个形参
    在下面的例子中,BBOX 就是参数

procedure( ComputeBBoxHeight( bBox ) 
      ll       = car( bBox )
      ur       = cadr( bBox )
      lly      = yCoord( ll )
      ury      = yCoord( ur )
      ury - lly 
      ) ; procedure

    To execute your function, you must provide a value for the parameter.

    要执行函数,您必须提供一个参数值。

bBox = list( 100:150 250:400)
bBoxHeight = ComputeBBoxHeight( bBox )


    4. 为您的函数选择前缀

    With only a few exceptions, the SKILL functions in this manual do not use a prefix identifier. Many examples in this manual use a "tr" prefix to indicate they are created for training purposes. If you look in other SKILL manuals, you will notice that functions for tools are usually grouped with identifiable, unique prefixes.

    For example, functions used for technology file administration are all prefixed with "tc". These prefixes vary across Cadence tools, but all use lowercase letters. It is recommended that you establish a unique prefix using uppercase letters for your own functions.    

    只有少数例外情况外,本手册中的SKILL函数不使用前缀标识。本手册中的许多例子都使用了“TR”前缀,以表明他们是以训练为目的而创建的。如果你在其他SKILL手册中你会发现对于工具的功能通常以能识别的独特的前缀来群组
    例如,用于技术文件管理功能带有前缀“TC”这些前缀Cadence工具各不相同,但都使用小写字母建议使用大写字母自己的函数建立唯一的前缀

    5. 保持SKILL源代码Maintaining SKILL Source Code

    The Cadence environment makes it easy to invoke an editor of your choice. Set the SKILL variable editor to a UNIX command line able to launch your editor.

    Cadence的环境可以很容易地调用你选择的编辑器在UNIX命令行设置SKILL变量editor可以启动您的编辑器

editor = "xterm -e vi"

    The ed function invokes an editor of your choice. If you optionally use the edl function, the system loads your file when you quit the editor.

    ed 函数调用您选择的一个编辑器。如果您选择使用 edl 函数,当您退出编辑器,系统加载你的文件。

ed( "myFile.il")

    alternatively, you can use an editor independent of the Cadence environment.    

    作为选择您可以使用独立了Cadence环境的编辑器



    6. 加载SKILL源代码

    The load function  load 函数

  • Evaluates each expression in a source code file  评估源代码文件中的每个表达式

  • Is typically used to define a collection of functions  通常用于定义函数的集合

  • Returns t if all expressions evaluate without errors  如果语句执行没有错误,则返回 t

  • Aborts if there are any errors, any expression following the offending expression is not evaluated 如果执行过程中存在任何错误,将放弃执行错误发生点后面的表达式。

    7. 相对路径

    When you pass a relative path to the load function, the system resolves it in terms of a list of directories called the SKILL path. You usually establish the SKILL path in your initialization file by using the setSkillPath or getSkillPath functions.

    当您使用相对路径加载函数,系统根据被调用的SKILL路径目录的list来解决。您通常在您的声明文件中使用 setSkillPath 或 getSkillPath 函数来建立SKILL路径。

  • The setSkillPath function sets the path to a list of directories. setSkillPath 函数设定路径到一个目录的list

  • The getSkillPath function returns a list of directories in search order. getSkillPath 函数设定路径到一个目录的list

    8. 输入一个函数

    Sometimes you need to define a function without saving the source code file. Using the mouse in your editor, select and paste the function into the command input line.

    有时您需要保存源代码文件的情况下定义一个文件。在编辑器中使用鼠标在命令输入行中选择和粘贴函数。

    9. 设定SKILL路径

    Use the setSkillPath function in conjunction with the prependInstallPath and getSkillPath functions to set the SKILL path.

    使用setSkillPath 结合 prependInstallPath getSkillPath 函数来设定SKILL 路径

trSamplesPath = list(
            prependInstallPath( "etc/context" )
            prependInstallPath( "local" )
            prependInstallPath( "samples/local" )
            )

    Use the prependInstallPath function to make a path relative to the installation directory. The function prepends your_install_dir /tools/dfII to the path. Assuming your installation path is /cds/9401 trSamplesPath is now:

    使用 prependInstallPath 函数建立一个相对于安装目录的路径。函数预先将your_install_dir /tools/dfII赋给路径。假设您的安装路径是 /cds/9401 ,现在 trSamplesPath 为:

("/cds/9401/tools.sun4/dfII/etc/context" 
 "/cds/9401/tools.sun4/dfII/local" 
 "/cds/9401/tools.sun4/dfII/samples/local")

    假如 windows下为安装路径为 D:\\Cadence\\SPB_16.6,则见下面代码

prependInstallPath( "etc/context" )

=>"D:\\Cadence\\SPB_16.6\\tools\\dfII\\etc\\context"

     注:SKILL \\ 和 /  才是正确的路径符号。

    Assuming your SKILL path is ("." "~"), you can set a new SKILL path using setSkillPath.

    假设您的SKILL路径是("." "~"),您可以使用 setSkillPath 设定SKILL路径

setSkillPath( append( trSamplesPath getSkillPath() ) )

    The return value of setSkillPath indicates a path that could not be located, not the actual SKILL path.

    setSkillPath的返回值显示一个中不到的路径,而不是实际的SKILL路径。

("/cds/9401/tools.sun4/dfII/samples/local")

The actual SKILL path is 实际的SKILL路径是(list形式

("/cds/9401/tools.sun4/dfII/etc/context" 
  "/cds/9401/tools.sun4/dfII/local" 
 "/cds/9401/tools.sun4/dfII/samples/local" "." "~")

    10. 重定义一个SKILL函数

    Users should be safeguarded against inadvertently redefining functions. Yet, while developing SKILL code, you often need to redefine functions.

The SKILL interpreter has an internal switch called writeProtect to prevent the virtual memory definition of a function from being altered during a session.

    By default writeProtect is set to nil. SKILL functions defined while writeProtect is t cannot be redefined during the same session. Typically, you set the writeProtect switch in your initialization file.

    用户应该防止无意地重定义函数。然而为了开发SKILL代码,您经常需要重定义函数。SKILL解释器有一个writeProtect内部开关,以防止一个会话期间改变函数的虚拟内存定义。

    默认情况下writeProtect 被设置为 nil 。当writeProtectt ,已定义的SKILl函数在同一个会话期间不能被重新定义。通常的,您可以将writeProtect 开关设在您的声明文件中。

sstatus( writeProtect t )        ;sets it to t
sstatus( writeProtect nil )      ;sets it to nil

This example tries to redefine trReciprocal to prevent division by 0.

sstatus( writeProtect t ) => t
procedure( trReciprocal( x ) 1.0 / x ) => trReciprocal
procedure( trReciprocal( x ) when( x != 0.0 1.0 / x ))
*Error* def: function name is write protected
      and cannot be redefined - trReciprocal

标签: Skill 用户手册 第一章

发表评论:

电子布局网  |  手机版  |  RSS  |  我要留言

All Rights Reserved. Powered by 电子布局--

sitemap