1
0
Kajetan Johannes Hammerle vor 7 Jahren
Ursprung
Commit
ee3768016f

BIN
.DS_Store


+ 1 - 3
nbproject/private/private.xml

@@ -2,8 +2,6 @@
 <project-private xmlns="http://www.netbeans.org/ns/project-private/1">
     <editor-bookmarks xmlns="http://www.netbeans.org/ns/editor-bookmarks/2" lastBookmarkId="0"/>
     <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
-        <group>
-            <file>file:/Users/kajetanjohannes/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Code.java</file>
-        </group>
+        <group/>
     </open-files>
 </project-private>

+ 104 - 32
src/me/hammerle/code/Code.java

@@ -20,16 +20,9 @@ public class Code implements Comparable<Code>
     private final Object value;
     private int jump;
     
-    public Code(String function, int level, int pars, int line, int subline, Object value, int jump)
+    private Code(String function, int level, int pars, int line, int subline, Object value, int jump)
     {
-        if(function != null)
-        {
-            this.function = function.toLowerCase();
-        }
-        else
-        {
-            this.function = null;
-        }
+        this.function = function;
         this.level = level;
         this.pars = pars;
         this.line = line;
@@ -61,6 +54,11 @@ public class Code implements Comparable<Code>
             stack.push(value);
             return;
         }
