Cadence - Skill - 语法详解(中文) 下载本文

1

常量、变量

常量是它的值等于自身的表达式,如123,”abc”… 变量是保存了其它值的表达式,如x=3, x即变量。 算术与逻辑操作符

函数名 语法 对应操作符 Data Access

arrayref a[index] [ ] setarray a[index] = expr bitfield1 x <> setqbitfield1 x=expr setqbitfield x=expr quote 'expr ' getqq g.s . getq g->s -> putpropqq g.s=expr, g->s=expr putpropq d~>s, d~>s =expr ~> Unary

preincrement ++s ++ postincrement s++ ++ predecrement --s -- postdecrement s-- -- minus -n -

2

not !expr ! bnot ~x ~ Binary

expt n1 ** n2 ** times n1 * n2 * quotient n1 / n2 / plus n1 + n2 + difference n1 - n2 - leftshift x1 << x2 << rightshift x1 >> x2 >> lessp n1n2 > leqp n1<=n2 <= geqp n1>=n2 >= equal g1 == g2 == nequal g1 != g2 != band x1 & x2 & bnand x1 ~& x2 ~& bxor x1 ^ x2 ^ bxnor x1 ~^ x2 ~^ bor x1 | x2 | bnor x1 ~| x2 ~|

3

and x1 && x2 && or x1 || x2 || range g1 : g2 : setq s = expr =

对于既有函数名又有操作符函数,采用函数名调用和采用操作符调用的效果是一样的。 示例 lessp(3 1)=>nil 等同于 3<1=>nil 预定义算术函数 语法 结果 通用函数

add1(n) n + 1 sub1(n) n – 1 abs(n) 绝对值

exp(n) 自然对数的n次方 log(n) max(n1 n2 ...) min(n1 n2 ...)

mod(x1 x2) 取模运算 round(n) sqrt(n)

sxtd(x w) 将x右扩展W个符号位 zxtd(x w) 和上面的功能相同,速度更快 三角函数

4

sin(n),cos(n),tan(n) asin(n),acos(n),atan(n) 随机数生成函数

random(x) 产生0~x-1的随机数 srandom(x) 初始化随机数生成函数的x

位操作

含义 操作符 位与 & 位或 | 位异或 ^ 左移位 >> 右移位 << 取反 ~

真值、假值

? 真值,除了nil以为的值都是真值。 ? 假值,nil 条件控制函数

if, when, unless, cond

? if if函数的语法结构

5

if( condition1 then ;当condition1为真值时执行代码块expA expA else

if( condition2 then ;当condition2为真值时执行代码块expB expB else … expC ) );end if

? when when函数语法结构

when( condition ;当condition为真值时执行代码块expA,否则跳过 expA ); end when

? unless unless语法结构

unless( condition ;当condition为假值时执行代码块expA,否则跳过

6

expA ); end unless

? cond cond语法结构

cond (

( condition1 expA... ) ;当condition1为真值时执行代码块expA ( condition2 expB ... ) ;… ( condition3 expC ... ) ;…

( t expN ) ;之前的条件都不满足时默认执行expN ); end cond

[注]:\表示注释 循环控制函数 while,for,foreach

? while while语法结构

while( condition is true ;当condition为真值时反复执行代码块expA,否则结束循环

expA

7

)

? for for语法结构

for( i 1 5 println(i) )

将输出 1 2 3 4 5

? foreach

foreach是简化版的for,上面的例子用foreach写如下

alist = ?(1 2 3 4 5) foreach( item alist

8

println( item ) )

foreach通常用于操作列表,因为它会遍历列表的每一个元素。 选择函数

? caseq的用法类似cond,功能也类似。

caseq( var

(condition1 expA) (condition2 expB) …

) ;case语法结构

循环结构中的局部变量

使用关键字prog可以在循环结构中定义局部变量。关于prog的详细介绍请参考函数章节。 返回函数

表示返回值的关键字是return。return可以强制一个prog结构立即结束,送出返回值,忽略剩余的循环操作。 示例 prog( ( ) for( i 0 10 when( oddp( i ) return( i )

9

) ; when ) ; for ) ; prog

