skill入门教程
skill入门
函数调用
ciw直接输入
1 |
|
load/loadi skill文件
1.loadi与load相同,除了loadi会忽略load过程中遇到的错误,打印出错误,然后继续执行后面的语句;load遇到错误会终止之后的语句
2.读者可以将上述语句写到文件里面,通过load文件的方式调用
3.如果函数没有嵌套,参数没有歧义可以省略 ( )
其他调用方法
在使用中还会使用menu、form、bindkey、callback等方式调用,在后面的章节都会讲解
注释
;(英文分号,单行注释)
/* */ (块注释)
数据类型
常用数据类型表
数据类型 | 类型符号 | 示例 | 判断类型函数 |
---|---|---|---|
Integer | x | 10 | integerp() |
floating point | f | 10.0 | floatp() |
symbol | s | ‘foo | symbolp() |
string | s | “hello kitty” | stringp() |
list | l | list(1 2 3) | ‘(1 (2 3) 4) |
boolean | b | t nil | booleanp() |
数据类型
查看数据类型type()
1 |
|
判断数据类型
各种数据类型都有对应函数判断是否是此类型,通常以数据类型+字母p表示
1 |
|
list
list简介
list是Skill数据对象的有序集合. list是Skill语言的核心,用途非常广泛. list的元素可以是任意的数据类型,包括变量,也可以任意嵌套
list(显示) | 说明 |
---|---|
(1 2 3) | 含有3个整数的list |
(1 “abc” 2.0) | 含有3个不同数据类型的list |
(1 (2 3) 4) | 嵌套的list,长度为3 |
() | 空list,等价于 nil,长度为0 |
(nil) | 含有一个空元素的list,长度为1 |
1.0:2.5 | 坐标x:y,也是一个list,等价于 (1.0 2.5) |
a=”abc” (1 a) | 含有变量的list |
创建list的方法
1 |
|
获取list的方法car cdr last nth
car获取list的第一个元素
cdr获取list除去第一个元素的剩下部分
last获取list的最后一个元素组成的list
nth获取list的第n个元素,n从0开始计
x=’(1 2 3 4 5 6 7)
y=’(((1 2 3) (4 5 6)) (7 8 9))
函数 | 返回值 | 说明 |
---|---|---|
car(x) | 1 | 元素 |
cdr(x) | (2 3 4 5 67) | list |
last(x) | (7) | list |
nth(2 x) | 3 | 元素 |
car(y) | ((1 2 3) (4 5 6)) | 元素(是个嵌套list) |
caar(y) | (1 2 3) | 等价于car(car(y)) |
caaar(y) | 1 | 等价于car(car(car(y))) |
cdar(y) | ((4 5 6)) | 等价于cdr(car(y)) |
cddar(y) | (1 2 3) | 等价于cdr(cdr(car(y))) |
c1234r()=c1r(c2r(c3r(c4r())))
list中添加元素 cons/xcons append1 tconoc
cons/xcons 向list头部添加元素
append1向list尾部添加元素
tconc 向list尾部添加元素,速度更快
注意tconc是破坏性函数,修改了原list,不需要赋值给原变量
1 |
|
x=’(1 2 3) y=’(4 5 6)
函数 | 返回值 | 说明 |
---|---|---|
cons(4 x) | (4 1 2 3) x 不变 | |
xcons(x 4) | (4 1 2 3) 与cons作用相同,参数位置不同 | |
k=append1(x 4) | (1 2 3 4) car(last(k)) 获取最后一个元素4 | |
z=tconc(nil 1) | ((1) 1) | |
tconc(z 2) | ((1 2) 2) | 修改了z本身 |
tconc(z 3) | ((1 2 3) 3) | 修改了z本身 |
tconc(z 4) | ((1 2 3 4) 4) | cadr(z) 获取z最后一个元素 4 |
list合并append nconc lconc
append()
nconc 速度更快
lconc 速度最快
nconc/lconc都是破坏性函数修改了原list,不需要赋值给原变量 破坏性函数的区别
x=’(1 2 3) y=’(4 5 6) z=’(1 2 3 4)
函数 | 返回值 | 说明 |
---|---|---|
append(x y) | (1 2 3 4 5 6) | x 不变 |
nconc(x y) | (1 2 3 4 5 6) | x 被修改为 (1 2 3 4 5 6) |
lconc(z ‘(5 6)) | ((1 2 3 4 5 6) 6) | 利用tconc结构,修改了z本身 |
list删除元素remove remd
remove 返回一个新list
remd 破坏性函数
注意:list的赋值实际上是指针的引用,例如 a=’(1 2) b=a, 变量a 和 b 共享值 (1 2),当a被修改时,b也同时被修改
x=’(2 4 6 8 10) y=x
函数 | 返回值 | 说明 |
---|---|---|
z=remove(6 x) | (2 4 8 10) | x→ (2 4 6 8 10) y→ (2 4 6 8 10) |
remd(6 x) | (2 4 8 10) | x→ (2 4 8 10) y→ (2 4 8 10) |
remd(2 x) | (2 4 8 10) | list的第1个元素不会被修改 x→(2 4 8 10) y→ (2 4 8 10) |
x=remd(2 x) | (4 8 10) | x被重新赋值 x → (4 8 10) y→ (2 4 8 10) |
替换list元素rplaca rplacd
rplaca 替换第一个元素
rplacd 替换除第一个元素之外剩下的部分
注意:这两个函数都是破坏性函数
x=’(2 4 6) y=’(2 4 6)
函数 | 返回值 | 说明 |
---|---|---|
rplaca(x 8) | (8 4 6) | x→ (8 4 6) y → ( 2 4 6) |
rplacd(y ‘(1 3 5)) | (2 1 3 5) | x→ (8 4 6) y→ (2 1 3 5) |
list数据其他操作member length reverse setof sort
member 判断元素是否存在于list
length 获取list长度
reverse 倒序list
setof 过滤
sort 排序
x=’(2 4 1 3 4) y=’(“bag” “Zoom” “dog”)
函数 | 返回值 | 说明 |
---|---|---|
member(4 x) | (4 1 3 4) | 返回从查看元素第一次出现到结尾的部分,不为空说明存在 |
member(5 x) | nil | 返回值nil,说明不存在 |
length(x) | 5 | 长度为5 |
length(nil) | 0 | nil等效于长度为0 的list |
length(‘(nil)) | 1 | 长度为1 |
reverse(x) | (4 3 1 4 2) | 倒序 |
setof(y x evenp(y)) | (2 4 4) | 过滤出偶数 |
setof(y x y>2) | (4 3 4) | 过滤出大于2的数 |
sort(x ‘lessp) | (1 2 3 4 4) | 数字从小到大排序 |
sort(y ‘alphalessp) | (“bag” “Zoom” “dog”) | 字符串按照字母排序 |
list常用操作方式
1 |
|
函数 | 返回值 |
---|---|
caar(bBox) leftEdge(bBox) |
xLL |
cadar(bBox) bottomEdge(bBox) |
yLL |
caadr(bBox) leftEdge(bBox) |
xUR |
cadadr(bBox) topEdge(bBox) |
yUR |
car(pLL) xCoord(pLL) |
xLL |
cadr(pLL) yCoord(pLL) |
yLL |
centerBox(bBox) | ((xLL+xUR)/2 (yLL+yUR)/2) |
string
string简介
string(字符串)是字符的有序集合,用”标识,string由以下两类字符组成:
1.可打印字符(除了”)就是字符本身,”A-Za-z0-9_”,”! ? - + . * …”
2.不可打印字符和”本身, 需要在前面加上转义字符\
不可打印字符 | 转义字符 | 说明 |
---|---|---|
new-line | \n | 换行 |
horizontal tab | \t | 制表符Tab |
vertical tab | \v | 纵向制表符 |
backspace | \b | 空格 |
carriage return | \r | 回车 |
form feed | \f | 换页符 |
backslash | \\ | |
double quote | \" | |
ASCII code ddd(octal) | \ddd |
string常用函数strcat length buildString parseString
函数 | 返回值 | 说明 |
---|---|---|
strcat(“AB” “cd” “3”) | “ABcd3” | 连接字符串 |
length(“ABcd3”) | 5 | 获取字符串长度 |
length(“”) | 0 | 空字符长度为0 |
length(“\n”) | 1 | 转义字符长度为1 |
buildString(‘(“AB” “cd” “3”)) | “AB cd 3” | 由list构造字符串,默认分隔符是空白符 |
buildString(‘(“AB” “cd” “3”) “-“) | “AB-cd-3” | 由list构造字符串,指定分隔符为 - |
parseString(“A-B a-b”) | (“A-B” “a-b”) | string转换成list,默认分隔符为空白符 |
parseString(“A-B parse String” “-“) | (“A” “B a” “b”) | string转换成list,指定分隔符为- |
string截取函数index rindex substring
字符串比较是指从左到右依次比较每个字符的大小,按第1个不相等的字符决定两个字符串大小
函数 | 返回值 | 说明 |
---|---|---|
index(“abcbdbce” ‘b) | “bcbdbce” | 截取从第2个参数第1次开始的剩余字符串 |
index(“abcbdbce” “bc”) | “bcbdbce” | 截取从第2个参数第1次开始的剩余字符串 |
rindex(“abcbdbce” “bc”) | “bce” | 从右截取第2个参数第1次开始的剩余字符串 |
substring((“abcdefgh” 2 4)) | “bcde” | 从第2个字符开始截取4个字符 |
substring((“abcdefgh” 4 2)) | “de” | 从第4个字符开始截取2个字符 |
substring((“abcdefgh” -4 2)) | “ef” | 从右侧第4个字符开始截取2个字符 |
string查找函数nindex
函数 | 返回值 | 说明 |
---|---|---|
nindex(“abcbdbce” “bc”) | 2 | 获取第2个参数开始的索 |
nindex(“abcbdbce” “bg”) | nil | nil说明stirng不存在第2个参数 |
string比较函数strcmp strncmp
函数 | 返回值 | 说明 |
---|---|---|
strcmp(“abc” “abb”) | 1 | 按字符比较字符串 |
strcmp(“abc” “abc”) | 0 | 按字符比较字符串 |
strcmp(“abc” “abd”) | -1 | 按字符比较字符串 |
strncmp(“abc” “ab”3 ) | 1 | 指定最多比较几个字符 |
strncmp(“abc” “de” 4) | -1 | 指定最多比较几个字符 |
strncmp(“abc” “ab” 2) | 0 | 指定最多比较几个字符 |
string排序函数sort
函数 | 返回值 | 说明 |
---|---|---|
sort(‘(“ab” “34” “XY” “123”) ‘alphalessp) | (“123” “34” “XY” “ab”) | 字符串排序 |
string大小写转换函数upperCase lowerCase
函数 | 返回值 | 说明 |
---|---|---|
upperCase(“abCdE”) | “ABCDE” | string转换成大写 |
lowerCase(“abCdE”) | “abcde” | string转换成小写 |
string正则
rexMatchp
可以按照正则的规则判断一个字符串中有无符合的字符,感觉这个功能非常鸡肋。
函数 | 返回值 | 说明 |
---|---|---|
rexMatchp(“[0-9][.][0-9][0-9]“ “100.001”) | t | 查找pattern,有 |
rexMatchp(“[0-9]*[.][0-9]+” “.001”) | t | 查找pattern,有 |
rexMatchp(“[0-9]*[.][0-9]+” “.”) | nil | 查找pattern,无 |
rexMatchp(“[0-9][.][0-9][0-9]“ “10.”) | nil | 查找pattern,无 |
正则匹配rexCompile rexExecute rexMatchp pcreCompile pcreMatchp
rexCompile用来创建正则的匹配规则,成功创建之后会返回t
1 |
|
rexExecute根据最后一次的rexCompile中的pattern进行查找
1 |
|
rexMatchp,使用这个函数,最近的pattern也会被修改
1 |
|
pcreCompile与rexCompile功能一致,但是好处是可以赋值给变量,直接调用变量即可
pcreMatchp与rexMatchp功能一致,建议使用pcer代替rex
正则替换rexReplace rexSubstitute pcreReplace pcreSubstitute
1 |
|
函数 | 返回值 |
---|---|
rexCompile( “[0-9]+” ) | t |
rexReplace( “abc-123-xyz-890-wuv” “(*)” 1) | “abc-(*)-xyz-890-wuv” |
rexReplace( “abc-123-xyz-890-wuv” “(*)” 2) | “abc-123-xyz-(*)-wuv” |
rexReplace( “abc-123-xyz-890-wuv” “(*)” 3) | “abc-123-xyz-890-wuv” |
rexReplace( “abc-123-xyz-890-wuv” “(*)” 0) | “abc-()-xyz-()-wuv” |
rexCompile(“^teststr”) | t |
rexReplace(“teststr_a” “bb” 0) | “bb_a” |
rexReplace(“teststr_a” “bb&” 0) | “bbteststr_a” |
rexReplace(“teststr_a” “[&]” 0) | “[teststr]_a” |
rexSubstitute的功能和rexReplace相反,是把没有匹配到的字符进行替换
1 |
|
函数 | 返回值 |
---|---|
p1=pcreCompile( “[0-9]+” ) | t |
pcreReplace( p1 “abc-123-xyz-890-wuv” “(*)” 1) | “abc-(*)-xyz-890-wuv” |
pcreReplace(p1 “abc-123-xyz-890-wuv” “(*)” 2) | “abc-123-xyz-(*)-wuv” |
pcreReplace(p1 “abc-123-xyz-890-wuv” “(*)” 3) | “abc-123-xyz-890-wuv” |
pcreReplace(p1 “abc-123-xyz-890-wuv” “(*)” 0) | “abc-()-xyz-()-wuv” |
p2=pcreCompile(“^teststr”) | t |
pcreReplace(p2 “teststr_a” “bb” 0) | “bb_a” |
pcreReplace(p2 “teststr_a” “bb&” 0) | “bbteststr_a” |
pcreReplace(p2 “teststr_a” “[&]” 0) | “[teststr]_a” |
number
数字分为浮点数和小数
整数之间加减乘除结果还是整数
整数与浮点数、浮点数与浮点数之间运算结果是浮点数
函数 | 返回值 | 说明 |
---|---|---|
abs(-1) | 1 | 绝对值 |
max(1 2 3) | 3 | 最大值 |
min(1 2 3) | 1 | 最小值 |
evenp oddp | 判断偶数/奇数 | |
floatp intp | 判断浮点数/整数 | |
float(1) | 1.0 | 转换成浮点数 |
int(1.2) | 1 | 转换成整数 |
mod(9 2) | 1 | 取余 |
modf(9.2 2.0) | 1.2 | 浮点数取余 |
ceiling(3.5) | 4 | 向上取整 |
floor(3.5) | 3 | 向下取整 |
round(3.5) | 4 | 四舍五入取整 |
round(3.49) | 3 | 四舍五入取整 |
sqrt(4) | 2.0 | 开平方 |
变量
变量的命名
Skill里的变量不需要事先声明
变量由字母/数字/下划线/问号组成 A-Za-z0-9_?
不建议使用?
不建议使用数字开头
命名有意义
作用域
全局变量:默认就是全局变量,在脚本中尽量避免使用全局变量,容易引起不易察觉的错误
局部变量:使用let 或是prog 定义局部变量,局部变量只在作用域内生效
数据结构
最常用的数据结构 defstruct 以及相关操作符 ~>defstruct 是一个包含一个或多个 属性名-属性值 对的集合
Skill的defstruct与python语言的字典类似,属性名-属性值对应python的键命-键值, 都有不同的方法(~>? 或 ~>??)获取属性名或者属性名-属性值
1 |
|
操作符
数学运算符号
操作符也有其对应的函数
1 |
|
完整的运算符请查阅文档的关键字Arithmetic and Logical Operators
比较运算符
函数 | 返回值 |
---|---|
2>1 | t |
2<1 | nil |
2>=1 | t |
2<=1 | nil |
2!=1 | t |
2==1 | nil |
逻辑运算符
空list的逻辑值为nil
其它逻辑值为t
逻辑运算符 | 返回值 | 说明 |
---|---|---|
t && nil | nil | 所有值都为t时,则返回t,否则返回nil |
0 && 1 && 2 | 2 | 如果都为t,则返回最后的值 |
t || nil | 1 | 所有值都为nil时,则返回nil,否则返回t |
nil || 1 || 2 | t | 如果有值为t,返回第一个非nil值 |
!t | nil | 取反 |
!list() | t | 取反 |
函数
function
skill里的function可以用三种形式
1 |
|
函数内括号内可以换行
一行可以写多个函数,空格分开
procedure
procedure的几种定义方式
无参数
1 |
|
FunName1();~>hello world
固定位置参数
1 |
|
FunName2(“hello” “world”);~>hello world
任意个数参数
1 |
|
FunName3(“1” “3” “2”);~>1 3 2
可选参数,必须给定默认值
1 |
|
FunName4();~>red
FunName(yellow);~>yellow
关键词参数,给定默认值
1 |
|
FunName5();~>apple red
FunName5(?name “pear”);~>pear red
FunName5(?color “blue” ?name “pear”);~>pear blue
组合参数@optional 和 @key 不能同时使用
1 |
|
FunName6(“apple”);~>apple is red
FunName6(“apple” “green”);~>apple is green
1 |
|
FunName7(“apple”);~> big apple is red
FunName7(“pear” ?color “yellow”);~> big pear is yellow
FunName7(“apple” ?color “green” ?size “small”);~> small apple is green
组合参数@rest 与 @optional或是@key混用时,@rest必须在最后面
1 |
|
FunName8(1);~> 2
FunName8(1 2);~> 3
FunName8(1 2 3 4);~> 10
匿名函数lambda
与procedure定义函数,需要指定函数名不同,lambda定义一个匿名函数,它返回一个函数对象,可以赋值给一个变量
lambda 函数经常导致代码难以理解,建议使用procedure定义函数;但是在某些情况下或者需要传递一个很小功能的函数时,ambda函数就非常有用了
1 |
|
apply(myPower ‘(3 2));~>9
1 |
|
~>> (
(“a” 0.4)
(“c” 1.5)
(“b” 2.5)
)
函数的范围
作用域
返回值
在let里,函数的最后一个表达式或是语句的结果作为返回值
在prog里使用return明确指定返回值, 如果没有return,则返回 nil
在prog里,可以有多个return语句,遇到哪个return,就执行哪个return;执行return语句之后跳出当前函数,return之后的语句不再执行
1 |
|
x=myFunc10();x~>2
1 |
|
x=myFunc11();x~>11
输出
print 输出内容
println 输出内容,末尾会额外打印一个换行符
printf 格式化输出,常用格式如
%L 默认格式
%d 整数
%–n.mf 浮点数 (n长度 m精度,- 左对齐)
%-ns string ( n长度,-左对齐) n长度是指如果内容的长度小于n,则用空格填充;如果内容长度大于n,则按照实际长度输出
Format | Type(s) of Argument | Prints |
---|---|---|
%d | 整数 | 十进制整数 |
%o | 整数 | 八进制整数 |
%x | 整数 | 十六进制整数 |
%f | 浮点数 | 浮点数 [-]ddd.ddd |
%e | 浮点数 | 科学计数法 [-]d.ddde[-]ddd |
%g | 浮点数 | 根据值的大小自动选择 %f 或者 %e,有可能有精度损失 |
%s | string、symbol | 不含引号的stirng或者是symbol的名字 |
%c | string、symbol | 第一个字符 |
%n | 整数、浮点数 | 数字 |
%P | list | X:Y 形式的点坐标 |
%B | list | (X1:Y1 X:Y2)形式的Box |
%N | any | Prints an object in the old style, that is,does not call the printself function |
%L | list | 默认格式 |
%A | any | Prints any type of object using the printself representation |
流程控制
条件判断分支branch
if(… then … else …)
当if 语句的条件为真时,执行then后面的语句;为假,执行else后面的语句.
if 语句可以嵌套, else 分支可选条件判断时,除了il和list() 其余都为真需要注意, if 与 ( 之间没有空格
1 |
|
when unless
如果只有then部分执行时候,使用when语句. 结构更加清晰
1 |
|
如果只有条件为假时执行,使用unless与if(… then…)正好相反,避免了假假为真这种令人困惑的写法
1 |
|
case
使用case可以进行多个条件的判断
case 语句自上而下依次比较变量的值,如果有相等的,执行当前分支;后面的分支不再执行
如果所有的值都不匹配,则执行最后的t分支
1 |
|
cond
与case 类似,可以做更复杂条件的判断
cond 语句自上而下依次进行测试,如果条件满足,执行当前分支;后面的分支不再执行
如果所有测试条件都不满足,则执行最后的t分支
1 |
|
循环迭代Iteration
while
1 |
|
for
1 |
|
foreach
1 |
|
1 |
|
1 |
|
文件操作
文件写入操作
1.outfile 打开文件并获取输出端口,需要确保输出与文件具有可写权限
2.fprintf 格式化写入数据到端口
3.close 关闭文件(输出端口)
1 |
|
文件读取操作
1.infile 打开文件并获取输出端口
2_1.fscanf 从输入端口格式化读入数据,读取的方式是以”word” (即以空白符(空格、Tab、换行符)为分隔的字符串) 为单位依次读取,然后赋值给变量.不可以读取空白符
2_2.gets 从输入端口以行为单位读取数据.可以读取空白符
3.close 关闭文件(输出端口)
1 |
|
1 |
|
快捷键绑定BindKey
1 |
|
KeyName | 键位说明和动作 |
---|---|
key | 就是键盘上的那些按键例如a 2,按下符号类按键需要写英文名字 |
Ctrl | Control key,控制键,需要与其他键组合使用 |
Shift | Shift key,控制键,需要与其他键组合使用 |
Alt | Alt key,控制键,需要与其他键组合使用 |
Btn1Down | 鼠标左键按下 |
Btn2Down | 鼠标中键按下 |
Btn3Down | 鼠标右键按下 |
Btn4Down | 鼠标滚轮前滚 |
Btn5Down | 鼠标滚轮后滚 |
DrawThru1 | 鼠标左键按下并且拖动 |
DrawThru2 | 鼠标中键按下并且拖动 |
DrawThru3 | 鼠标右键按下并且拖动 |
1 |
|
api命名规则
API的命名规则如下
类别 动作 对象
类别通过不同的前缀区分,常用前缀与含义如下
动作常用的 Get Set, 其它如 Create,Add ,Select, Open, Close,Move ,Align ,Copy Save 等等
对象:例如 Pin, Rect,Inst ,Path, Wire ,CellView等等
prefix | 含义或类别 | 一般用法 |
---|---|---|
le | Layout Edit (GUI) | 编辑版图 |
sch | schematic(GUI) | 编辑电路 |
hi | (GUI) | 编辑gui里的内容(各类弹窗) |
ge | Graphic Edit(GUI) | 与hi类似 |
db | database (None GUI) | 数据结构 |
dd | ||
pte | Palette, 包括LSW/Objects/Grids等 | |
cdf | CDF(Component Description Format) | pcell制作 |