OverScript - интерпретируемый язык программирования с открытым исходным кодом, написанный на C#. Это простой и мощный си-подобный язык со статической типизацией, который отлично подходит как для встраивания в .NET-программы, так и для создания обычных приложений. Проект разрабатывался с нуля, без оглядки на традиционные подходы к созданию интерпретаторов. Уникальный подход позволяет языку выйти за рамки стандартных возможностей и иметь большой потенциал развития.

Несколько примеров
WriteLine("Hello, world!"); //выводит "Hello, world!" с переносом строки
ReadKey(); //ожидание нажатия любой клавиши
Point[] arr = new Point[]{new Point(25, 77), new Point(122, 219)}; //создание массива из двух экземпляров класса Point
int n; // имеет значение 0 по умоланию
foreach(Point p in arr){ // перебор всех элементов массива
    n++;
    WriteLine($"{n}) {p.X}; {p.Y}"); // вывод значений с помощью интерполяции строк
}
//1) 25; 77
//2) 122; 219
ReadKey();

class Point{
    public int X, Y;
    New(int x, int y){ // конструктор
        X=x;
        Y=y;
    }
}
//Сортировка пузырьком (в реальных программах можно использовать встроенную функцию Sort(arr))
int[] arr = new int[]{24, 59, 15, 23, 7, 99, 0};
int len = arr.Length(); //получение длины массива. arr.Length() - это Length(arr). Писать можно и так и так.
int v;
foreach(int i in Range(len - 1)){ //Range генерирует последовательность целых чисел в заданном диапазоне (не включая последнее значение).
    foreach(int j in Range(i + 1, len)){ //вместо foreach можно: for(int j = i + 1; j < len; j++)
        if(arr[i] > arr[j]){
            v = arr[i];
            arr[i] = arr[j];
            arr[j] = v;
        }
    }
}

WriteLine(Join(", ", arr)); //Join сцепляет элементы указанного массива, помещая между ними заданный разделитель. 
//0, 7, 15, 23, 24, 59, 99
ReadKey();
//Пример создания списка
StringList list = new StringList();
list.Add("Hello");
list.Add("World");
WriteLine(list.Count); //2
WriteLine(list[0]); //Hello
WriteLine(list[1]); //World
list.Remove(0);
WriteLine(list[0]); //World
list.Clear();
WriteLine(list.Count); //0
ReadKey();

class StringList{
    public int Capacity;
    public int Count;
    string[] Items;
    
    New(){
        Clear();
    }
    public Add(string v){
        if(Count>=Capacity-1){
            Capacity*=2; 
            Items.Resize(Capacity); //то же, что и Resize(Items, Capacity);
        }
        Items[Count]=v;
        Count++;
        
    }
    public Clear(){
        Capacity=10;
        Count=0;
        Items=new string[Capacity];
    }
    public Remove(int index){
        int c=Count-1;
        for(int i=index; i<c; i++) 
            Items[i]=Items[i+1];
        
        Count=c;
    }
    public string GetItem(int index){ //это метод индексатора возвращающий значение
        return Items[index];
    }
    public SetItem(int index, string value){ //это метод индексатора устанавливающий значение
        Items[index]=value;
    }
}
//Работа с .NET-типом с помощью Reflection, используя стрелку
object list=Create("System.Collections.Generic.List`1[System.String], System.Collections"); //создаём объект типа List<string> (так он в C# записывается)
list->AddRange(new string[]{"Hello", "World", "Test"}); //добавляем 3 элемента: "Hello", "World" и "Test".
int count := list->Count; //получаем кол-во элементов. Оператор := конвертирует значение справа в int (оно object, т.к. у list нет подсказки типа, а значит интерпретатор не сможет сразу знать тип свойства Count).

for(int i = 0; i < count; i++) 
    WriteLine(list->Item[i]); //Item - имя индексатора. Для интерпретатора list->Item[i] - это @GetMemberValue(list, "Item", i).
