| 
					
				 | 
			
			
				@@ -172,17 +172,27 @@ static bool cSetVar(const char* literal) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return b; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static bool cCallFunction(const char* literal) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int cCallFunctionArguments() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int arguments = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         arguments++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!cExpression()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } else if(cConsumeTokenIf(T_COMMA) && tPeekToken() == T_CLOSE_BRACKET) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             cUnexpectedToken(tPeekToken()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return arguments; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool cCallFunction(const char* literal) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cAddOperation(OP_PUSH_INT); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cAddInt(0); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int arguments = cCallFunctionArguments(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(arguments == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int address = fmSearchAddress(&functions, literal, arguments); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     if(address == -1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cError("unknown function on line %d", line); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -210,57 +220,30 @@ static bool cLiteral() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static bool cLine(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-static bool cFunction() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(varIndex == 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cError("function inside function on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(!cConsumeToken(T_LITERAL)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    const char* name = tReadString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(name == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cError("function literal without a function name on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(!cConsumeToken(T_OPEN_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    varIndex = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    vars[1].entries = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static int cFunctionArguments() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int arguments = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     while(!cConsumeTokenIf(T_CLOSE_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(!cConsumeToken(T_LITERAL)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         arguments++; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         const char* arg = tReadString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(arg == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             cError("function argument literal without string on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         cAddVar(arg); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(cConsumeTokenIf(T_COMMA) && tPeekToken() != T_LITERAL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             cUnexpectedToken(tPeekToken()); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-            return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+            return -1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return arguments; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(!cConsumeToken(T_OPEN_CURVED_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    cAddOperation(OP_GOTO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    int gotoIndex = cReserveInt(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				- 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    if(!fmAdd(&functions, name, arguments, code->length)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        cError("function registered twice on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool cLine(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool cFunctionInnerBody(int arguments) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddOperation(OP_PUSH); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     int pushIndex = cReserveInt(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddInt(arguments); 
			 | 
		
	
	
		
			
				| 
					
				 | 
			
			
				@@ -270,22 +253,61 @@ static bool cFunction() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         if(cConsumeTokenIf(T_END)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             cError("unexpected end of file: function not closed on line %d", oldLine); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-        if(!cLine()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        } else if(!cLine()) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				             return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				         } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				-    varIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddOperation(OP_POP); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddInt(vars[1].entries); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cSetInt(pushIndex, vars[1].entries); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool cFunctionBody(const char* name, int arguments) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!cConsumeToken(T_OPEN_CURVED_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    cAddOperation(OP_GOTO); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int gotoIndex = cReserveInt(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(!fmAdd(&functions, name, arguments, code->length)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cError("function registered twice on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if(!cFunctionInnerBody(arguments)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddOperation(OP_RETURN); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cSetInt(gotoIndex, code->length); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				  
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+static bool cFunction() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(varIndex == 1) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cError("function inside function on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if(!cConsumeToken(T_LITERAL)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    const char* name = tReadString(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(name == NULL) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        cError("function literal without a function name on line %d", line); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } else if(!cConsumeToken(T_OPEN_BRACKET)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    varIndex = 1; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    vars[1].entries = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    int arguments = cFunctionArguments(); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    if(arguments == -1 || !cFunctionBody(name, arguments)) { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+        return false; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    } 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    varIndex = 0; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+    return true; 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+} 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				+ 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				 static bool cPrint() { 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     bool b = cExpression() && cConsumeToken(T_SEMICOLON); 
			 | 
		
	
		
			
				 | 
				 | 
			
			
				     cAddOperation(OP_PRINT); 
			 |