Example #1
0
        public node colour_blend(ColourBlendBlock block)
        {
            // Blend two colours together.
            var colour1 = valueToCode(block, "COLOUR1");

            if (colour1 == null)
            {
                colour1 = new str_node(this, "#000000");
            }
            var colour2 = valueToCode(block, "COLOUR2");

            if (colour2 == null)
            {
                colour2 = new str_node(this, "#000000");
            }
            var ratio = valueToCode(block, "RATIO");

            if (ratio == null)
            {
                ratio = new int_node(this, 0);
            }
            var p = new JsArray <node>()
            {
                colour1, colour2, ratio
            };

            return(new fcall_node(this, intern("colour_blend"), p, null));
        }
Example #2
0
        public node logic_compare(LogicCompareBlock block)
        {
            // Comparison operator.
            var OPERATORS = new Dictionary <string, string>()
            {
                { "EQ", "==" },
                { "NEQ", "!=" },
                { "LT", "<" },
                { "LTE", "<=" },
                { "GT", ">" },
                { "GTE", ">=" },
            };
            var @operator = OPERATORS[block.getFieldValue("OP")];
            var argument0 = valueToCode(block, "A");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var argument1 = valueToCode(block, "B");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            return(new call_node(this, argument0, intern(@operator), argument1));
        }
Example #3
0
        public node colour_rgb(ColourRGBBlock block)
        {
            // Compose a colour from RGB components expressed as percentages.
            var r = valueToCode(block, "RED");

            if (r == null)
            {
                r = new int_node(this, 0);
            }
            var g = valueToCode(block, "GREEN");

            if (g == null)
            {
                g = new int_node(this, 0);
            }
            var b = valueToCode(block, "BLUE");

            if (b == null)
            {
                b = new int_node(this, 0);
            }
            var p = new JsArray <node>()
            {
                r, g, b
            };

            return(new fcall_node(this, intern("colour_rgb"), p, null));
        }
Example #4
0
        public node math_number_property(MathNumberPropertyBlock block)
        {
            // Check if a number is even, odd, prime, whole, positive, or negative
            // or if it is divisible by certain number. Returns true or false.
            var number_to_check = valueToCode(block, "NUMBER_TO_CHECK");

            if (number_to_check == null)
            {
                number_to_check = new int_node(this, 0);
            }
            var  dropdown_property = block.getFieldValue("PROPERTY");
            node code = null;

            if (dropdown_property == "PRIME")
            {
                return(new fcall_node(this, intern("is_prime"), new JsArray <node>()
                {
                    number_to_check
                }, null));
            }
            switch (dropdown_property)
            {
            case "EVEN":
                return(new call_node(this, number_to_check, intern("even?")));

            case "ODD":
                return(new call_node(this, number_to_check, intern("odd?")));

            case "WHOLE":
                code = new call_node(this, number_to_check, intern("%"), new int_node(this, 1));
                return(new call_node(this, code, intern("=="), new int_node(this, 0)));

            case "POSITIVE":
                return(new call_node(this, number_to_check, intern(">"), new JsArray <node>()
                {
                    new int_node(this, 0)
                }, null));

            case "NEGATIVE":
                return(new call_node(this, number_to_check, intern("<"), new JsArray <node>()
                {
                    new int_node(this, 0)
                }, null));

            case "DIVISIBLE_BY":
                var divisor = valueToCode(block, "DIVISOR");
                // If "divisor" is some code that evals to 0, Ruby will raise an error.
                if (divisor == null || (divisor is int_node && ((int_node)divisor).to_i() == 0) ||
                    (divisor is float_node && ((float_node)divisor).to_f() == 0.0))
                {
                    return(new false_node(this));
                }
                code = new call_node(this, number_to_check, intern("%"), divisor);
                return(new call_node(this, code, intern("=="), new int_node(this, 0)));
            }
            return(null);
        }
Example #5
0
        public node controls_repeat(ControlsRepeatBlock block)
        {
            // Repeat n times (internal number).
            var times   = block.getFieldValue("TIMES");
            var repeats = new int_node(this, times == null ? 0 : Int32.Parse(times));
            var branch  = statementToCode(block, "DO");

            return(new call_node(this, repeats, intern("times"), new JsArray <node>(), new block_node(this, new JsArray <node>(), branch, false)));
        }