//Hello
//World
//Test
    
WriteLine();
foreach(string item in list) //можно и foreach использовать
    WriteLine(item); 
    
ReadKey();
//Работа с потоками
object thread = Thread(WriteLine("")); //создание потока, который выполнит метод WriteLine
StartThread(thread, "Hello, world!"); //запуск потока. Можно написать thread.StartThread("Hello, world!").
Wait(thread); //ожидание завершения потока
//Hello, world!
ReadKey();

//То же самое, но с локальным потоком (может работать с переменными из области создания)
string s="Hello, world!";
thread = LocalThread(WriteLine(s)); //создание потока, который выполнит WriteLine(s)
StartThread(thread); 
Wait(thread); 
//Hello, world!
ReadKey();

//***********************
//Использование таймера
object timer=Timer(OnTimedEvent(null, null), 1000); //создание таймера
StartTimer(timer); //запуск таймера
Sleep(3000); //пауза 3 секунды
//15.09.2021 15:08:35
//15.09.2021 15:08:36
//15.09.2021 15:08:37
StopTimer(timer);
ReadKey();

OnTimedEvent(object source, object e){
    WriteLine(e->SignalTime); 
}
//Наследование и приведение типа
Bar b = new Bar(15, 25); 
b.Test(); //Test at Bar!
WriteLine(b.X + "; " + b.Y); //15; 25
(Foo\b).Test(); //Test at Foo!  // Foo\b это то же самое, что (Foo)b в C#. В OverScript можно и так и так.
ReadKey();

class Foo{
    public int X;
    public Test(){
        WriteLine("Test at Foo!");
    }
}
class Bar:Foo{ //через запятую можно несколько родительских классов указать (наследование будет слева направо)
    public int Y;
    public Test(){
        WriteLine("Test at Bar!");
    }
    New(int x, int y){ //конструктор по умолчанию public
        X=x; Y=y;
    }
}


Интерпретатор
OverScript.zip
1.0.1.0, 2022-04-02
Исходный код и примеры
github.com/overscript-lang


Если ещё не читали
OverScript — язык программирования, написанный на C#

Привет! Меня зовут Дмитрий, я написал на C# свой интерпретируемый язык программирования, который назвал — OverScript. Это си-подобный язык со статической типизацией. Сразу скажу, что это не прототип, а готовый проект. Весь код на 100% мой. Я подробно не интересовался, как написаны другие языки, поэтому вся реализация интерпретатора это моя чистая импровизация. Мой подход неконвенциональный, поэтому к техническим аспектам стоит относиться без ассоциаций с тем, что вы могли ранее видеть в других языках, несмотря на то, что некоторые вещи могут казаться знакомыми.

Читать на habr.com


Язык написан на C# и работает везде, где можно установить .NET 6 (x64).
OverScript похож на C#, но является другим языком. В нём есть только то, что упоминается в документации. Интерпретатор OverScript представляет собой слой абстракции над стандартными .NET типами, взаимодействие с которыми осуществляется либо через встроенные (базовые) функции, либо через Reflection.
  • В отличие от большинства интерпретируемых языков, в нём статическая типизация, что даёт возможность интерпретатору проверять согласованность типов во время загрузки кода.
  • Язык имеет привычный для C#-программистов базовый синтаксис и использует знакомые типы.
  • Интерпретатор работает на платформе .NET, которая постоянно развивается, а значит и возможности OverScript будут расширяться.
  • OverScript перспективен в качестве встраиваемого языка для .NET-программ.
  • Реализация OverScript полностью независимая, не содержит легаси-кода и не привязана ни к каким сторонним библиотекам.
  • Не успел добавить. Пока добавил только основные, без которых не обойтись. Буду добавлять их по мере возможности и исходя из потребностей пользователей. Имеется возможность подключать функции из своих DLL.


    Контакты

    Свои вопросы и предложения пишите мне на support@overscript.org. Идеи, требующие публичного обсуждения, пишите на форум.