6
4

More than 3 years have passed since last update.

新言語シールド言語フレームワークの提案

Last updated at Posted at 2020-01-02
1 / 2

新言語の提案

新言語としてシールド言語(shield lang)を提案します。
1.シールド言語の特徴
GUIや3DCGや画像処理のフレームワークがとても揃っている。動的型作成可能な静的型付けの言語(Jitコンパイラ型(インタプリタ併用)と事前コンパイル/バイトコード型(.jcp(Jit Compiled Program の略)ファイル生成(VMで起動できる形式)上記にはGCが存在する),ネイティブコードコンパイル型(ポインタやRustのようなスコープや,マクロ(構造を改革可能)が存在するので学習コストがとても高いがC++並みの速度が出せる(動的型作成不可))の3つある。前者は学習コストが低めにしたが、ネイティブコードコンパイルにするとJava並み。文法はC#とPythonとKotlinに似ている強い静的型付け言語です(キャストなしに型変換はできない)。
2.シールド言語の文法

ex.shie
#これはコメントです。
(*これもコメントです。*)
#コンパイラ付属 from ~ using *で名前空間を省略可
from system using * #exit(プログラム終了),TapKey(キー入力),type(型),Rtype(制限型)など
using os #id(アドレスの出力),exit(終了) ptr(ポインタ操作)など
using rapt #標準便利機能
from console using * #print,read,error,linef(終了関数)など 
using err # comment,debugなど
from collection using * #Array<>,List<>,Dict<>,range()等
#ファイル操作はusing file

 #外部ファイルはimport 今回はOpenCVをimportしている。
import cv

rect = rapt.rect #namespace rapt class rectをrectにしている
using texisnone as rapt.texture.isnone #def rapt.textureisnone(bool)()を別名を与えている。
var n1 = 5
var s1 = "string1"
any d = 5 #動的型
d = "あいう"
#代入は"=",比較は"=="
var str s2 = "string2"
opt var str s3 = None #参照型はNone 
opt var float n2 = Null #値型はNull
var lst = new [1,"ABC",3.141592] #listは参照型かつobj派生型一度型が決まれば変わらない。
lst[1] = 3 #コンパイルエラー
lst += 4 #リストの最後に3を追加
print(lst[3]) #output 4
nlst = lst + 8.3 #lstとその後に8.3を追加したnlstを作成
# var lsta = new List<int>[3]{1,2,3}<-特定の型のみ入れられるリスト
# var lsta = new List<new List<int>>[3,3]{{1,2,3}{4,5,6}{7,8,9}}
var arr = Array<str>[3]{"1","ABC","3.141592"} #配列は値型
var tupple = new (1,"ABC",3.14159265358979)
#var tupple := new {1,"ABC",3.14159265358979}でも宣言可能
var dic = new Dict<Tupple<str,int>>[2]{("あいう",1),("うえお",2)}
#constだと定数宣言が可能。const時は束縛(:=)を使う
const Anum := 5 
var Aiu[Anum] = Array<int>{1,2,3,4,5}
tupple[2] =3.14 #コンパイルエラー
var str Moji = '1' + '3' 
print(Moji) #output "13"
var errs1 = '1' + 3 #コンパイルエラー:型が安全でありません(str + int)
var MRC_OK = int('1') + int('3')
print(str(MRC_OK)) #output '4'

#主な型bool,str,int,var,byte,float,obj,ref~,enum派生型,struct派生型,class派生型,ジェネリクス型

if(type(n1) is int or opt int):#true
    print(f"{n1}")

s1 = switch(s1) case "2" case "3" as "s1は"+s1+"です" break case "string1" case "string2" default as "s1は2ではありません" break
print(f"{s1}") #output "s1は2ではありません"

enum VakKey:#ほんの一部
    LEFT = 0x25
    RIGHT
    UP 
    DOWN
    a = 0x41
    b
    c
    d

var vk[] = new VakKey()<-すべての状態を知る箱を作成

using val as vk,using VakKey: #返り値ではなくswitchのカッコ内がtrueかを知りたい場合with val as ~構文を使う。この時はcontinueを使う。
    switch(system.TapKey(int(val))):
        case .RIGHT as #以下が実行されます。
        print("Right")
        continue
        case .LEFT as
        print("Left")
        continue
        case .UP as
        print("Up")
        continue
        case .DOWN as
        print("Down")
        continue

#構造体のコンストラクタは var 構造体タグ名 = 構造体名(コンストラクタ引数) 
struct tanf: #構造体は値型(self,空オブジェクト:Null)

    pub unsafe def _init(var int m,var str w,var x) without self: #コンストラクタは戻り値不要
        .m = m #without内では.~で書くことができる。
        .w = w
        .x = global s1 #グローバル変数やclass外変数、ポインタを使うときunsafeを使う。
        return self

    pub def show()():#()は戻り値の型voidの時は省略可能return None
        read (f"{self.m}")
        for(i in range(self.m)):
            print(str(i)+"回目")
            print(f"{self.w}が{self.x}です")
            pass

    pub set(val) pub get var int m #範囲設定
    pub var str w 
    pub set(val) pub get del var x

dat class Mycdat(obj)(opt var str mydat1,opt var int mydat2)#(継承/aspect)(データ)
dat struct Mysdat(opt var str mydat1,opt var int mydat2)

#classコンストラクタは var オブジェクト名 = new クラス名(コンストラクタ引数)
class Myclass(obj):#(継承/aspect)クラスは参照型オブジェクト(this,空オブジェクト:None) baseだと親メソッドに接続可能

    pub def _init(int m,ref rect rc,var h,var y,var t[931]):
        this.m = m
        this.rc = rc
        this.h = h
        this.y = y
        this.t = [if(t[i] is Null) 5 else t[i];for i in range(931)]

    pub def show()(int m = 3):
        this.m = m
        var n = 0
        for(not n is this.m and rc is not None):# 
            print(rc.left,rc.right,rc.top,rc.bottom)
        var rect_is_live = if(m < 3) true elif(6 < m and m < 10) false else true
        this.rc = if(not rect_is_live) None else pass

    pub def show()(var h):
        var n = 0
        for(not n is this.m and rc is not None):# 
            print(rc.left,rc.right,rc.top,rc.bottom)
        var rect_is_live = if(m < 3) true elif(6 < m and m < 10) false else true
        this.rc = if(not rect_is_live) None else pass

    pub operator==(bool)(Myclass T): #演算子オーバーロード+,-,==,is,and,or,not,xor,*,/,++,--,**,//,%,^,<<,>>,<=,>=,<,>,|,&,!(後ろ7つはビット演算子) 但し,as,=, :=,., ?:, ->, new,typeはオーバーロード不可
        #+=, -=, *=, /=, %=, &=, |=, ^=, <<=, >>=,!=は2項演算子をオーバーロードすれば可能
        return (if(not this.m is not T.m) false elif(this.rc is not T.rc) false elif(this.h is not T.h) false elif(this.y is not T.y) false elif(this.t is not T.t) false else true)

    set(val) get int m
    del opt ref rect rc
    var h
    var y
    ref var t

#条件つきジェネリクス(簡易ジェネリクスはvarで作成可能)
def Tshow<T>()(T t) when T is Rtype(opt ref in(int or str or float)) : #RtypeでなくtypeでもOK但し冗長なのでオススメしません。
    opt int s = if(T)
default when:
    err.comment("vakerror0001:この型でジェネリクスは作られていません")

def sum(var)(var t1,var t2):
    return t1 + t2 #コンパイル時にt1とt2の型が間違えていると読んでいるとコンパイル時エラーが出る。

#名前空間(基本は名前空間に書く今回は特別に外)namespaceとimport名を分けることにより日本語文字列の名前空間をできるだけ排除しやすいようにする。

namespace ex:
    main(opt int)():
        return Null 
        #名前空間内ex.main()でアクセス可能。(下まで読まれた後main関数が起動する(もし外部にあった場合コンパイル時にmain関数にinline化されmainの中に入る)。)

#アスペクト(共通アスペクト)
diversity MyLogging(asp):
    def log(int i):
        print(f"{i}です")

シールド言語について

よく似た言語にBoo言語がありますが、Python以上にC言語に似ていないため流行らなかったのだと思い、少しでもC,C++,C#風に書ける静的型付けでコンパイルしやすいPythonとして作ってみました。従って,C#やKotlinも参考にしました。次のはポインタあり版です(こちらはマクロも記述可能)。.shieでもいいですが、少し文法が違うので.shiexにしました。

ex.shiex
using system;
using os;
using rapt;
using console;
using err;
using collection;
@pragma out_console #out console,only_window,out_window(デフォルトはout_console)
@pragma out_native #out_native out_compile(.jcp) use_jit(jitコンパイル/デフォルト)組み合わせも可
@pragma style Signal_Colon#C言語スタイルで書くことが可能。
#主なポインタ
#thisptr->thisは参照型。thisptrはポインタ。(namespace osに付属)
#ptr,o_ptr->*だと掛け算と見間違える可能性もあり可読性が低下するため(namespace osに付属)
#os.id(name)
#マクロ
@def MyMacro{
    @operator when(tex as when rapt.Texture)#引数の型条件つき#マクロオペレーター大体のののが使える(自分で構造を変更することができる強力なマクロ)。
}@as if(tex is not None) true else false;

@def PI = 3.14159265358979 #定数(文字列)置き換え
@def TEXT = "ABC"
@def BEGIN @as { 
@def END @as }

def unsafe main(opt int)(){
    var A[4] = collection.Array<int>{1,2,3,4};
    opt int os.ptr s_p = os.id(A);
    print(os.o_ptr s_p);#output 1
    s_p++;
    int s = os.o_ptr s_p;
    s_p = os.nullptr;
    ref int AA = new {4,5,3,2};
    rapt.Texture tx = None;
    bool A = MyMacro{when(tx)} 
    print(A); #output false
    if(true) BEGIN ref int BB = AA; END
    print(AA[2]); #コンパイルエラー
    print(BB[2]); #コンパイルエラー
    print(A[1]); #2
    print(s); #output 2
    return Null;#正常終了
}

誰か作れる技術のある方は是非とも作っていただきたい。書いて思ったことは、IDEがないと書きずらいな。

バージョン 0.1

今回の改革点
struct(class)でコンストラクタで変数宣言ができるようにしました。
class(参照型)のメソッドで変数の数の変更をできるようにしました。
namespace外に書かれているメソッド(クラスの内部にあるdef)やプロシージャー(クラスの外部にあるdef)は自分のファイル名の名前空間に属します。
ifdef()/eldef()/undefキーワードの追加(varの型,変数の存在)等
オプション型(Null,None)は代入時に明確な場合はoptキーワード省略可能。
var(数値はミュータブル/型はイミュータブル),const(型数値共にイミュータブル),dynamic(型宣言が全く不要/型が変更できる)のいずれの何も書かれていなければ(=だと基本的にvar(),:=だと基本的にconst,;=だと基本的にdynamic(関数呼び出し内やif文ではvar))
コンパイラ付属
using,using ~ as ~,from~ using ,from~ using~ as ~
サードパーティー製(自分で作成したプログラム)
import,import ~ as ~,from~ import *,from~ import~ as ~,from~(ファイル名)with~(namespace)as
(ファイル内で特定の名前空間を無効化),from~ with~ as~(~ファイル内で特定の名前空間を名前変更)
from hogehoge with hugahuga as huga hogehoge.shie内の名前空間hugahugaをhugaにする(hugahuga.Huga->huga.Huga,hogehogeのhugahugaのものは使えない)。
標準入出力(consoleクラス)を整理しました

console.shie
print(str) = return None #文字列が出力可能(¥n無し)高速でセキュア!
scan() = return (type)str #文字列が出力可能(¥n無し)高速でセキュア!
white(type<genelic>) = return None #文字列,数値が出力可能(¥n無し)CLIカレンダー等!
read(type<genelic>) = return (type)str #文字列,数値が入力可能(¥n無し)改行が邪魔な時
whiteline(type<genelic>) = return None #文字列,数値が出力可能(¥n有)普段はこれを使う
readline(type<genelic>) = return (type)str #文字列,数値が入力可能(¥n有)普段はこれを使う
input(type<genelic> or f"",~) = return None #F文字列使用可能(¥n有)f文字列が使える便利さが欲しい時
output(type<genelic> or f"",~) = return (type)str #F文字列使用可能(¥n有)f文字列が使える便利さが欲しい時
linef() return '¥n'
(type)str->format()
exp.shie
from system using *
from console using *
from collection using *

#名前空間外プロシージャー
def sum(var)(var i,var j):
    return i+j

#名前空間外クラス
class Main:

    pub def main(var int)():        
        abc = new nan.ABC("あいう",10)
        output(for(i in range(abc.get_n())) abc.get_is_Nothing())#output "false" * 10
        abc.show(3.14159265358979)#output "3.14159265358979"*10
        abc.show(3,4,true) #output true*3 false*4
        return Null

namespace nan:
    class ABC(obj):

        pub def _init(str m,int n) without this:
            pub set(val) pub get del var .is_Nothing = if(m is None) true elif(m.isEmpty()) true else false
            pub set(val) pub get var .n = n

        pub def show()(var K)without this:
            pub set(val) get var .K = K
            output(for(i in range(.n)) .Kです)

        pub def operetor== (bool)(ABC abc)without this:
            ifdef(.K):
                return .isNothig == abc.get_isNothig() and .n == abc.get_n() and .K == abc.k() 
            undef:
                return .isNothig == abc.get_isNothig() and .n == abc.get_n()

        #オーバーロード
        pub def show()(int A,int B,bool C):
            var bcd = exp.BCD(A,B,C)
            bcd.show()

#名前空間外構造体
struct BCD:

    pub def _init(int A,int B,bool C) without self:
        pub set(val) pub get del var .A = A
        .B = B
        .C = C

    pub def show()()without self:
        print(for(a in range(.A))C,for(b in range(.B))not C)


6
4
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
4