Deeg is a static, object-oriented, strongly-typed language that has powerful and efficient features, including type inferencing, list comprehensions, optionals, string interpolation and first class functions. Deeg compiles nicely into JavaScript. Deeg is the future, and if you don't think so, then you are living in the past, buddy.
- First class functions
- Optional parameters/default parameters
- Terminal 'end' instead of curly braces
- Parenthesis are optional, except for functions
- Optionals
- .deeg file extension
- String Interpolation
- Type Inference
- "make" usage
- Specify type with
:
, optionaly specifying as optional with trailing?
- List Comprehensions
- Pattern Matching
The rules here are ordered. Matches are attempted from top to bottom.
newline ::= (\s* \r* \n*)+
letter ::= [a-zA-Z]
digit ::= [0-9]
keyword ::= 'make' | 'to'
| 'deeg' | 'end' | 'thru' | 'till' | 'by'
| 'and' | 'or' | 'exists' | 'unless'
| 'if' | 'else' | 'then'
| 'not' | 'true' | 'false'
| 'for' | 'while' | 'does' | 'count' | 'counts'
| 'match' | 'with'
id ::= letter (letter | digit | '_')*
intlit ::= digit+
floatlit ::= digit+ '.' digit+ <!-- ([Ee] [+-]? digit+)? -->
relop ::= '<' | '<=' | '==' | '!=' | '>=' | '>'
addop ::= '+' | '-'
mulop ::= '*' | '/' | '%'
prefixop ::= '-' | 'not' | '!'
boollit ::= 'true' | 'false'
escape ::= [\\] [rnst'"\\]
char ::= [^\p{Cc}'"\\] | escape
stringlit ::= ('"' char* '"') | (\x27 char* \x27)
comment ::= '#' [^\n]* newline
| '###' .*? '###'
type ::= 'bool' | 'int' | 'float' | 'string'
format can be directly input into Gunther Rademacher's Railroad Diagram Generator
Program ::= Block
Block ::= (Stmt newline)*
Stmt ::= WhileStmt | ForStmt | MatchStmt | IfStmt
| ReturnStmt | ClassDef | Binding
| Exp | VarDeclaration
ClassDef ::= 'class' id ('extends' id)? (newline Block | Stmt) 'end'
IfStmt ::= 'if' Exp 'then' (newline Block | Stmt) ('else if' Exp 'then' (newline Block | Stmt))* ('else' (newline Block | Stmt ))? 'end'
WhileStmt ::= 'while' Exp 'then' (newline Block 'end' | Stmt 'end')
MatchStmt ::= 'match' Exp 'with' newline PatBlock 'end'
PatBlock ::= (Patline newline)*
Patline ::= '>>' Patterns ('if' Exp)? 'then' Stmt
Patterns ::= Pattern ('|' Pattern)*
Pattern ::= (Exp | WildCard) Type?
ForStmt ::= 'for' (StdFor | CountFor | CountsFor) 'then' (newline Block 'end' | Stmt 'end')
StdFor ::= id Type? 'in' Exp (',' id Type? 'in' Exp)*
CountsFor ::= id 'counts' Exp
CountFor ::= 'count' Exp
ReturnStmt ::= 'deeg' Exp
Type ::= ':' (type | 'Dict' | ('List' (':' Type)?) | ('Function(' (Type (',' Type)*)? ')' (':' Type)?))
Exp ::= VarAssignment
| FunctionExp
| Exp0
VarDeclaration ::= 'make' id Type? '=' Exp
VarAssignment ::= VarExp '=' Exp
VarExp ::= id ( '.' Exp9
| '[' Exp4 ']'
| (Args ('.' Exp9 | '[' Exp4 ']')) )*
Args ::= '(' ExpList? ')'
ExpList ::= newline? Exp (',' newline? Exp)* newline?
FunctionExp ::= Params Type? 'does' (newline Block | Stmt) 'end'
Params ::= '(' ParamList? ')'
ParamList ::= newline? Exp Type? (',' newline? Exp Type?)* newline?
Exp0 ::= Exp1 ('if' Exp1 ('else' Exp1)?)?
Exp1 ::= Exp2 ('or' Exp2)*
Exp2 ::= Exp3 ('and' Exp3)*
Exp3 ::= Exp4 (relop Exp4)?
Exp4 ::= Exp5 (('thru'|'till') Exp5 ('by' Exp5)?)?
Exp5 ::= Exp6 (addop Exp6)*
Exp6 ::= Exp7 (mulop Exp7)*
Exp7 ::= prefixop? Exp8
Exp8 ::= Exp9 ('**' Exp9)?
Exp9 ::= Exp10 ('.' Exp10 | '[' Exp4 ']' | Args)*
Exp10 ::= boollit | intlit | floatlit | id | '(' Exp ')' | stringlit
| DictLit | ListLit
ListLit ::= '[' ExpList? ']'
DictLit ::= '{' BindingList? '}'
BindingList ::= Binding (',' Binding)*
Binding ::= newline? id Type? 'to' Exp newline?
# commented to the end of line
### multi-line comment
comments
comments
###
make example_variable = "this string"
make example_variable2 = 200
make a = 4
make b = 8
a, b = b, a
make c, d = 2, 16
We have four primitive types: int
float
bool
string
and however many reference types: Dict
Function
List
make boo = "far"
make hap:string = "py"
make friends_list = ["Bob", "Donna", "Shaggy"]
make grades_list:List:int = [99, 95, 90, 96]
make mapping:Dict = {
key to "value",
key2 to 91,
funKey to (x, y) does deeg x * y,
funKey2 to (a, b) does
deeg a + b
end
}
Hierarchy of types:
int -> float -> string
This hierarchy is what determines auto conversions. A type can be upconverted automatically if needed. If you want to convert down the tree, then you need to specify it with a type converter function like int()
or float()
. Some conversions may return optionals if conversion cannot be guaranteed
make year = 99 # Inferred int
make fraction = 2.5 # Inferred float
make is_finished = true # Inferred bool
make name = "Deeg" # Inferred string
make grade:float = 95 # Forced to be 95.0
make number_of_people:string = 56 # Forced to be "56"
make grade:int = int(95.0) # manual conversion down heirarchy
make gpa:int? = int('none') # ex. converting from strings to nums return optionals
[1 thru 10] # 1 up to 10, inclusive
[1 till 10] # 1 up to 10, exclusive
[1 thru 9 by 3] # [1, 4, 7]
make meal:string = "artichokes"
meal[0,1,2] # We grab "art"
meal[0 till 3] # Since [0 till 3] == [0,1,2] this is also "art"
meal[0 till 8 by 3] # We grab "aio"
if bool_expression then
# perform action
else
# other action
end
if bool_expression then
# action
else if bool_expression then
# other conditional action
else
# if nothing else
end
if bool_expression then ###action### else ###else action### end
make interesting_result = "happy times" if bool_expression else "sad times"
for cat in cat_array then
print("mr. " + cat)
end
for duck in duck_array and dog in dog_array then
print(duck + " and " + dog)
end
for count int_expression then
print("hello")
end
for count 5 then
print("sup")
end
for i counts int_expression then
print(i + " hello(s)")
end
while is_running then
runFaster()
end
In place of a return
keyword, we have deeg
.
make add_pizazz = (bore:string) does
deeg bore + "!"
end
make f:Function(int, int):int
f = (a, b) does
deeg (a, b) = deeg a + b
end
make deeginator = (x, y:float):bool does
make isAwesome = (x - y * 2 == 69)
# isAwesome should always be true
deeg isAwesome
end
Classes that are also extendable
class Living toString to () does deeg "I'm alive" end end
### Equivalent to above
class Living
toString to () does
deeg "I'm alive"
end
age to 21
end
###
class Animal extends Living
constructor to (@name) does end
toString to () does deeg "\{@name} is alive" end
end
Optionals are not the default type for variables.
make toys = ["bear"]
make unicorn:int? = toys.indexOf("unicorn")
if unicorn exists
print(unicorn)
else
print("dreams crushed")
end
make array = ["Hello", "Goodbye"]
make i = array.indexOf("Hi")
###
equivalent to:
make i:int? = array.indexOf("Hi")
###
print(array[i]) # returns error becasue i is i:int? and array[] requires full int
if i exists
print(array[i])
else
print("not found")
end
make str = array[i] if i exists else "not found"
make array = ["Hello", "Goodbye"]
make dict = { name to "Bob", age:int to 35, isPresident to false}
dict.name:string # every key of a dictionary has a specific type
dict.age:int
dict.isPresident:bool
print(array[0]) # prints "Hello"
print(array[2]) # maybe array[2] returns an optional, else this errors
make combo = array + dict # combo is an object with keys 0 and 1
print(size(dict)) # prints 3
print(size(array)) # prints 2
print(size(combo)) # prints 5
make array_multi = array * 3 # array_multi is ["Hello", "Goodbye", "Hello", "Goodbye", "Hello", "Goodbye"]
make array_combine = array + ["Hi"] # array_combine is ["Hello", "Goodbye", "Hi"]
make array_alt = ["Hi"] + array # array_alt is ["Hi", "Hello", "Goodbye"]
make array_str = array + "Hi" # array_str is ["Hello", "Goodbye", "Hi"]
make arr:List:float = array # convert to array of floats
make int_array:List:int = [2, 3] # arrays are homogeneous
make all_dict:Dict = { # dictionaries are heterogeneous
fun:bool to true,
days to 3
}
print(int_array + all_dict)
###
prints
{
0:int to 2,
1:int to 3,
days:int to 3,
fun:bool to true
}
###
Matches on values, types, and lists. In the Deeg future, matches on dictionaries as well.
make func = (x) does
match x with
>> 5 then deeg true
>> 72 then deeg true
>> _ then deeg false
end
end
make func = (l) does
match l with
>> head|tail if head > 5 then deeg head
>> _|tail then deeg false
end
end
make func = (param) does
match param with
>> _:int then deeg true
>> _:float then deeg false
>> _:string then deeg "Hello, World!"
>> _ then deeg "Get with the primitives."
end
end
Deeg on the left, JavaScript on the right
print("hello world") console.log("hello world");
make foo = 69 var foo = 69;
make bar:string = 69 var bar = "69";
make adder = (a:int, b=10):int does deeg a + b var adder = function (a, b) {
return a + b;
}
make even_and_true = (x:int, f():bool) does var even_and_true = function (x, f) {
if (f(x)) then if (f(x)) {
deeg x + 2 return x + 2;
else } else {
deeg x + 4 return x + 4;
end }
}
make fibonacci = (x) does function fibonacci(x) {
make a = 0, b = 1, c var a = 0, b = 1, c;
if (x < 3) deeg 1 if (x < 3) return 1;
while (--x > 0) does while (--x > 0) {
c = a + b, a = b, b = c c = a + b, a = b, b = c;
end }
deeg c return c;
end }
make gcd = (a, b) does var gcd = function(a, b) {
if (!b) exists deeg a end if ( ! b) {
deeg gcd(b, a % b) return a;
end }
return gcd(b, a % b);
};