Spiiin's blog

daScript - мелочи

Научился читать грамматику для 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