Example #6
0
        public node switch_case_number(SwitchCaseNumberBlock block)
        {
            // case/when/else condition.
            var argument0 = valueToCode(block, "SWITCH");

            if (argument0 == null)
            {
                argument0 = new int_node(this, -1);
            }
            var code = new JsArray <case_node.when_t>();

            for (int n = 0; n <= block.cases_.Length; n++)
            {
                var branch    = statementToCode(block, "DO" + n);
                var argument1 = block.getFieldValue("CONST" + n);
                if (argument1 != null)
                {
                    var when = new case_node.when_t()
                    {
                        body = branch
                    };
                    when.value.Push(new int_node(this, argument1 == null ? 0 : Int32.Parse(argument1)));
                    code.Push(when);
                }
                else
                {
                    var min = block.getFieldValue("RANGE_MIN" + n);
                    var max = block.getFieldValue("RANGE_MAX" + n);
                    if ((min != null) && (max != null))
                    {
                        var when = new case_node.when_t()
                        {
                            body = branch
                        };
                        when.value.Push(new dot2_node(this,
                                                      new int_node(this, min == null ? 0 : Int32.Parse(min)),
                                                      new int_node(this, max == null ? 0 : Int32.Parse(max))));
                        code.Push(when);
                    }
                }
            }
            if (block.defaultCount_ != 0)
            {
                var branch = statementToCode(block, "DEFAULT_DO");
                if (branch != null)
                {
                    var when = new case_node.when_t()
                    {
                        body = branch
                    };
                    code.Push(when);
                }
            }
            return(new case_node(this, argument0, code));
        }
Example #7
0
        public node variables_set(VariablesSetBlock block)
        {
            // Variable setter.
            var argument0 = valueToCode(block, "VALUE");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var varName = get_var_name(block.getFieldValue("VAR"));

            return(new asgn_node(this, new_var_node(varName), argument0));
        }
Example #8
0
        public node math_change(MathChangeBlock block)
        {
            // Add to a variable in place.
            var argument0 = valueToCode(block, "DELTA");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var varName = get_var_name(block.getFieldValue("VAR"));

            return(new op_asgn_node(this, new_var_node(varName), intern("+"), argument0));
        }
Example #9
0
        public node math_modulo(MathModuloBlock block)
        {
            // Remainder computation.
            var argument0 = valueToCode(block, "DIVIDEND");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var argument1 = valueToCode(block, "DIVISOR");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            return(new call_node(this, argument0, intern("%"), argument1));
        }
Example #10
0
        public node controls_repeat_ext(ControlsRepeatExtBlock block)
        {
            // Repeat n times (external number).
            var repeats = valueToCode(block, "TIMES");

            if (repeats == null)
            {
                repeats = new int_node(this, 0);
            }
            if (repeats is int_node)
            {
            }
            else
            {
                repeats = new call_node(this, repeats, intern("to_i"));
            }
            var branch = statementToCode(block, "DO");

            return(new call_node(this, repeats, intern("times"), new JsArray <node>(), new block_node(this, new JsArray <node>(), branch, false)));
        }
Example #11
0
        public node math_arithmetic(MathArithmeticBlock block)
        {
            // Basic arithmetic operators, and power.
            var @operator = ARITHMETIC_OPERATORS[block.getFieldValue("OP")];
            var argument0 = valueToCode(block, "A");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var argument1 = valueToCode(block, "B");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            var code = argument0 + @operator + argument1;

            return(new call_node(this, argument0, intern(@operator), argument1));
        }
Example #12
0
        public node math_random_int(MathRandomIntBlock block)
        {
            // Random integer between [X] and [Y].
            var argument0 = valueToCode(block, "FROM");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var argument1 = valueToCode(block, "TO");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            var code = new dot2_node(this, argument0, argument1);

            return(new fcall_node(this, intern("rand"), new JsArray <node>()
            {
                code
            }, null));
        }
