Pull to refresh

«OOC для C, — это как Scala для Java»

Reading time 7 min
Views 2.2K
Сегодня на Hacker News наткнулся на пост о (похоже очень) новом языке "ooc". Бросил на день все дела, занялся ковырятельством — уж больно интересно выглядит.

Итак, "ooc — это современный, объектно-ориентированный, функционально(ватый), высокоуровневый, низкоуровневый, секси язык программирования". (Именно секси его и представляют разработчики, ну а я бы добавил что еще и "компилируемый")

По сути — ooc — транслятор языка высокого уровня в C со сборщиком мусора.

Как выразился один из посетителей сайта: "ooc для C, — это как Scala для Java" (jimbokun@HN).

Обязательный «Hello, World» на ooc:

hello.ooc:
"Hi, softer world =)" println()

на выходе hello.c и hello.exe.

ooc-компилятор транслирует это в c-код и использует доступный c компилятор (gcc, mingw, icc, tinycc) чтобы сделать из этого hello.exe (или ./hello). Поддержка tinycc заявлена, но в реальности ждем поддержки C99 в самом tinycc (автор обещал сделать обходные пути, но пока не работает), поэтому наслждаемся пока что довольно неслабого размера .exe'шниками (gcc от mingw других не делает).

Итак, что у нас уже есть в языке: классы, объекты, строгая типизация, угадывание типов (n := "Beer" length()), chaining (.dothis().dothat()), совместимость с c-библиотеками, абстрактные классы, шаблоны из C++, списки, разреженные(sparse) списки, хеши (ArrayList, SparseList, HashMap), for (i in list) { ... }, обертки для c-шных функций и классов, перегрузка операторов, полиморфизм, сборщик мусора (отключаемый), import file/name (не нужны .h, но .h можно использовать как extern), closures, eiffel's contracts, исключения, reflections, pattern matching, ranges, ternary operator, bindings, generics, coroutines, GTK, SDL, OpenGL, GLU, GLUT bindings…

Как сказал товарищ varjag@HN: «Я думаю это розыгрыш, сделанный пользователями Ruby, но нигде этого в тексте не вижу.» Нет, этот язык существует на самом деле. Примеры, линки, установка, подводные коряги — под катом...

Еще примеры

Функции:
add: func(a, b : Int) -> Int {
 a + b
}

Приятный for:
for(i in 0..10) {
  printf("%d\n", i)
}

for(i in list) {
  printf("%d\n", i)
}

Списки:
ints := SparseList<Int> new()
ints add(13)
lucky := ints get(0)

ООП:
Vector3f: class {
   x, y, z : Float
   init: func(=x, =y, =z)
}

ooc знает что x это float, поэтому тип можно и не указывать, как и то, что сохранять его в this x (в «ooc» точки перед методами и свойствами объекта не нужны). Аналог вышесказанного на C++:
class Vector3f {
   float x,y,z;
   Vector3f(float x_, float y_, float z_): x(x_), y(y_), z(z_) {};
};
// (да простят меня спецы C++ если тут что-то лишнее).

Chaining:
me := RandomGuy new()
me eatBreakfast() .drinkCoffee() .yawn() .goBackToBed()

но при этом не нужно возвращать this в этих методах.

Абстрактные классы:
Animal: abstract class {
   shout: abstract func
}

Dog: class extends Animal {
   shout: func { "Woof, woof!" println() }
}

Cat: class extends Animal {
   shout: func { "Meoooww!" println() }
}

malloc со сборщиком мусора:
myRawArray := gc_malloc(Int size * 100) as Int*  // free не нужен.

GUI приложение:
use gtk
import gtk/[Gtk, Window] // acts like: import gtk/Gtk, gtk/Window
exit: extern func
  
main: func {
   w := Window new("Hi, world")
   w setUSize(800, 600) .connect("destroy", exit) .showAll()
   Gtk main()
}

Чтение файла
import io/FileReader

main: func {
  fr := FileReader new("/etc/hosts")
  
  while (fr hasNext())
    fr read() print()
  
}

coroutines(!) (передача исполнения кода из одной подпрограммы в другую без переполнения стека):
import coroutine/Coro
firstCoro, secondCoro : Coro

secondTask: func (context: Pointer) {
  num := 0
  printf("secondTask created with value %d\n", (context as Int*) @)
  while (true) {
    printf("secondTask: %d %d\n", secondCoro bytesLeftOnStack(), num += 1)
    secondCoro switchTo(firstCoro)
  }
}

firstTask: func (context: Pointer) {
  value := 2
  num := 0
  printf("firstTask created with value %d\n", (context as Int*) @)
  secondCoro = Coro new()
  firstCoro startCoro(secondCoro, value&, secondTask)
  while (true) {
    printf("firstTask: %d %d\n", firstCoro bytesLeftOnStack(), num += 1)
    firstCoro switchTo(secondCoro)
  }
}

main: func {
  mainCoro := Coro new()
  value := 1
  mainCoro initializeMainCoro()
  firstCoro = Coro new()
  mainCoro startCoro(firstCoro, value&, firstTask)
}


Из того, что нашлось еще в исходниках/на блоге: atexit, iniparser, filewriter, list, map, stack, os (launch,subprocess), regexp, threads, i/o, events.

GTK/SDL/OpenGL/GLU/GLUT bindings.

Итак, язык довольно-таки действительно «секси». К сожалению, конечно, пока что сыроват. Много ошибок и проблем, но если Вы любите пожить на острие — добро пожаловать в мир хакинга.

Установка ooc

Что понадобится?

