Jelajahi Sumber

array syntax, optimized syntax handling, break, continue

Kajetan Johannes Hammerle 7 tahun lalu
induk
melakukan
e2a981b3c1

+ 1 - 2
nbproject/private/private.xml

@@ -4,8 +4,7 @@
     <open-files xmlns="http://www.netbeans.org/ns/projectui-open-files/2">
         <group>
             <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/LineCompiler.java</file>
-            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/Code.java</file>
-            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/Instruction%20List%20–%20SmileBasic.html</file>
+            <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/todo.html</file>
             <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/code/SnuviParser.java</file>
             <file>file:/home/kajetan/Dropbox/Projekte/Informatik/SnuviScript/src/me/hammerle/snuviscript/SnuviScript.java</file>
         </group>

+ 67 - 3
src/me/hammerle/code/Code.java

@@ -13,6 +13,7 @@ public class Code
     protected final int pars;
     protected final byte layer;
     protected Object value;
+    protected boolean stackPush;
     
     private Code(String function, int pars, Object value, int realLine, byte layer)
     {
@@ -21,6 +22,7 @@ public class Code
         this.value = value;
         this.realLine = realLine;
         this.layer = layer;
+        this.stackPush = true;
     }
     
     public Code(String function, int pars, int realLine, byte layer)
@@ -64,7 +66,7 @@ public class Code
             input = new Object[0];
         }
         Object output = parser.parseFunction(sc, function, input);
-        if(output != Void.TYPE)
+        if(stackPush && output != Void.TYPE)
         {
             stack.push(output);
         }
@@ -96,6 +98,11 @@ public class Code
                 sb.append(value);
                 sb.append(")");
             }
+            
+            if(!stackPush)
+            {
+                sb.append(" no-push");
+            }
         }
         else
         {
@@ -432,6 +439,11 @@ public class Code
             {
                 continue;
             }
+            else if(s.equals("break") || s.equals("continue"))
+            {
+                co.add(new Code(s, 0, realCodeLine.get(i), layer));
+                continue;
+            }
             else if(lines.get(Math.min(i + 1, lines.size() - 1)).equals("{"))
             {
                 layer++;
@@ -455,6 +467,7 @@ public class Code
             line = realCodeLine.get(i);
             compiler.reset(line, layer, s);
             compiler.compile(co, strings);
+            co.get(co.size() - 1).stackPush = false;
         }
         
         // ---------------------------------------------------------------------
@@ -500,6 +513,57 @@ public class Code
             }
             oldLayer = newLayer;
         }
+        
+        // ---------------------------------------------------------------------
+        // generating break and continue
+        // ---------------------------------------------------------------------
+
+        String f;
+        Code data;
+        for(int i = 0; i < c.length; i++)
+        {
+            f = c[i].function;
+            if(f != null)
+            {
+                if(f.equals("break"))
+                {
+                    for(int j = i; j < c.length; j++)
+                    {
+                        data = c[j];
+                        if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
+                        {
+                            c[i].value = j - i;
+                            j += (int) data.value + 1;
+                            for(; j < c.length; j++)
+                            {
+                                if("while".equals(c[j].function))
+                                {
+                                    break;
+                                }
+                                else if("for".equals(c[j].function))
+                                {
+                                    c[i] = new Code("breakreset", 0, c[i].value, c[i].realLine, c[i].layer);
+                                }
+                            }
+                            break;
+                        }
+                    }
+                }
+                else if(f.equals("continue"))
+                {
+                    for(int j = i; j < c.length; j++)
+                    {
+                        data = c[j];
+                        if("gotoline".equals(data.function) && data.value != null && (int) data.value != 0)
+                        {
+                            c[i].value = j - i + (int) data.value;
+                            break;
+                        }
+                    }
+                }
+                
+            }
+        }
 
         // end
         System.out.println((System.currentTimeMillis() - startTime) + " ms");  
@@ -517,6 +581,7 @@ public class Code
             {
                 switch(c[j].function)
                 {
+                    case "for":
                     case "while":
                         return -j;
                     case "if":
@@ -596,5 +661,4 @@ public class Code
     {
         return convertInput(null, s, false);
     }
-}
-// 916
+}

+ 319 - 114
src/me/hammerle/code/LineCompiler.java

