SKILL for the Skilled: What is SKILL++? (訳)

本記事は、
"SKILL for the Skilled: What is SKILL++?"
の訳です。誤訳がふんだんに含まれていると思いますので、詳細は、オリジナルの英語のブロクを参照してください。

ここから

関数の扱い方という点で、SKILL++は従来のSKILLとは異なっている。この記事では、SKILL++でデザインの階層をたどっていく方法を紹介することで、SKILL++を紹介したい。

What is SKILL++?(SKILL++とは何か?)

SKILL++はSKILLとは異なる言語だと考えているかもしれませんが、実際にはSKILLのサブセットです。SKILL++の構文は非常に小さいものですが、1990年代中頃には、SKILLコアに強力な拡張性をもたらしました。そして、今ではたくさんのCadenceツールの中で使用することができます。実際、SKILLがロードされ実行されるプログラム(例えば、Virtuoso, VirtuosoXL, pipo, Assura, Dracula, PVS, Allegro-PCB, cdnsip, その他色々)であれば、SKILL++で置き換えることができます。

基本的な言語の機能は以下のとおりです。

  • レキシカルスコープの変数
  • 単一関数/変数名前空間(Lisp-1)
  • CLOS準拠のオブジェクトシステム

対照的に、SKILLはダイナミックスコープの変数システムであり、変数と関数の名前空間も別々であった(Lisp2)。ダイナミックもレキシカルスコープもどちらもそれぞれの目的を達成するために便利なものである。

What are dynamic and lexical variables? (変数におけるダイナミックスコープとレキシカルスコープとは?)

この二つの違いは文法的なものではなく、セマンティックなものである。SKILL++に現れる変数は全てレキシカルスコープであるのに対して、SKILLでは、全ての変数はダイナミックスコープである。

両者のセマンティックの違いは以下のものである

  • ダイナミック変数は、SKILLが実行中(つまり、関数もしくは、その関数から呼び出された関数が評価を一時停止している間)に特定の値をコントロールするための仕組みである。この評価が一時停止している期間では、ダイナミック変数は、明示的に他の閉じた環境に隠蔽されない限りは、大域環境から見ることができる。
  • レキシカル変数は、関数からオブジェクトの可視性を分離するためのものである。そのため、限られた表現のみでしか、名前を通して値にアクセスすることができない。評価が一時停止している間でもアクセスすることはできない。

Perceptions of SKILL++

この記事では、SKILL++のオブジェクトシステムについては説明せずに、SKILL++の上の二つの特徴について述べる。ここは、SKILL++がSchemeの方言と呼ばれる部分である。残念なことに、他のSchemeの方言は市場に通じる名前を持っていない。そのため、我々は、SKILLの名前を借りて、SKILL++ Scheme方言ではなく、SKILL++と呼ぶことにした。

もし、SKILL++をまだ使ったことがないなら、基礎はあなたが考える以上にシンプルであることに驚くだろう。
また、もしSKILL自体が初めてだとしたら、SKILL++が簡単でかつ直感的であることに驚くだろう。もし、あなたがベテランのSKILLプログラマだとしたら、あなたがSKILLを学び始めた25年前と同じように、SKILL++を使えるようになるであろう。つまり、あなたは既に困難なことは習得済みなのである。今や簡単に習得することができるだろう。

How to create SKILL++ code(SKILL++コードの作り方)

SKILLインタプリタにSKILL++として解釈させたい場合、プログラムの拡張子に.ilsを付けるだけで良い(ちなみに、.ilはSKILLプログラムのことである)。つまり、file.ilsはSKILL++プログラムと解釈され、file.ilはSKILLプログラムと解釈される。

ここから先に出てくるコードは全てSKILL++用のものである。

SKILL++ by example

最初の例は、walkCvHierである。これは、デザインの階層を辿る最もシンプルなプログラムである。あなたが必要な機能は満たしていないが、例としては分かりやすいものである。

(defun walkCvHier (cv consume)              ;(1.1)
  (foreach inst cv~>instances               ;(1.2)
    (walkCvHier inst~>master consume))      ;(1.3)
  (consume cv))                             ;(1.4)

この関数は、引数の一つに関数をとっている。すなわち、高階関数である。後の記事で紹介する予定であるが、SKILL++では、引数に応じて、実行時に他の関数を作ったりすることが可能である。SKILLでも高階関数をつくることは可能であるが、もし、高階関数を作る必要があるならば、常にSKILL++を使ったほうがよいであろう。

これは、どのように働くだろうか? walkCvHier関数は、指定されたcell view(例えばlayout view)を通って、下層のインスタンスマスターに階層ダウンする。それぞれの階層で、引数として与えた関数が適用される。関数がその引数としてcellViewを取れる限り、関数を実行することができる。walkCvHier関数は階層を持ったcellViewと関数を指定したら、全てのインスタンスに対して、関数が実行される。

Saving the hierarchy?

walkCvHierを使用した例を示す。saveCvHier関数は、階層内の全cellViewに対して、dbSaveが呼ばれるように、walkCvHier関数に渡したものである。

(defun saveCvHier (cv)        ;(2.1)
  (walkCvHier cv dbSave))     ;(2.2)

walkCvHier関数は、1.1行で宣言されているように、ローカル変数consumeを持っている。そして、consumeは、1.4行で関数呼び出しの位置(consume cv)で使われている。このプログラムはSKILL++なので、consumeと言う大域関数を参照しているのではなく、consumeと言うローカル変数に束縛されているモノを使用しているのである。今の場合、consumeが束縛している値は関数である(単なる変数が束縛されている場合、実行時エラーとなる)
。2.2行目では、saveCvHier関数は第2引数としてdbSave関数を呼んでいる。以下に、このプログラムの重要な点を書く。

  • 2.2行目のdbSaveの指定時にクォート(')を付けていない。なぜだろうか? これは、SKILL++では大域関数の名前を変数名と同様に扱えるためである。
  • consume関数は、1.4行で通常の関数と同じように呼び出されている。なぜだろうか? SKILL++では大域関数もローカル関数も同じ文法で呼び出すことができるからである。
  • consumeと言う名前は、camlケースでもアンダースコアでも書かれていない。真にローカル変数の命名ルールに従っているからである。

Reporting the hierarchy(階層的なレポーティング)

階層ツリーでdbSaveを呼ぶのではなく、ビルトイン関数ではない何かを呼ぶことを考える。例えば、階層を下っていって、cellViewが見つかるたびにcellViewの情報をレポートしたい場合、一つのcellViewの情報を出力する関数を定義してやればよい。一つの方法としては、以下のように、_reportCvと言う補助関数を定義する方法である。

(defun _reportCv (cv)                 ;(3.1)
  (println (list cv~>libName          ;(3.2)
                 cv~>cellName         ;(3.3)
                 cv~>viewName)))      ;(3.4)
                                      ;(3.5)
(defun reportCvHier (cv)              ;(3.6)
  (walkCvHier cv _reportCv))          ;(3.7)

ここで、_reportCvはプライベートな関数であり、一度しか呼ばれないにも関わらず、_reportCvはdefunで定義されているため(procedureでも同様)、大域の関数になってしまう。すなわち、プライベートな状態にはならないのである。過去、SKILLでは名前付けの慣習やドキュメントに記載することで、アクセシビリティを実装していた。SKILL++では、もっとシステマチックな方法で、データを隠蔽することができる。

...to be continued...

つづく

What's next?

次回の記事では、局所関数、クロージャ(状態を持った関数)、そして、walkCvHierの別の例を示す。

Jim Newton