Lua (мова програмування)

Lua є швидкий і легковстраваемий скриптова мова програмування. Він поєднує в собі простий процедурний синтаксис з гнучкими конструкціями опису даних, заснованих на асоціативних масивах та розширюється семантиці. Lua є динамічно типізованим і інтерпретується. Інтерпретатор перекладає вихідний код в байт-код для реєстрової віртуальної машини і є вільно-поширюваним, з відкритими початковими кодами на мові Сі. У стандартній віртуальній машині Lua використовується розподіл пам'яті із збіркою сміття (аналогічно Java або .NET).

Історія створення

Lua 1.0 була спроектована так, що її конструктори об'єктів включали в себе синтаксис мови SOL (звідси назва Lua: по-португальськи sol - «сонце», lua - «місяць»). Керуючі конструкції Lua були взяті з Modula (if, while, repeat / until), CLU (паралельне присвоювання, множинне повертається значення функції як більш проста альтернатива замість передачі параметрів по посиланню або явних покажчиків), C ++, SNOBOL і AWK (асоціативні масиви).

Версії Lua аж до 5.0 випускалися під ліцензією, подібної ліцензії BSD. Починаючи з версії 5.0 і вище Lua поширюється під ліцензією MIT. Обидві ліцензії є пермісивними і практично ідентичні.

Інструменти

Автономний інтерпретатор (також званий lua.c по імені файлу вихідного коду, або просто lua по виконуваного файлу) представляє собою невелику програму, що дозволяє пряме використання Lua. Коли інтерпретатор завантажує файл, він ігнорує перший рядок, якщо вона починається з "знака числа" ( "#"). Ця особливість дозволяє використовувати Lua як інтерпретатор скриптів в Unix-системах. Якщо ви про це попереджую свій код рядком виду

(За умови, що автономний інтерпретатор розташований в / usr / local / bin), або

то ви можете викликати (виконувати) програму безпосередньо, без необхідності попередньо запускати інтерпретатор Lua.

Всі параметри є необов'язковими. Як ми вже бачили, коли lua запускається без аргументів, інтерпретатор переходить в інтерактивний режим. Ключ -e дозволяє вводити код безпосередньо в командний рядок.

(В системі Unix необхідно ставити подвійні лапки для поділу команд інтерпретатора від власне виконуваного коду.) Як було сказано вище, ключ -l завантажує файл, а -i переводить інтерпретатор в інтерактивний режим після обробки інших ключів (опцій). Так, наприклад, виклик

завантажить файл a.lua, потім виконає присвоювання x = 10, і, нарешті, надасть командний рядок для введення.

Скрипти на мові позначаються розширенням .lua. Для завдань, критичних за часом, є JIT-компілятор Lua - LuaJIT. Також розроблений компілятор llvm-lua, що генерує код для віртуальної машини LLVM, що надає можливість подальшої компіляції в дуже ефективний машинний код для процесорів різної архітектури.

Основні принципи

лексичні угоди

Іменами (ідентифікаторами) в Lua можуть бути будь-які рядки з букв, цифр і символу підкреслення, що не починаються з цифри. Наступні ключові слова зарезервовані і не можуть бути використані в іменах:

Lua є мовою, чутливим до регістру символів: and - ключове слово, тоді як And і AND- два різних допустимих ідентифікатора. За угодою, імена, що починаються з символу підкреслення і записані у верхньому регістрі (наприклад _VERSION), зарезервовані для використання в якості внутрішніх глобальних змінних, використовуваних Lua. Літеральние рядки повинні бути укладені в одинарні або подвійні лапки і можуть містити С-подібні escape-поледовательності.

Типи і змінні

