# Description (My bad opinionated opinions :D) ## 0. [Reason - Why?](reason_why.md) ## 1. Naming Compiler `dopp` for `doppelganger` (also `dopp` command), Language `DE[F]-lang` for `Dlang [with -- influenced by / inspiration from] Erlang [Flavoured language]`. File extension - `*.de`. File text code - utf8 without BOM. # 2. Syntax and Ideas ### (partial moved to next versions) ## 2.1 toml file for config keys-values ```toml indent_type = 0 indent_matter = 4 indent_out = 2 ``` `indent_type = 0` for whitespaces, 1 for tabs; `indent_matter = 4` means we have basic indent (Off-side rule) as 4 whitespaces, so we do not got error when next line have 5, 6 or 3, 2 whitespaces etc - needs to have more (+- 4) whitespaces for change indent (Off-side rule) for next level. `indent_out = 2` means we got 2 whitespaces indents in resu;t files. ## 2.2 do not use any reserved words (keywords) for function definition (like in Erlang) todo add examples ## 2.3 Pattern Matching that transforms into ```if .. else if .. else ..``` or ```switch .. case``` https://dlang.org/spec/statement.html#SwitchStatement https://dlang.org/spec/statement.html#case-range https://tour.dlang.org/tour/uk/basics/controlling-flow https://dlang.org/spec/expression.html#IsExpression todo add examples ## 2.4 Pattern Matching at functions too (like in Erlang) Function overloading in dlang allows to define the same function but with different versions for different data types: ``` int my_func(int x){ return x; } int my_func(string x){ return x.length; // or other operation(s) with argument } ``` that similar to erlang's functions clauses: ```erlang my_func(X) when is_integer(X) -> X; my_func(Y) when is_binary(Y) orelse is_list(Y) -> string:length(Y). %% is_list for list string (list chars codes) ``` other example ```erlang my_func(1) -> 1; my_func(5) -> 5 * 2; my_func(9) -> 9 * 3; my_func(X) -> X * 4. ``` -> ``` int my_func(int x){ if(x == 1){ return 1; }else if(x == 5){ return x * 2; }else if(x == 9){ return x * 3; }else{ // other cases return x * 4; } } // or int my_func(int x){ switch (x){ case 1: return 1; // if x == 1 case 5: return x * 2; // if x == 5 case 9: return x * 3; // if x == 9 default: return x * 4; // other cases } } ``` note that compiler can optimise few comparison conditions for ```switch``` better than that in ```if .. else```. ### 2.4.1 pattern matching on strings There are Pattern Matching on strings/binaries in Erlang, that looks like: ``` my_func(<<"test", Rest/binary>>) -> true; my_func(_) -> false. % or my_func("test" ++ Rest) -> true; my_func(_) -> false. ``` similar code in D - dlang: ``` bool my_func(string str){ if(str.length >= 4 && str[0..4] == "test"){ return true; } return false; } // also we can get rest import std.stdio; bool my_func(string str, out string rest){ if(str.length >= 4 && str[0..4] == "test"){ rest = str[4..$]; return true; } rest = str; return false; } void main(){ string rest; writeln(my_func("test123", rest)); // true, rest = "123" writeln(rest); // "123" writeln(my_func("example", rest)); // false, rest = "example" } // also we can to match from string ending bool has_end_test(string str){ if(str.length >= 4){ if(str[$-4 .. $] == "test"){ return true; } } return false; } ``` In My Humble Opinion be better to make this syntax similar (laconic) as in Erlang. upd. whitespaces count between function name and first argument do not matter (>=1 e.g. " " = [␣]{1, }), between first argiment and second (and next) must be at least comma and 1 whitespase (", " = [␣]{0,}[,]{1}[␣]{1,} ). ### 2.4.2 pattern matching examples ``` // left = function type, right = arguments type bool = string str has_begin_test "test" ++ _ = true has_begin_test _ = false -> bool has_begin_test(string str){ if(str.length >= 4 && str[0..4] == "test"){ return true; } return false; } ``` ``` // left = function type, right = arguments type bool = string str, out string rest has_begin_test "test" ++ rest = true has_begin_test _ = false -> // import std.stdio; bool has_begin_test(string str, out string rest){ if(str.length >= 4 && str[0..4] == "test"){ rest = str[4..$]; return true; } rest = str; return false; } /* void main(){ string rest; writeln( has_begin_test("test123", rest) ); // true, rest = "123" writeln(rest); // "123" writeln( has_begin_test("test", rest) ); // true, rest = "" writeln(rest); // "" writeln( has_begin_test("example", rest) ); // false, rest = "example" writeln(rest); // "example" } */ ``` ``` // function type = arguments type = // next lines function body bool has_end_test = string str = has_end_test _ ++ "test" = true has_end_test _ = false -> // match from string ending bool has_end_test(string str){ if(str.length >= 4){ if(str[$-4 .. $] == "test"){ return true; } } return false; } ``` ``` // function type = arguments type = // next lines function body bool has_end_test = string str, out string rest = has_end_test rest ++ "test" = true has_end_test _ = false -> // import std.stdio; bool has_end_test(string str, out string rest){ if(str.length >= 4 && str[$-4 .. $] == "test"){ rest = str[0 .. $-4]; return true; } rest = str; return false; } /* void main(){ string rest; writeln( has_end_test("hellotest", rest) ); // true, rest = "hello" writeln(rest); // "hello" writeln( has_end_test("example", rest) ); // false, rest = "example" writeln(rest); // "example" writeln( has_end_test("test", rest) ); // true, rest = "" writeln(rest); // "" } */ ``` ``` // function type = arguments type = // next lines function body my_func int = int x = my_func 1 = 1 my_func 5 = 5 * 2 my_func 9 = 9 * 3 my_func X = X * 4 -> int my_func(int x){ if(x == 1){ return 1; }else if(x == 5){ return 5 * 2; // return x * 2; }else if(x == 9){ return 9 * 3; // return x * 3; }else{ // other cases return x * 4; } } ``` ``` // function type = arguments type = // next lines function body // "_sw" in function name' end for use switch (no "_sw" in dlang function name) int my_func_sw = int x = my_func_sw 1 = 1 my_func_sw 5 = 5 * 2 my_func_sw 9 = 9 * 3 my_func_sw X = X * 4 -> int my_func(int x){ switch(x){ case 1: return 1; // if x == 1 case 5: return 5 * 2; // return x * 2; // if x == 5 case 9: return 9 * 3; // return x * 3; // if x == 9 default: return x * 4; // other cases } } ``` ``` // ptn = pattern = for pattern matching like `case X of` in erlang y = ptn x 1 = 1 5 = 5 * 2 9 = 9 * 3 _ = x * 4 -> if (x == 1){ y = 1; }else if(x == 5){ y = 5 * 2; // return x * 2; }else if(x == 9){ y = 9 * 3; // return x * 3; }else{ // other cases y = x * 4; } ``` ``` // ptns = use switch in dlang for this pattern matching y = ptns x 1 = 1 5 = 5 * 2 9 = 9 * 3 _ = x * 4 -> switch(x){ case 1: y = 1; // if x == 1 case 5: y = 5 * 2; // y = x * 2; // if x == 5 case 9: y = 9 * 3; // y = x * 3; // if x == 9 default: y = x * 4; // other cases } ``` todo more examples -- with switch case dlang ## 2.10 reserved words (keywords) list including https://dlang.org/spec/lex.html#keywords ``` abstract alias align asm assert auto bool break byte case cast catch char class const continue dchar debug default delegate deprecated do double else enum export extern false final finally float for foreach foreach_reverse function goto if immutable import in inout int interface invariant is lazy long macro mixin module new nothrow null out override package pragma private protected public pure real ref return scope shared static struct super switch synchronized template this throw true try typeid typeof ubyte uint ulong union unittest ushort version void wchar while with __FILE__ __FILE_FULL_PATH__ __FUNCTION__ __LINE__ __MODULE__ __PRETTY_FUNCTION__ __gshared __parameters __rvalue __traits __vector __DATE__ __EOF__ __TIME__ __TIMESTAMP__ __VENDOR__ __VERSION__ [deprecated keywords] body cdouble cent cfloat creal delete idouble ifloat ireal ucent ptn ptns _ ++ *_sw (function name end) ``` todo ### [todo_v2](todo_v2.md), [todo_v3](todo_v3.md) etc