这个for循环不会运行10次,首次oddp(i)为真值的时候循环就会结束。 正则表达式

在很多的skill应用中都会用到正则表达式,比如在一个字符串数组中查找带有关键字user的字符串。示例:

lStr = '(\ lRes = nil foreach( item lStr

if( rexMatchp(\ lRes = cons( item lRes) println(item) ) )

输出:

\

lRes =>(\

10

这里的关键命令是rexMatchp,函数形式为rexMatchp(t_pattern S_target),这个命令将在第二个参数中查找满足第一个参数(模式)的条件,如果找到返回真值,否则返回假值。

? 正则表达式(pattern)的组成字符 语法 含义

c 匹配任意非特殊字符 . 匹配任意字符

\\ 用在特殊字符前面代表特殊字符本身,用在 <, >, (, ), and 1,...,9, 的含义在下面描述

[c...] 一对方括号中包含一些字符将匹配括号中的任意一个字符,如果第一个字符是 ^ 则表示不匹配括号中的所有字符,[a-z]表示匹配a到z之间的任一字符,\”表示范围。 * 用在一个以上描述的字符或pattern后表示匹配该字符或pattern0次或多次。 + 类似*,区别在于匹配至少一次

\\(..\\) 如果包含在这个符号中的字符串匹配上了,被匹配的字符可以被提取出来(最多支持9中匹配)

\\n 和上一个符号对应,反斜杠后跟一个数字将可以提前到上一个符合保留的字符串

\\<...\\> 这个符号表示完全匹配一个字符串的开始和结尾 rs 2个正则表达式的组合将尽可能多的匹配r并匹配一个s ^, $ ^表示字符串的开始, $表示字符串的结尾

? 常用正则匹配函数

11

rexCompile,rexExecute,rexMatchp,rexSubstitute 示例: 使用 rexCompile和rexExecute实现开头的示例

lStr = '(\ lRes = nil

rexCompile(\foreach( item lStr

if( rexExecute(item) then lRes = cons( item lRes) println(item) ) )

将得到和前一个示例一样的结果。示例: 使用rexSubstitute提取字符, 在给定格式的列表中提取symbol名字和对应的坐标

lStr = list(\\

\“C666x3535.00y-3135.00” “C785x1929.00y-3750.00” “U628x3865.00y-2025.00” “C737x3010.00y-3155.00” “R754x2770.00y-2730.00”) rexCompile( \结构表示匹配的部分将可以用\\\\1..9提取出来

; [A-Z]表示匹配A~Z的字符,+表示至少有一个这样的字符 foreach( item lStr

12

when( rexExecute( item ) str1 = rexSubstitute( \ str2 = rexSubstitute( \ str3 = rexSubstitute( \

printf(\ ) );

将输出:

C17<->855.00<->-2790.00 C676<->3499.50<->-2676.40 Q690<->3406.00<->-2701.00 C785<->1929.00<->-3750.00 U628<->3865.00<->-2025.00 C737<->3010.00<->-3155.00 R754<->2770.00<->-2730.00

? 更多示例,参考Skill正则表达式应用举例

13

Skill正则表达式应用举例 处理Dangling Line Report

allegro的report命令在report dangling line的时候也会同时report dangling via 出来。

如果你record过script,就会发现产生dangling line report的allegro命令是reports \。

这个命令会在当前allegro工作的文件夹下产生一个叫dangling_lines.rpt的文件。

;------------------------------------------------ <>

Power TOP *(7710.00 -1865.00) to *(6705.00 -1615.00) GND BOTTOM *(7890.00 -1774.00) to *(6575.00 -2045.00) 1V5 INT3 *(7860.00 -1930.00) to *(6675.00 -2660.00) 12V INT5 *(7830.00 -1930.00) to *(6705.00 -2660.00) << Dangling Vias >>

GND VIA24C12P (5505.00 -320.00) 1V5 VIA24C12P (5465.00 -320.00)

现在我想用正则表达式来找到Via的信息,而排除line的以及一些其它的文字信息。 下面是我想到的patten:

14

\

在skill环境下简单试一下

rexMatchp(\“ 1V5

VIA24C12P (5465.00 -320.00)” )=>t

rexMatchp(\A-Z0-9_<>*]+[ ]+[A-Z0-9_]+[ ]+([-0-9.]+ [-0-9.]+)$\“ 1V5 VIA24C12P (5465.00 -320.00)to(5465.00 -320.00)” )=>nil

所以是满足我们的要求的! 完整的提取程序:

axlShell( \\\\Dangling Lines Report\\\\ ) pDanglingFile= infile( \ ) dl_list = nil

unless( getc( pDanglingFile )

axlMsgPut( \ ) while( gets( dl_entry pDanglingFile )

when( rexMatchp(\ dl_entry ) ;;因为gets读进来的dl_entry还带了个\,所以必须在之前定义的patten

15

后面再加上一个“.\来匹配它

dl_entry = buildString( parseString(dl_entry) \ \) ;;因为report结果里面的via net, padstack以及坐标间隔很大,这个让间隔变小一点

dl_list = cons( dl_entry dl_list ) ) )

close(pDanglingFile)

dl_list = sort(dl_list nil) ;根据字符串大小的默认排序 )

这样就得到了dangling via的列表了。接下来的操作就随个人了,比如把它显示到一个form里面。

另一个例子

\rexCompile(\

这样就可以得到带括号的坐标

rexCompile(\

得到不带括号的坐标

16

特殊字符,注释,空格,圆括号和其它标记法的使用

? 特殊字符 SKill中的特殊字符列表

字符 全名 含义

\\ 反斜杠 辅助输出特殊字符

() 圆括号 组织数据列表和调用函数列表 [] 中括号 数组索引,超级右中括号 {} 大括号 使用progn时组织一系列表达式 ' 单引号 单引号中的表达式不会被解析 \ 双引号 字符串分界符

, 逗号 列表中可选的元素分界符; 在反引号作用范围内使用强制表达式解析

; 分号 行注释

: 冒号 位分隔符,范围操作 . 点号 getq操作

+,–,*,/ 算术运算 算术运算符; 同时\和\组合也用于多行注释 !,^,&,| 逻辑运算 逻辑运算符

<,>,= 关系运算 比较运算,赋值以及位运算 # # 用在第一列表示信号的特别解析

@ @ 用在第一个字符表示保留字;另外在反引号作用范围内使用将强制表达式解析

? 问号 如果是第一个字符表示关键字

17

` 反引号 引号内的表达式不被解析 % 百分号

$ - 保留为将来使用

[注]:输出这些特殊字符都需要在字符前加\。

? 注释

? 行注释方法, 使用分号\,注释范围在分号当前行。 ? 多行注释,使用\和\对,注释范围在这这对符号内。

? 空格,空格的限制比较少,只是要注意下面几个情况

? 函数名和跟在后面的圆括号之间不能有空格,如max(4 2)是对的,而max (4 2)则是错的;

? 表示负数的符号\和数字之间不能有空格,如-5, -(a*b)有效,而- 5,- (a*b)无效;

? 表示算术运算的\在2个数字之间的位置要对称,如a - b, a-b有效,而a -b无效。

? 圆括号

? 圆括号在skill中用于函数调用,分隔多个表达式,控制表达式的解析顺序 ? skill中调用函数有2种方式,max(a b)和(max a b)都有效。

? 超级右中括号,不推荐使用

? 在使用了很多\的表达式后,可以用\来代表很多个用于结尾的\。

如f1( f2( f3( f4( x ) ) ) )等效于f1( f2( f3( f4( x ]。

18

? 反引号,逗号和逗号加@ 示例1. y = 1

'(x y z) => (x y z) ;反引号使得表达式不被解析,所以其中的y不会被1代替 '(x ,y z) => (x 1 z) ;增加一个逗号在反引号表达式中,逗号后面的表达式将被解析 示例2. x = 1 y = '(a b c)

'(,x ,y z) => (1 (a b c) z);逗号后的表达式都被解析了

'(,x ,@y z) => (1 a b c z) ;\的作用和逗号一样,只是被解析对象是列表,且解析出来的元素代替了原来的列表

? 续行符\

? 使用\可以让在一行的文字多行表示, 如

string = \

a test.\

? 初始化列表的最大长度6000,但是在程序运行中列表的长度无限制。 文件系统接口

? 路径

? 绝对路径:Unix中以\开始的路径,Windows中以磁盘\开始的路径

19

? 相对路径,不是绝对路径的情况就是相对路径

? 以\开始的路径表示被查询的路径是用户的home文件夹; ? 以\开始的路径,如果username正好是一个用户的名字,那么被查询的路径将是该用户的home文件夹; ? 以\开始的路径表示被查询的位置是当前的工作目录

? 以\开始的路径表示被查询的位置为当前工作目录的父文件夹

? Skill路径

? skill支持用户定义若干不同的路径来存放skill源文件,并通过skill的路径管理函数来设置各个路径的访问顺序。如果同一个文件在不同路

径下都存在,按照先到先得原则,即使用第一个被找到的文件。 ? 设置skill查询路径的函数setSkillPath, 如setSkillPath(\\\,就设置了3个skill查询路径,先后顺序分别为\-当前工作路径,\-home文件夹,\-用户自定义文件夹。

? 获取skill查询路径列表的函数getSkillPath,如setSkillPath(\\; getSkillPath()=>(\

? 安装路径

? 获

取

安

装

路

径

函

数

getInstallPath

,

如

getInstallPath()=>\

? 检测文件状态

? 检测文件是否存在函数isFile,isFileName ? 检测文件夹是否存在函数isDir

? 检测文件或文件夹的是否可以被读取的函数isReadable ? 检测文件或文件夹的是否可以被写入的函数isWritable

? 路径操作

? 生成和删除文件夹

20

? createDir(arg), 如createDir(\,将在c:/temp下创建一个skill文件夹;

? deleteDir(arg),如deleteDir(\,将删除这个skill文件夹,如果这是个空文件夹,且用户具有删除它的权限。

? 删除文件函数deleteFile

? 获取指定文件夹下所有文件名函数getDirFiles ? 获取当前工作目录getWorkingDir ? 改变工作目录changeWorkingDir

端口

所有数据的输入输出都是经由一个被称为端口的东西实现的。 预定义的标准端口 端口名 作用

piport 标准输入端口,等同于C中的stdin poport 标准输出端口,等同于C中的stdout errport 错误输出端口,等同于C中的stderr ptport 跟踪信息端口,等同于C中的stderr

? 打开端口

? 打开一个文件读取端口infile

infile(\

? 打开一个文件输出端口outfile

21

p = outfile(\

? 关闭端口close

p = outfile(\ close(p)

I/O

? 输出

? 非格式化输出

print(\ ; 输出 \ println(\ ; 输出 \加换行

? 格式化输出

常见格式化输出规范

格式 参数类型 输出结果 %d fixnum 十进制整数 %o fixnum 八进制整数 %x fixnum 十六进制整数

%f flonum 浮点数,格式为[-]ddd.ddd %e flonum 浮点数,格式为[-]d.ddde[-]ddd

%g flonum 不改变浮点数精度的情况下,以最少的空间表示 %s string, symbol 输出字符串

22

%c string, symbol 输出第一个字符 %n fixnum, flonum 数字 %L list 数据的默认形式输出 %P list 点Point %B list Box

示例

printf( \ \ )=> \

printf( \ 20 20 )=> \ ;把一个十进制书转换成16 sprintf( sMsg \ \ )=> sMsg=\

fprintf( port \ 10 ); 输出\到文件 printf( \\\\%s\\\\ \\\\\text.il\); 输出file is \,这里带了双引号

? 输入 输入函数列表

输入源 读取函数(评估版) 读取函数(未评估版) 操作函数

File文件 load/loadi lineread infile/gets/getc/fscanf/close String

字符串

evalstring/loadstring/errsetstring

linereadstring

instring/gets/getc/fscanf/close

文件输入输出示例

23

? 创建文件并输出数据到该文件的函数 procedure( DataOut() lData = list(

'(\ 10 5.5) '(\ 20 10.2) '(\ 30 15.0) '(\ 40 17.8) '(\ 50 1.2) ); 定义数据列表lData

fDataOut = strcat( getTempDir() \ \) ; 输出文件名和路径,%temp%/data.txt。

pDataOut = outfile( fDataOut \ ); 建立输出端口 foreach( item lData

fprintf( pDataOut \\\n\ ; 输出数据到文件端口 car(item) cadr(item) caddr(item) ; item=>每一个在lData中的列表

); end fprintf ); end foreach

close( pDataOut ) ; 关闭端口

printf( \ fDataOut ); 输出提示信息

); end procedure

? 从指定文件读取数据

24

procedure( DataIn()

prog( (fDataIn pDataIn lData sWord nNum fNum) ;设置局部变量 fDataIn = strcat( getTempDir() \ \) ; 输入文件

unless( isFile( fDataIn ) ; 如果文件不存在则跳转到函数末尾,结束函数 printf(\ fDataIn) go(SkipToEnd) ; 在prog中支持go操作 )

pDataIn = infile( fDataIn ); 建立输入端口 lData = nil 初始化列表变量

while( fscanf( pDataIn \ sWord nNum fNum ) ; 安照数据文件格式读取

lData = cons( list( sWord nNum fNum ) lData ) ); end while

; 读取完毕lData里的数据将和上例中的一样 close( pDataIn ) SkipToEnd ); end prog ); end procedure

数字

? 整数

进制列表: 前缀 示例[十进制值]

二进制 0b或0B 0b1010 [10]

25

八进制 0 012 [10] 十进制 10 十六进制 0x或0X 0x11 [17]

? 浮点数

和其它的编程语言一样,如1.0,1.,0.5,.5,1e6……

? 比例因子

比例因子 字符 全名 比例 示例 Y Yotta 1.00E+24 10Y [ 10e+25 ] Z Zetta 1.00E+21 10Z [ 10e+22 ] E Exa 1.00E+18 10E [ 10e+19 ] P Peta 1.00E+15 10P [ 10e+16 ] T Tera 1.00E+12 10T [ 10e+13 ] G Giga 1.00E+09 10G [ 10e+10 ] M Mega 1.00E+06 10M [ 10e+7 ] k or K kilo 1.00E+03 10k [ 10e+4 ] % percent 1.00E-02 5% [ 0.05 ] m milli 1.00E-03 5m [ 5.0e-3 ] u micro 1.00E-06 1.2u [ 1.2e-6] n nano 1.00E-09 1.2n [ 1.2e-9 ] p pico 1.00E-12 1.2p [ 1.2e-12 ] f femto 1.00E-15 1.2f [ 1.2e-15 ]

26

a atto 1.00E-18 1.2a [ 1.2e-18 ] z zepto 1.00E-21 1.2z [ 1.2e-21 ] y yocto 1.00E-24 1.2y [ 1.2e-24 ]

? 常用的skill函数

通常整数和浮点数在一个表达式中计算的时候,结果默认是浮点数。

? 判断数字类型

numberp(data),判断data是不是数字类型; fixp(data),判断data是不是整型数; floatp(data),判断data是不是浮点数;

示例: numberp( 5 ) => t,

fixp( 5 ) => t, 和integer(5)一样 floatp( 5 ) => nil,

(t, nil分别代表真值和假值)。

? 浮点数、整数转换

round(data),转换浮点数到最近的整数; fix(data),转换浮点数到不大于它的最大的整数 float(data),转换整数到相等大小的浮点数

27

示例:round(1.8) => 2, round(1.4) => 1 fix(1.8) => 1, fix(1.4) => 1 float(2) => 2.0

? 字符串转换成数字

atoi(data), 转换字符串到对应的整数 atof(data), 转换字符串到对应的浮点数

示例:atoi(“3s”) => 3, atof(“3s”)=> 3.0

? 其它数学运算函数

abs, cos, atan, log…具体请参考skill函数参考书sklangref。 字符

skill中没有一个专门的类型叫char,字符通常都是用symbol类型代表,如 type(?A)=>symbol。(skill中的symbol相当于C语言中的变量) 可以使用ASCII来申明一个字符, 比如 char=?\\120, char=>p。 一些特殊的字符(转义序列)

new-line (line feed) \\n horizontal tab \\t vertical tab \\v

28

backspace \\b carriage return \\r form feed \\f backslash \\\\ double quote \\\ ASCII code ddd (octal) \\ddd

字符串

? 字符串定义

字符串是字符序列,比如”123”, “abs”…。字符串用双引号来定义,就像C语言一样。 可以直接打印的字符(处双引号本身)都可以直接被直接定义成字符串, 如”a”, “01”。 需要借助转义字符(\\)才可以打印的字符,以及双引号被定义成字符串时都需要和转义字符一起, 如”\\””, “\\\\” 分别定义了字符串” 和\\。

? 字符串限制

直接赋值的字符串长度不能超过8191,但是在程序运行过程中的字符串长度没有限制。

? 常用函数

? 判断字符串类型

stringp(data), 判断是否为字符串;

? 合成,分开,提取

strcat( s_string1 s_string2 …), 合成所有提供的字符串生成一个新的字符串 substring(s_string index length), 从指定位置提取特定长度的字符 parseString(s_string breakchar), 用特定字符将原字符串断开

buildString(l_string breakchar), 用特定的字符将给定的字符串列表合成字符串

29

示例 strcat(“a” “1 b” “ 3 c”) => “a1 b 3 c”; substring(“abcdef” 3 2) => “cd”;

parseString(“a-bc-def” “-“) => ?( “a” “bc” “def” ) buildString( ?(“1” “23” “4” “5a”) “+”) => “1+23+4+5a”

? 字符串长度、比较

strlen(s_string),得到字符串长度

strcmp(s_string1 s_string2),比较2个字符串的大小 equal(s_string1 s_string2),判断2个字符串是否相等

示例 strlen(“abc”) => 3

strcmp(“abc” “abb”) => 1, strcmp(“abc” “abc”) => 0 equal( “abc” “abb” ) => nil

? 输出与格式化

println( “hello” )=>”hello”, 输出hello;

printf(“folat num is %0.2f” 10.2)=>”float num is 10.20。

? 其它

symbolToString,timeToString…… 参考skill函数文档 逻辑值

? t 表示逻辑真值

30

? nil 表示逻辑假值 数组 array

? 申明一个数组

申明数组需要用到关键字declare,如declare(week[7]), 申明了一个能包含7个元素的数组week。数组元素从week[0]到week[7-1]也即week[6]。

? 赋值与读取

给数组的元素赋值, 如week[0]=”Mon”;读取数组的一个元素,如week[0] => ”Mon”

? 特殊性

skill中数组不同于其它语言的一点就是数组中的元素可以不是同一种类型,也即数组中可以既有字符串,又有数字等等。

? 常用的函数

arrayp,判断是否为数组类型。

列表 list

skill中最常用到的一种类型就是列表,列表是一系列元素的结合,元素不必是同一个类型。比如?(1 “as” “1”)就是一个包含了三个元素1、“as”和“1”的列表,而且这列表中这三个元素的位置上固定了的,比如说第二个元素就一定是”as”。

? 申明列表

申明列表有2种方式一种使用关键字list,如a=list(“ab” “c” “de”),另一种用单引号”?”,如a=?(“ab” “c” “de”),这2种方式定义的列表是一样的,这里都是定义了一个包含3个元素的列表。

? 常用操作列表函数

? 访问列表元素

car(list), cdr(list),分别获取列表的第一个元素和列表除第一个元素以外的元素列表 car和cdr可以组合在一起使用,如cadr(list)<=>car(cdr(list)),得到列表的第二个元素

31

nth(index list),获取指定位置的列表元素 nth(0 list)<=>car(list) member( item list ),查询列表中是否包含指定元素

示例 a=?( 1 3 5 7 9 ) car(a) => 1

cdr(a) => ?(3 5 7 9 ) cadr(a) => 3 nth(4 a) => 9

member( 5 a ) =>?(5 7 9) member( 4 a ) => nil

? 添加和移除元素

cons( item list ),将单个元素插入到列表的最前面成为列表的第一个元素; append1(item list),和cons正好相反,将元素插入到列表的最末尾; append(list1 list2),合并2个列表为一个; remove(item list),从列表中删除指定的元素。

示例 a=?(1 3 5 7 9)

cons( 2 a )=>?(2 1 3 5 7 9) append1( a 2 ) => ?(1 3 5 7 9 2 )

append( a ?(“a” “bc”))=>?(1 3 5 7 9 “a” “bc”) remove( 5 a )=>?( 1 3 7 9 )

32

? 列表元素排序

sort(list comparefunc),根据比较函数来给列表排序,比较函数可以自己定义; reverse(list),反向排列列表

示例 a=?(5 3 7 0 9)

sort( a ?lessp )=>?(0 3 5 7 9) reverse(a)=>?(9 0 7 3 5)

? 其它

length,sortcar,tableToList,listp,last…请参考skill函数文档

? 关联列表

列表中的每个元素都是一个子列表,且这些字列表由2个元素组成,也就是所谓的键值对,这样的列表称为关联列表。如'( ( \,参考函数assoc。

关联表格 table

关联表格和数组类似,每一个表格相对应一个数值,同样在一个表格里面的数据类型可以是不一样的,不同的是数组的索引值是数字如 declare(week[7]), week[0]=”Mon”,而列表的索引值可以是任何值,如table = makeTable(“new table”), table[1]=”hello”, table[“yes”]=”sure”。

? 申明表格

申明表格使用关键字makeTable,如table1=makeTable(“hello” 1),定义了表格table,这个表格的名字是”hello”,所有未初始化的表格元素的值都是1,table1[1]=>1, table1[“a”]=1。

? 常用函数

tableToList(table),转换表格为列表形式,如tableToList(table1)=>?((1 1) (“a” 1))

33

tablep(table),判断是否为表格类型

struct

? 待写

Cadence数据库数据dbid

dbid及database id,就是数据库中的标识,每个Cadence软件平台中的数据都有这样的一个dbid,skill函数就是通过这些id来操作数据库文件。比如说PCB Layout工具allegro,每一个在一个设计中的线路,电阻,网络都各自有个dbid,通过相应的函数可以直接读取到这个id。通过这个id可以得到这个id的相关信息,也可以得到相关信息的dbid… 定义函数

Skill 中常用的2个定义函数的关键字是procedure,lambda。

? procedure procedure的基本语法,

procedure( funcname( args) expX… )

示例

procedure( trAdd( x y ) ;定义了包含2个参数的函数trAdd printf( \ x+y ;默认的返回值

34

)

=> trAdd

trAdd( 6 7 ) => 13 ;函数名trAdd,2个参数6和7

? lambda lambda的基本语法,

trAddWithMessageFun = lambda( ( x y )

printf( \ x+y

) => funobj:0x1814b90

lambda定义的函数没有函数名,所以将其赋值给一个变量。使用apply调用一个lambda函数,apply( trAddWithMessageFun '( 4 5 ) ) => 9 局部和全局变量

? 定义局部变量

定义局部变量的2个关键字let和prog。let和prog的区别在于函数的返回值,let的返回值是let()中的最后一句表达式,prog的返回值比较多样,还包括return命令的返回值。相对于let,prog还多了项功能,在prog()中多了一个循环功能,支持go命令。

? let

如let( ( args ) expX…),在let中的变量args在let()范围有效,在let()范围外没有意义,不存在。

35

? prog

如prog( ( args ) expX…),在prog中的变量args在prog()范围有效,在prog()范围外没有意义,不存在。

? 定义全局变量

不在prog和let里面指定定义变量的地方定义的变量都是全局变量,但是请尽量少使用全局变量。关键字defvar可以用来定义全局变量,如defvar(globalvar)。 返回值

如上节所示,使用let或不使用let和prog的函数返回值都是函数中最后的表达式,使用prog的情况下,会增加因为return语句带来的返回情况。 输入参数定义

输入参数有2种必然情况和3中可选情况

? 必然

? 不含参数的函数

如 procedure( hello() println( “hello, world!”) ) 运行它 hello=>”hello,world!”

? 含参数的函数

如 procedure( hello( arg )

printf(“hello, how are you %s” arg) )

运行它 hello=>函数调用错误,必须提供一个参数 hello(“Emily”)=>”hello,how are you Emily”

36

? 可选,有3种可选的情况,@rest,@optional,@key

? @rest

@rest选项允许任意数量的参数以列表的形式传入函数,跟在@rest后面的参数的名字是任意的,请参考下例

procedure( trTrace( fun @rest args ) let( ( result )

printf( \ result = apply( fun args )

printf( \ result ) ; let ) ; procedure

调用函数 trTrace( 'plus 1 2 3 ) => 6,其实是运行了apply( plus 1 2 3 )。

? @optional

@optional选项允许设置一些有默认值的输入参数,如果调用函数的过程中提供了这些参数的值,新值将替换默认值。

procedure( trBuildBBox( height width @optional ( xCoord 0 ) ( yCoord 0 ) ) list(

37

xCoord:yCoord ;;; lower left

xCoord+width:yCoord+height ;;; upper right ) ) ; procedure

在这个示例中xCoord和yCoord的默认值都是0。运行

trBuildBBox( 1 2 ) => ((0 0) (2 1)) ; xCoord,yCoord值保持0

trBuildBBox( 1 2 4 ) => ((4 0) (6 1)) ; xCoord值改为4,yCoord值保持0 trBuildBBox( 1 2 4 10) => ((4 10) (6 11)) ; xCoord值改为4,yCoord值改为10

? @key

@key作用和@optional相同,只是@key中的参数可以以任意的顺序调用。

procedure( trBuildBBox(

@key ( height 0 ) ( width 0 ) ( xCoord 0 ) ( yCoord 0 ) ) list(

xCoord:yCoord ;;; lower left

xCoord+width:yCoord+height ;;; upper right ) ) ; procedure

38

运行

trBuildBBox() => ((0 0) (0 0)) ; 什么默认值都不改变

trBuildBBox( ?height 10 ) => ((0 0) (0 10)) ;只改变height的值

trBuildBBox( ?width 5 ?xCoord 10 ) => ((10 0) (15 0));改变width和xCoord

4.5 类型检查 Skill提供了函数输入参数类型的检查的功能。

字符 含义

S Symbol or string

n Number (fixnum, flonum)

u Function – either the name of a function(symbol) or a lambda function body (list) g Any data type

示例 procedure( f(x y \,nn表示函数f需要2个数字类型的参数输入 函数的限制 函数的几个限制

? 必须的参数数量小于255 ? 可选的参数数量少于255

? 在let, prog中使用的参数数量少于255 ? 一个函数所能容纳的参数量不多于32k 示例

39

? go在prog中的应用

procedure( guessNum(arg) prog(

unless( numberp(arg)

println(\

go( SkipToEnd ) ;如果输入类型不对,程序将直接跳转到SkipToEnd )

if( fixp( arg ) then

println( \ else

println( \ ); end if SkipToEnd ); end prog ); end procedure

? lambda的运用

signalList = '( “abc\ \sort( signalList

'lambda( ( a b ) strlen(a) <= strlen(b) )

; lambda这里定义了一个字符长度比较函数

40

); 输出结果为?(\