Giter VIP home page Giter VIP logo

adelie's Introduction

The Adelie Programming Language

Windows Linux license

Adelie is a .Net-compatible statically typed language that aims to combine the benefits of Rust and C#.

Goals

  • A language that takes advantage of Rust and C#
  • GUI application development using designer

Getting started

Please see Docs

Sample

FizzBuzz

fn main() {
    let mut i: i32 = 1;

    while i <= 100 {
        if i % 15 == 0 {
            println!("FizzBuzz");
        } else if i % 3 == 0 {
            println!("Fizz");
        } else if i % 5 == 0 {
            println!("Buzz");
        } else {
            println!(i);
        }
        i += 1;
    }
}

MessageBox

#[link(name="System.Windows.Forms.dll", publickeytoken="B7 7A 5C 56 19 34 E0 89")]
extern {
    mod System {
        mod Windows {
            mod Forms {
                enum DialogResult {}
                struct MessageBox {}
                impl MessageBox {
                    fn Show(text: string) -> DialogResult {}
                }
            }
        }
    }
}
fn main() {
    System::Windows::Forms::MessageBox::Show("hello!");
}

LICENSE

MIT

adelie's People

Contributors

kumavale avatar

Stargazers

 avatar

Watchers

 avatar

adelie's Issues

`extern`の実装

#[link(name = "System.Console.dll")]
extern {
    mod System {
        struct Console {}
        impl Console {
            fn WriteLine(_: string) {}
        }
    }
}
#[link(name = "System.Windows.Forms.dll")]
extern {
    mod System {
        mod Windows {
            mod Forms {
                struct DialogResult {}
                struct MessageBox {}
                impl MessageBox {
                    fn Show(text: string) -> DialogResult {}
                }
            }
        }
    }
}
fn main() {
    System::Windows::Forms::MessageBox::Show("hello!");
    System::Console::WriteLine("ok");
}

言語としては物凄く面倒くさい仕様になってしまうが、最終的に外部crateとしてこの部分(System名前空間)を提供すれば使いやすくなるのではないか。

