diff --git a/README.md b/README.md
index da30590cf73397b3a12480e807317844228d6ebf..f5cfbe5ca39c3c17612d363951779a1271e5390b 100644
--- a/README.md
+++ b/README.md
@@ -31,18 +31,18 @@ $ ./main.py
 $ ./main.py -d
 > 4+4
 Debug: lexer returned: '[(1, '4'), (3, '+'), (1, '4'), (0, None)]'
-Debug: parser returned: '<interpreter.BinaryOp object at 0x7f0f0b51e790>'
+Debug: parser returned: '((4.0)+(4.0))'
 8.0
 > 
 ```
 ```bash
-$ ./main.py -c "5*(0+5+0)"
+$ ./main.py -c "5(0+5+0)"
 25.0
 ```
 ```bash
-$ ./main.py -dc "3*sin(cos(2))"
+$ ./main.py -dc "3sin(cos(2))"
 Debug: lexer returned: '[(1, '3'), (3, '*'), (4, 'sin'), (2, '('), (4, 'cos'), (2, '('), (1, '2'), (2, ')'), (2, ')'), (0, None)]'
-Debug: parser returned: '<interpreter.BinaryOp object at 0x7f7a676a7790>'
+Debug: parser returned: '((3.0)*sin(cos((2.0))))'
 -1.2127174615567973
 ```
 ```bash
@@ -77,7 +77,7 @@ AST kerättyä se suoritetaan tulkilla. Se käy rekursiivisesti läpi kaikki sen
 ### Funktiot:
 ```bash
 $ ./main.py
-> fn f(x) = 2*x^3-4*x+12
+> fn f(x) = 2x^3-4x+12
 ok
 > f(2)
 20.0
@@ -100,10 +100,17 @@ ok
 54.0
 > 
 ```