Example #13
0
        public node lists_repeat(ListsRepeatBlock block)
        {
            // Create a list with one element repeated.
            var argument0 = valueToCode(block, "ITEM");

            if (argument0 == null)
            {
                argument0 = new nil_node(this);
            }
            var argument1 = valueToCode(block, "NUM");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            var a = new array_node(this, new JsArray <node>()
            {
                argument0
            });

            return(new call_node(this, a, intern("*"), argument1));
        }
Example #14
0
        public node math_constrain(MathConstrainBlock block)
        {
            // Constrain a number between two limits.
            var argument0 = valueToCode(block, "VALUE");

            if (argument0 == null)
            {
                argument0 = new int_node(this, 0);
            }
            var argument1 = valueToCode(block, "LOW");

            if (argument1 == null)
            {
                argument1 = new int_node(this, 0);
            }
            var argument2 = valueToCode(block, "HIGH");

            if (argument2 == null)
            {
                argument2 = new fcall_node(this, intern("Float"), new JsArray <node>()
                {
                    new str_node(this, "inf")
                }, null);
            }
            node code = new array_node(this, new JsArray <node>()
            {
                argument0, argument1
            });

            code = new call_node(this, code, intern("max"));
            code = new array_node(this, new JsArray <node>()
            {
                code, argument2
            });
            return(new call_node(this, code, intern("min")));
        }
Example #15
0
        public node text_charAt(TextCharAtBlock block)
        {
            // Get letter at index.
            // Note: Until January 2013 this block did not have the WHERE input.
            var where = block.getFieldValue("WHERE");
            if (String.IsNullOrEmpty(where))
            {
                where = "FROM_START";
            }
            var at = valueToCode(block, "AT");

            if (at == null)
            {
                at = new int_node(this, 1);
            }
            var text = valueToCode(block, "VALUE");

            if (text == null)
            {
                text = new str_node(this, "");
            }

            // Blockly uses one-based indicies.
            if (at is int_node)
            {
                // If the index is a naked number, decrement it right now.
                at = new int_node(this, (int)(((int_node)at).to_i() - 1));
            }
            else
            {
                // If the index is dynamic, decrement it in code.
                at = new call_node(this, at, intern("to_i"));
                at = new call_node(this, at, intern("-"), new int_node(this, 1));
            }

            switch (where)
            {
            case "FIRST":
                return(new call_node(this, text, intern("[]"), new JsArray <node>()
                {
                    new int_node(this, 0)
                }, null));

            case "LAST":
                return(new call_node(this, text, intern("[]"), new JsArray <node>()
                {
                    new int_node(this, -1)
                }, null));

            case "FROM_START":
                return(new fcall_node(this, intern("text_get_from_start"), new JsArray <node>()
                {
                    text, at
                }, null));

            case "FROM_END":
                return(new fcall_node(this, intern("text_get_from_end"), new JsArray <node>()
                {
                    text, at
                }, null));

            case "RANDOM":
                return(new fcall_node(this, intern("text_random_letter"), new JsArray <node>()
                {
                    text
                }, null));
            }
            throw new Exception("Unhandled option (text_charAt).");
        }
