public IType Visit(CASE_OF node)
        {
            IType type_exp = Visit(node.exp);

            List <IType> types_branches = new List <IType>();

            foreach (var br in node.branches.list_Node)
            {
                types_branches.Add(Visit(br));
            }

            IType type = types_branches[0];

            for (int i = 1; i < types_branches.Count; i++)
            {
                if (type == null || types_branches[i] == null)
                {
                    return(null);
                }

                type = type.LCA(types_branches[i]);
            }

            return(type);
        }
Beispiel #2
0
        public string Visit(CASE_OF node)
        {
            var exp        = node.exp.Visit(this);
            var solution   = method.Add_local("expr", true);
            var exp_type   = method.Add_local("exp_type", true);
            var match_type = method.Add_local("match", true);
            var cmp        = method.Add_local("cmp", true);

            method.Add_Instruction(new CIL_Typeof(exp_type, exp));

            var finish = method.current_scope.Var("finish");

            method.Add_Instruction(new CIL_Assig(match_type, "9999"));
            List <string> distances = new List <string>();
            List <string> labels    = new List <string>();

            foreach (var item in node.branches.list_Node)
            {
                labels.Add(method.current_scope.Var("label"));
                string branch_type = method.Add_local("branch_type", true);
                string branch_inst = method.Add_local("branch_inst", true);
                method.Add_Instruction(new CIL_Allocate(branch_inst, item.formal.type.s));
                method.Add_Instruction(new CIL_Typeof(branch_type, branch_inst));
                string distans = method.Add_local("distans", true);
                distances.Add(distans);
                method.Add_Instruction(new CIL_Call(distans, "__distans", "this", new List <string>()
                {
                    branch_type, exp_type
                }));
                method.Add_Instruction(new CIL_ArithExpr(cmp, match_type, distans, "<"));
                var _if = method.current_scope.Var("if");
                method.Add_Instruction(new CIL_ConditionalJump(cmp, _if));
                method.Add_Instruction(new CIL_Assig(match_type, distans));

                method.Add_Instruction(new CIL_Label(_if));
            }

            for (int i = 0; i < distances.Count; i++)
            {
                method.Add_Instruction(new CIL_ArithExpr(cmp, match_type, distances[i], "="));
                method.Add_Instruction(new CIL_ConditionalJump(cmp, labels[i]));
            }

            for (int i = 0; i < distances.Count; i++)
            {
                method.Add_Instruction(new CIL_Label(labels[i]));
                method.Add_scope("branch");
                var dest       = method.Add_local(node.branches.list_Node[i].formal.name.name);
                var exp_branch = node.branches.list_Node[i].exp.Visit(this);
                method.Add_Instruction(new CIL_Assig(solution, exp_branch));
                method.End_scope();
                method.Add_Instruction(new CIL_Goto(finish));
            }
            method.Add_Instruction(new CIL_Label(finish));
            return(solution);
        }
        public bool Visit(CASE_OF node)
        {
            bool solve = Visit(node.exp);

            foreach (var br in node.branches.list_Node)
            {
                solve &= Visit(br);
            }

            return(solve);
        }