ホームページに戻る

NoFollow

辿らない言語

NoFollowは僕の作ったプログラミング言語です。その名の通り、「辿らないこと」を目標にしています。

普通、Cのコードはこのように書きます。

#include <stdio.h>
int test(int x, int y){
  return (x + y);
}
int main(void){
  int x;
  int y;
  int a;
  x = 5;
  y = 7;
  a = test(x,y);
  printf("%d\n", a);
}

このC言語のコードでは、testを辿っていくことで、プログラムの理解へと近づきます。

NFは、こういう時、「プログラマが明示することで、辿らなくても大体のプログラムは分かる」ようにするための言語です。

例えば、

int main(void)

だけでも、このように分析出来ます。

int: func type;

main: func name;

void: func argument;

そして、それらはdefinitionです。

ですが、長くなってしまうと、そういうことを、コードを見て少し考えないと、分からなくなってしまいます。

このNFでは、このような「プログラムをあとで理解する思考コスト」を削減します。

そして、出来る限り、見ただけで分かるようにします。入門書を読む必要を無くします。

そういうわけで、NFでは以下のようなプログラムになります。

@def &main {
  @head {
    @type: main
    @return_type: int
    @arguments{
      $$_ { @type: void }
    }
  }
  @body {
    @def {
      $x { @type: int }
      $y { @type: int }
      $a { @type: int }
    }
    @run {
      $x = 5
      $y = 7
      $a = [return] [run] &test {
        $$value1 = $x
        $$value2 = $y
      }
      [run] &printf {
        $$format = "%d\n"
        $$option = $a
      }
    }
  }
}
@def &test {
  @head {
    @type: method
    @return_type: int
    @arguments{
      $$value1 { @type: int }
      $$value2 { @type: int }
    }
  }
  @body {
    @run {
      [run] &return { [run] &calculation { ($$value1 + $$value2) } }
    }
  }
}

なんとなく、最後の方のreturnやcalculationを何故引数の名前を明記しないのか、など、課題は残りますが、とりあえず、変数の引数まで名前をきちんと明記するような、そういう言語にしたいと思っています。

あまり意味がないですが、最近Rustと言う言語に関心があります。自分が見て、こうしたら良いと思うな、などと思うこともあります。技術力をつけて、Rustの改良が出来るようになったら良いなと思っています。

2016.12.15

ロボット

この言語を用いて、僕の人工知能のロボットを書いてみました。

[headers]
#include <stdio.h>
#include <stdlib.h>

@def _obj:: {
  @type: struct
  @items {
    $o { @type: int }
    $n { @type: int }
  }
}

