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 (.NET 6) 1.0.1.0, 2022-04-02 OverScriptStandard.zip (.NET Standard 2.1) 1.1.0.0, 2022-08-21 |
Исходный код и примеры github.com/overscript-lang |
Привет! Меня зовут Дмитрий, я написал на C# свой интерпретируемый язык программирования, который назвал — OverScript. Это си-подобный язык со статической типизацией. Сразу скажу, что это не прототип, а готовый проект. Весь код на 100% мой. Я подробно не интересовался, как написаны другие языки, поэтому вся реализация интерпретатора это моя чистая импровизация. Мой подход неконвенциональный, поэтому к техническим аспектам стоит относиться без ассоциаций с тем, что вы могли ранее видеть в других языках, несмотря на то, что некоторые вещи могут казаться знакомыми.
Читать на habr.comСвои вопросы и предложения пишите мне на support@overscript.org. Идеи, требующие публичного обсуждения, пишите на форум.