Własny język skryptowy a operator return

0

Witam,

Pisze sobie prosty język skryptowy ze składnią a'la C wszystko jest fajnie mam instukcję if, deklarowanie zmiennych oraz funkcji ale nie mogę dojść jak mogę ort! jakąś wartość funkcji czy to ze strikte kodu języka czy z samych skryptów za pomocą return piszę w C# jeśli będzie trzeba pokażę kod, macie jakieś pomysły podpowiedzi?

Z góry dziękuje i pozdrawiam.

0

Jak realizujesz wywołanie funkcji?

0

Witam ponownie, przepraszam za błędy ortograficzne oraz interpunkcyjne mam nadzieję, że się już nie powtórzą ;)

@up
Kod wykonujący "wyprasowane" i przetworzone na rozkazy polecenia skryptu:

        public void Run(int start = 0, int stop = -1)
        {
            if(stop == -1)
                stop += order_stack.Count;

            /*foreach (Orders order in order_stack)
            {
                Console.WriteLine(order.GetType() + " " + order.GetLevel());
            }*/

            //Console.WriteLine(start + " " + stop);

            for (int i = start; i <= stop; i++){
                Orders order = order_stack[i];

                switch(order.GetType())
                {
                    case OrderType_t.ORDER_PRINT:
                        string tmp = "";
                        foreach (Variable var in ReplaceParams(order.GetParamList()))
                            tmp += var.ToString() + " ";

                        Console.WriteLine(tmp);
                    break;
                    case OrderType_t.ORDER_INPUT:
                    /*tmp = Console.ReadLine();
                    foreach (Variable var in ReplaceParams(order.GetParamList()))
                        tmp += var.ToString() + " ";

                    Console.WriteLine(tmp);*/
                    break;
                    case OrderType_t.ORDER_IF:
				        int rbracket = -1;
				        for(int j= i+1; j <= stop; j++){
                            if (order_stack[j].GetType() == OrderType_t.ORDER_RBRACKET && order_stack[j].GetLevel() == order_stack[i].GetLevel())
                            {
						        rbracket = j;
						        break;
					        }
				        }

				        if(rbracket < 0)
					        throw new Exception("Blad wykonania skryptu - niedomkniety blok if");
				        
                        List<Variable> vars = ReplaceParams(order.GetParamList());
                        if (IsTrue(vars[0], vars[1], vars[2]))
                            Run(i + 1, rbracket - 1);
                        else
                        {
                            int _else = -1;
                            for (int j = rbracket + 1; j <= stop; j++)
                            {
                                if (order_stack[j].GetType() == OrderType_t.ORDER_ELSE && order_stack[j].GetLevel() == order_stack[i].GetLevel())
                                    _else = j;
                                else if (order_stack[j].GetType() == OrderType_t.ORDER_RBRACKET && order_stack[j].GetLevel() == order_stack[i].GetLevel())
                                {
                                    rbracket = j;
                                    break;
                                }
                                else if((order_stack[j].GetType() != OrderType_t.ORDER_ELSE || order_stack[j].GetType() != OrderType_t.ORDER_RBRACKET) && _else == -1)
                                    throw new Exception("Invalid syntax!");
                            }

                            if (_else < 0)
                                goto end;

                            if (rbracket < 0)
                                throw new Exception("Blad wykonania skryptu - niedomkniety blok else");

                            Run(_else + 1, rbracket - 1);
                        }
					    
                        end:
                        i = rbracket;
                    break;
                    case OrderType_t.ORDER_CALL_FUNC:
                        RunFunc(order.GetName());
                    break;
                    case OrderType_t.ORDER_ELSE:
                    case OrderType_t.ORDER_FUNC:
				        rbracket = -1;
				        for(int j= i+1; j <= stop; j++){
                            if (order_stack[j].GetType() == OrderType_t.ORDER_RBRACKET && order_stack[j].GetLevel() == order.GetLevel())
                            {
						        rbracket = j;
						        break;
					        }
				        }

				        if(rbracket < 0)
                            if (order.GetType() == OrderType_t.ORDER_FUNC)
					            throw new Exception("Blad wykonania skryptu - niedomkniety blok funkcyjny");
                            else
                                throw new Exception("Blad wykonania skryptu - niedomkniety blok else");

                        i = rbracket;
                    break;
                    case OrderType_t.ORDER_VAR:
                        Console.WriteLine(order.GetName());
                        vars_stack[order.GetName()] = order.GetParamList()[0];
                    break;
                }
            }
        }

Kod wykonujący funkcję ze skryptu generalnie działa to rekurencyjnie :P

        public void RunFunc(string func_name)
        {
            int begin = 0, end = 0;
            FindPFunccInStack(func_name, out begin, out end);
            Run(begin, end);
        }

        private void FindPFunccInStack(string func_name, out int begin, out int end)
        {
            if (!func_stack.Contains(func_name))
                throw new Exception("Can not found \"" + func_name + "\" function!");

            int def = -1, rbracket = -1;
            for (int i = 0; i < order_stack.Count; i++)
            {
                Orders order = order_stack[i];

                if (order.GetType() == OrderType_t.ORDER_FUNC && order.GetName() == func_name)
                {
                    def = i + 1;

                    for (int j = i + 1; j < order_stack.Count; j++)
                    {
                        if (order_stack[j].GetType() == OrderType_t.ORDER_RBRACKET && order_stack[j].GetLevel() == order.GetLevel())
                        {
                            rbracket = j - 1;
                            break;
                        }
                    }
                }
            }
                    
            if(rbracket < 0 || def < 0)
			    throw new Exception("Blad wykonania skryptu - niedomkniety blok funkcyjny");

            begin = def;
            end = rbracket;
        }

Przykładowy skrypt:

func test(){
print("Test")
if(lol < 4)
{
print("Test 2")
}
else{
print("Test 3")
}
}

lol = 5;
print("Miziak", 123, lol)

if(lol == 5){
print("Prawda")
test()
}

Jakieś pomysły?

1

Nie podałeś dokumentacji wszystkich symboli których używasz, trudno się trochę połapać w Twoim kodzie.

Ale taki pomysł, dodatkowo całkiem bliski temu co się dzieje w faktycznych kompilatorach:

  1. Dodanie prymitywnego rozkazu wyjścia z funkcji:
case OrderType_t.ORDER_EXIT: return; 
  1. Dodanie globalnej zmiennej LAST_RETURN_VALUE.
    I teraz zapis return 5 zapisujesz do rozkazów jako
LAST_RETURN_VALUE = return_what;
ORDER_EXIT

(zmieniasz globalną zmienną na zwracaną wartość i wychodzisz z funkcji)

A jeśli jakaś funkcja korzysta z tej zwracanej wartości, wykonujesz funkcję normalnie i bierzesz LAST_RETURN_VALUE jako zwróconą wartość

2.b) Inną opcją jest wrzucanie zwracanej wartości na stos

1 użytkowników online, w tym zalogowanych: 0, gości: 1