1. git (нужен чтобы скачать дистрибутив)
2. Java JDK 5 или выше
3. gcc под Linux или MingW под Windows (ссылка не ведет на mingw.org, а на более современную сборку, хотя может сейчас и настоящий mingw догнал gcc 4)
4. Ant (система сборки, типа «make»)

JAVA??? Скомпилированный файл не использует Java VM. Только сам транслятор ooc->c использует Java (прозрачно для Вас). Конечный пользователь получает нативный(native) код — проще говоря: .exe, который не требует Java ни в каком виде.

Ставим все вышесказанное, под Виндой добавляем папки git, mingw/bin, java/bin, ant/bin в PATH (в линуксе после yum install/sudo apt-get все уже будет само настроено).

Проверка на правильность PATH: запустите по порядку команды «git», «javac», «ant», «gcc» в командной строке. Если что-то не нашлось («неправильно указан путь или имя файла») — значит ищем куда это конкретное распаковывали и добавляем в PATH путь к нему.

К.О.: PATH указывается в Windows+Break, Дополнительно, Переменные среды, в нижнем окошке, Изменить. После каждого изменения надо будет нажимать OK и запускать заново командную строку. Разделители; (точка с запятой).

Переходим в командную строку и дальше делаем:

git clone git://github.com/nddrylliog/ooc.git
cd ooc/
ant

Если все успешно, находим где собрался файл ooc.jar — это примерно папка ooc/bin/ooc.jar.

Делаем (под Виндой) файлик ooc.bat и кладем куда-нибудь в PATH:

java -jar d:\ooc\bin\ooc.jar %*
(здесь вписываем свой путь к своему ooc.jar — см.выше)

под Линуксом делаем:

sudo cp utils/ooc /usr/bin/
export OOC_DIST=/home/username/ooc/
если скачали в /home/username/ooc/

Делаем hello.ooc:
main: func {
  "Hello world!" println()
}

теперь делаем:
ooc hello.ooc -r
и в идеале получаем hello.exe. ("-r" — это «run», еще можно "-noclean" — не удалять сгенеренные .c исходники).

Ну, а работает?

… а на деле — язык еще сырой. Серьезно сырой, так что наверняка получаем какую-нибудь ошибку и заходим на irc.freenode.com канал #ooc-lang. Товарищ «nddryliog» — автор языка. Задаем вопросы, получаем ответы. (Я там иногда появляюсь как «slavav»).

Да и кстати, язык развивается, ребята-авторы не прочь обсуждать даже изменения или нововведения в синтаксис языка на канале (сами пишут — типа "предлагайте новшества для внесения в язык, будем думать как сделать"). Плюс тут в том, что нет какой-то большой организации или комитета стоящего за языком, так что все развивается быстро и даже Ваше личное мнение может быть учтено.

На деле hello.exe мне получить удалось, а вот с FileReader к примеру под виндой процесс глухо завис. Но разработчики трудятся, ищут, доделывают. Канал #ooc-lang очень дружелюбен и люди реально помогают с проблемами в реальном времени (особенно если nddryliog в онлайне).

С другой стороны, есть Rock — компилятор ooc написанный на самом ooc. Так что не думаю что все настолько плохо. Просто у авторов Linux и они больше под ним тестируют, поэтому совместимость с виндой пока менее чем великолепная.

Да, если будет тормозить компиляция — отключайте антивирусы. У меня hello.exe компилировался 30 секунд, при отключенном антивире (Comodo) за 3 секунды.

Если Вам на канале помогут — обновить версию языка можно с помощью: "git pull && ant clean && ant".

Еще на аглицком:
Главная страница, примеры
Установка ooc
Блог проекта (must read!)
Обсуждение на Hacker News (вопросы-ответы)
docs.ooc-lang.org — полезная документация, хотя и мало, например, о том как делать код на c доступным из ooc.
Bindings для GTK, GL и т.п. + Rock — Экспериментальный компилятор ooc написанный на самом ooc.

Bindings скачиваются и экспериментальным путем установлено, что распаковывать их в src/sdk относительно папки ooc. (Через FileMon смотрел где ooc их ищет, на сайте про это ни слова).

Лайценз

Кстати, код ooc распространяется под BSD лицензией, что на русском значит: «ты можешь скачивать, использовать, можешь петь блюзы и мести двор, только не пыли! Можешь продавать, покупать, никаких исходников никуда открывать не надо. Если обещаешь не подавать в суд — можешь распечатать код и сунуть лист в нос. Только автора указывай.» (Для ясности — автор языка — не я, к языку никакого отношения не имею, просто делюсь перспективной находкой с сообществом).

OOC. We'll run out of slogans eventually

Слоганы на главной проекта веселые — меняются при рефреше. Среди них «Y2k совместимый» :), «Ваша страховка от скуки», «Объектно-ориентированный, с подвывертом», «Рукодельное хакерство», «Ошибка, доведенная до совершенства» и «У нас кончатся слоганы, рано или поздно»…

Документация

ooc-lang.org — Created On: 30-May-2009, так что разбираем, пока горячее. (В общем, языку — 5 месяцев)

Тут, да, беда. Авторы сами признают это, так что все с чем разберетесь по ходу дела — старайтесь публиковать — поможете следующим.

Еще одна подводная коряга — буквально на днях гит репозиторий сменил свою дислокацию, так что Вы можете обнаруживать ссылки на github.com, которых не существует, в этом случае заменяйте «github.comamoswenger/...» в URL на -> «github.comnddrylliog/...».

Source code was highlighted with Source Code Highlighter.


Йои Хаджи,
вид с Хабра
Tags:
Hubs:
+38
Comments 67
Comments Comments 67

Articles