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.
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.
todo add examples
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
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:
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
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
.
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,} ).
// 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
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