Ejemplo n.º 1
0
        public node lists_isEmpty(ListsIsEmptyBlock block)
        {
            // Is the list empty?
            var argument0 = valueToCode(block, "VALUE");

            if (argument0 == null)
            {
                argument0 = new array_node(this, new JsArray <node>());
            }
            return(new call_node(this, argument0, intern("empty?")));
        }
Ejemplo n.º 2
0
        public node lists_length(ListsLengthBlock block)
        {
            // List length.
            var argument0 = valueToCode(block, "VALUE");

            if (argument0 == null)
            {
                argument0 = new array_node(this, new JsArray <node>());
            }
            return(new call_node(this, argument0, intern("length")));
        }
Ejemplo n.º 3
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));
        }
Ejemplo n.º 4
0
        public node controls_forEach(ControlsForEachBlock block)
        {
            // For each loop.
            var lv = local_switch();

            var loopVar   = local_add_f(block.getFieldValue("VAR"));
            var argument0 = valueToCode(block, "LIST");

            if (argument0 == null)
            {
                argument0 = new array_node(this, new JsArray <node>());
            }
            var branch = statementToCode(block, "DO");

            local_resume(lv);

            var exec = new block_node(this, new JsArray <node>()
            {
                new arg_node(this, loopVar)
            }, branch, false);

            return(new call_node(this, argument0, intern("each"), new JsArray <node>(), exec));
        }
Ejemplo n.º 5
0
        public node lists_indexOf(ListsIndexOfBlock block)
        {
            // Find an item in the list.
            var search = valueToCode(block, "FIND");

            if (search == null)
            {
                search = new str_node(this, "");
            }
            var list = valueToCode(block, "VALUE");

            if (list == null)
            {
                list = new array_node(this, new JsArray <node>());
            }
            var finder = block.getFieldValue("END") == "FIRST" ? "find_first" : "find_last";
            var p      = new JsArray <node>()
            {
                search
            };

            return(new call_node(this, list, intern("finder"), p, null));
        }
Ejemplo n.º 6
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")));
        }
Ejemplo n.º 7
0
        public node math_on_list(MathOnListBlock block)
        {
            // Math functions for lists.
            var func = block.getFieldValue("OP");
            var list = valueToCode(block, "LIST");

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

            switch (func)
            {
            case "SUM":
                code = new call_node(this, list, intern("sum"));
                break;

            case "MIN":
                code = new call_node(this, list, intern("numbers"));
                code = new call_node(this, code, intern("min"));
                break;

            case "MAX":
                code = new call_node(this, list, intern("numbers"));
                code = new call_node(this, code, intern("max"));
                break;

            case "AVERAGE":
                code = new call_node(this, list, intern("average"));
                break;

            case "MEDIAN":
                code = new call_node(this, list, intern("median"));
                break;

            case "MODE":
                // As a list of numbers can contain more than one mode,
                // the returned result is provided as an array.
                // Mode of [3, "x", "x", 1, 1, 2, "3"] -> ["x", 1].
                code = new fcall_node(this, intern("math_modes"), new JsArray <node>()
                {
                    list
                }, null);
                break;

            case "STD_DEV":
                code = new call_node(this, list, intern("standard_deviation"));
                break;

            case "RANDOM":
                code = new call_node(this, list, intern("size"));
                code = new fcall_node(this, intern("rand"), new JsArray <node>()
                {
                    code
                }, null);
                code = new call_node(this, list, intern("[]"), new JsArray <node>()
                {
                    code
                }, null);
                break;

            default:
                throw new Exception("Unknown operator: " + func);
            }
            return(code);
        }
Ejemplo n.º 8
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));
        }
Ejemplo n.º 9
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).");
        }
Ejemplo n.º 10
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).");
        }