@def &action {
  @head {
    @type: mathod
    @return_type: void
    @arguments{
      $$[p]p { @type: [p]int }
      $$[p]obj { @type: [p]struct _obj:: }
    }
  }
  @body {
[block "action-body"] //インデントを一度解除します。

[run] &case {

  @if "1" : //今回はPython風のインデントです。
    @match: { ($$*p == 0) }
    @run { [run] &printf { $$format = "[1] テレビは、つまらない\n"} }

  @if "2" :
    @match: { ($$*p == 1) }
    @run { [run] &printf { $$format = "[2] テレビは、面白い\n"} }

  @if "3" :
    @match: { ($$*p == 2) }
    @run { [run] &printf { $$format = "[3] パソコンは、つまらない\n"} }

  @if "4" :
    @match: { ($$*p == 3) }
    @run { [run] &printf { $$format = "[4] パソコンは、面白い\n"} }

  @if "5" :
    @match: { ($$*p == 4) }
    @run { [run] &printf { $$format = "[5] テレビやパソコンは、機械だ。\n"} }

  @if "6" :
    @match: { ($$*p == 5) }
    @run { [run] &printf { $$format = "[6] テレビやパソコンは、生き物ではない。\n"} }

  @if "7" :
    @match: { ($$*p == 6) }
    @run { [run] &printf { $$format = "[7] テレビって何なのだろう。\n"} }

  @if "8" :
    @match: { ($$*p == 7) }
    @run { [run] &printf { $$format = "[8] テレビとパソコンは好きだ。\n"} }

  @if "9" :
    @match: { ($$*p == 8) }
    @run { [run] &printf { $$format = "[9] テレビとパソコンは嫌いだ。\n"} }

  @if "10" :
    @match: { ($$*p == 9) }
    @run { [run] &case {
      @if "A" :
        @match: { ($$obj->$n == 0) }
        @run { [run] &printf { $$format = "[10] 比較すると、テレビの方が普通だ。\n"} }

      @if "B" :
        @match: { ($$obj->$n == 1) }
        @run { [run] &printf { $$format = "[11] 比較すると、パソコンの方が普通だ。\n"} }

    }

  @if "11":
    @match: { ($$*p == 10) }
    @run { [run] &case {
      @if "C" :
        @match: { ($$obj->$n == 0) }
        @run {
          [run] &printf { $$format = "[12] テレビよりパソコンの方が普通かな。\n"}
          $$obj->$n = 1
        }

      @else_if "D" :
        @match: { ($$obj->$n == 1) }
        @run {
          [run] &printf { $$format = "[13] パソコンよりテレビの方が普通かな。\n"}
          $$obj->$n = 0
        }
    }


  @if "12":
    @match: { ($$*p == 11) }
    @run { [run] &case {
      @if "E" :
        @match: { ($$obj->$o == 0) }
        @run { [run] &printf { $$format = "[14] リンゴが好きです。\n"} }

      @if "F" :
        @match: { ($$obj->$o == 1) }
        @run { [run] &printf { $$format = "[15] みかんが好きです。\n"} }
    }

  @if "13":
    @match: { ($$*p == 12) }
    @run { [run] &case {
      @if "G" :
        @match: { ($$obj->$o == 0) }
        @run {
          [run] &printf { $$format = "[16] リンゴより、みかんが好きになりました。\n"}
          $$obj->$o = 1
        }

      @else_if "H" :
        @match: { ($$obj->$o == 1) }
        @run {
          [run] &printf { $$format = "[17] みかんより、リンゴが好きになりました。\n"}
          $$obj->$o = 0
        }
    }
  }
[/block "action-body"]

  }
}

@def &main {
  @head {
    @type: main
    @return_type: int
    @arguments{
      $$_ { @type: void }
    }
  }
  @body {
    @def {
      $p { @type: int }
      $obj { @type: struct _obj:: }
    }
    @run {
      $p = 0
      $obj.$o = 0
      $obj.$n = 0

      [run] &loop {
        @terms { (1) }
        @run {
          $p = [run] &calc { [run] &rand {} % 13 }
          [run] &action {
            $$[p]p = &($p)
            $$[p]obj = &($obj)
          }
        }
      }
    }
  }
}

色々と大変だ。これで読みやすくなったとは言うが、自分が見てもただ無駄に長くなっただけだ。

2016.12.16

マクロテンプレート

ちなみに、この言語ではマクロテンプレートと言うものを用意して、ファイル処理やWindowsメッセージループを簡単に見やすく書けるようにします。

メッセージループの場合:

@@windows_msg {
  @msg "button1のクリック" {
    @event: button_click
    @select: button1
    @run: { }
  }

  @msg "button2のクリック" {
    @event: button_click
    @select: button2
    @run: { }
  }
}

ファイル処理の場合

@@file_open {
  @open {
    @file: <DATAFILE>
    @path: /home/myname/file
    @loop {
      @get { $line = <DATAFILE> }
      @run {
        [run] &print { $$format =  "$line\n" }
      }
    }
}

WindowsからPerlまで、何でもこなせる優れた言語が、NFです。

出来れば、jQueryのような、セレクタに対してイベントが起きた時の処理をするような、そういう言語にしたいです。

マクロテンプレートは、プラグインのようなものだと思ってください。標準では、メッセージループとファイル処理を搭載して、誰もが手軽に作れるようにします。

コンパイラはありません。頑張って、C言語に変換出来るようになると良いと思います。誰か、作ってください!

2016.12.17

テキスト処理

テキスト処理はこういう風に書く。

@@text {
  @file: "file.txt"
  @block '<p>' to '</p>' {
    @rep {'\(.*\):\(.*\)<br>' to '\1->\2\n'}
  }
}

どこからどこまでの範囲で - @block、何をどのように置換するか - \(.*\) to \1、を簡単に書ける。

以下のようにすると、最初の1〜2行だけを編集できる。

@@text {
  @line (1-2) { }
}

2017.02.07

GUI

GUIはこういう風にする。

@@method_def {
  @def: { %image: &show/&copy }
  @def: { %text: &edit/&copy }
  @def: { %link: &go}
}

まず、マウスをクリックした時は、その領域を選択(処理ではなく、選択)する。

そして、画像なら、showとcopyのメニューを表示する。

テキストなら、editとcopyのメニューを表示する。

リンクなら、goのメニューを表示する。

そして、それらのメニューをクリックした時に、それぞれの処理を行う。

メインメニューと言うよりは、コンテキスト・メニューに近い。

2017.03.06

奴隷的言語

ツイッターに投稿した、奴隷的言語について。

要は、パソコンの方にコマンドを打ってほしい。その中でやることは自分が決める。そういう、「奴隷的言語」がこの言語だ。
posted at 18:58:24

ただ、それならもっと違う形態で、main関数の中にあるブロックを関数から実行出来る。int main(){ [action(): test(int x) {printf("%d", x); } ] } void action(){ test(2) };となる。
posted at 18:58:00

人間みたいになった。今までは人間が主導権を持って関数を実行していた。人間がコマンドを打ち込む感覚だ。今からは、関数が主導権を持つ。コマンドの方が人間がやることを決める、と言う感覚だ。
posted at 18:48:23

これで、呼び出し元にあるblock1とblock2の宣言場所で、action関数を実行し、gm1関数とgm2関数を関数の中で実行することが出来る。
posted at 18:47:33

int main(){ [action(block1)] printf("\n"); [action(block2)]} void action(){[block1]{gm1();}[block2]{gm2();}}
posted at 18:46:39

僕は、もう少し改良して、人間が呼び出すコードを関数の方で変えられるようにしたい。
posted at 18:46:37

ある意味、相手によって言うことを変える、二枚舌のようなプログラミング言語になった。
posted at 18:04:30

int calc(int x, int y){[method1: x=3;y=4;][method2: x=2;y=1;]return x+y;} int method1{calc[method1](?);} int method2{calc[method2](?);}とする。
posted at 18:03:56

分からない。書いている本人も分かっていない。本当は、ただ従うだけではなく、相手から注文をつけてくるような、そういう言語を作りたかった。
posted at 17:49:34

自分でも、グローバル・メソッドが何を意味しているのか、良く分かっていない。要は、実行の主導権を呼び出される側に与える、と言うことだから、gm(3,4);とするのではなく、[id:1]gm();としてgm(void){if(id==1)action1(3,4);}とするのだと思う。
posted at 17:48:54

ただ、プログラムを描く、と言う中で、いつも関数の実行の側に主導権があるが、これを関数の呼ばれる側に主導権を作っても良い。関数を呼び出した時の処理を、関数の中で変えられるようにし、関数を変えることで全ての処理を変えられるようにする。グローバル・メソッドと言う名前にしても良い。
posted at 17:31:19

僕は、今のところパソコンが人間に忠実に従っているが、これがパソコンが人間に意見するようになると、それですでにパソコンは人間だと思う。何かをする時に、パソコンの方から「こういう風に操作してはいかがですか?」と言ったことを問いかけるようにする。人工知能を作るより、その方が先進的だ。
posted at 17:29:47

2017.03.20

MetaC

ツイッターに投稿した、構文を関数として実装することで、自由に構文を定義することの出来るメタ言語「MetaC」について。

頑張れば、GUIのイベント駆動型プログラムを一行で書くことも出来るだろう。メタ言語のCだから、名前は「MetaC」とする。
posted at 18:49:12

例えば、View::v.list(page1){open(clicked(menu1)){new_open(this)};close(clicked(menu2)){kill(this)};}と言うコードが書ける。
posted at 18:47:18

むしろ、Class::Object.Function(values){Messages(Events){Code}}と言う風にするのは、美しい。そういう風に、関数を定義すると良いかもしれない。
posted at 18:41:50

例えば、spnew(Object_name, Class_name).Function_name(x,y,z).{print;save;}のように、ありえないほど高度で複雑怪奇な言語を作れる。ただ、全てを関数として実行するだけで、構文を独自に定義し、メタ言語を作れる。
posted at 18:35:45

ある意味、この言語はNFと融和して、「言語を作る言語」にすると面白い。Java、C++、Perl、Ruby、PHPなど、全部の言語をこの言語の拡張として実装する。そして、誰でも外部の人間が自由に言語を作れるようにする。spifだけではなく、newを改良してspnewにも出来る。
posted at 18:33:53

例えば、spifと言う関数を宣言して、if(){}とする代わりに、spif(){}(){}と出来るかもしれない。そこでどんな風に処理を実行するかは、プログラマの自由だ。
posted at 18:13:09

オブジェクト指向では全てをオブジェクトにするが、それは僕はあまり良い実装ではないような気がする。()と{}の違いを無くするならLispのようにも出来る。Rubyのようにしても良い。if () {}をもっと変えることで、if () {} {} {}のようにも出来るのだ。
posted at 18:12:02

ある意味、言語的仕様を少なくすることで、構文を関数の範疇として、全てを関数にすることが出来る。あるいは、関数でもなく、全てをブロック的実行とすることも出来る。ある意味、代入や演算も何かもっと根源的なものとして、実装出来るかもしれない。
posted at 18:11:05

僕は、C言語で言うifやforなどの文で、特に{}で囲まれた部分を変数や引数とすることで、C言語の構文を少なくし、ユーザーが自由に定義出来るようにし、ifやforも関数で実現することが出来ると思う。それは、エレガントで美しい。
posted at 18:09:52

2017.04.03

マルチスレッド言語

なんとなく、こんな並列処理言語があっても良い。

multi-thread {
  while(1){printf("1\n");}
} {
  while(1){printf("2\n");}
}

これを、ifやforの拡張として、関数として実現すると、面白い。

2017.04.05