Example #16
0
        public node lists_getIndex(ListsGetIndexBlock block)
        {
            // Get element at index.
            var mode = block.getFieldValue("MODE");

            if (String.IsNullOrEmpty(mode))
            {
                mode = "GET";
            }
            var where = block.getFieldValue("WHERE");
            if (String.IsNullOrEmpty(where))
            {
                where = "FROM_START";
            }
            var at = valueToCode(block, "AT");

            if (at == null)
            {
                at = new int_node(this, 1);
            }
            var list = valueToCode(block, "VALUE");

            if (list == null)
            {
                list = new array_node(this, new JsArray <node>());
            }

            if (where == "FIRST")
            {
                if (mode == "GET")
                {
                    return(new call_node(this, list, intern("first")));
                }
                else
                {
                    if (mode == "GET_REMOVE")
                    {
                        return(new call_node(this, list, intern("shift")));
                    }
                    else if (mode == "REMOVE")
                    {
                        return(new call_node(this, list, intern("shift")));
                    }
                }
            }
            else if (where == "LAST")
            {
                if (mode == "GET")
                {
                    return(new call_node(this, list, intern("last")));
                }
                else
                {
                    var code = list + ".pop";
                    if (mode == "GET_REMOVE")
                    {
                        return(new call_node(this, list, intern("pop")));
                    }
                    else if (mode == "REMOVE")
                    {
                        return(new call_node(this, list, intern("pop")));
                    }
                }
            }
            else if (where == "FROM_START")
            {
                // Blockly uses one-based indicies.
                if (at is int_node)
                {
                    // If the index is a naked number, decrement it right now.
                    at = new int_node(this, (int)(((int_node)at).to_i() - 1));
                }
                else
                {
                    // If the index is dynamic, decrement it in code.
                    at = new begin_node(this, new call_node(this, at, intern("-"), new int_node(this, 1)), true);
                    at = new call_node(this, at, intern("to_i"));
                }
                if (mode == "GET")
                {
                    return(new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
                else if (mode == "GET_REMOVE")
                {
                    return(new call_node(this, list, intern("delete_at"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
                else if (mode == "REMOVE")
                {
                    return(new call_node(this, list, intern("delete_at"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
            }
            else if (where == "FROM_END")
            {
                at = new call_node(this, at, intern("-@"), (node)null);
                if (mode == "GET")
                {
                    return(new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
                else if (mode == "GET_REMOVE")
                {
                    return(new call_node(this, list, intern("delete_at"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
                else if (mode == "REMOVE")
                {
                    return(new call_node(this, list, intern("delete_at"), new JsArray <node>()
                    {
                        at
                    }, null));
                }
            }
            else if (where == "RANDOM")
            {
                if (mode == "GET")
                {
                    return(new fcall_node(this, intern("lists_random_item"), new JsArray <node>()
                    {
                        list
                    }, null));
                }
                else
                {
                    if (mode == "GET_REMOVE")
                    {
                        return(new fcall_node(this, intern("lists_remove_random_item"), new JsArray <node>()
                        {
                            list
                        }, null));
                    }
                    else if (mode == "REMOVE")
                    {
                        return(new fcall_node(this, intern("lists_remove_random_item"), new JsArray <node>()
                        {
                            list
                        }, null));
                    }
                }
            }
            throw new Exception("Unhandled combination (lists_getIndex).");
        }
Example #17
0
        public node math_single(Block block)
        {
            // Math operators with single operand.
            var  @operator = block.getFieldValue("OP");
            node code      = null;
            node arg;

            if (@operator == "NEG")
            {
                // Negation is a special case given its different operator precedence.
                code = valueToCode(block, "NUM");
                if (code == null)
                {
                    code = new int_node(this, 0);
                }
                return(new call_node(this, code, intern("-@"), (node)null));
            }
            if (@operator == "SIN" || @operator == "COS" || @operator == "TAN")
            {
                arg = valueToCode(block, "NUM");
                if (arg == null)
                {
                    arg = new int_node(this, 0);
                }
            }
            else
            {
                arg = valueToCode(block, "NUM");
                if (arg == null)
                {
                    arg = new int_node(this, 0);
                }
            }
            // First, handle cases which generate values that don't need parentheses
            // wrapping the code.
            var math = new const_node(this, intern("Math"));

            switch (@operator)
            {
            case "ABS":
                code = new call_node(this, arg, intern("abs"));
                break;

            case "ROOT":
                code = new call_node(this, math, intern("sqrt"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "LN":
                code = new call_node(this, math, intern("log"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "LOG10":
                code = new call_node(this, math, intern("log10"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "EXP":
                code = new call_node(this, math, intern("exp"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "POW10":
                code = new call_node(this, new int_node(this, 10), intern("exp"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "ROUND":
                code = new call_node(this, arg, intern("round"));
                break;

            case "ROUNDUP":
                code = new call_node(this, arg, intern("ceil"));
                break;

            case "ROUNDDOWN":
                code = new call_node(this, arg, intern("floor"));
                break;

            case "SIN":
                arg  = new call_node(this, arg, intern("/"), new float_node(this, 180.0));
                arg  = new call_node(this, arg, intern("*"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, math, intern("sin"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "COS":
                arg  = new call_node(this, arg, intern("/"), new float_node(this, 180.0));
                arg  = new call_node(this, arg, intern("*"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, math, intern("cos"), new JsArray <node>()
                {
                    arg
                }, null);
                break;

            case "TAN":
                arg  = new call_node(this, arg, intern("/"), new float_node(this, 180.0));
                arg  = new call_node(this, arg, intern("*"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, math, intern("tan"), new JsArray <node>()
                {
                    arg
                }, null);
                break;
            }
            if (code != null)
            {
                return(code);
            }
            // Second, handle cases which generate values that may need parentheses
            // wrapping the code.
            switch (@operator)
            {
            case "ASIN":
                code = new call_node(this, math, intern("asin"), new JsArray <node>()
                {
                    arg
                }, null);
                code = new call_node(this, code, intern("/"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, code, intern("*"), new float_node(this, 180.0));
                break;

            case "ACOS":
                code = new call_node(this, math, intern("acos"), new JsArray <node>()
                {
                    arg
                }, null);
                code = new call_node(this, code, intern("/"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, code, intern("*"), new float_node(this, 180.0));
                break;

            case "ATAN":
                code = new call_node(this, math, intern("atan"), new JsArray <node>()
                {
                    arg
                }, null);
                code = new call_node(this, code, intern("/"), new colon2_node(this, math, intern("PI")));
                code = new call_node(this, code, intern("*"), new float_node(this, 180.0));
                break;

            default:
                throw new Exception("Unknown math operator: " + @operator);
            }
            return(new begin_node(this, code, true));
        }
Example #18
0
        public node lists_setIndex(ListsSetIndexBlock block)
        {
            // Set element at index.
            var list = valueToCode(block, "LIST");

            if (list == null)
            {
                list = new array_node(this, new JsArray <node>());
            }
            var mode = block.getFieldValue("MODE");

            if (String.IsNullOrEmpty(mode))
            {
                mode = "GET";
            }
            var where = block.getFieldValue("WHERE");
            if (String.IsNullOrEmpty(where))
            {
                where = "FROM_START";
            }
            var at = valueToCode(block, "AT");

            if (at == null)
            {
                at = new int_node(this, 1);
            }
            var value = valueToCode(block, "TO");

            if (value == null)
            {
                value = new nil_node(this);
            }

            if (where == "FIRST")
            {
                if (mode == "SET")
                {
                    return(new asgn_node(this, new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        new int_node(this, 0)
                    }, null), value));
                }
                else if (mode == "INSERT")
                {
                    return(new call_node(this, list, intern("unshift"), new JsArray <node>()
                    {
                        value
                    }, null));
                }
            }
            else if (where == "LAST")
            {
                if (mode == "SET")
                {
                    return(new asgn_node(this, new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        new int_node(this, -1)
                    }, null), value));
                }
                else if (mode == "INSERT")
                {
                    return(new call_node(this, list, intern("push"), new JsArray <node>()
                    {
                        value
                    }, null));
                }
            }
            else if (where == "FROM_START")
            {
                // Blockly uses one-based indicies.
                if (at is int_node)
                {
                    // If the index is a naked number, decrement it right now.
                    at = new int_node(this, (int)(((int_node)at).to_i() - 1));
                }
                else
                {
                    // If the index is dynamic, decrement it in code.
                    at = new begin_node(this, new call_node(this, at, intern("-"), new int_node(this, 1)), true);
                    at = new call_node(this, at, intern("to_i"));
                }
                if (mode == "SET")
                {
                    return(new asgn_node(this, new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        at
                    }, null), value));
                }
                else if (mode == "INSERT")
                {
                    return(new call_node(this, list, intern("insert"), new JsArray <node>()
                    {
                        at, value
                    }, null));
                }
            }
            else if (where == "FROM_END")
            {
                if (mode == "SET")
                {
                    // Blockly uses one-based indicies.
                    if (at is int_node)
                    {
                        // If the index is a naked number, decrement it right now.
                    }
                    else
                    {
                        // If the index is dynamic, decrement it in code.
                        at = new call_node(this, at, intern("to_i"));
                    }
                    return(new asgn_node(this, new call_node(this, list, intern("[]"), new JsArray <node>()
                    {
                        at
                    }, null), value));
                }
                else if (mode == "INSERT")
                {
                    // Blockly uses one-based indicies.
                    if (at is int_node)
                    {
                        // If the index is a naked number, decrement it right now.
                        at = new int_node(this, (int)(((int_node)at).to_i() + 1));
                    }
                    else
                    {
                        // If the index is dynamic, decrement it in code.
                        at = new begin_node(this, new call_node(this, at, intern("+"), new int_node(this, 1)), true);
                        at = new call_node(this, at, intern("to_i"));
                    }

                    at = new call_node(this, at, intern("-@"), (node)null);
                    return(new call_node(this, list, intern("insert"), new JsArray <node>()
                    {
                        at, value
                    }, null));
                }
            }
            else if (where == "RANDOM")
            {
                if (mode == "SET")
                {
                    return(new fcall_node(this, intern("lists_set_random_item"), new JsArray <node>()
                    {
                        list, value
                    }, null));
                }
                else if (mode == "INSERT")
                {
                    return(new fcall_node(this, intern("lists_insert_random_item"), new JsArray <node>()
                    {
                        list, value
                    }, null));
                }
            }
            throw new Exception("Unhandled combination (lists_setIndex).");
        }
Example #19
0
        public node text_getSubstring(TextGetSubstringBlock block)
        {
            // Get substring.
            var text = valueToCode(block, "STRING");

            if (text == null)
            {
                text = new str_node(this, "");
            }
            var where1 = block.getFieldValue("WHERE1");
            var where2 = block.getFieldValue("WHERE2");
            var at1    = valueToCode(block, "AT1");

            if (at1 == null)
            {
                at1 = new int_node(this, 1);
            }
            var at2 = valueToCode(block, "AT2");

            if (at2 == null)
            {
                at2 = new int_node(this, 1);
            }
            if (where1 == "FIRST" || (where1 == "FROM_START" && at1 is int_node && ((int_node)at1).to_i() == 1))
            {
                at1 = new int_node(this, 0);
            }
            else if (where1 == "FROM_START")
            {
                // Blockly uses one-based indicies.
                if (at1 is int_node)
                {
                    // If the index is a naked number, decrement it right now.
                    at1 = new int_node(this, (int)(((int_node)at1).to_i() - 1));
                }
                else
                {
                    // If the index is dynamic, decrement it in code.
                    at1 = new call_node(this, at1, intern("to_i"));
                    at1 = new call_node(this, at1, intern("-"), new int_node(this, 1));
                }
            }
            else if (where1 == "FROM_END")
            {
                if (at1 is int_node)
                {
                    at1 = new int_node(this, (int)(-((int_node)at1).to_i()));
                }
                else
                {
                    at1 = new call_node(this, at1, intern("-@"), (node)null);
                    at1 = new call_node(this, at1, intern("to_i"));
                }
            }
            if (where2 == "LAST" || (where2 == "FROM_END" && at2 is int_node && ((int_node)at2).to_i() == 1))
            {
                at2 = new int_node(this, -1);
            }
            else if (where2 == "FROM_START")
            {
                if (at2 is int_node)
                {
                    at2 = new int_node(this, (int)(((int_node)at2).to_i() - 1));
                }
                else
                {
                    at2 = new call_node(this, at2, intern("to_i"));
                    at2 = new call_node(this, at2, intern("-"), new int_node(this, 1));
                }
            }
            else if (where2 == "FROM_END")
            {
                if (at2 is int_node)
                {
                    at2 = new int_node(this, (int)(-((int_node)at2).to_i()));
                }
                else
                {
                    at2 = new call_node(this, at2, intern("-@"), (node)null);
                    at2 = new call_node(this, at2, intern("to_i"));
                }
            }
            var code = new dot2_node(this, at1, at2);

            return(new call_node(this, text, intern("[]"), new JsArray <node>()
            {
                code
            }, null));
        }
Example #20
0
        public node lists_getSublist(ListsGetSublistBlock block)
        {
            // Get sublist.
            var list = valueToCode(block, "LIST");

            if (list == null)
            {
                list = new array_node(this, new JsArray <node>());
            }
            var where1 = block.getFieldValue("WHERE1");
            var where2 = block.getFieldValue("WHERE2");
            var at1    = valueToCode(block, "AT1");

            if (at1 == null)
            {
                at1 = new int_node(this, 1);
            }
            var at2 = valueToCode(block, "AT2");

            if (at2 == null)
            {
                at2 = new int_node(this, 1);
            }
            if (where1 == "FIRST" || (where1 == "FROM_START" && at1 is int_node && ((int_node)at1).to_i() == 1))
            {
                at1 = new int_node(this, 0);
            }
            else if (where1 == "FROM_START")
            {
                // Blockly uses one-based indicies.
                if (at1 is int_node)
                {
                    at1 = new int_node(this, (int)(((int_node)at1).to_i() - 1));
                }
                else
                {
                    at1 = new call_node(this, at1, intern("to_i"));
                    at1 = new call_node(this, at1, intern("-"), new int_node(this, 1));
                }
            }
            else if (where1 == "FROM_END")
            {
                if (at1 is int_node)
                {
                    at1 = new int_node(this, (int)(-((int_node)at1).to_i()));
                }
                else
                {
                    at1 = new call_node(this, at1, intern("-@"), (node)null);
                    at1 = new call_node(this, at1, intern("to_i"));
                }
            }
            if (where2 == "LAST" || (where2 == "FROM_END" && at2 is int_node && ((int_node)at2).to_i() == 1))
            {
                at2 = new int_node(this, -1);
            }
            else if (where2 == "FROM_START")
            {
                if (at2 is int_node)
                {
                    at2 = new int_node(this, (int)(((int_node)at2).to_i() - 1));
                }
                else
                {
                    at2 = new call_node(this, at2, intern("to_i"));
                    at2 = new call_node(this, at2, intern("-"), new int_node(this, 1));
                }
            }
            else if (where2 == "FROM_END")
            {
                if (at2 is int_node)
                {
                    at2 = new int_node(this, (int)(-((int_node)at2).to_i()));
                }
                else
                {
                    at2 = new call_node(this, at2, intern("-@"), (node)null);
                    at2 = new call_node(this, at2, intern("to_i"));
                }
            }
            return(new fcall_node(this, intern("lists_sublist"), new JsArray <node>()
            {
                list, at1, at2
            }, null));
        }
Example #21
0
        public node controls_for(ControlsForBlock block)
        {
            // For loop.
            var lv = local_switch();

            var loopVar = local_add_f(block.getFieldValue("VAR"));
            var fromVal = valueToCode(block, "FROM");

            if (fromVal == null)
            {
                fromVal = new int_node(this, 0);
            }
            var toVal = valueToCode(block, "TO");

            if (toVal == null)
            {
                toVal = new int_node(this, 0);
            }
            var increment = valueToCode(block, "BY");
            var branch    = statementToCode(block, "DO");

            if (fromVal is int_node && toVal is int_node &&
                (increment == null || increment is int_node))
            {
                if (increment == null)
                {
                    increment = new int_node(this, 1);
                }

                // All parameters are simple numbers.
            }
            else
            {
                fromVal = new call_node(this, fromVal, intern("to_f"));
                toVal   = new call_node(this, toVal, intern("to_f"));
                if (increment == null)
                {
                    increment = new float_node(this, 1);
                }
                else
                {
                    increment = new call_node(this, increment, intern("to_f"));
                }
            }

            local_resume(lv);

            var arg = new hash_node(this, new JsArray <hash_node.kv_t>()
            {
                new hash_node.kv_t(new sym_node(this, intern("from")), fromVal),
                new hash_node.kv_t(new sym_node(this, intern("to")), toVal),
                new hash_node.kv_t(new sym_node(this, intern("by")), increment),
            });
            var exec = new block_node(this, new JsArray <node>()
            {
                new arg_node(this, loopVar)
            }, branch, false);

            return(new fcall_node(this, intern("for_loop"), new JsArray <node>()
            {
                arg
            }, exec));
        }