@@ -58,7 +58,6 @@ public class LineCompiler
     {
         if(function)
         {
-            //System.out.println("push last result");
             if(index + 1 != lastSpecial.peek())
             {
                 co.add(new Code(Code.convertInput(strings, line.substring(index + 1, lastSpecial.pop()), true), realLine, layer));
@@ -92,146 +91,352 @@ public class LineCompiler
     
     public void compile(ArrayList<Code> co, HashMap<String, String> strings)
     {
-        int old;
-        int j = line.length() - 1;    
-        int commas;
-        String syntax;
-        while(j >= 0)
+        try
         {
-            syntax = null;
-            switch(line.charAt(j))
+            int old;
+            int j = line.length() - 1;    
+            boolean arrayState = true;
+            String arrayFunction = null;
+            int commas;
+            String syntax;
+            while(j >= 0)
             {
-                case '+': syntax = "add"; break;
-                case '-': syntax = "sub"; break;
-                case '*': syntax = "mul"; break;
-                case '/': syntax = "div"; break;
-                case '%': syntax = "math.mod"; break;
-                case '^': syntax = "math.pow"; break;
-                case '<': syntax = "less"; break;
-                case '>': syntax = "greater"; break;
-                /* 
-                    changeBiSyntax("||", "or", sb, false);
-                    changeBiSyntax("&&", "and", sb, false);
-                */  
-                case '=':
+                syntax = null;
+                switch(line.charAt(j))
                 {
-                    char before = line.charAt(j - 1);
-                    switch(before)
-                    {
-                        case '=': syntax = "equal"; break;
-                        case '!': syntax = "notequal"; break;
-                        case '>': syntax = "greaterequal"; break;
-                        case '<': syntax = "lessequal"; break;
-                    }
-                    if(syntax != null)
+                    case '+': 
+                        if(line.charAt(j - 1) == '+')
+                        {
+                            int last = lastSpecial.pop();
+                            if(last - j >= 2)
+                            {
+                                // ++i
+                                if(j + 1 - last == 0)
+                                {                                  
+                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
+                                }
+                                co.add(new Code(line.substring(j + 1, last), realLine, layer));
+                                co.add(new Code("inc", 1, realLine, layer));
+                                j--;
+                            }
+                            else
+                            {
+                                Code c = co.get(co.size() - 1);
+                                if("array.get".equals(c.function))
+                                {
+                                    co.set(co.size() - 1, new Code("array.inc", 2, c.realLine, c.layer));
+                                    j--;
+                                    lastSpecial.push(j);
+                                    function = true;
+                                    break;
+                                }
+                                // i++
+                                j--;
+                                old = j;
+                                j--;
+                                if(line.charAt(j) == ']')
+                                {
+                                    arrayFunction = "postinc";
+                                    lastSpecial.push(j);
+                                    j--;
+                                    continue;
+                                }
+                                while(j >= 0 && isAllowedChar(line.charAt(j)))
+                                {
+                                    j--;
+                                }
+                                j++;
+                                if(j - old == 0)
+                                {
+                                    co.forEach(s -> System.out.println(s));
+                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
+                                }
+                                co.add(new Code(line.substring(j, old), realLine, layer));
+                                co.add(new Code("postinc", 1, realLine, layer));
+                            }
+                            lastSpecial.push(j);
+                            function = true;
+                            break;
+                        }
+                        syntax = "add"; 
+                        break;
+                    case '-': 
+                        if(line.charAt(j - 1) == '-')
+                        {
+                            int last = lastSpecial.pop();
+                            if(last - j >= 2)
+                            {
+                                // ++i
+                                if(j + 1 - last == 0)
+                                {                                  
+                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
+                                }
+                                co.add(new Code(line.substring(j + 1, last), realLine, layer));
+                                co.add(new Code("dec", 1, realLine, layer));
+                                j--;
+                            }
+                            else
+                            {
+                                Code c = co.get(co.size() - 1);
+                                if("array.get".equals(c.function))
+                                {
+                                    co.set(co.size() - 1, new Code("array.dec", 2, c.realLine, c.layer));
+                                    j--;
+                                    lastSpecial.push(j);
+                                    function = true;
+                                    break;
+                                }
+                                // i++
+                                j--;
+                                old = j;
+                                j--;
+                                if(line.charAt(j) == ']')
+                                {
+                                    arrayFunction = "postdec";
+                                    lastSpecial.push(j);
+                                    j--;
+                                    continue;
+                                }
+                                while(j >= 0 && isAllowedChar(line.charAt(j)))
+                                {
+                                    j--;
+                                }
+                                j++;
+                                if(j - old == 0)
+                                {
+                                    throw new PreScriptException(scriptName, realLine, "unexpected character");
+                                }
+                                co.add(new Code(line.substring(j, old), realLine, layer));
+                                co.add(new Code("postdec", 1, realLine, layer));
+                            }
+                            lastSpecial.push(j);
+                            function = true;
+                            break;
+                        }
+                        syntax = "sub"; 
+                        break;
+                    case '*': syntax = "mul"; break;
+                    case '/': syntax = "div"; break;
+                    case '%': syntax = "math.mod"; break;
+                    case '^': syntax = "math.pow"; break;
+                    case '<': syntax = "less"; break;
+                    case '>': syntax = "greater"; break;
+                    case '|': 
                     {
-                        function = push(strings, co, j);
-                        nextFunction.put(bracketCounter, syntax);
-                        j--;
-                        lastSpecial.push(j);
-                        j--;
-                        continue;
+                        if(line.charAt(j - 1) == '|')
+                        {
+                            function = push(strings, co, j);
+                            nextFunction.put(bracketCounter, "or");
+                            j--;
+                            lastSpecial.push(j);
+                            j--;
+                            continue;
+                        }
+                        break;
                     }
-                    function = push(strings, co, j);
-                    //if(function)
-                    //{
-                        //System.out.println("push last result");
-                    //}
-                    int checker = j - 2;
-                    while(checker >= 0)
+                    case '&': 
                     {
-                        if(!isAllowedChar(line.charAt(checker)))
+                        if(line.charAt(j - 1) == '&')
                         {
-                            throw new PreScriptException(scriptName, realLine, "unexpected character");
+                            function = push(strings, co, j);
+                            nextFunction.put(bracketCounter, "and");
+                            j--;
+                            lastSpecial.push(j);
+                            j--;
+                            continue;
                         }
-                        checker--;
+                        break;
                     }
-                    String var;
-                    switch(before)
+                    case ']':
                     {
-                        case '+': syntax = "add"; break;
-                        case '-': syntax = "sub"; break;
-                        case '*': syntax = "mul"; break;
-                        case '/': syntax = "div"; break;
-                        default:
-                            var = line.substring(0, j);
-                            co.add(new Code(var, realLine, layer));
+                        bracketCounter++;
+                        lastSpecial.push(j);
+                        break;
                     }
-                    if(syntax != null)
+                    case '[':
                     {
-                        var = line.substring(0, j - 1);
-                        co.add(new Code(Code.convertInput(strings, var, true), realLine, layer));
-                        co.add(new Code(syntax, 2, realLine, layer));
-                        //System.out.println("push last result");
-                        co.add(new Code(var, realLine, layer));
+                        old = lastSpecial.pop();
+                        if(old - j >= 2)
+                        {
+                            co.add(new Code(Code.convertInput(strings, line.substring(j + 1, old), true), realLine, layer));
+                        }
+                        String sNextFunction = nextFunction.remove(bracketCounter);
+                        if(sNextFunction != null)
+                        {
+                            co.add(new Code(sNextFunction, 2, realLine, layer));
+                        }
+                        old = j;
+                        j--;
+                        while(j >= 0 && isAllowedChar(line.charAt(j)))
+                        {
+                            j--;
+                        }
+                        j++;
+                        co.add(new Code(line.substring(j, old), realLine, layer));
+                        if(arrayFunction != null)
+                        {
+                            if(arrayFunction.equals("postinc") || arrayFunction.equals("postdec"))
+                            {
+                                co.add(new Code("array." + arrayFunction, 2, realLine, layer));
+                                arrayFunction = null;
+                                lastSpecial.push(j);
+                                break;
+                            }
+                            co.add(new Code("array." + arrayFunction, 3, realLine, layer));
+                            arrayFunction = null;
+                            j = -1;
+                            continue;
+                        }
+                        else if(arrayState)
+                        {
+                            co.add(new Code("array.get", 2, realLine, layer));
+                        }
+                        else
+                        {
+                            co.add(new Code("array.set", 3, realLine, layer));
+                        }
+                        lastSpecial.push(j);
+                        function = true;
+                        bracketCounter--;
+                        break;
                     }
-                    co.add(new Code("setvar", 2, realLine, layer));
-                    j = -1;
-                    continue;
-                }
-                case ')':
-                {
-                    bracketCounter++;
-                    lastSpecial.push(j);
-                    commaCounter.push(0);
-                    break;
-                }
-                case ',':
-                {
-                    commaCounter.push(commaCounter.pop() + 1);
-                    function = push(strings, co, j);
-                    lastSpecial.push(j);
-                    break;
-                }
-                case '(':
-                {
-                    commas = commaCounter.pop() + 1;
-                    //if(function)
-                    //{
-                        //System.out.println("push last result");
-                    //}
-                    if(line.charAt(j + 1) != ')')
+                    case '=':
                     {
-                        if(j + 1 != lastSpecial.peek())
+                        char before = line.charAt(j - 1);
+                        switch(before)
+                        {
+                            case '=': syntax = "equal"; break;
+                            case '!': syntax = "notequal"; break;
+                            case '>': syntax = "greaterequal"; break;
+                            case '<': syntax = "lessequal"; break;
+                            case ']': syntax = "bracket"; break;
+                        }
+                        if(syntax != null)
+                        {
+                            if(syntax.equals("bracket"))
+                            {
+                                arrayState = false;
+                                function = push(strings, co, j);
+                                j--;
+                                lastSpecial.push(j);
+                                j--;
+                                continue;
+                            }
+                            function = push(strings, co, j);
+                            nextFunction.put(bracketCounter, syntax);
+                            j--;
+                            lastSpecial.push(j);
+                            j--;
+                            continue;
+                        }
+                        function = push(strings, co, j);
+                        int checker = j - 2;
+                        char c;
+                        while(checker >= 0)
+                        {
+                            c = line.charAt(checker);
+                            if(c == ']')
+                            {
+                                break;
+                            }
+                            else if(!isAllowedChar(c))
+                            {
+                                throw new PreScriptException(scriptName, realLine, "unexpected character");
+                            }
+                            checker--;
+                        }
+                        String var;
+                        switch(before)
+                        {
+                            case '+': syntax = "add"; break;
+                            case '-': syntax = "sub"; break;
+                            case '*': syntax = "mul"; break;
+                            case '/': syntax = "div"; break;
+                            default:
+                                var = line.substring(0, j);
+                                co.add(new Code(var, realLine, layer));
+                        }
+                        if(syntax != null)
+                        {
+                            if(line.charAt(j - 2) == ']')
+                            {
+                                arrayFunction = syntax;
+                                j -= 2;
+                                continue;
+                            }
+                            co.add(new Code(line.substring(0, j - 1), realLine, layer));
+                            co.add(new Code(syntax + "var", 2, realLine, layer));
+                        }
+                        else
                         {
-                            co.add(new Code(Code.convertInput(strings, line.substring(j + 1, lastSpecial.pop()), true), realLine, layer));
+                            co.add(new Code("setvar", 2, realLine, layer));
                         }
+                        j = -1;
+                        continue;
                     }
-                    else
+                    case ')':
                     {
-                        commas = 0;
+                        bracketCounter++;
+                        lastSpecial.push(j);
+                        commaCounter.push(0);
+                        break;
                     }
-                    String sNextFunction = nextFunction.remove(bracketCounter);
-                    if(sNextFunction != null)
+                    case ',':
                     {
-                        co.add(new Code(sNextFunction, 2, realLine, layer));
-                        //System.out.println("push last result");
+                        commaCounter.push(commaCounter.pop() + 1);
+                        function = push(strings, co, j);
+                        lastSpecial.push(j);
+                        break;
                     }
-                    bracketCounter--;
-                    function = true;
-                    old = j;
-                    j--;
-                    while(j >= 0 && isAllowedChar(line.charAt(j)))
+                    case '(':
                     {
+                        commas = commaCounter.pop() + 1;
+                        if(line.charAt(j + 1) != ')')
+                        {
+                            if(j + 1 != lastSpecial.peek())
+                            {
+                                co.add(new Code(Code.convertInput(strings, line.substring(j + 1, lastSpecial.pop()), true), realLine, layer));
+                            }
+                        }
+                        else
+                        {
+                            commas = 0;
+                        }
+                        String sNextFunction = nextFunction.remove(bracketCounter);
+                        if(sNextFunction != null)
+                        {
+                            co.add(new Code(sNextFunction, 2, realLine, layer));
+                        }
+                        bracketCounter--;
+                        function = true;
+                        old = j;
                         j--;
+                        while(j >= 0 && isAllowedChar(line.charAt(j)))
+                        {
+                            j--;
+                        }
+                        j++;
+                        String functionName = line.substring(j, old).toLowerCase();
+                        if(!parser.isRegisteredFunction(functionName))
+                        {
+                            throw new NoSuchMethodException(scriptName, realLine, functionName);
+                        }
+                        co.add(new Code(functionName, commas, realLine, layer));
+                        lastSpecial.push(j);
                     }
-                    j++;
-                    String functionName = line.substring(j, old);
-                    if(!parser.isRegisteredFunction(functionName))
-                    {
-                        throw new NoSuchMethodException(scriptName, realLine, functionName);
-                    }
-                    co.add(new Code(functionName, commas, realLine, layer));
+                }
+                if(syntax != null)
+                {
+                    function = push(strings, co, j);
+                    nextFunction.put(bracketCounter, syntax);
                     lastSpecial.push(j);
                 }
+                j--;
             }
-            if(syntax != null)
-            {
-                function = push(strings, co, j);
-                nextFunction.put(bracketCounter, syntax);
-                lastSpecial.push(j);
-            }
-            j--;
+        }
+        catch(StringIndexOutOfBoundsException ex)
+        {
+            throw new PreScriptException(scriptName, realLine, "unexpected character");
         }
     }
 }

+ 42 - 17
src/me/hammerle/code/Script.java

@@ -5,10 +5,12 @@ import java.util.Arrays;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Stack;
+import java.util.TreeMap;
 import me.hammerle.exceptions.CodeTooLongException;
 import me.hammerle.exceptions.GotoLabelNotFoundException;
 import me.hammerle.exceptions.HoldCodeException;
 import me.hammerle.exceptions.PreScriptException;
+import me.hammerle.math.Fraction;
 
 public class Script 
 {
@@ -24,6 +26,7 @@ public class Script
     private final HashSet<String> events;
     private final Stack<Object> valueStack;
     private final Stack<Integer> returnStack;
+    private final TreeMap<Integer, Fraction> forMap;
     
     private Code[] code;
     private int position;
@@ -50,6 +53,7 @@ public class Script
         events = new HashSet<>();
         valueStack = new Stack<>();
         returnStack = new Stack<>();
+        forMap = new TreeMap<>();
         
         this.code = Code.generate(parser, name, code, gotos);
         if(this.code.length == 0)
@@ -83,6 +87,7 @@ public class Script
         gotos.clear();
         valueStack.clear();
         returnStack.clear();
+        forMap.clear();
         this.code = Code.generate(parser, name, code, gotos);
         position = -1;
         halt = false;
@@ -293,27 +298,15 @@ public class Script
     
     public void gotoLabel(String label, boolean scheduled)
     {
-        if(label == null)
-        {
-            Object o = code[position].value;
-            if(o != null)
-            {
-                position += (int) o;
-                incLoopCounter();
-                return;
-            }
-        }
-        try
-        {
-            int i = gotos.get(label);
-            incLoopCounter();
-            position = i - (scheduled ? 0 : 1);
-        }
-        catch(NullPointerException ex)
+        Integer i = gotos.get(label);
+        if(i == null)
         {
             parser.logger.printException(new GotoLabelNotFoundException(label), "goto", this, getActiveRealCodeLine());
             throw new HoldCodeException();
         }
+        forMap.clear();
+        incLoopCounter();
+        position = i - (scheduled ? 0 : 1);
     }  
     
     public void resetLoopCounter()
@@ -377,4 +370,36 @@ public class Script
     {
         return tryJumpLine; 
     }
+    
+    // -----------------------------------------------------------------------------------
+    // for
+    // -----------------------------------------------------------------------------------
+    
+    public boolean repeatFinished(Fraction value, Fraction step, Fraction border)
+    {
+        return (step.isNegative() && border.compareTo(value) > 0) || border.compareTo(value) < 0;
+    }
+    
+    public Fraction nextRepeatData(Fraction start, Fraction step)
+    {
+        Fraction f = forMap.get(position);
+        if(f == null)
+        {
+            forMap.put(position, start);
+            return start;
+        }
+        f = f.add(step);
+        forMap.put(position, f);
+        return f;
+    }
+    
+    public void clearRepeatData()
+    {
+        forMap.remove(position);
+    }
+    
+    public void clearLastRepeatData()
+    {
+        forMap.pollLastEntry();
+    }
 }

+ 124 - 25
src/me/hammerle/code/SnuviParser.java

@@ -24,7 +24,6 @@ import java.util.function.BiConsumer;
 import java.util.function.Consumer;
 import java.util.function.Predicate;
 import java.util.stream.Collectors;
-import jdk.internal.org.objectweb.asm.tree.JumpInsnNode;
 import me.hammerle.exceptions.FileIOException;
 import me.hammerle.exceptions.PreScriptException;
 import me.hammerle.math.Fraction;
@@ -225,9 +224,63 @@ public class SnuviParser
         registerConsumer("array.new", (args, sc) ->                                                
                 sc.setVar(args[0].toString(), new Object[ScriptUtils.getInt(args[1])]));
         registerConsumer("array.set", (args, sc) ->                            
-                ((Object[]) args[0])[ScriptUtils.getInt(args[1])] = args[2]);
+                ((Object[]) sc.getVar(args[0].toString()))[ScriptUtils.getInt(args[1])] = args[2]);
         registerFunction("array.get", (args, sc) ->                            
-                ((Object[]) args[0])[ScriptUtils.getInt(args[1])]);
+                ((Object[]) sc.getVar(args[0].toString()))[ScriptUtils.getInt(args[1])]);
+        registerFunction("array.inc", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).add(new Fraction(1));
+                    return o[i];
+                });
+        registerFunction("array.dec", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).sub(new Fraction(1));
+                    return o[i];
+                });
+        registerFunction("array.postinc", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    Fraction f = (Fraction) o[i];
+                    o[i] = f.add(new Fraction(1));
+                    return f;
+                });
+        registerFunction("array.postdec", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    Fraction f = (Fraction) o[i];
+                    o[i] = f.sub(new Fraction(1));
+                    return f;
+                });
+        registerConsumer("array.add", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).add((Fraction) args[2]);
+                });
+        registerConsumer("array.sub", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).sub((Fraction) args[2]);
+                });
+        registerConsumer("array.mul", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).mul((Fraction) args[2]);
+                });
+        registerConsumer("array.div", (args, sc) -> 
+                {
+                    Object[] o =  (Object[]) sc.getVar(args[0].toString());
+                    int i = ScriptUtils.getInt(args[1]);
+                    o[i] = ((Fraction) o[i]).div((Fraction) args[2]);
+                });
         registerFunction("array.getsize", (args, sc) ->                            
                 ((Object[]) args[0]).length);
         registerConsumer("array.swap", (args, sc) ->                                           
@@ -276,7 +329,7 @@ public class SnuviParser
                     }
                     else
                     {
-                        Arrays.fill((Object[]) args[0], ScriptUtils.getInt(args[1]), ScriptUtils.getInt(args[2]), args[1]); 
+                        Arrays.fill((Object[]) args[0], ScriptUtils.getInt(args[2]), ScriptUtils.getInt(args[3]), args[1]); 
                     }
                 });
                 
