options gen2
options indenting = 4
options strict_smart_pointers = true
module instance_function shared private
//! Generic function instantiation annotation.
//!
//! ``[instance_function(generic_name, TT="int")]`` replaces the body of the annotated
//! function with an instantiation of the named generic, substituting the specified
//! type parameters. Useful for creating concrete exports of generic functions.
require daslib/ast
require daslib/rtti
require daslib/ast_boost
require daslib/templates_boost
require daslib/defer
require strings
[function_macro(name="instance_function")]
class InstanceFunctionAnnotation : AstFunctionAnnotation {
//! [instance_function(generic_name,type1=type1r,type2=type2r,...)] macro creates instance of the generic function with a particular set of types.
//! In the followin example body of the function inst will be replaced with body of the function print_zero with type int::
//!
//! def print_zero ( a : auto(TT) )
//! print("{[[TT]]}\n")
//! [export, instance_function(print_zero,TT="int")]
//! def inst {}
def override apply(var func : FunctionPtr; var group : ModuleGroup; args : AnnotationArgumentList; var errors : das_string) : bool {
var generic_name = ""
var rules : Template
for (argv in args) {
let val = get_annotation_argument_value(argv)
if (val is tBool) {
if (!empty(generic_name)) {
errors := "unexpected {argv.name}, name of the generic or function is already specified as {generic_name}"
return false
}
generic_name = "{argv.name}"
} elif (val is tString) {
rules |> replaceType("{argv.name}", "{val as tString}")
} else {
errors := "invalid argument type {argv.name}"
return false
}
}
if (empty(generic_name)) {
errors := "expecting name of the generic or function"
return false
}
var fn = compiling_module() |> find_unique_generic(generic_name)
if (fn == null) {
errors := "generic not found {generic_name}"
return false
}
func.body = clone_expression(fn.body)
apply_template(rules, func.at, func.body)
return true
}
}