+```bash
+$ x = 3pi
+ok
+> x
+9.42477796076938
+> 
+```
 #### Funktiot tallennetaan:
 ```bash
 $ ./main.py
-> fn f(x) = 2*x^3-4*x+12
+> fn f(x) = 2x^3-4x+12
 ok
 > ^C
 $ ./main.py
diff --git a/calc_interpreter.py b/calc_interpreter.py
index 1e83dceb7a30b75ee898e9398ae1c1192bb8e5f2..10ffaccc382137905d6d0fb4708e65f884e5bfbb 100644
--- a/calc_interpreter.py
+++ b/calc_interpreter.py
@@ -38,9 +38,11 @@ class Memory:
 			"round": lambda memory, x: Result.ok(round(x)),
 		};
 
-		self.custom_functions = {}
+		self.custom_functions = {};
 
-		self.arguments = {}
+		self.arguments = {};
+
+		self.depth = 0;
 
 		self.load();
 
@@ -74,6 +76,15 @@ class Num:
 	def __str__(self):
 		return f"{self.val}";
 
+def call_function(func, memory, *args):
+	memory.depth += 1;
+	if memory.depth >= 16:
+		return Result.err(f"Error: Recursion limit");
+	
+	result = func(memory, *args);
+	memory.depth -= 1;
+	return result;
+
 class Const:
 	def __init__(self, name):
 		self.name = name;
@@ -95,7 +106,7 @@ class Const:
 			if func != None:
 				func_argc = func.argc() if custom else (len(inspect.signature(func).parameters) - 1);
 				if func_argc == 0:
-					return func(memory);
+					return call_function(func, memory);
 		
 		if const == None:
 			if func != None:
@@ -141,7 +152,7 @@ class Func:
 		if func_argc != given_argc:
 			return Result.err(f"Error: function argument count mismatch for: '{self.func}' got {given_argc} expected {func_argc}");
 		
-		calc_result = func(memory, *args);
+		calc_result = call_function(func, memory, *args);
 		if calc_result.is_err:
 			return calc_result;
 		calc_result = calc_result.inner;
@@ -226,7 +237,10 @@ class BinaryOp:
 		elif self.op == '*':
 			return Result.ok(lhs * rhs);
 		elif self.op == '/':
-			return Result.ok(lhs / rhs);
+			if rhs == 0:
+				return Result.err(f"Error: Division by zero. LHS: {lhs}");
+			else:
+				return Result.ok(lhs / rhs);
 		elif self.op == '^':
 			return Result.ok(lhs ** rhs);
 		else:
diff --git a/calc_parser.py b/calc_parser.py
index 73d0f1ae9e7ffd78eb7f4f018bba85c668c4823c..d2ca05422da039d45f15bf8a6e4ace41768a19e9 100644
--- a/calc_parser.py
+++ b/calc_parser.py
@@ -6,7 +6,34 @@ from calc_interpreter import *;
 
 
 def parse(debug_mode: bool, tokens: []):
-	return parse_stmt(debug_mode, tokens);
+	# insert missing multiplication ops
+	index = 0;
+	while index < len(tokens) - 1:
+		left = tokens[index];
+		right = tokens[index + 1];
+
+		r_num = right[0] == calc_lexer.TOKEN_NUM;
+		l_num = left[0] == calc_lexer.TOKEN_NUM;
+		r_ident = right[0] == calc_lexer.TOKEN_IDENT;
+		l_r_group = left[0] == calc_lexer.TOKEN_GROUP and left[1] == ')';
+		r_l_group = right[0] == calc_lexer.TOKEN_GROUP and right[1] == '(';
+
+		if (l_num and r_ident) or (l_num and r_l_group) or (l_r_group and r_l_group) or (l_r_group and r_l_group) or (l_r_group and r_num) or (l_r_group and r_ident):
+			tokens.insert(index + 1, (calc_lexer.TOKEN_OP, '*'));
+		
+		index += 1;
+
+	ast = parse_stmt(debug_mode, tokens);
+
+	if ast.is_err:
+		return ast;
+
+	if len(tokens) > 1:
+		tokens.pop(len(tokens) - 1);
+		token_str = ' '.join([str(token[1]) for token in tokens]);
+		return Result.err(f"Error: leftover tokens: '{token_str}'");
+
+	return ast;
 
 # -------
 # calc_parsers
@@ -194,9 +221,28 @@ def parse_fn_impl(tokens: []):
 
 	return Result.ok(ImplFunc(name, csv, expr));
 
+def parse_const_impl(tokens: []):
+	name = parse_ident(tokens);
+	if name.is_err:
+		return name;
+	name = name.inner;
+
+	if not is_eq(*tokens.pop(0)):
+		return Result.err("Expected '='");
+
+	expr = parse_expr(tokens);
+	if expr.is_err:
+		return expr;
+	expr = expr.inner;
+
+	return Result.ok(ImplFunc(name, [], expr));
+
+
 def parse_stmt(debug_mode: bool, tokens: []):
 	if is_fn_keyword(*tokens[0]):
 		return parse_fn_impl(tokens);
+	elif is_eq(*tokens[1]):
+		return parse_const_impl(tokens);
 	else:
 		return parse_expr(tokens);
 
@@ -213,5 +259,8 @@ def is_comma(token_type, token):
 def is_fn_keyword(token_type, token):
 	return token_type == calc_lexer.TOKEN_IDENT and token == "fn";
 
+def is_cn_keyword(token_type, token):
+	return token_type == calc_lexer.TOKEN_IDENT and token == "cn";
+
 def is_eq(token_type, token):
 	return token_type == calc_lexer.TOKEN_EQ;
\ No newline at end of file
diff --git a/main.py b/main.py
index 1a0072d761117a786534ce57667ec4d4bff1746c..7bbf716a300affa4ff8c2308a93656a01e043a77 100755
--- a/main.py
+++ b/main.py
@@ -11,7 +11,7 @@ from calc_interpreter import Memory;
 def run(debug_mode: bool, dump: bool, text: str):
 	tokens = calc_lexer.lex(debug_mode, text);
 	if debug_mode:
-		print(f"Debug: calc_lexer returned: '{tokens}'");
+		print(f"Debug: lexer returned: '{tokens}'");
 	
 	ast = calc_parser.parse(debug_mode, tokens);
 	if ast.is_err:
@@ -19,14 +19,14 @@ def run(debug_mode: bool, dump: bool, text: str):
 		return True;
 	ast = ast.inner;
 	if debug_mode:
-		print(f"Debug: calc_parser returned: '{ast}'");
+		print(f"Debug: parser returned: '{ast}'");
 
 	if dump:
 		print(f"{ast}");
 	else:
 		calc_result = ast.visit(Memory());
 		if calc_result.is_err:
-			print(f"calc_interpreter error: {calc_result.inner}");
+			print(f"Interpreter error: {calc_result.inner}");
 			return True;
 		calc_result = calc_result.inner;
 		print(f"{calc_result}");