Toyng v.0.9.1


Введение

Динамический “игрушечный” интерпретируемый язык программирования.

Название возникло как аббревиатура TOY programming laNGuage. Toyng произносится как “toying”.

В процессе разработки: репозиторий.

Текущая версия интерпретатора: bti-170620.

Структура программы

Комментарии

Поддерживаются однострочные комментарии, открываемые символом #.

Выражение

Операнды

Типы данных

Функции и переменные

Операции

Обозначения операндов: x y — числа, a b — строки, f g — функции, u v — число или строка, z w — любые типы, n — имя переменной.

Префиксы

Префиксы
Операция Смысл
+x модуль x
+a длина строки a
-x смена знака x
*x квадрат x
*a строка, полученная конкатенацией a и a
%f arg => f f arg
/x 1/x
^x квадратный корень x
not x отрицание: [x = 0] (0 или 1)
not a проверка строки на пустоту: [a = ’’]
let n определение новой константы
var n определение новой переменной


Таблица приоритетов префиксов
Операции Приоритет
let, var 300
not 800
+, - 1000
*, /, % 1100
^ 1200


Инфиксы

Инфиксы
Операция Смысл
z ; w последовательность: применить побочные эффекты z, вернуть w
n = z присваивание
n += z комбинированное присваивание (аналогично для -, *, /, ^, %, mod, xor)
n => z лямбда-выражение (создание замыкания)
x + y сумма
f + g arg => f arg + g arg (аналогично для прочих инфиксов кроме % и сравнений)
f + u arg => f arg + u (аналогично для прочих инфиксов кроме % и сравнений)
u + f arg => u + f arg (аналогично для прочих инфиксов кроме % и сравнений)
x - y разность
x * y произведение
a * b конкатенация
a * x приведение числа к строковой форме и конкатенация
x * a аналогично a * x
x / y деление
x / a выборка префикса (подстроки) длины x из a
a / x выборка суффикса (подстроки) длины x из a
x mod y остаток от деления (fmod)
x ^ y возведение в степень
a ^ x повторение строки a x раз
z == w сравнение на равенство (разнотипные значения не равны)
z != w сравнение на неравенство
u < v сравнение на меньше
u <= v сравнение на меньше или равно
u > v сравнение на больше
u >= v сравнение на больше или равно
u and v логическое и: возвращает v, если u “истинен”, иначе u
u or v логическое или: возвращает u, если u “истинен”, иначе v
u xor v булевское исключающее или: то же, что (not u) != (not v)
f % g композиция-продолжение: arg => g f arg
f z вычисление f(z)
x u то же, что x * u
u f arg => u f arg
a x выборка символа с номером x из строки a
a b то же, что a * b
z if w if-выражение
z else w else-выражение, z должно быть if-выражением


Таблица приоритетов инфиксов (R — правоассоциирующие операции)
Операции Приоритет
; 100
= 200R
=> 300R
if, else 400R
or, xor 600
and 700
==, !=, <, >, <=, >= 900
+, - 1000
*, /, mod, % 1100
^ 1200R


Замечания

Синтаксический сахар

Предопределённые константы

toyng — версия Toyng (число). Текущая версия 900 (0.9).

inf — условное значение “бесконечность”.

nan — условное значение “нечисло”.

epsilon — машинный “эпсилон” (минимальное положительное число ε такое, что 1 + ε ≠ 1).

pi — число пи.

euler_e — число e (константа Эйлера).

nl — символ перевода строки.

tab — символ горизонтальной табуляции.

squo — символ “кавычка” '.

dquo — символ “двойная кавычка” ".

Предопределённые функции

Управление исполнением программы

exit x — выйти из программы, вернув код x.

rmvar a — удалить переменную a, возвращает 1 (если переменная была удалена) или 0 (если переменная не была удалена).

eval a — выполнить строку a как код Toyng.

evalc a — выполнить строку a как код Toyng, используя временную копию контекста.

module a — загрузить модуль (файл с исходным кодом) с именем a в строку.

exec a — выполнить команду интерпретатора:

Стандартные потоки ввода-вывода

write a — вывести значение a в stdout.

writeln a — вывести значение a и перевод строки в stdout.

error a — вывести значение a в stderr.

readln a — прочитать строку (все символы до перевода строки), в случае неудачи вернуть a.

readnum a — прочитать число, в случае неудачи вернуть a.

readch a — прочитать один символ, в случае неудачи вернуть a.

