<commit_before>#!/usr/bin/tclsh
# -*- mode: Tcl; c-basic-offset: 4; indent-tabs-mode: nil; -*-
#
# Copyright 2019-2020 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set model_files [lindex $argv 0]
set working_dir [lindex $argv 1]
puts "UHDM MODEL GENERATION"
puts "Working dir: $working_dir"

variable myLocation [file normalize [info script]]

set DEBUG 0

proc log { arg } {
    global DEBUG
    if {$DEBUG == 1} {
        puts $arg
    }
}

proc lognnl { arg } {
    global DEBUG
    if {$DEBUG == 1} {
        puts -nonewline $arg
    }
}

proc exec_path {} {
    variable myLocation
    return [file dirname $myLocation]
}

proc project_path {} {
    variable myLocation
    return [file dirname [file dirname $myLocation]]
}


file mkdir [project_path]/src
file mkdir [project_path]/headers

source [exec_path]/pdict.tcl
source [exec_path]/parse_model.tcl
source [exec_path]/generate_elaborator.tcl

proc find_file { baseDir filename } {
    set filepath [ file join $baseDir $filename ]
    if { [file exists $filepath] } { return $filepath; }

    set dirs [ glob -nocomplain -type d [ file join $baseDir * ] ]
    foreach dir $dirs {
        set filepath [ find_file $dir $filename ]
        if { [file exists $filepath] } { return $filepath; }
    }
}

proc parse_vpi_user_defines { } {
    global ID
    set fid [open "[project_path]/include/vpi_user.h"]
    set content [read $fid]
    set lines [split $content "\n"]
    foreach line $lines {
        if [regexp {^#define[ ]+(vpi[a-zA-Z0-9]*)[ ]+([0-9]+)} $line tmp name value] {
            set ID($name) $value
        }
    }
    close $fid
}

# Above sv_vpi_user.h and vhpi_user.h ranges
set OBJECTID 2000

proc printMethods { classname type vpi card {real_type ""} } {
    global methods_cpp
    set methods ""
    if {$type == "string"} {
        set type "std::string"
    }
    if {$type == "value"} {
        set type "std::string"
    }
    if {$type == "delay"} {
        set type "std::string"
    }
    if {$vpi == "uhdmType"} {
        set type "UHDM_OBJECT_TYPE"
    }
    set final ""
    set virtual ""
    if {$vpi == "vpiParent" || $vpi == "uhdmParentType" || $vpi == "uhdmType" || $vpi == "vpiLineNo" || $vpi == "vpiFile" } {
        set final " final"
        set virtual "virtual "
    }
    set check ""
    if {$type == "any"} {
        set check "if (!${real_type}GroupCompliant(data)) return false;"
    }
    if {$card == "1"} {
        set pointer ""
        set const ""
        if {($type != "unsigned int") && ($type != "int") && ($type != "bool") && ($type != "std::string")} {
            set pointer "*"
            set const "const "
        }


        if {$type == "std::string"} {
            append methods "\n    ${virtual}bool [string toupper ${vpi} 0 0](const ${type}${pointer}\\& data)$final;\n"
            if {$vpi == "vpiFullName" } {
                append methods "\n    ${virtual}const ${type}${pointer}\\&  [string toupper ${vpi} 0 0]() const$final;\n"
                append methods_cpp "\nconst ${type}${pointer}\\&  ${classname}::[string toupper ${vpi} 0 0]() const { 
  if (${vpi}_) {
    return serializer_->symbolMaker.GetSymbol(${vpi}_); 
  } else {
    std::vector<std::string> names;
    const BaseClass* parent = this;
    while (parent) {
      if (parent->UhdmType() == uhdmdesign) break;
      const std::string\\& name = (parent->VpiName() != \"\") ? parent->VpiName() : parent->VpiDefName();
      if (name != \"\") 
        names.push_back(name);
      parent = parent->VpiParent();
    }
    std::string fullName;
    if (names.size()) {
      unsigned int index = names.size() -1;
      while(1) {
        fullName += names\[index\];
        if (index > 0) fullName += \".\";
        if (index == 0) break;
        index--;
      }
    }  
    ((${classname}*)this)->VpiFullName(fullName);
    return serializer_->symbolMaker.GetSymbol(${vpi}_); 
  }
}\n"
            } else {
             append methods "\n    ${virtual}const ${type}${pointer}\\& [string toupper ${vpi} 0 0]() const$final;\n"
             append methods_cpp "\nconst ${type}${pointer}\\& ${classname}::[string toupper ${vpi} 0 0]() const { return serializer_->symbolMaker.GetSymbol(${vpi}_); }\n"
            }
            append methods_cpp "\nbool ${classname}::[string toupper ${vpi} 0 0](const ${type}${pointer}\\& data) { ${vpi}_ = serializer_->symbolMaker.Make(data); return true; }\n"
        } else {
            append methods "\n    ${virtual}${const}${type}${pointer} [string toupper ${vpi} 0 0]() const$final { return ${vpi}_; }\n"
            if {$vpi == "vpiParent"} {
                append methods "\n    virtual bool [string toupper ${vpi} 0 0](${type}${pointer} data) final {${check} ${vpi}_ = data; if (data) uhdmParentType_ = data->UhdmType(); return true;}\n"
            } else {
                append methods "\n    ${virtual}bool [string toupper ${vpi} 0 0](${type}${pointer} data)$final {${check} ${vpi}_ = data; return true;}\n"
            }
        }
    } elseif {$card == "any"} {
        append methods "\n    VectorOf${type}* [string toupper ${vpi} 0 0]() const { return ${vpi}_; }\n"
        append methods "\n    bool [string toupper ${vpi} 0 0](VectorOf${type}* data) {${check} ${vpi}_ = data; return true;}\n"
    }
    return $methods
}

proc printCapnpSchema {type vpi card} {
    if {$type == "string"} {
        set type "UInt64"
    }
    if {$type == "unsigned int"} {
        set type "UInt64"
    }
    if {$type == "int"} {
        set type "Int64"
    }
    if {$type == "bool"} {
        set type "Bool"
    }
    if {$type == "any"} {
        set type "Int64"
    }
    if {$type == "value"} {
        set type "UInt64"
    }
    if {$type == "delay"} {
        set type "UInt64"
    }
    if {$card == "1"} {
        return [list ${vpi} ${type}]
    } elseif {$card == "any"} {
        return [list ${vpi} List(${type})]
    }
}

proc printMembers { type vpi card } {
    set members ""
    if {$type == "string" || $type == "value" || $type == "delay"} {
        set type "std::string"
    }
    if {$card == "1"} {
        set pointer ""
        if {($type != "unsigned int") && ($type != "int") && ($type != "bool") && ($type != "std::string")} {
            set pointer "*"
        }
        if {$type == "std::string"} {
            append members "\n    SymbolFactory::ID ${vpi}_;\n"
        } else {
            append members "\n    ${type}${pointer} ${vpi}_;\n"
        }
    } elseif {$card == "any"} {
        append members "\n    VectorOf${type}* ${vpi}_;\n"
    }
    return $members
}

proc printTypeDefs { type card } {
    global CONTAINER
    set typedefs ""
    if {$card == "any"} {
        if ![info exist CONTAINER($type)] {
            set CONTAINER($type) 1
            if {$type != "any"} {
                append typedefs "class $type;\n"
            }
            append typedefs "typedef std::vector<${type}*> VectorOf${type};\n"
            append typedefs "typedef std::vector<${type}*>::iterator VectorOf${type}Itr;\n"
        }
    }
    return $typedefs
}

proc printIterateBody { name classname vpi card } {
    set vpi_iterate_body ""
    if {$card == "any"} {
        append vpi_iterate_body "
  if (handle->type == uhdm${classname}) {
    if (type == $vpi) {
      if ((($classname*)(object))->[string toupper ${name} 0 0]())
       return NewHandle(uhdm${name}, (($classname*)(object))->[string toupper ${name} 0 0]());
      else return 0;
    }
  }"
        printVpiVisitor $classname $vpi $card
        return $vpi_iterate_body
    }
}

proc printGetHandleByNameBody { name classname vpi card } {
    if {$card == 1} {
        set vpi_handle_by_name_body "
  if (handle->type == uhdm${classname}) {
    if ((($classname*)(object))->[string toupper ${name} 0 0]()) {
      if ((($classname*)(object))->[string toupper ${name} 0 0]()->VpiName() == name) {
        return NewHandle((($classname*)(object))->[string toupper ${name} 0 0]()->UhdmType(), (($classname*)(object))->[string toupper ${name} 0 0]());
      }
    }
  }"
    } else {
        set vpi_handle_by_name_body "
  if (handle->type == uhdm${classname}) {
    if ((($classname*)(object))->[string toupper ${name} 0 0]()) {
      for (auto\\& obj : *(($classname*)(object))->[string toupper ${name} 0 0]()) {
        if (obj->VpiName() == name) {
          return NewHandle(obj->UhdmType(), obj);
        }
      }
    }
  }"
    }
    return $vpi_handle_by_name_body
}

proc printGetBody {classname type vpi card} {
    set vpi_get_body ""
    if {($card == 1) && ($type != "string") && ($type != "value") && ($type != "delay")} {
        append vpi_get_body "
  if (handle->type == uhdm${classname}) {
    if (property == $vpi) {
      return (($classname*)(obj))->[string toupper ${vpi} 0 0]();
    }
  }"
    }
    return $vpi_get_body
}

proc printGetValueBody {classname type vpi card} {
    set vpi_get_value_body ""
    if {($card == 1) && ($type == "value")} {
        append vpi_get_value_body "
  if (handle->type == uhdm${classname}) {
    const s_vpi_value* v = String2VpiValue((($classname*)(obj))->VpiValue());
    if (v) {
      *value_p = *v;
    }
  }"
    }
    return $vpi_get_value_body
}

proc printGetDelayBody {classname type vpi card} {
    set vpi_get_delay_body ""
    if {($card == 1) && ($type == "delay")} {
        append vpi_get_delay_body "
  if (handle->type == uhdm${classname}) {
    const s_vpi_delay* v = String2VpiDelays((($classname*)(obj))->VpiDelay());
    if (v) {
      *delay_p = *v;
    }
  }"
    }
    return $vpi_get_delay_body
}


proc printGetHandleBody { classname type vpi object card } {
    if {$type == "BaseClass"} {
        set type "(($classname*)(object))->UhdmParentType()"
    }
    set vpi_get_handle_body ""
    set need_casting 1
    if {$vpi == "vpiParent" && $object == "vpiParent"} {
        set need_casting 0
    }
    if {$card == 1} {
        set casted_object1 "(object"
        set casted_object2 "object"
        if {$need_casting == 1} {
            set casted_object1 "((BaseClass*)(($classname*)(object))"
            set casted_object2 "(($classname*)(object))"
        }
        append vpi_get_handle_body "
  if (handle->type == uhdm${classname}) {
     if (type == $vpi) {
       if ($casted_object1->[string toupper ${object} 0 0]()))
         return NewHandle($casted_object1->[string toupper ${object} 0 0]())->UhdmType(), $casted_object2->[string toupper ${object} 0 0]());
       else return 0;
     }
  }"
        printVpiVisitor $classname $vpi $card
        #printVpiListener $classname $vpi $card
    }
    return $vpi_get_handle_body
}

proc printGetStrVisitor {classname type vpi card} {
    set vpi_get_str_body ""
    if {($card == 1) && ($type == "string") && ($vpi != "vpiFile")} {
        append vpi_get_str_body "    if (const char* s = vpi_get_str($vpi, obj_h))
      stream_indent(out, indent) << \"|$vpi:\" << s << \"\\n\";
"
    }
    return $vpi_get_str_body
}

proc printGetVisitor {classname type vpi card} {
    set vpi_get_body ""
    if {$vpi == "vpiValue"} {
        append vpi_get_body "    s_vpi_value value;
    vpi_get_value(obj_h, \\&value);
    if (value.format) {
      stream_indent(out, indent) << visit_value(\\&value);
    }
"
    } elseif {$vpi == "vpiDelay"} {
        append vpi_get_body "    s_vpi_delay delay;
    vpi_get_delays(obj_h, \\&delay);
    if (delay.da != nullptr) {
      stream_indent(out, indent) << visit_delays(\\&delay);
    }
"
    } elseif {($card == 1) && ($type != "string") && ($vpi != "vpiLineNo") && ($vpi != "vpiType")} {
        append vpi_get_body "    if (const int n = vpi_get($vpi, obj_h))
      if (n != -1)
        stream_indent(out, indent) << \"|$vpi:\" << n << \"\\n\";
"
    }
    return $vpi_get_body<commit_msg>Fixed indent issue<commit_after>#!/usr/bin/tclsh
# -*- mode: Tcl; c-basic-offset: 4; indent-tabs-mode: nil; -*-
#
# Copyright 2019-2020 <NAME>
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#    http://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

set model_files [lindex $argv 0]
set working_dir [lindex $argv 1]
puts "UHDM MODEL GENERATION"
puts "Working dir: $working_dir"

variable myLocation [file normalize [info script]]

set DEBUG 0

proc log { arg } {
    global DEBUG
    if {$DEBUG == 1} {
        puts $arg
    }
}

proc lognnl { arg } {
    global DEBUG
    if {$DEBUG == 1} {
        puts -nonewline $arg
    }
}

proc exec_path {} {
    variable myLocation
    return [file dirname $myLocation]
}

proc project_path {} {
    variable myLocation
    return [file dirname [file dirname $myLocation]]
}


file mkdir [project_path]/src
file mkdir [project_path]/headers

source [exec_path]/pdict.tcl
source [exec_path]/parse_model.tcl
source [exec_path]/generate_elaborator.tcl

proc find_file { baseDir filename } {
    set filepath [ file join $baseDir $filename ]
    if { [file exists $filepath] } { return $filepath; }

    set dirs [ glob -nocomplain -type d [ file join $baseDir * ] ]
    foreach dir $dirs {
        set filepath [ find_file $dir $filename ]
        if { [file exists $filepath] } { return $filepath; }
    }
}

proc parse_vpi_user_defines { } {
    global ID
    set fid [open "[project_path]/include/vpi_user.h"]
    set content [read $fid]
    set lines [split $content "\n"]
    foreach line $lines {
        if [regexp {^#define[ ]+(vpi[a-zA-Z0-9]*)[ ]+([0-9]+)} $line tmp name value] {
            set ID($name) $value
        }
    }
    close $fid
}

# Above sv_vpi_user.h and vhpi_user.h ranges
set OBJECTID 2000

proc printMethods { classname type vpi card {real_type ""} } {
    global methods_cpp
    set methods ""
    if {$type == "string"} {
        set type "std::string"
    }
    if {$type == "value"} {
        set type "std::string"
    }
    if {$type == "delay"} {
        set type "std::string"
    }
    if {$vpi == "uhdmType"} {
        set type "UHDM_OBJECT_TYPE"
    }
    set final ""
    set virtual ""
    if {$vpi == "vpiParent" || $vpi == "uhdmParentType" || $vpi == "uhdmType" || $vpi == "vpiLineNo" || $vpi == "vpiFile" } {
        set final " final"
        set virtual "virtual "
    }
    set check ""
    if {$type == "any"} {
        set check "if (!${real_type}GroupCompliant(data)) return false;"
    }
    if {$card == "1"} {
        set pointer ""
        set const ""
        if {($type != "unsigned int") && ($type != "int") && ($type != "bool") && ($type != "std::string")} {
            set pointer "*"
            set const "const "
        }


        if {$type == "std::string"} {
            append methods "\n    ${virtual}bool [string toupper ${vpi} 0 0](const ${type}${pointer}\\& data)$final;\n"
            if {$vpi == "vpiFullName" } {
                append methods "\n    ${virtual}const ${type}${pointer}\\&  [string toupper ${vpi} 0 0]() const$final;\n"
                append methods_cpp "\nconst ${type}${pointer}\\&  ${classname}::[string toupper ${vpi} 0 0]() const { 
  if (${vpi}_) {
    return serializer_->symbolMaker.GetSymbol(${vpi}_); 
  } else {
    std::vector<std::string> names;
    const BaseClass* parent = this;
    while (parent) {
      if (parent->UhdmType() == uhdmdesign) break;
      const std::string\\& name = (parent->VpiName() != \"\") ? parent->VpiName() : parent->VpiDefName();
      if (name != \"\") 
        names.push_back(name);
      parent = parent->VpiParent();
    }
    std::string fullName;
    if (names.size()) {
      unsigned int index = names.size() -1;
      while(1) {
        fullName += names\[index\];
        if (index > 0) fullName += \".\";
        if (index == 0) break;
        index--;
      }
    }  
    ((${classname}*)this)->VpiFullName(fullName);
    return serializer_->symbolMaker.GetSymbol(${vpi}_); 
  }
}\n"
            } else {
             append methods "\n    ${virtual}const ${type}${pointer}\\& [string toupper ${vpi} 0 0]() const$final;\n"
             append methods_cpp "\nconst ${type}${pointer}\\& ${classname}::[string toupper ${vpi} 0 0]() const { return serializer_->symbolMaker.GetSymbol(${vpi}_); }\n"
            }
            append methods_cpp "\nbool ${classname}::[string toupper ${vpi} 0 0](const ${type}${pointer}\\& data) { ${vpi}_ = serializer_->symbolMaker.Make(data); return true; }\n"
        } else {
            append methods "\n    ${virtual}${const}${type}${pointer} [string toupper ${vpi} 0 0]() const$final { return ${vpi}_; }\n"
            if {$vpi == "vpiParent"} {
                append methods "\n    virtual bool [string toupper ${vpi} 0 0](${type}${pointer} data) final {${check} ${vpi}_ = data; if (data) uhdmParentType_ = data->UhdmType(); return true;}\n"
            } else {
                append methods "\n    ${virtual}bool [string toupper ${vpi} 0 0](${type}${pointer} data)$final {${check} ${vpi}_ = data; return true;}\n"
            }
        }
    } elseif {$card == "any"} {
        append methods "\n    VectorOf${type}* [string toupper ${vpi} 0 0]() const { return ${vpi}_; }\n"
        append methods "\n    bool [string toupper ${vpi} 0 0](VectorOf${type}* data) {${check} ${vpi}_ = data; return true;}\n"
    }
    return $methods
}

proc printCapnpSchema {type vpi card} {
    if {$type == "string"} {
        set type "UInt64"
    }
    if {$type == "unsigned int"} {
        set type "UInt64"
    }
    if {$type == "int"} {
        set type "Int64"
    }
    if {$type == "bool"} {
        set type "Bool"
    }
    if {$type == "any"} {
        set type "Int64"
    }
    if {$type == "value"} {
        set type "UInt64"
    }
    if {$type == "delay"} {
        set type "UInt64"
    }
    if {$card == "1"} {
        return [list ${vpi} ${type}]
    } elseif {$card == "any"} {
        return [list ${vpi} List(${type})]
    }
}

proc printMembers { type vpi card } {
    set members ""
    if {$type == "string" || $type == "value" || $type == "delay"} {
        set type "std::string"
    }
    if {$card == "1"} {
        set pointer ""
        if {($type != "unsigned int") && ($type != "int") && ($type != "bool") && ($type != "std::string")} {
            set pointer "*"
        }
        if {$type == "std::string"} {
            append members "\n    SymbolFactory::ID ${vpi}_;\n"
        } else {
            append members "\n    ${type}${pointer} ${vpi}_;\n"
        }
    } elseif {$card == "any"} {
        append members "\n    VectorOf${type}* ${vpi}_;\n"
    }
    return $members
}

proc printTypeDefs { type card } {
    global CONTAINER
    set typedefs ""
    if {$card == "any"} {
        if ![info exist CONTAINER($type)] {
            set CONTAINER($type) 1
            if {$type != "any"} {
                append typedefs "class $type;\n"
            }
            append typedefs "typedef std::vector<${type}*> VectorOf${type};\n"
            append typedefs "typedef std::vector<${type}*>::iterator VectorOf${type}Itr;\n"
        }
    }
    return $typedefs
}

proc printIterateBody { name classname vpi card } {
    set vpi_iterate_body ""
    if {$card == "any"} {
        append vpi_iterate_body "
  if (handle->type == uhdm${classname}) {
    if (type == $vpi) {
      if ((($classname*)(object))->[string toupper ${name} 0 0]())
       return NewHandle(uhdm${name}, (($classname*)(object))->[string toupper ${name} 0 0]());
      else return 0;
    }
  }"
        printVpiVisitor $classname $vpi $card
        return $vpi_iterate_body
    }
}

proc printGetHandleByNameBody { name classname vpi card } {
    if {$card == 1} {
        set vpi_handle_by_name_body "
  if (handle->type == uhdm${classname}) {
    if ((($classname*)(object))->[string toupper ${name} 0 0]()) {
      if ((($classname*)(object))->[string toupper ${name} 0 0]()->VpiName() == name) {
        return NewHandle((($classname*)(object))->[string toupper ${name} 0 0]()->UhdmType(), (($classname*)(object))->[string toupper ${name} 0 0]());
      }
    }
  }"
    } else {
        set vpi_handle_by_name_body "
  if (handle->type == uhdm${classname}) {
    if ((($classname*)(object))->[string toupper ${name} 0 0]()) {
      for (auto\\& obj : *(($classname*)(object))->[string toupper ${name} 0 0]()) {
        if (obj->VpiName() == name) {
          return NewHandle(obj->UhdmType(), obj);
        }
      }
    }
  }"
    }
    return $vpi_handle_by_name_body
}

proc printGetBody {classname type vpi card} {
    set vpi_get_body ""
    if {($card == 1) && ($type != "string") && ($type != "value") && ($type != "delay")} {
        append vpi_get_body "
  if (handle->type == uhdm${classname}) {
    if (property == $vpi) {
      return (($classname*)(obj))->[string toupper ${vpi} 0 0]();
    }
  }"
    }
    return $vpi_get_body
}

proc printGetValueBody {classname type vpi card} {
    set vpi_get_value_body ""
    if {($card == 1) && ($type == "value")} {
        append vpi_get_value_body "
  if (handle->type == uhdm${classname}) {
    const s_vpi_value* v = String2VpiValue((($classname*)(obj))->VpiValue());
    if (v) {
      *value_p = *v;
    }
  }"
    }
    return $vpi_get_value_body
}

proc printGetDelayBody {classname type vpi card} {
    set vpi_get_delay_body ""
    if {($card == 1) && ($type == "delay")} {
        append vpi_get_delay_body "
  if (handle->type == uhdm${classname}) {
    const s_vpi_delay* v = String2VpiDelays((($classname*)(obj))->VpiDelay());
    if (v) {
      *delay_p = *v;
    }
  }"
    }
    return $vpi_get_delay_body
}


proc printGetHandleBody { classname type vpi object card } {
    if {$type == "BaseClass"} {
        set type "(($classname*)(object))->UhdmParentType()"
    }
    set vpi_get_handle_body ""
    set need_casting 1
    if {$vpi == "vpiParent" && $object == "vpiParent"} {
        set need_casting 0
    }
    if {$card == 1} {
        set casted_object1 "(object"
        set casted_object2 "object"
        if {$need_casting == 1} {
            set casted_object1 "((BaseClass*)(($classname*)(object))"
            set casted_object2 "(($classname*)(object))"
        }
        append vpi_get_handle_body "
  if (handle->type == uhdm${classname}) {
     if (type == $vpi) {
       if ($casted_object1->[string toupper ${object} 0 0]()))
         return NewHandle($casted_object1->[string toupper ${object} 0 0]())->UhdmType(), $casted_object2->[string toupper ${object} 0 0]());
       else return 0;
     }
  }"
        printVpiVisitor $classname $vpi $card
        #printVpiListener $classname $vpi $card
    }
    return $vpi_get_handle_body
}

proc printGetStrVisitor {classname type vpi card} {
    set vpi_get_str_body ""
    if {($card == 1) && ($type == "string") && ($vpi != "vpiFile")} {
        append vpi_get_str_body "    if (const char* s = vpi_get_str($vpi, obj_h))
      stream_indent(out, indent) << \"|$vpi:\" << s << \"\\n\";
"
    }
    return $vpi_get_str_body
}

proc printGetVisitor {classname type vpi card} {
    set vpi_get_body ""
    if {$vpi == "vpiValue"} {
        append vpi_get_body "
    s_vpi_value value;
    vpi_get_value(obj_h, \\&value);
    if (value.format) {
      std::string val = visit_value(\\&value);
      if (val != \"\") {
        stream_indent(out, indent) << val;
      }
    }
"
    } elseif {$vpi == "vpiDelay"} {
        append vpi_get_body "    s_vpi_delay delay;
    vpi_get_delays(obj_h, \\&delay);
    if (delay.da != nullptr) {
      stream_indent(out, indent) << visit_delays(\\&delay);
    }
"
    } elseif {($card == 1) && ($type != "string") && ($vpi != "vpiLineNo") && ($vpi != "vpiType")} {
        append vpi_get_body "    if (const int n = vpi_get($vpi, obj_h))
      if (n != -1)
        stream_indent(out, indent) << \"|$vpi:\" << n << \"\\n\";
"
    }
    return $vpi_get_body
{'fraction_non_alphanumeric': 0.17571312143439283, 'fraction_numerical': 0.009290953545232274, 'mean_word_length': 2.519936890418818, 'pattern_counts': {'":': 0, '<': 43, '<?xml version=': 0, '>': 89, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '1037736', 'n_tokens_mistral': 8682, 'n_tokens_neox': 8365, 'n_words': 2172}