Tasks

  • modをネストできるように
  • 名前空間のマージ
  • to_ilstrでアセンブリ参照と完全パス名を生成できるように
  • アセンブリ参照を自動で読み込む(.assembly extern System.Console {}
    -> extern宣言でpublickeytokenも定義させて、それを元に生成...?

可変長引数を実装

Rustには無い機能だから、実装は要検討。

メリット

  • TODO

デメリット

  • TODO

try/catchを実装

Rustには無い機能だから要検討。
try/catchはunsafe。
既存の例外を発生する.NETの提供する関数はResultを返すラッパーを作成

型推論の実装

Nodeが所持しているTypeは全てRRTypeになって、il生成の前に型推論を実行する。

同名の変数が宣言できてしまう

object.rs > find_name_current_scopeでチェックする処理が抜けている。

Adelie/src/object.rs

Lines 69 to 78 in 68dd6ee

pub fn find_name_current_scope(&self, name: &str) -> Option<&Rc<RefCell<Object>>> {
if let Some(current_scope) = self.scopes.last() {
for obj in current_scope {
if obj.borrow().name == name {
return Some(obj);
}
}
}
None
}

parser.rs > parse_let_stmt内に以下の旨の処理を追加する。

if symbol_table.find_name_current_scope(&ident).is_some() {
    panic!("A local variable or function named '{}' is already defined in this scope", &ident);
}

メソッドの仮引数に代入できない

fn assign_param(mut a: i32) -> i32 { a = 3; a }
ハンドルされていない例外: System.InvalidProgramException: 共通言語ランタイムが無効なプログラムを検出しました。
   場所 Rectangle.assign_param(Int32 a)
   場所 Main()

構造体のメンバー変数に代入できない

fn update(&mut self, w: i32, h: i32) { self.width = w; self.height = h; }
./target/debug/adelie test/struct.ad > test/struct.il
thread 'main' panicked at 'not implemented: primitive type', src/codegen.rs:388:17
note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace

名前空間の実装

Tasks

  • System::Console::WriteLine("ok")を処理
  • 強引にSystem::Windows::Forms::MessageBox::Show("hi")を処理してみた
  • dllから名前空間毎の関数テーブルを作成するローダを開発
  • moduleの実装

Box化した構造体のフィールドにアクセスできない

struct Foo { a: i32 }
let f = Foo { 1 };
*f.a;

上記のような時、fをDerefしてからaを見に行くべきであるが、*(f.a)のような状態になっており、コンパイルできない。
明示的に(*f).aと書けば現状でも正常にコンパイル/動作できる。

と、予想している 🤔

プロパティ機能の実装(提案)

プロパティ機能があると.Net側のプロパティが呼びやすくなる。
無くても、set_Foo,get_Fooを定義すれば行けるけど、スマートじゃない。

プロパティを実装する場合、valueがキーワードとなる。
自動プロパティの場合、_textに相当する変数は「backing field」として実装する。

class Foo {
    _text: string,
    Text: string {
        set { self._text = value; }
        get { self._text }
    },
    // 自動プロパティ
    Name: string { get; set; },  // カンマは無くても良い
}

クロージャにするのも良いかも。
valueをキーワードにする必要も無くなるし、型を厳密に注釈できる。

set {
    |value: string| { self._text = value }
}
get {
    || -> string { self._text }
}

あと、バッキングフィールドはフィールドブロックの中で宣言するのはどうだろうか

class Foo {
-     _text: string,
    Text: string {
+       _text: string,
        set { |value: string| { self._text = value } }
        get { || -> string { self._text } }
    }
}

複数ファイルのコンパイル

main.rs以外のファイルは、

mod ファイル名から`.rs`を除いたもの {
    ファイルの中身
}

に置換して読み込み、最後にmain.rsの文字列と合わせる。

`.ctor`はコンストラクタを示す特別なキーワードとしたい。

.ctorはコンストラクタを示す特別なキーワードとしたい。

staticなメソッドではなく、インスタンスとして呼ばれる。
-> しかし、&selfは付けない。
-> 戻り値はType::Voidに限る。

#[link(name = "System.Drawing.Primitives.dll")]
extern {
    mod System {
        mod Drawing {
            struct Size {
                Width: i32,
                Height: i32,
            }
            impl Size {
                fn .ctor(width: i32, height: i32) {}
            }
        }
    }
}
fn main() {
    let s: System::Drawing::Size = System::Drawing::Size::.ctor(2, 3);
    assert_eq!(s.Width == 2 && s.Height == 3);
}

Originally posted by @kumavale in #40 (comment)

関数式は`.locals`で宣言せず、`newobj`する

下記の場合、左辺と右辺共に.localsに宣言されている。
右辺をnewobjしたものを左辺へ代入するべき。

struct Foo {
    a: i32,
}
fn main() {
    let foo: Foo = Foo { 42 };
}
.class private sequential auto sealed beforefieldinit Foo extends System.ValueType
{
	.field public int32 a
}
.method static void Main() cil managed {
	.entrypoint
	.maxstack 32
	.locals init (
			valuetype Foo V_0,
		valuetype Foo V_1)
	ldloca 1
	initobj Foo
	ldloca 1
	ldc.i4 42
	stfld int32 Foo::a
	ldloc 1
	stloc 0
	ret
}

newobjしたものを一旦ローカル変数へ格納し、アドレスをロードして.ctorを呼ぶ必要があるので、このissueは無効とする。

errorの場合てきとうなType等を返すのではなく、エラーを意味するものを返す

構造体のフィールドが見つからない(e0015)場合、現状ではType::Voidを返している。
見つからなかった時点でそれ以降のそのフィールドに関する評価は行いたくない。
下記の場合だと、E0024のエラーは無意味である。

foo.c == 'a';
error[E0015]: no field `n` on type `Foo`
  --> test/box.ad:12:9
12 |     foo.n == 'a';
   |         ^
   2: adelie::codegen::gen_il_field
             at ./src/codegen.rs:311:13
   3: adelie::codegen::gen_il
             at ./src/codegen.rs:36:13

error[E0024]: no implementation for `void` == `char`
  --> test/box.ad:12:7
12 |     foo.n == 'a';
   |     ^^^^^^^^^^^^
   2: adelie::codegen::gen_il_binaryop
             at ./src/codegen.rs:756:13
   3: adelie::codegen::gen_il
             at ./src/codegen.rs:69:13

error: could not compile due to 2 previous errors

`extern`内で入れ子ではない`mod`を複数入れると挙動がおかしい

コード

#[link(name="System.Windows.Forms.dll", publickeytoken="B7 7A 5C 56 19 34 E0 89")]
extern {
    mod System {
        mod Windows {
            mod Forms {
                class Form {
                    Text: string,
                    ClientSize: System::Drawing::Size,
                }
                impl Form {
                    fn .ctor() {}
                }
                class Application {}
                impl Application {
                    fn Run(_: Form) {}
                }
            }
        }
        mod Drawing {
            struct Size {
                Width: i32,
                Height: i32,
            }
            impl Size {
                fn .ctor(w: i32, h: i32) {}
            }
        }
    }
}

struct Form1 {
    _form: System::Windows::Forms::Form,
}
impl Form1 {
    fn Text(&mut self, text: string) { self._form.Text = text }
    fn ClientSize(&mut self, size: System::Drawing::Size) { self._form.ClientSize = size }
}
fn main() {
    let form1: Form1 = Form1 { System::Windows::Forms::Form::.ctor() };
    form1.Text("text");
    form1.ClientSize(System::Draing::Size::.ctor(200, 100));
    System::Windows::Forms::Application::Run(form1._form);
}

エラーメッセージ

error: failed to resolve: use of undeclared crate or module `System::Draing::Size`
  --> test/counter.ad:41:27
41 |     form1.ClientSize(System::Draing::Size::.ctor(200, 100));
   |                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
   2: adelie::codegen::gen_il_path
             at ./src/codegen.rs:902:17
   3: adelie::codegen::gen_il_path
             at ./src/codegen.rs:894:13

継承機能の提案

例えば、Formアプリケーションを作る時に継承が出来ないと大分困る。

#[link(name="System.Windows.Forms.dll", publickeytoken="B7 7A 5C 56 19 34 E0 89")]
extern {
    mod System {
        mod Windows {
            mod Forms {
                class Form {
                    Text: string { get; set; }
                }
                impl Form {
                    fn .ctor() {}
                }
            }
        }
    }
}

Textはプロパティであり、実体はbase.Textが持っている。
FormクラスはContainerControlを継承しており、それもまた他クラスを継承している。

public override string Text {
    get { return base.Text; }
    set { base.Text = value; }
}

ilを生成する時に、きちんと継承元を参照する必要があることから、

callvirt instance void [System.Windows.Forms]System.Windows.Forms.Control::set_Text(string)

下記のような継承構文をexternブロック内でのみ実装するべきだと思う。

class Form : ContainerControl {
    Text: string { get; set; }
}

エラーメッセージ(E0012)の修正

コード

fn foo(a: i32) {}
fn main() {
    foo("a");
}

エラーメッセージ

error[E0012]: expect `string`, found `i32`
  --> test/struct.ad:36:11
36 |     foo("a");
   |         ^^^
thread 'main' panicked at 'explicit panic', src/error.rs:106:5

期待するメッセージ

error[E0012]: expect `i32`, found `string`

原因

expectとfoundの型が逆になっている。
codegen.rs::gen_il_method内の処理だと思われる。

所有権の実装

概要

Rustの中心的な機能の一つ「所有権」を実装する。
Adelieとしては、.Netのガベージコレクション機能を使用させないことで高速化を図りたい。

所有権のルール

  • 各値は、所有者と呼ばれる変数と対応している。
  • いかなる時も所有者は一つである。
  • 所有者がスコープから外れたら、値は破棄される。

参考

UseTreeの実装

use Foo::Bar;

useされたRc<RefCell<NameSpace>>のリストを保持すれば良いのかな?

二項演算子の型チェックが甘い

codegen.rs > gen_il_binaryop()

BinaryOpKindを基準に判定すべき?

match kind {
    BinaryOpKind::Add => {
        match (ltype, rtype) {
            (Type::Numeric(..), Type::Numeric(..)) => {}
            ...
        }
    }
    ...
}

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.