У Lua вісім основних типів: nil (невизначений), boolean (логічний), number (числовий), string (строковий), function (функція), userdata (призначені для користувача дані), thread (потік), і table (таблиця).

  1. Nil - це тип значення nil [пусте значення]. Його головна властивість - відрізнятися від всіх інших значень і позначати відсутність придатного значення.
  2. До типу Boolean відносяться значення false (брехня) і true (істина). Значення nil і false вважаються помилковими, будь-яке інше значення вважається дійсним. До типу Number відносяться речові числа (подвійний точності з плаваючою комою).
  3. String позначає масиви символів. Рядки Lua можуть містити будь-які 8 бітні символи, включаючи нуль ( '\ 0').
  4. Тип userdata (призначені для користувача дані) дозволяє зберігати будь-які дані з C в змінних Lua. Значення цього типу є посиланням на блок фізичної пам'яті і не має визначених операцій в Lua, за винятком привласнення і перевірки на рівність. Однак, використовуючи метатабліци, програмист може визначити операції над значеннями цього типу.
  5. Тип thread (потік) позначає незалежний потік виконання і використовується при реалізації механізму співпрограми. Не можна ототожнювати потоки Lua з потоками операційної системи. Lua підтримує підпрограми навіть в тих системах, де потоки на рівні операційної системи не підтримуються.
  6. Тип table (таблиця) визначає асоціативні масиви. Такі масиви можуть індексуватися не тільки числами, а й будь-якими значеннями (за винятком nil). Таблиця може містити значення відразу декількох типів (крім nil). Таблиці є єдиний механізм структурування даних в Lua; вони можуть використовуватися як прості масиви, таблиці символів, множини, поля записів, дерева і так далі. Для уявлення словників Lua використовує ім'я поля в якості індексу таблиці. Подання у вигляді a.name вважається тотожним поданням a [ "name"]. Так як функції є значеннями вбудованого типу, поля таблиці можуть містити і функції. Таким чином, таблиці можуть зберігати методи methods.

Змінні типу table, function, thread і userdata не містять самих даних, в них зберігаються тільки посилання на відповідний об'єкт.

У Lua є три види змінних: глобальні. локальні і поля таблиць. Будь-яка змінна вважається глобальною, якщо вона явно не оголошена як локальна. Локальні змінні існують в лексичному контексті: локальні змінні доступні функціями, визначеними всередині цього контексту.

У Lua підтримується в загальному стандартний набір операторів, майже як в Pascal або C. Він складається з операторів присвоювання, операторів управління потоком виконання, виконання функцій і опису змінних.

Нижче перераховані основні операції:

При порівнянні на рівність не виробляється перетворення типів. Об'єкти різних типів завжди вважаються різними. При обчисленні значення використовується коротка схема - другий аргумент обчислюється тільки якщо це необхідно. Діє наступна таблиця пріоритетів і асоціативності операцій:

У Lua немає виділеної функції, з якої починається виконання програми. Інтерпретатор послідовно виконує оператори, які він отримує з файлу або від керуючої програми. При цьому він попередньо компілює програму в двійкове подання, яке також може бути збережено.

Будь-блок коду виконується як анонімна функція, тому в ньому можна визначати локальні змінні і з нього можна повертати значення.

