2024年12月22日くいなちゃん


プログラミング言語Kuin」の言語仕様9、スコープとファイルについてです。

1Kuinのスコープ

Kuinでは、ローカルなものの識別子を指定するときは名前そのままを書き、グローバルなものの識別子を指定するときは名前の前に「@」を付けて書きます(図1-1)。
  1. func globalFunc()
  2. end func
  3.  
  4. func main()
  5.   func localFunc()
  6.   end func
  7.  
  8.   do @globalFunc()
  9.   do localFunc()
  10. end func
図1-1: グローバルとローカルの識別子
この例では、グローバルな関数「globalFunc」を呼び出すときは「@globalFunc()」とし、ローカルな関数「localFunc」を呼び出すときはそのまま「localFunc()」としています。
グローバルなものはどこからでも参照できますが、ローカルなものは、それと同じかそれよりも内側のブロックからでしか参照できません。
例えば、ブロックの中にブロックがあった場合、内側から外側のブロックを参照できますが、外側から内側へは参照できません(図1-2)。
  1. func main()
  2.   for i(1, 10)
  3.     var m: int :: 2 + i
  4.     for j(1, 10)
  5.       var n: int :: i + j + m
  6.       var o: int :: n
  7.     end for
  8.   end for
  9. end func
図1-2: ブロックのスコープ
この例では、forブロック「i」「j」の内側で「i+j+m」のように参照したり、forブロック「i」の内側で「2+i」のように参照していますが、この「2+i」のところを「2+j」や「2+n」と書き換えることは、「j」や「n」が内側のブロックにあるためできません。

2Kuinのファイル

2.1ファイルの分割



Kuinでは、ソースコードを別のソースファイルに分けて読み込むことができます。
先ほど、ローカルのものはそのままの識別子で参照、グローバルのものは「@」を付けて参照と説明しましたが、別のソースのグローバルなものは「\ソース名@識別子」と書き、また標準ライブラリとして用意されているものは「ソース名@識別子」と書きます(図2-1)。
  1. func main()
  2.   do \other@f()
  3.   do lib@sleep(1000)
  4. end func
図2-1: 別ソースファイルの関数呼び出し
この例では、「other.kn」として作成した別ファイルのグローバル関数「f()」を呼び出しています。 また、Kuinの標準ライブラリ「lib.kn」の関数である「sleep(1000)」も呼び出しています。
ソース名の先頭に「\」が付いていればコンパイルするソースと同じディレクトリからソースがロードされ、「\」が付いていなければ標準ライブラリのディレクトリからロードされます。
また、ユーザが作成したソースは「\dir1\dir2\other@f()」のようにディレクトリを潜ってロードすることもできます。 「\..\」のようにディレクトリを上ることはできません。
ファイル名やディレクトリ名に使える文字は、小文字と数字と「_」のみで、先頭は数字以外にする必要があります。
ちなみに意図しないアクセスを防ぐために、デフォルトではすべてのものは別ファイルからアクセスできないようになっていて、アクセスできるようにするものには定義の先頭に「+」を付ける必要があります。 例えば、先ほどのother.knに定義されている関数「f」は、図2-2のように定義する必要があります。
  1. +func f()
  2. end func
図2-2: パブリックな関数
「+」を付けて別ファイルに公開できるものは、「func」の他に、グローバルの「var」「const」「alias」「enum」「class」があります。
以上をまとめると、表2-1のようになります。
表2-1: Kuinの識別子の参照方法
種類 参照方法
ローカル 識別子 do f()
自身のソースのグローバル @識別子 do @f()
別のソースのグローバル \ソース名@識別子 do \src@f()
標準ライブラリ ソース名@識別子 do src@f()

2.2include文



「@」より左側のソース名は同じままで、ソースコードを別ファイルに分割したいときは、include文を使います。
例えば「main.kn」の中身を、「main.part1.kn」と「main.part2.kn」の2つに分けて、「main.kn」の中に図2-3のように書くと、2つのファイルの中身が「main.kn」の中に埋め込まれて、「main.kn」の中に「main.part1.kn」と「main.part2.kn」の中身を直接書いたことと同じように扱われます。
  1. include part1
  2. include part2
  3.  
  4. func main()
  5. end func
図2-3: include文
1734843445jaf