Научился читать грамматику для bison, нашёл несколько новых для себя мелочей синтаксиса daScript.
1. assume
Аналог #define
в си, текстовая подстановка выражений. Со всеми ее минусами.
var a = "global_string"
[export]
def main
assume x = a //not capture global var a, but only text name
var a = "local string"
x = "changed string" //change local, but not global a!
print("{a}\n")
print("{::a}\n")
//changed string
//global_string
2. =>
Символ стрелки используется для записи коротких блоков/лямбд/безымянных функций:
def radd(var ext:int&; b:block<(var arg:int&):int>):int
return invoke(b,ext)
def radd(var ext:int&; b:lambda<(var arg:int&):int>):int
return invoke(b,ext)
def radd(var ext:int&; b:function<(var arg:int&):int>):int
return invoke(b,ext)
[export]
def main
var x = 0
radd(x, $(a) => a++)
radd(x, @(a) => a++)
radd(x, @@(a) => a++)
print("{x}\n")
//Output: 3
А также для записи создания кортежей и таблиц:
var x <- [[auto 1=>"one"]] //работает также в массивах [[auto 1=>"one"; 2=>"two"]]
print("{x} {typeinfo(typename x)}\n")
//[[ 1; one]] tuple<int;string> - кортеж
var y <- {{ 1=>"one"}}
print("{y} {typeinfo(typename y)}\n")
//[[ 1 : one]] table<int;string> - таблица
3. auto для инициализации
auto при инициализации может выводить тип массивов (статических и динамических) и кортежей. Для структур — не может
def printType(a) { print("{typeinfo(typename a)}\n"); }
printType([[auto 1=>2]]) //tuple<int;int> const
printType([[auto 1,2]]) //tuple<int;int> const
printType([[auto 1;2]]) //int const[2]
printType([{auto 1;2}]) //array<int> const
4. сокращенная запись при обьявлении переменных ссылочных типов
let a = 1
let ar& = a //let ar: int& = a
5. if после выражений
Условие может стоять после определённых выражений (с опциональной веткой else):
def fun
print("1") if true else print("2") //expr if
while true
break if true else continue //break if
continue if false //continue if
return <- generator<int>() <| $()
for t in range(0,10)
yield t if true //yield if
return false if true //return if
6. aka
Синоним для имени переменной (как намного менее “злобный” вариант assume
)
var a aka b: int
b = 1
print("{a}\n") //1
7. expect
Ключевое слово для тестового фреймворка dasTest
expect 10003:1, 20000:1
//ожидается по одной ошибке компилятора типа 10003 и 20000 (незакрытая кавычка и неожиданный конец файла)
[export]
def test
print("ok
Для запуска теста нужно вызвать скрипт
dastest и передает в параметре
test
имя скрипт для тестирования (или директории с группой скриптов):
daScript dastest.das -- --test my_test.das
|
8. named arguments
Функцию можно вызвать с явными именами аргументов.
def foo(a:int=13; b: int)
return a + b
foo([b = 2]) // same as foo(13, 2)
Также можно скомбинировать первые неименованные аргументы, или вызов через пайп:
def func(a:int; b=1; c=2)
pass
func([a=0, c=2] //ok
func(0, [c=2]) //error
0 |> func([c=2]) //error
Больше примеров. Логика выбора — именованные аргументы применяются после неименованных и могут “перекрывать” их.
9. with
with позволяет внутри блока обращаться к полям структуры без явного указания её имени:
struct S
a, b: int
var s = [[S a=1, b=2]]
with s
print("{a}, {b}\n") //s.a, s.b