@@ -420,10 +473,54 @@ public class SnuviParser
                 ((Fraction) args[0]).add((Fraction) args[1]));
         registerFunction("sub", (args, sc) -> 
                 ((Fraction) args[0]).sub((Fraction) args[1]));
+        registerConsumer("addvar", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).add((Fraction) args[1]));
+                });
+        registerConsumer("subvar", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).sub((Fraction) args[1]));
+                });
+        registerConsumer("mulvar", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).mul((Fraction) args[1]));
+                });
+        registerConsumer("divvar", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    sc.setVar(s, ((Fraction) sc.getVar(s)).div((Fraction) args[1]));
+                });
         registerFunction("inc", (args, sc) -> 
-                increaseVar(args[0], sc, 1)); 
+                {
+                    String s = args[0].toString();
+                    Fraction n = ((Fraction) sc.getVar(s)).add(new Fraction(1));
+                    sc.setVar(s, n);
+                    return n;
+                });
         registerFunction("dec", (args, sc) -> 
-                increaseVar(args[0], sc, -1));
+                {
+                    String s = args[0].toString();
+                    Fraction n = ((Fraction) sc.getVar(s)).add(new Fraction(-1));
+                    sc.setVar(s, n);
+                    return n;
+                });
+        registerFunction("postinc", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    Fraction n = (Fraction) sc.getVar(s);
+                    sc.setVar(s, n.add(new Fraction(1)));
+                    return n;
+                });
+        registerFunction("postdec", (args, sc) -> 
+                {
+                    String s = args[0].toString();
+                    Fraction n = (Fraction) sc.getVar(s);
+                    sc.setVar(s, n.add(new Fraction(-1)));
+                    return n;
+                });
         registerFunction("mul", (args, sc) -> 
                 ((Fraction) args[0]).mul((Fraction) args[1]));
         registerFunction("div", (args, sc) -> 
@@ -439,7 +536,7 @@ public class SnuviParser
         registerConsumer("wait", (args, sc) -> 
                 { sc.resetLoopCounter(); throw new HoldCodeException(); });
         registerConsumer("goto", (args, sc) -> 
-                goTo(args, sc));
+                sc.gotoLabel(args[0].toString(), false));
         registerConsumer("sgoto", (args, sc) -> 
                 scheduleGoto(args, sc));
         registerConsumer("gosub", (args, sc) -> 
@@ -459,6 +556,25 @@ public class SnuviParser
                 sc.jump());   
         registerConsumer("while", (args, sc) -> 
                 whileFunction(args, sc)); 