+        else if(value == null && function == null)
+        {
+            stack.push(value);
+            return;
+        }
         Object[] input;
         if(pars > 0)
         {
@@ -89,7 +87,7 @@ public class Code implements Comparable<Code>
     @Override
     public String toString() 
     {
-        StringBuilder sb = new StringBuilder(">>>");
+        StringBuilder sb = new StringBuilder(">");
         for(int i = 1; i < level; i++)
         {
             sb.append(">");
@@ -103,8 +101,15 @@ public class Code implements Comparable<Code>
         if(value != null)
         {
             sb.append("push ");
-            sb.append(value.getClass());
-            sb.append(" value = '");
+            sb.append(value.getClass().getSimpleName());
+            sb.append(" '");
+            sb.append(value);
+            sb.append("'");
+            return sb.toString();
+        }
+        else if(value == null && function == null)
+        {
+            sb.append("push Null '");
             sb.append(value);
             sb.append("'");
             return sb.toString();
@@ -184,7 +189,7 @@ public class Code implements Comparable<Code>
         return start;
     }
     
-    private static int findStartOfSyntax(String code, int pos)
+    private static int findStartOfSyntax(StringBuilder code, int pos)
     {
         int bracketCounter = 0;
         char c;
@@ -217,6 +222,7 @@ public class Code implements Comparable<Code>
                 case '*':
                 case '/':
                 case '^':
+                case '@':
                 case '=':
                 case '>':
                 case '<':
@@ -249,7 +255,12 @@ public class Code implements Comparable<Code>
         return 0;
     }
     
-    private static int findEndOfSyntax(String code, int pos)
+    private static int findEndOfSyntax(StringBuilder code, int pos)
+    {
+        return findEndOfSyntax(code, pos, false);
+    }
+    
+    private static int findEndOfSyntax(StringBuilder code, int pos, boolean b)
     {
         int bracketCounter = 0;
         char c;
@@ -266,6 +277,15 @@ public class Code implements Comparable<Code>
                 pos++;
                 continue;
             }
+            if(b && c == '\n')
+            {
+                if(bracketCounter != 0)
+                {
+                    pos++;
+                    continue;
+                }
+                return pos;
+            }
             switch(c)
             {
                 case ';':
@@ -282,6 +302,7 @@ public class Code implements Comparable<Code>
                 case '*':
                 case '/':
                 case '^':
+                case '@':
                 case '=':
                 case '>':
                 case '<':
@@ -314,7 +335,7 @@ public class Code implements Comparable<Code>
         return code.length();
     }
     
-    private static int findSyntax(String find, String code, int pos)
+    private static int findSyntax(String find, StringBuilder code, int pos)
     {
         int length = code.length();
         char c;
@@ -354,13 +375,13 @@ public class Code implements Comparable<Code>
         StringBuilder newSyntax;
         while(pos < sb.length())
         {
-            pos = findSyntax(syntax, sb.toString(), pos + 1);
+            pos = findSyntax(syntax, sb, pos + 1);
             if(pos == -1)
             {
                 break;
             }
-            start = findStartOfSyntax(sb.toString(), pos - 1);
-            end = findEndOfSyntax(sb.toString(), pos + slength);
+            start = findStartOfSyntax(sb, pos - 1);
+            end = findEndOfSyntax(sb, pos + slength);
             newSyntax = new StringBuilder(f);
             newSyntax.append("(");
             if(b)
@@ -394,13 +415,13 @@ public class Code implements Comparable<Code>
         StringBuilder newSyntax;
         while(pos < sb.length())
         {
-            pos = findSyntax(syntax, sb.toString(), pos + 1);
+            pos = findSyntax(syntax, sb, pos + 1);
             if(pos == -1)
             {
                 break;
             }
-            start = findStartOfSyntax(sb.toString(), pos - 1);
-            end = findEndOfSyntax(sb.toString(), pos + slength);
+            start = findStartOfSyntax(sb, pos - 1);
+            end = findEndOfSyntax(sb, pos + slength);
             newSyntax = new StringBuilder("setvar(\"");
             first = sb.substring(start, pos).trim();
             newSyntax.append(first);
@@ -453,11 +474,21 @@ public class Code implements Comparable<Code>
         int pos = 0;
         while(true)
         {
-            pos = findSyntax(keyWord, sb.toString(), pos);
+            pos = findSyntax(keyWord, sb, pos);
             if(pos == -1)
             {
                 break;
             }
+            if(pos >= 1 && Character.isLetter(sb.charAt(pos - 1)))
+            {
+                pos += length;
+                continue;
+            }
+            if(pos + length < sb.length() && Character.isLetter(sb.charAt(pos + length)))
+            {
+                pos += length;
+                continue;
+            }
             if(!sb.substring(pos).startsWith(with))
             {
                 sb.replace(pos, pos + length, with);
@@ -476,12 +507,12 @@ public class Code implements Comparable<Code>
         StringBuilder sb = new StringBuilder(code);
         while(true)
         {
-            old = findSyntax("/*", sb.toString(), old);
+            old = findSyntax("/*", sb, old);
             if(old == -1)
             {
                 break;
             }
-            pos = findSyntax("*/", sb.toString(), old);
+            pos = findSyntax("*/", sb, old);
             if(pos == -1)
             {
                 throw new PrescriptException(scriptName, sb.substring(old, Math.min(old + 20, sb.length())), "/* without */");
@@ -491,12 +522,12 @@ public class Code implements Comparable<Code>
         old = 0;
         while(true)
         {
-            old = findSyntax("//", sb.toString(), old);
+            old = findSyntax("//", sb, old);
             if(old == -1)
             {
                 break;
             }
-            pos = findSyntax("\n", sb.toString(), old);
+            pos = findSyntax("\n", sb, old);
             if(pos == -1)
             {
                 sb.replace(old, sb.length(), "");
@@ -505,11 +536,34 @@ public class Code implements Comparable<Code>
             sb.replace(old, pos + 1, "");
         }
         // end comments
+        
+        // allowing labels without ;
+        old = 0;
+        while(true)
+        {
+            pos = findSyntax("@", sb, old);
+            if(pos == -1)
+            {
+                break;
+            }
+            pos++;
+            old = pos;
+            pos = findEndOfSyntax(sb, pos, true);
+            if(pos == -1)
+            {
+                break;
+            }
+            if(sb.charAt(pos) != ';')
+            {
+                sb.insert(pos, ';');
+            }
+        }
 
         // key words without ()
         addKeyWordBrackets("else", sb);        
         addKeyWordBrackets("try", sb);   
         addKeyWordBrackets("catch", sb);   
+        //System.out.println(sb);
         // end key words
 
         // replacing of function syntax
@@ -536,8 +590,22 @@ public class Code implements Comparable<Code>
         changeUnSyntax("*=", "mul", sb);
 
         changeBiSyntax("=", "setvar", sb, true);
+        
+        // numbers like -5 turn to sub(,5) --> fixing
+        pos = 0;
+        while(true)
+        {
+            pos = findSyntax("sub(,", sb, pos);
+            if(pos == -1)
+            {
+                break;
+            }
+            sb.insert(pos + 4, '0');
+            pos++;
+        }
 
         code = sb.toString();
+        //System.out.println(code);
         // end of substitution
         // split code into lines
         ArrayList<Code> list = new ArrayList<>();
@@ -815,16 +883,16 @@ public class Code implements Comparable<Code>
         int end = findClosingBracket(f, start);
         if((start != -1 || end != -1) && (((start == -1 || end == -1) && start != end) || end != f.length() - 1))
         {
-            throw new PrescriptException(scriptName, "unbalanced ()", f);
+            throw new PrescriptException(scriptName, f, "unbalanced ()");
         }
         if(start == -1)
         {
-            list.add(new Code(level, 0, line, sublines, convertInput(f)));
+            list.add(new Code(level, 0, line, sublines, convertInput(f, true)));
             return;
         }
         else if(start >= end - 1)
         {
-            String functionName = f.substring(0, start).trim();
+            String functionName = f.substring(0, start).trim().toLowerCase();
             if(!parser.isRegisteredFunction(functionName))
             {
                 throw new NoSuchMethodException(scriptName, f, functionName);
@@ -833,7 +901,7 @@ public class Code implements Comparable<Code>
             return;
         }
         ArrayList<String> splitted = splitComma(f.substring(start + 1, end));
-        String functionName = f.substring(0, start).trim();
+        String functionName = f.substring(0, start).trim().toLowerCase();
         if(!parser.isRegisteredFunction(functionName))
         {
             throw new NoSuchMethodException(scriptName, f, functionName);
@@ -842,7 +910,7 @@ public class Code implements Comparable<Code>
         splitted.forEach(s -> splitFunctions(list, s, level, line));
     }
     
-    public static Object convertInput(String s)
+    public static Object convertInput(String s, boolean variable)
     {
         if(s == null)
         {
@@ -883,7 +951,11 @@ public class Code implements Comparable<Code>
         }
         catch(NumberFormatException ex)
         {
-            return new Variable(s);
+            if(variable)
+            {
+                return new Variable(s);
+            }
+            return s;
         }
     }
 }

+ 2 - 2
src/me/hammerle/code/ISnuviScheduler.java

@@ -2,6 +2,6 @@ package me.hammerle.code;
 
 public interface ISnuviScheduler 
 {
-    public void scheduleTask(Runnable r);  
-    public void scheduleTask(Runnable r, long delay);
+    public int scheduleTask(Runnable r);  
+    public int scheduleTask(Runnable r, long delay);
 }

+ 72 - 1
src/me/hammerle/code/Script.java

@@ -1,8 +1,10 @@
 package me.hammerle.code;
 
 import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
+import java.util.List;
 import java.util.Stack;
 import me.hammerle.exceptions.CodeTooLongException;
 import me.hammerle.exceptions.GotoLabelNotFoundException;
@@ -24,7 +26,7 @@ public class Script
     private final Stack<Object> valueStack;
     private final Stack<Integer> returnStack;
     
-    private final Code[] code;
+    private Code[] code;
     private int position;
 
     private int loopCounter;
@@ -49,6 +51,10 @@ public class Script
         returnStack = new Stack<>();
         
         this.code = Code.generate(parser, name, code, gotos);
+        /*for(Code c : this.code)
+        {
+            System.out.println(c);
+        }*/
         
         position = 0;
 
@@ -70,6 +76,54 @@ public class Script
         
     }
     
+    public void overload(String code)
+    {       
+        gotos.clear();
+        valueStack.clear();
+        returnStack.clear();
+        this.code = Code.generate(parser, name, code, gotos);
+        position = 0;
+        halt = false;
+        valid = true;
+        tryJumpLine = -1;
+    }
+    
+    public Code[] getCode(int line)
+    {
+        int start = 0;
+        int end = code.length;
+        int helper;
+
+        while(end - start > 1)
+        {
+            helper = (start + end) >> 1;
+            if(code[helper].line > line)
+            {
+                end = helper;
+            }
+            else if(code[helper].line <= line)
+            {
+                start = helper;
+            }
+        }
+        int realEnd = start;
+        start = 0;
+        end = code.length;
+        while(end - start > 1)
+        {
+            helper = (start + end) >> 1;
+            if(code[helper].line >= line)
+            {
+                end = helper;
+            }
+            else if(code[helper].line < line)
+            {
+                start = helper;
+            }
+        }
+        return Arrays.copyOfRange(code, end, realEnd + 1);
+    }
+    
     // -----------------------------------------------------------------------------------
     // Script-Daten
     // -----------------------------------------------------------------------------------
@@ -184,6 +238,23 @@ public class Script
         return variables.get(var);
     }
     
+    public HashMap<String, Object> getVars()
+    {
+        return variables;
+    }
+    
+    public boolean getBooleanVar(String var)
+    {
+        try
+        {
+            return (boolean) getVar(var);
+        }
+        catch(ClassCastException | NullPointerException ex)
+        {
+            return false;
+        }
+    }
+    
     public void removeVar(String var)
     {
         variables.remove(var);

+ 81 - 1
src/me/hammerle/code/ScriptUtils.java

@@ -1,8 +1,14 @@
 package me.hammerle.code;
 
+import java.io.File;
+import java.io.IOException;
+import java.nio.charset.MalformedInputException;
+import java.nio.file.Files;
 import java.util.Arrays;
+import java.util.Collection;
 import java.util.Random;
 import java.util.stream.Collectors;
+import me.hammerle.exceptions.PrescriptException;
 
 public class ScriptUtils
 {
@@ -13,8 +19,82 @@ public class ScriptUtils
         return RANDOM.nextInt((max - min) + 1) + min;
     }
     
+    // -----------------------------------------------------------------------------------
+    // number getter
+    // -----------------------------------------------------------------------------------
+    
+    public static int getInt(Object o)
+    {
+        return ((Number) o).intValue();
+    }
+    
+    public static byte getByte(Object o)
+    {
+        return ((Number) o).byteValue();
+    }
+    
+    public static double getDouble(Object o)
+    {
+        return ((Number) o).doubleValue();
+    }
+    
+    public static float getFloat(Object o)
+    {
+        return ((Number) o).floatValue();
+    }
+    
+    // -----------------------------------------------------------------------------------
+    // connectors
+    // -----------------------------------------------------------------------------------
+    
     public static String connect(Object[] o, int skip)
     {
-        return Arrays.stream(o, skip, o.length).map(ob -> String.valueOf(ob)).collect(Collectors.joining());
+        return Arrays.stream(o, skip, o.length).map(ob -> String.valueOf(ob))
+                .collect(Collectors.joining());
+    }
+    
+    public static String connect(Collection<Object> c, int skip)
+    {
+        return c.stream().skip(skip).map(o -> o.toString()).collect(Collectors.joining());
+    }
+    
+    public static String connect(Object[] c, String s, int skip)
+    {
+        return Arrays.stream(c, skip, c.length).map(o -> o.toString()).collect(Collectors.joining(s));
+    }
+    
+    public static String connect(Collection<Object> c, String s, int skip)
+    {
+        return c.stream().skip(skip).map(o -> String.valueOf(o)).collect(Collectors.joining(s));
+    }
+    
+    // -----------------------------------------------------------------------------------
+    // file stuff
+    // -----------------------------------------------------------------------------------
+    
+    public static String readCode(String filename, String ending)
+    {
+        File script = new File("./" + filename + ending);  
+        if(script.exists())
+        {
+            try
+            {
+                return String.join("\n", Files.readAllLines(script.toPath()));
+            } 
+            catch (MalformedInputException ex) 
+            {
+                throw new PrescriptException(filename, "", "file contains an illegal character, change file encoding");
+            }
+            catch (IOException ex) 
+            {
+                throw new PrescriptException(filename, "", "file '" + filename + "' cannot be read");
+            }
+        }
+        throw new PrescriptException(filename, "", "file '" + filename + "' does not exist");
+    }
+    
+    public static String readCode(String filename)
+    {
+        return readCode(filename, ".snuvi");
     }
 }

+ 87 - 16
src/me/hammerle/code/SnuviParser.java

@@ -28,7 +28,7 @@ public class SnuviParser
     protected final ISnuviLogger logger;
     private final ISnuviScheduler scheduler;
     private final HashMap<String, BiFunction<Object[], Script, Object>> functions;
-    private boolean printStack;
+    public boolean printStack;
     
     private int idCounter;
     private final HashMap<Integer, Script> scripts;
@@ -101,6 +101,27 @@ public class SnuviParser
         registerFunction("event.isloaded", (args, sc) -> 
                 sc.isLoadedEvent(args[0].toString())); 
 
+        // -------------------------------------------------------------------------------    
+        // bit
+        // ------------------------------------------------------------------------------- 
+        
+        registerFunction("bit.rightshift", (args, qd) -> 
+                (double) (getInt(args[0]) >> getInt(args[1])));
+        registerFunction("bit.leftshift", (args, qd) -> 
+                (double) (getInt(args[0]) << getInt(args[1])));
+        registerFunction("bit.and", (args, qd) -> 
+                (double) (getInt(args[0]) & getInt(args[1])));
+        registerFunction("bit.or", (args, qd) -> 
+                (double) (getInt(args[0]) | getInt(args[1])));
+        registerFunction("bit.xor", (args, qd) -> 
+                (double) (getInt(args[0]) ^ getInt(args[1])));
+        registerFunction("bit.invert", (args, qd) -> 
+                (double) (~getInt(args[0])));
+        registerFunction("bit.set", (args, qd) -> 
+                (double) (getInt(args[0]) | (getInt(args[2]) << getInt(args[1]))));
+        registerFunction("bit.get", (args, qd) -> 
+                (double) ((getInt(args[0]) & (1 << getInt(args[1])))) != 0);
+        
         // -------------------------------------------------------------------------------    
         // math
         // -------------------------------------------------------------------------------    
@@ -159,7 +180,7 @@ public class SnuviParser
         registerFunction("list.contains", (args, sc) ->                            
                 ((List) args[0]).contains(args[1]));
         registerFunction("list.getsize", (args, sc) ->                            
-                ((List) args[0]).size());
+                (double) ((List) args[0]).size());
         registerFunction("list.getindex", (args, sc) ->                            
                 ((List) args[0]).get(getInt(args[1])));
         registerConsumer("list.setindex", (args, sc) ->                            
@@ -167,7 +188,7 @@ public class SnuviParser
         registerConsumer("list.clear", (args, sc) ->                            
                 ((List) args[0]).clear());
         registerFunction("list.getindexof", (args, sc) ->                            
-                ((List) args[0]).indexOf(args[1]));  
+                (double) ((List) args[0]).indexOf(args[1]));  
         registerConsumer("list.sort", (args, sc) ->  
                 sortList((List<Object>) args[0], sc));
         registerConsumer("list.reverse", (args, sc) ->                            
@@ -189,7 +210,7 @@ public class SnuviParser
         registerFunction("map.contains", (args, sc) ->                            
                 ((HashMap) args[0]).containsKey(args[1]));
         registerFunction("map.getsize", (args, sc) ->                            
-                ((HashMap) args[0]).size());
+                (double) ((HashMap) args[0]).size());
         registerFunction("map.get", (args, sc) ->                            
                 ((HashMap) args[0]).get(args[1]));
         registerConsumer("map.clear", (args, sc) ->                            
@@ -209,15 +230,15 @@ public class SnuviParser
         registerFunction("set.contains", (args, sc) ->                            
                 ((HashSet) args[0]).contains(args[1]));
         registerFunction("set.getsize", (args, sc) ->                            
-                ((HashSet) args[0]).size());
+                (double) ((HashSet) args[0]).size());
 
         // -------------------------------------------------------------------------------  
         // time
         // -------------------------------------------------------------------------------
         registerFunction("time.get", (args, sc) ->                            
-                (double) System.currentTimeMillis());
+                getDouble(System.currentTimeMillis()));
         registerFunction("time.nextday", (args, sc) ->         
-                (double) getNextDay(args));   
+                getDouble(getNextDay(args)));   
         registerFunction("time.getyear", (args, sc) ->         
                 (double) getYear(args));   
         registerFunction("time.getmonth", (args, sc) ->         
@@ -230,7 +251,15 @@ public class SnuviParser
                 (double) getMinute(args));   
         registerFunction("time.getsecond", (args, sc) ->         
                 (double) getSecond(args));                   
-               
+              
+        // -------------------------------------------------------------------------------    
+        // text
+        // -------------------------------------------------------------------------------   
+        registerFunction("text.number", (args, sc) ->         
+                doubleToString(getDouble(args[0]))); 
+        registerFunction("text.class", (args, sc) ->         
+                args[0].getClass().getSimpleName()); 
+        
         // -------------------------------------------------------------------------------    
         // commands without library
         // -------------------------------------------------------------------------------    
@@ -357,6 +386,11 @@ public class SnuviParser
         return scripts.get(id);
     }
     
+    public boolean termUnsafe(Script sc)
+    {
+        return scripts.remove(sc.getId()) != null;
+    }
+    
     public void termSafe(Script sc)
     {
         if(sc == null)
@@ -410,17 +444,25 @@ public class SnuviParser
         return startScript(new Script(this, idCounter, scriptName, code));
     }
     
-    public Script startScript(Class<? extends Script> c, String scriptName, String code, boolean b, Object... o)
+    public <T extends Script> T startScript(Class<T> c, String scriptName, String code, boolean b, Object... o)
     { 
         try
         {
-            return startScript(c.getDeclaredConstructor(
+            return (T) startScript(c.getDeclaredConstructor(
                     SnuviParser.class, int.class, String.class, String.class, boolean.class)
                     .newInstance(this, idCounter, scriptName, code, b), o);
         }
         catch(IllegalAccessException | IllegalArgumentException | InstantiationException |
                 InvocationTargetException | NoSuchMethodException | SecurityException ex)
         {
+            if(ex instanceof InvocationTargetException)
+            {
+                Throwable t = ((InvocationTargetException) ex).getCause();
+                if(t != null && t instanceof SnuviException)
+                {
+                    logger.printException((SnuviException) t);
+                }
+            }
             return null;
         }
     }
@@ -437,33 +479,56 @@ public class SnuviParser
                 .forEach(sc -> 
                 {
                     sc.setVar("event", name);
-                    before.accept(sc);
+                    if(before != null)
+                    {
+                        before.accept(sc);
+                    }
                     sc.runCode();
-                    after.accept(sc);
+                    if(after != null)
+                    {
+                        after.accept(sc);
+                    }
                     sc.eventVars.forEach(s -> sc.removeVar(s));
                     sc.eventVars.clear();
                 });
         term();
     }
     
-    public void callEvent(String name, Script sc, Consumer<Script> before, Consumer<Script> after)
+    public boolean callEvent(String name, Script sc, Consumer<Script> before, Consumer<Script> after)
     {
         if(sc.isLoadedEvent(name))
         {
             sc.setVar("event", name);
-            before.accept(sc);
+            if(before != null)
+            {
+                before.accept(sc);
+            }
             sc.runCode();
-            after.accept(sc);
+            if(after != null)
+            {
+                after.accept(sc);
+            }
             sc.eventVars.forEach(s -> sc.removeVar(s));
             sc.eventVars.clear();
             term();
+            return true;
         }
+        return false;
     }
     
     // -----------------------------------------------------------------------------------
     // functions
     // -----------------------------------------------------------------------------------
     
+    private String doubleToString(Double d)
+    {
+        if(d.doubleValue() == d.longValue())
+        {
+            return String.valueOf(d.longValue());
+        }
+        return d.toString();
+    }
+    
     private void ifFunction(Object[] args, Script sc)
     {
         if(Arrays.stream(args).anyMatch(s -> !((boolean) s)))
@@ -547,6 +612,7 @@ public class SnuviParser
             return false;
         }
         // this is needed for comparing different number types (e.g. Integer and Double)
+        // allthough there should be no numbers except doubles...
         else if(args[1] instanceof Number && args[0] instanceof Number)
         {
             return ((Number) args[0]).doubleValue() == ((Number) args[1]).doubleValue();
@@ -558,7 +624,7 @@ public class SnuviParser
     {
         sc.setVar(args[0].toString(), 
                 Arrays.stream(ScriptUtils.connect(args, 2).split(args[1].toString()))
-                        .map(s -> Code.convertInput(s)).collect(Collectors.toList()));
+                        .map(s -> Code.convertInput(s, false)).collect(Collectors.toList()));
     }
     
     // -----------------------------------------------------------------------------------   
@@ -575,6 +641,11 @@ public class SnuviParser
         return ((Number) o).longValue();
     }
     
+    private double getDouble(Object o)
+    {
+        return ((Number) o).doubleValue();
+    }
+    
     // -----------------------------------------------------------------------------------    
     // time handler
     // -----------------------------------------------------------------------------------

+ 6 - 0
src/me/hammerle/exceptions/IllegalStringException.java

@@ -12,6 +12,12 @@ public class IllegalStringException extends SnuviException
         this.s = s;
     }
     
+    public IllegalStringException(String s)
+    {
+        super(null);
+        this.s = s;
+    }
+    
     public String getBadString()
     {
         return s;

+ 35 - 2
src/me/hammerle/exceptions/SnuviException.java

@@ -1,22 +1,33 @@
 package me.hammerle.exceptions;
 
+import java.util.ArrayList;
+import me.hammerle.code.Code;
 import me.hammerle.code.Script;
 
 public class SnuviException extends RuntimeException
 {
     private final Exception ex;
     private final String scriptName;
-    private final String code;
+    private final ArrayList<String> code;
     private final int line;
     
     public SnuviException(Exception ex, String scriptName, int line, String code)
     {
         this.ex = ex;
         this.scriptName = scriptName;
-        this.code = code;
+        this.code = new ArrayList<>();
+        addCode(code);
         this.line = line;
     }
     
+    private void addCode(String code)
+    {
+        if(code != null)
+        {
+            this.code.add(code);
+        }
+    }
+    
     public SnuviException(Exception ex, String scriptName, String code)
     {
         this(ex, scriptName, -1, code);
@@ -30,6 +41,19 @@ public class SnuviException extends RuntimeException
     public SnuviException(Exception ex, Script sc)
     {
         this(ex, sc.getName(), sc.getActiveCodeLine());
+        int i = sc.getActiveCodeLine();
+        if(i != -1)
+        {
+            for(Code c : sc.getCode(line))
+            {
+                this.code.add(c.toString());
+            }
+        }
+    }
+    
+    public SnuviException(Exception ex)
+    {
+        this(ex, null, -1);
     }
     
     public Exception getOriginalException()
@@ -43,6 +67,15 @@ public class SnuviException extends RuntimeException
     }
     
     public String getCode()
+    {
+        if(code.isEmpty())
+        {
+            return null;
+        }
+        return code.get(0);
+    }
+    
+    public ArrayList<String> getWholeCode()
     {
         return code;
     }

+ 7 - 11
src/me/hammerle/snuviscript/SnuviScript.java

@@ -4,6 +4,7 @@ import me.hammerle.code.Script;
 import me.hammerle.code.SnuviParser;
 import me.hammerle.exceptions.SnuviException;
 import me.hammerle.code.ISnuviScheduler;
+import me.hammerle.code.ScriptUtils;
 
 public class SnuviScript 
 {
@@ -19,28 +20,23 @@ public class SnuviScript
         }, new ISnuviScheduler() 
         {
             @Override
-            public void scheduleTask(Runnable r) 
+            public int scheduleTask(Runnable r) 
             {
                 System.out.println("Schedule");
+                return 0;
             }
 
             @Override
-            public void scheduleTask(Runnable r, long delay) 
+            public int scheduleTask(Runnable r, long delay) 
             {
                 System.out.println("Schedule");
+                return 0;
             }
         });
         parser.registerConsumer("debug", (o, sc) -> System.out.println(o[0]));
+        parser.registerFunction("ggv", (o, sc) -> o[0]);
         
         parser.startScript(Script.class, "test", 
-                "wusi = 5;\n" +
-                "@test;\n" +
-                "while(wusi < 10)\n" +
-                "{\n" +
-                "    wusi += 1;\n" +
-                "    debug(wusi);\n" +
-                "}\n" + 
-                "if( wusi > 100) { term();}" +
-                "debug(wusi); wusi += 5; goto(\"test\");", true);
+                "debug(equal(2, null));", true);
     }   
 }