2.30. 精确化
表达式精确化用于以方便的方式生成 AST 表达式树。 它提供了一组转义序列,以允许不同类型的表达式替换。 在顶层,多个 call 宏支持精确化,这些宏用于生成不同的 AST 对象。
精确化在 daslib/templates_boost 中实现。
2.30.1. 简单示例
让我们回顾一下以下示例:
var foo = "foo"
var fun <- qmacro_function("madd") <| $ ( a, b ) {
return $i(foo) * a + b
}
print(describe(fun))
输出将是:
def public madd ( a:auto const; b:auto const ) : auto {
return (foo * a) + b
}
这里发生的情况是调用宏 qmacro_function
会生成一个名为 madd 的新函数。
该函数的参数和主体取自块,该块被传递给函数。
转义序列 $i 以字符串的形式获取其参数,并将其转换为标识符 (ExprVar)。
2.30.2. Quote 宏
具体化宏类似于 quote
表达式,因为参数不经过类型推断。
相反,将生成 ast 树并对其进行作。
2.30.2.1. qmacro
``qmacro``是最简单的具体化。解析转义序列后,输入按原样返回:
var expr <- qmacro(2+2)
print(describe(expr))
prints:
(2+2)
2.30.2.2. qmacro_block
qmacro_block
将一个块作为输入并返回未加引号的块。为了说明 qmacro
和 qmacro_block
之间的区别,让我们回顾一下下面的例子:
var blk1 <- qmacro <| $ ( a, b ) { return a+b; }
var blk2 <- qmacro_block <| $ ( a, b ) { return a+b; }
print("{blk1.__rtti}\n{blk2.__rtti}\n")
输出将是:
ExprMakeBlock
ExprBlock
这是因为 block 子表达式是 decorated,即 (ExprMakeBlock(ExprBlock (…))), 和 qmacro_block
删除此类装饰。
2.30.2.3. qmacro_expr
qmacro_expr
将带有单个表达式的块作为输入,并将该表达式作为结果返回。
某些表达式,如 return 之类的不能作为调用的参数,因此它们不能直接传递给 qmacro
。
解决方法是将它们作为块的第一行传递:
var expr <- qmacro_block() {
return 13
}
print(describe(expr))
prints:
return 13
2.30.2.4. qmacro_type
qmacro_type
将类型表达式 (type<…>) 作为输入,并在解析转义序列后将子类型作为 TypeDeclPtr 返回。
请考虑以下示例:
var foo <- typeinfo ast_typedecl(type<int>)
var typ <- qmacro_type <| type<$t(foo)?>
print(describe(typ))
TypeDeclPtr foo 作为具体化序列传递给 qmacro_type
,并生成一个新的指针类型。
输出为:
int?
2.30.2.5. qmacro_function
qmacro_function
需要两个参数。第一个是生成的函数名称。第二个是具有函数体和参数的块。
默认情况下,生成的函数仅设置了 FunctionFlags generated 标志。
2.30.2.6. qmacro_variable
qmacro_variable
将变量名称和类型表达式作为输入,并在解析转义序列后将变量作为 VariableDeclPtr 返回:
var vdecl <- qmacro_variable("foo", type<int>)
print(describe(vdecl))
prints:
foo:int
2.30.3. 转义序列
具体化提供了多个转义序列,用于其他模板替换。
2.30.3.1. $i(ident)
$i
将 string
或 das_string
作为参数,并用标识符替换它。
在变量声明和使用:
var bus = "bus"
var qb <- qmacro_block() {
let $i(bus) = "busbus"
let t = $i(bus)
}
print(describe(qb))
prints:
let bus:auto const = "busbus"
let t:auto const = bus
2.30.3.2. $f(field-name)
$f
将 string
或 das_string
作为参数,并将其替换为字段名称:
var bar = "fieldname"
var blk <- qmacro_block() {
foo.$f(bar) = 13
}
print(describe(blk))
prints:
foo.fieldname = 13
2.30.3.3. $v(value)
$v
将任何值作为参数,并将其替换为生成该值的表达式。
该值不必是常量表达式,但将在替换表达式之前对表达式进行计算。
将生成适当的 make 基础设施:
var t = (1,2.,"3")
var expr <- qmacro($v(t))
print(describe(expr))
prints:
(1,2f,"3")
在上面的示例中,元组被替换为生成此元组的表达式。
2.30.3.4. $e(expression)
$e
将任何表达式作为 ExpressionPtr
形式的参数。表达式将按原样替换:
var expr <- quote(2+2)
var qb <- qmacro_block() {
let foo = $e(expr)
}
print(describe(qb))
prints:
let foo:auto const = (2 + 2)
2.30.3.5. $b(array-of-expr)
$b
将 array<ExpressionPtr>
或 das::vector<ExpressionPtr>
又名 dasvector`smart_ptr`Expression
作为参数,并按顺序替换为输入数组中的每个表达式:
var qqblk : array<ExpressionPtr>
for ( i in range(3) ) {
qqblk |> emplace_new <| qmacro(print("{$v(i)}\n"))
}
var blk <- qmacro_block() {
$b(qqblk)
}
print(describe(blk))
prints:
print(string_builder(0, "\n"))
print(string_builder(1, "\n"))
print(string_builder(2, "\n"))
2.30.3.6. $a(arguments)
$a
将 array<ExpressionPtr>
或 das::vector<ExpressionPtr>
又名 dasvector`smart_ptr`Expression
作为参数,并按顺序将调用参数替换为输入数组中的每个表达式:
var arguments <- [quote(1+2); quote("foo")]
var blk <- qmacro <| somefunnycall(1,$a(arguments),2)
print(describe(blk))
prints:
somefunnycall(1,1 + 2,"foo",2)
请注意函数的其他参数是如何保留的,并且可以同时替换多个参数。
参数可以在函数声明本身中替换。在这种情况下,$a期望 array<VariablePtr>
:
var foo <- [
new Variable(name:="v1", _type<-qmacro_type(type<int>)),
new Variable(name:="v2", _type<-qmacro_type(type<float>), init<-qmacro(1.2))
]
var fun <- qmacro_function("show") <| $ ( a: int; $a(foo); b : int ) {
return a + b
}
print(describe(fun))
prints:
def public add ( a:int const; var v1:int; var v2:float = 1.2f; b:int const ) : int {
return a + b
}
2.30.3.7. $t(type)
$t
将 TypeDeclPtr
作为输入,并将其替换为类型表达式。
在以下示例中:
var subtype <- typeinfo ast_typedecl(type<int>)
var blk <- qmacro_block() {
var a : $t(subtype)?
}
print(describe(blk))
我们创建指向子类型的指针:
var a:int? -const
2.30.3.8. $c(call-name)
$c
将 string
或 das_string
作为输入,并替换调用表达式名称:
var cll = "somefunnycall"
var blk <- qmacro ( $c(cll)(1,2) )
print(describe(blk))
prints:
somefunnycall(1,2)