+        registerConsumer("for", (args, sc) -> 
+                {
+                    Fraction f = sc.nextRepeatData((Fraction) args[1], (Fraction) args[3]);
+                    sc.setVar(args[0].toString(), f);              
+                    if(sc.repeatFinished(f, (Fraction) args[3], (Fraction) args[2]))
+                    {
+                        sc.clearRepeatData();
+                        sc.jump();
+                    }
+                }); 
+        registerConsumer("break", (args, sc) -> 
+                sc.jump()); 
+        registerConsumer("breakreset", (args, sc) -> 
+                { 
+                    sc.jump(); 
+                    sc.clearLastRepeatData();
+                }); 
+        registerConsumer("continue", (args, sc) -> 
+                sc.jump()); 
         registerFunction("equal", (args, sc) -> 
                 isEqual(args));
         registerAlias("equals", "equal");
@@ -776,14 +892,7 @@ public class SnuviParser
             sc.runCode();
         }, l); 
         throw new HoldCodeException();
-    }   
-    
-    private Number increaseVar(Object var, Script sc, int value)
-    {
-        Fraction n = ((Fraction) sc.getVar(var.toString())).add(new Fraction(value));
-        sc.setVar(var.toString(), n);
-        return n;
-    }   
+    }    
     
     private static boolean isEqual(Object[] args)
     {
@@ -805,16 +914,6 @@ public class SnuviParser
                         .map(s -> Code.convertInput(null, s, false)).collect(Collectors.toList()));
     }
     