Элементарные математические функции

ceil x — ближайшее к x целое со стороны +inf.

floor x — ближайшее к x целое со стороны -inf.

round x — ближайшее к x целое.

trunc x — целая часть x.

frac x — дробная часть x.

abs x — модуль x, абсолютная величина числа (также +x).

sign x — “знак” x, -1 или 1 (вычисляется через signbit).

sqrt x — квадратный корень x (также ^x).

cbrt x — кубический корень x.

exp xex.

exp2 x — 2x.

log x — натуральный логарифм x.

log2 x — двоичный логарифм x.

log10 x — десятичный логарифм x.

sin x, cos x, tan x, asin x, acos x, atan x — обычные тригонометрические функции аналогично стандартным C (на самом деле, и вычисляемые через них).

Строковые функции

len a — длина строки a (также +a).

to_num a — распознать префикс строки a как число (какой результат, если число не распознано?).

reverse a — обратить порядок символов в строке a.

Примеры кода

Все перечисленные ниже примеры корректно выполняются в текущей версии интерпретатора.

HelloWorld

writeln 'hello, world!'

или просто

'hello, world!'

Hello

write 'What is your name? ';
name = readln ''; # read line, failure result is ''
writeln ('Hello, ' * name)

Quadratic

write 'input a b c: ';
a = readnum 1; # read number, failure result is 1
b = readnum 0;
c = readnum 1;
d = *b - 4*a*c;
x1 = (-b - ^d) / 2a; # * may be omitted just after a literal constant
x2 = (-b + ^d) / 2a;
writeln ('x1 = ' * x1 * ', x2 = ' * x2);
writeln ('value at x1 is ' * ((a*x1 + b)*x1 + c))

Quadratic solver

quadratic_d = a => b => c =>
  *b - 4*a*c;
 
quadratic_left_root = a => b => c =>
  (-b - ^quadratic_d a b c) / 2a;
 
quadratic_right_root = a => b => c =>
  (-b + ^quadratic_d a b c) / 2a;
 
writeln (quadratic_left_root 1 (-5) 2);
writeln (quadratic_right_root 1 (-5) 2)

Sgn

sgn = x =>
 -1 if x < 0 else
 +1 if x > 0 else
  0;
 
sgn (-10) # --> -1

Substr

# A substring may be extracted by prefix/suffix operations.
substr = str from count =>
  count / (str / (+str - from));
 
substr 'alphax' 2 3 # --> 'pha'

Factorial

# Direct recursion, fact is just a global variable.
fact = n => 1 if n < 2 else n * fact(n - 1);
fact 10 # --> 3628800

Twice

twice = f x => f(f x); 
# Brackets are important here, because
# function application is done from left to right.
inc = x => x + 1;
twice inc 2
# --> 4, inc applied to 2 twice.

Z combinator

# Factorial through Z combinator.
Z = f =>
  (x => f(v => x x v))
  (x => f(v => x x v));
  
f0 = f => n => 1 if n < 2 else n*f(n - 1);
fact = Z f0;
fact 10 # --> 3628800

Linear Fibonacci

fib_n = n a b =>
  a if n < 1 else
  fib_n (n - 1) b (a + b);
 
fib = n => fib_n n 0 1;
 
fib 100 # --> 3.54224848179262e+020

Sum

# List operation simulation.
end = x => x; # A tag representing the end of a list.
 
sum = a b =>
  a if b == end else
  sum (a + b);
 
sum 1 2 3 4 end # --> 10

For

for = from to action =>
 0 if from == to else
 (action from; 1 + for (from + 1) to action);
 
# Multiplication table
for 2 10 (i =>
(
  for 2 10 (j => write (i*j * tab));
  write nl
)

Bisection

# Bisection method, solves f(x)=0, x in [a, b].
bisection = f a b =>
(
  let _m = 0.5*(a + b); # the middle of [a, b]
  writeln ('a = '*a*', b = '*b); # report the current bracket
  _m if a == _m or b == _m else
  (
    let _fm = f _m;
    _m               if _fm == 0              else
    bisection f _m b if sign _fm == sign(f a) else
    bisection f a _m
  )
);
 
bisection (x=>sin (5x) + cos x) 0 pi
# --> 1.8325957145940461

План реализации

v.0.9.1: 2017-06-20

v.0.9: 2017-06-18

Не реализовано


Кувшинов Д.Р. 2017