Оператори можна (але не обов'язково) розділяти символом ';'.

Нижче перераховані основні оператори:

Блок do. end перетворює послідовність операторів в один оператор і відкриває нову область видимості, в якій можна визначати локальні змінні.

В операторах if. while і repeat все значення виразу, відмінні від false і nil трактуються як справжні. Оператор return може не містити значень, що повертаються або містити одне або кілька виразів (список). Оператори return і break повинні бути останніми операторами в блоці (тобто повинні бути або останніми операторами в блоці коду, або розташовуватися безпосередньо перед словами end. Else. Elseif. Until).

Оператор for виконується для всіх значень змінної циклу починаючи від стартового значення і закінчуючи фінішним значенням включно. Третє значення, якщо воно задано, використовується як крок зміни змінної циклу. Всі ці значення повинні бути числовими. Вони обчислюються тільки один раз перед виконанням циклу. Мінлива циклу локальна в цьому циклі і не доступна поза його тіла. Значення змінної циклу не можна змінювати всередині тіла циклу. Ось псевдокод, що демонструє виконання оператора for.

Визначення функції - це виконується вираз (конструктор функції), результатом обчислення якого є об'єкт типу функція:

У дужках розміщується список (можливо порожній) аргументів функції. Список аргументів функції може закінчуватися трикрапкою - в цьому випадку функція має змінне число аргументів. Між закривається дужкою і оператором end розміщується тіло функції.

У момент виконання конструктора функції будується також замикання - таблиця всіх доступних у функції і зовнішніх по відношенню до неї локальних змінних. Якщо функція передається як значення, що повертається, то вона зберігає доступ до всіх змінним, що входять в її замикання. При кожному виконання конструктора функції будується нове замикання.

Виклик функції складається із заслання на функцію і укладеного в круглі дужки списку аргументів (можливо порожнього). Посиланням на функцію може бути будь-який вираз, результатом обчислення якого є функція. Між посиланням на функцію і відкривається круглої дужкою не може бути переведення рядка.

Якщо функція приймає єдиний аргумент і трактує його як таблицю, елементи якої індексуються іменами формальних параметрів функції, то в цьому випадку фактично реалізується виклик механізм названих аргументів:

Мета-таблиці

Кожна таблиця і об'єкт типу userdata можуть мати мета-таблицю - звичайну таблицю, поля якої визначають поведінку вихідного об'єкта при застосуванні до нього деяких спеціальних операцій. Наприклад, коли об'єкт виявляється операндом при додаванні, інтерпретатор шукає в мета-таблиці поле з ім'ям __add і, якщо таке поле присутній, то використовує його значення як функцію, що виконує додавання. Індекси (імена полів) в мета-таблиці називаються подіями, а відповідні значення (обробники подій) - метаметодамі.

За замовчуванням новостворена таблиця не має мета-таблиці. Будь-яку таблицю mt можна зробити мета-таблицею таблиці t. викликавши функцію setmetatable (t, mt). Функція getmetatable (t) повертає мета-таблицю таблиці t або nil. якщо таблиця не має мета-таблиці.

Lua визначає наступні події:

Приклади використання мета-таблиць

У наступному прикладі мета-таблиці використовуються для призначення значення за замовчуванням для відсутніх елементів таблиці:

Ось більш нетривіальне рішення, яке не використовує окремої мета-таблиці для кожного замовчуваного значення:

Мета-метод __index цієї мета-таблиці перехоплює звернення до відсутнім полях таблиці і повертає значення, збережене в самій таблиці за індексом key.

Пакети - основний спосіб визначати набір взаємозв'язаних функцій, не забруднюючи при цьому глобальну область видимості. Зазвичай пакет являє собою окремий файл, який в глобальному контексті визначає єдину таблицю, яка містить всі функції цього пакета:

Також можна робити всі функції локальними і окремо формувати таблицю експортованих функцій:

Пакет завантажується за допомогою функції require (). причому під час завантаження ім'я, передане цієї функції (воно може не містити розширення, яке додається автоматично) доступно через змінну _REQUIREDNAME.

Класи і об'єкти

Тут функція class створює порожню таблицю, підготовлену до того, щоб стати мета-таблицею об'єкта. Методи класу робляться полями цієї таблиці тобто клас є таблицею, одночасно містить методи об'єкта і його мета-методи.

Функція object () створює об'єкт заданого класу - таблицю, у якій в якості мета-таблиці встановлений заданий клас. У другому аргументі може бути передана таблиця, яка містить проініціалізувати поля об'єкта.

стандартні бібліотеки

Стандартні Lua біблтотекі містять часто використовувані функції, які виконуються безпосередньо в C API. Деякі з цих функцій надають важливі сервіси мови (наприклад, type та getmetatable); інші забезпечують доступ до "зовнішнім" сервісів (наприклад, введення / висновок); частково вони реалізовані на Lua, проте часто використовувані і мають критичний час виконання, реалізовані на C (наприклад, sort).

Всі бібліотеки викликаються через офіційний C API і виконуються як окремі C модулі. На даний момент, Lua має наступні стандартні бібліотеки:

  • базова бібліотека (basic library);
  • бібліотека пакетів (package library);
  • робота з рядками (string manipulation);
  • робота з таблицями (table manipulation);
  • математичні функції (sin, log, і т.п.);
  • ввід вивід;
  • робота з операційною системою (operating system facilities);
  • налагодження (debug facilities).

Кожна бібліотека, виключаючи базову і бібліотеку пакетів, представляє всі функції як поля глобальної таблиці або як методи об'єктів.

Список літератури

Схожі статті