-    private void goTo(Object[] args, Script sc)
-    {
-        if(args.length == 0)
-        {
-            sc.gotoLabel(null, false);
-            return;
-        }
-        sc.gotoLabel(args[0].toString(), false);
-    }
-    
     private void readFile(Object[] args, Script sc)
     {
         try

+ 5 - 0
src/me/hammerle/math/Fraction.java

@@ -281,6 +281,11 @@ public final class Fraction extends Number implements Comparable<Fraction>
         return new Fraction(denominator, numerator);
     }
     
+    public boolean isNegative()
+    {
+        return numerator < 0;
+    }
+    
     // -------------------------------------------------------------------------
     // functions from math library
     // -------------------------------------------------------------------------

+ 10 - 1
src/me/hammerle/snuviscript/SnuviScript.java

@@ -106,7 +106,16 @@ public class SnuviScript
     "    debug(\"nein\");\n" +
     "}\n" +
     "debug(\"Ende\");";*/
-            String s = "debug(add(1, 1));";
+            //String s = "wusi = 3; wusi /= 2; debug(wusi);";
+            // array.set("wusi", 1, arrays.get("wusi", 1) + 4)
+            //String s = "debug(wusi[1]);";
+            String s = "for(\"i\", 4, 10, 1)\n" +
+"{\n" +
+"    debug(i);\n" +
+//"    goto(\"wusi\");\n" +
+"    @wusi;\n" +
+"} ";
+            //String s = "i = 0; while(i++ < 10) { debug(i);}";
             //String s = "error(); debug(1+1);";
             //System.out.println(s);
             //System.out.println("___________");