Skip to content

Instantly share code, notes, and snippets.

@spiiin
Last active July 1, 2022 16:17
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save spiiin/247837dc45ba11c4a5d87eb3127c6634 to your computer and use it in GitHub Desktop.
Save spiiin/247837dc45ba11c4a5d87eb3127c6634 to your computer and use it in GitHub Desktop.
module macro_test
require ast
require daslib/ast_boost
require daslib/templates
require daslib/templates_boost
require daslib/functional
// reduce value, any invokable
def private reduce_while_any(it:iterator<auto(TT)>;functor; condition)
var left : TT -&
var first = true
var iteration = 0
for right in it
if first
first = false
static_if typeinfo(can_copy type<TT>)
left = right
else
left := right
else
if !invoke(condition, left, ++iteration)
break
static_if typeinfo(can_copy type<TT>)
left = invoke(functor,left,right)
else
left := invoke(functor,left,right)
if first
panic("can't reduce empty sequence")
return left
// reduce with lambda
def reduce_while(it:iterator<auto(TT)>;blk:lambda<(left,right:TT -&):TT const -&>;condition)
//! iterates over `it` and yields the reduced (combined) result of `blk` for each element
//! and previous reduction result
return reduce_while_any(it,blk,condition)
// reduce with function
def reduce_while(it:iterator<auto(TT)>;blk:function<(left,right:TT -&):TT const -&>;condition)
return reduce_while_any(it,blk,condition)
// reduce with block
def reduce_while(it:iterator<auto(TT)>;blk:block<(left,right:TT -&):TT const -&>;condition)
return reduce_while_any(it,blk,condition)
def makeSumExpr(a, b: ExpressionPtr const): ExpressionPtr const
return new [[ExprOp2() op:="+", left := a, right := b]]
def always(a: ExpressionPtr const; iteration:int)
return true
[structure_macro(name=dump_fields)]
class DumpFields : AstStructureAnnotation
def override finish ( var st:StructurePtr; var group:ModuleGroup; args:AnnotationArgumentList; var errors : das_string ) : bool
print("struct {st.name} \{\n")
for field in st.fields
print("\t{describe_cpp(field._type)} {field.name};\n")
print("\}\n")
return true
let intAstType <- typeinfo(ast_typedecl type<int>)
def generateStructureFields(var st:StructurePtr)
let fieldsLen = st.fields |> length
var ptrsCount = 0
var ptrsOwnCount = 0
var ptrsTypeIndexes : array<int>
var ptrsOwnTypeIndexes : array<int>
ptrsTypeIndexes |> reserve(fieldsLen)
ptrsOwnTypeIndexes |> reserve(fieldsLen)
for i in range(0, fieldsLen)
if st.fields[i]._type.baseType == Type tPointer
var memblockAnnExist = find_arg("in_memblock", st.fields[i].annotation) ?as tBool ?? false
if !memblockAnnExist
ptrsOwnCount++
ptrsOwnTypeIndexes |> push(i)
st.fields[i].annotation |> add_annotation_argument("in_memblock", true)
ptrsCount++
ptrsTypeIndexes |> push(i)
//if first memblock in inheritance hierarchy
let hasMemField = ptrsOwnCount != ptrsCount
let memFieldAddIndex = hasMemField ? 0 : 1
if !hasMemField
//add one field for memblock and one field per pointer type to handle count of object per type
st.fields |> resize(fieldsLen+ ptrsOwnCount + 1)
//create "mem" field of type array<uint8>
st.fields[fieldsLen] := *new [[ FieldDeclaration() name:="mem", _type <- typeinfo(ast_typedecl type<array<uint8>>)]]
else
st.fields |> resize(fieldsLen+ ptrsOwnCount)
for i in range(0, ptrsOwnCount)
let fieldCountName = "{st.fields[ptrsOwnTypeIndexes[i]].name}{"`count"}"
st.fields[fieldsLen+i+memFieldAddIndex] := *new [[ FieldDeclaration() name:=fieldCountName, _type := intAstType]]
return <-ptrsTypeIndexes
def generateStructureInitFunction(var st:StructurePtr; ptrsTypeIndexes:array<int>&)
let ptrFieldsLen = ptrsTypeIndexes |> length
let fnname = "init`struct`{st.name}"
var fn <- new [[Function() at=st.at, atDecl=st.at, name:=fnname]]
fn.flags |= FunctionFlags generated
fn.flags |= FunctionFlags privateFunction
//function signature
unsafe
fn.arguments |> emplace_new <| new [[Variable() at=st.at, name:= "memblock", _type <- new [[TypeDecl() baseType=Type tStructure, structType=addr(*st)]]]]
for i in range(0, ptrFieldsLen)
let argumentName = "{st.fields[ptrsTypeIndexes[i]].name}`count"
fn.arguments |> emplace_new <| new [[Variable() at=st.at, name:= argumentName, _type := intAstType]]
fn.result := typeinfo(ast_typedecl type<void>)
var blk <- new [[ExprBlock() at=st.at]]
//-------------------------
//memblock.a`count = aCount
for i in range(0, ptrFieldsLen)
let argumentName = "{st.fields[ptrsTypeIndexes[i]].name}`count"
blk.list |> emplace_new <| qmacro_expr(
${memblock.$f(argumentName) = $i(argumentName);}
)
//-------------------------
//let aSize = typeinfo(sizeof *memblock.a) * aCount
for i in range(0, ptrFieldsLen)
let argumentName = "{st.fields[ptrsTypeIndexes[i]].name}"
let argumentNameSize = "{argumentName}Size"
let argumentNameCount = "{argumentName}`count"
blk.list |> emplace_new <| qmacro_expr(
${let $i(argumentNameSize) = typeinfo(sizeof *memblock.$f(argumentName)) * $i(argumentNameCount);}
)
//-------------------------
//memblock.mem |> resize(aSize + bSize + cSize)
var sumArgumentsArray: array<ExpressionPtr>
sumArgumentsArray |> emplace(new [[ExprConstInt() value=0]])
for i in range(0, ptrFieldsLen)
let argumentName = "{st.fields[ptrsTypeIndexes[i]].name}"
let nameSize := "{argumentName}Size"
sumArgumentsArray |> emplace <| qmacro_expr(${$i(nameSize);})
unsafe
var sumExpr <- reduce(each(sumArgumentsArray), @@makeSumExpr)
blk.list |> emplace_new <| qmacro_expr(
${memblock.mem |> resize($e(sumExpr));}
)
//-------------------------
//memblock.a = reinterpret<int?> addr(memblock.mem[0])
for i in range(0, ptrFieldsLen)
let argumentName = "{st.fields[ptrsTypeIndexes[i]].name}"
unsafe
var exprStartAddress <- reduce_while(each(sumArgumentsArray), @@makeSumExpr, @(e:ExpressionPtr; counter:int):bool => counter <= i)
var subtype := st.fields[ptrsTypeIndexes[i]]._type
var exprAssign <- qmacro_expr <|
unsafe{ memblock.$f(argumentName) = reinterpret<$t(subtype)> addr(memblock.mem[$e(exprStartAddress)]); }
blk.list |> emplace_new(exprAssign)
fn.body <- blk
compiling_module() |> add_function(fn)
[structure_macro(name=memblock)]
class GenMemblock : AstStructureAnnotation
def override apply (var st:StructurePtr; var group:ModuleGroup; args:AnnotationArgumentList; var errors : das_string ) : bool
var ptrsTypeIndexes <- generateStructureFields(st)
generateStructureInitFunction(st, ptrsTypeIndexes)
return true
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment