在 pascal define 中传递参数
Pass parameter in pascal define
我正在尝试用 pascal (freepascal) 定义一些东西。
与在 C++ 中一样,您可以像这样传递变量定义宏:
#define REP(i,k) for(int i=0; i<k; i++)
你如何用 Pascal 实现?
我在第一行添加了{$MACRO ON}
命令,结果它可以运行正常定义而没有错误,如{$define lala:='hello world'}
。
但是当我尝试 {define lala(i):=i}
程序出现错误。
如何在 Pascal define 中传递可变参数?
使用外部预处理器,并在对结果使用 Pascal 编译器之前在构建系统中执行它。
FPC 宏系统不是用于元编程,而是用于在 headers 中调用约定宏,仅用于压缩 enable/disable 逻辑(如 home-brewn 断言和其他调试日志代码)和不支持参数化。
非 hygienic 宏与 Pascal 单位系统根本不兼容,而 hygienic 宏被内联覆盖 function/procedures。
您可以结合使用宏和包含来实现类似于标记粘贴的效果...
ACME_Integer.inc
const ACME_1 = ACME_3;
const ACME_2 = pred(1 shl ACME_1);
type ACME_0 = 0..ACME_2;
//clear the passed in parameters so they can be reused in the next inclusion
{$undef ACME_0}{$undef ACME_1}{$undef ACME_2}{$undef ACME_3}
somefile.pas
{$macro on}
{$define ACME_0:=TAllocationPatchIndex}
{$define ACME_1:=TAllocationPatchIndex_bits}
{$define ACME_2:=TAllocationPatchIndex_high}
{$define ACME_3:=16}
{$Include ACME_Integer.inc}
{$define ACME_0:=TAllocationId}
{$define ACME_1:=TAllocationId_bits}
{$define ACME_2:=TAllocationId_high}
{$define ACME_3:=28}
{$Include ACME_Integer.inc}
扩展到
const TAllocationPatchIndex_bits = 16;
const TAllocationPatchIndex_high = pred(1 shl TAllocationPatchIndex_bits);
type TAllocationPatchIndex= 0..TAllocationPatchIndex_high;
const TAllocationId_bits = 28;
const TAllocationId_high = pred(1 shl TAllocationId_bits);
type TAllocationId= 0..TAllocationId_high;
虽然此示例使用的代码多于它节省的代码,但您可以明显地看到包含文件可能非常复杂,需要多次自定义的重复代码。
更新 - 使用 named/optional 个参数的更复杂的宏
ACME_Integer.inc
{$ifdef ACME_packed_array}
{$undef ACME_array}
{$define ACME_array:=ACME_packed_array}
{$undef ACME_array_decl}
{$define ACME_array_decl:=packed array}
{$else}
{$ifdef ACME_bitpacked_array}
{$undef ACME_array}
{$define ACME_array:=ACME_bitpacked_array}
{$undef ACME_array_decl}
{$define ACME_array_decl:=bitpacked array}
{$else}
{$undef ACME_array_decl}
{$define ACME_array_decl:=array}
{$endif}
{$endif}
{$ifndef ACME_array_type}
{$define ACME_array_type:=byte}
{$endif}
{$ifdef ACME_bitconst}
// we want to keep the X_bits constant
const ACME_bitconst = ACME_bits; //X_bits
{$ifdef ACME_high}
// we want to keep the X_high constant
const ACME_high = pred(1 shl ACME_bitconst); //X_high
type ACME_type = 0..ACME_high; //X
{$else}
// we don't care about keeping the X_high constant
type ACME_type = 0..pred(1 shl ACME_bitconst); //X
{$endif}
{$else}
{$ifdef ACME_high}
// we don't care about keeping the X_bits constant
const ACME_high = pred(1 shl ACME_bits); //X_high
type ACME_type = 0..ACME_high; //X
{$else}
// we don't care about keeping the X_high or X_bits constants
type ACME_type = 0..pred(1 shl ACME_bits); //X
{$endif}
{$endif}
{$ifdef ACME_array}
type ACME_array = ACME_array_decl [ACME_type] of ACME_array_type;
{$ifdef ACME_array_length}
const ACME_array_length = sizeof(ACME_array);
{$endif}
{$ifdef ACME_array_pointer}
type ACME_array_pointer=^ACME_array;
{$endif}
{$undef ACME_array}
{$endif}
{$undef ACME_type}
{$undef ACME_bitconst}
{$undef ACME_high}
{$undef ACME_bits}
{$undef ACME_packed_array}
{$undef ACME_bitpacked_array}
{$undef ACME_array}
{$undef ACME_array_pointer}
{$undef ACME_array_type}
{$undef ACME_array_decl}
{$undef ACME_array_length}
somefile.pas
{$macro on}
{$define ACME_type:=TSha256IndexSliceMagic}
{$define ACME_bitconst:=TSha256IndexSliceMagic_bits}
{$define ACME_high:=TSha256IndexSliceMagic_high}
{$define ACME_bits:=17}
{$Include ACME_Integer.inc}
{$define ACME_type:=TSha256DataBufferIndex}
{$define ACME_bitconst:=TSha256DataBufferIndex_bits}
{$define ACME_high:=TSha256DataBufferIndex_high}
{$define ACME_bits:=9}
{$define ACME_packed_array:=TSha256DataBuffer}
{$define ACME_array_pointer:=PSha256DataBuffer}
{$Include ACME_Integer.inc}
扩展到
const TSha256IndexSliceMagic_bits = 17;
const TSha256IndexSliceMagic_high = pred(1 shl TSha256IndexSliceMagic_bits);
type TSha256IndexSliceMagic= 0..TSha256IndexSliceMagic_high;
const TSha256DataBufferIndex_bits = 9;
const TSha256DataBufferIndex_high = pred(1 shl TSha256DataBufferIndex_bits);
type TSha256DataBufferIndex= 0..TSha256DataBufferIndex_high;
type TSha256DataBuffer = packed array [TSha256DataBufferIndex] of byte;
type PSha256DataBuffer = ^TSha256DataBuffer;
我正在尝试用 pascal (freepascal) 定义一些东西。 与在 C++ 中一样,您可以像这样传递变量定义宏:
#define REP(i,k) for(int i=0; i<k; i++)
你如何用 Pascal 实现?
我在第一行添加了{$MACRO ON}
命令,结果它可以运行正常定义而没有错误,如{$define lala:='hello world'}
。
但是当我尝试 {define lala(i):=i}
程序出现错误。
如何在 Pascal define 中传递可变参数?
使用外部预处理器,并在对结果使用 Pascal 编译器之前在构建系统中执行它。
FPC 宏系统不是用于元编程,而是用于在 headers 中调用约定宏,仅用于压缩 enable/disable 逻辑(如 home-brewn 断言和其他调试日志代码)和不支持参数化。
非 hygienic 宏与 Pascal 单位系统根本不兼容,而 hygienic 宏被内联覆盖 function/procedures。
您可以结合使用宏和包含来实现类似于标记粘贴的效果...
ACME_Integer.inc
const ACME_1 = ACME_3;
const ACME_2 = pred(1 shl ACME_1);
type ACME_0 = 0..ACME_2;
//clear the passed in parameters so they can be reused in the next inclusion
{$undef ACME_0}{$undef ACME_1}{$undef ACME_2}{$undef ACME_3}
somefile.pas
{$macro on}
{$define ACME_0:=TAllocationPatchIndex}
{$define ACME_1:=TAllocationPatchIndex_bits}
{$define ACME_2:=TAllocationPatchIndex_high}
{$define ACME_3:=16}
{$Include ACME_Integer.inc}
{$define ACME_0:=TAllocationId}
{$define ACME_1:=TAllocationId_bits}
{$define ACME_2:=TAllocationId_high}
{$define ACME_3:=28}
{$Include ACME_Integer.inc}
扩展到
const TAllocationPatchIndex_bits = 16;
const TAllocationPatchIndex_high = pred(1 shl TAllocationPatchIndex_bits);
type TAllocationPatchIndex= 0..TAllocationPatchIndex_high;
const TAllocationId_bits = 28;
const TAllocationId_high = pred(1 shl TAllocationId_bits);
type TAllocationId= 0..TAllocationId_high;
虽然此示例使用的代码多于它节省的代码,但您可以明显地看到包含文件可能非常复杂,需要多次自定义的重复代码。
更新 - 使用 named/optional 个参数的更复杂的宏
ACME_Integer.inc
{$ifdef ACME_packed_array}
{$undef ACME_array}
{$define ACME_array:=ACME_packed_array}
{$undef ACME_array_decl}
{$define ACME_array_decl:=packed array}
{$else}
{$ifdef ACME_bitpacked_array}
{$undef ACME_array}
{$define ACME_array:=ACME_bitpacked_array}
{$undef ACME_array_decl}
{$define ACME_array_decl:=bitpacked array}
{$else}
{$undef ACME_array_decl}
{$define ACME_array_decl:=array}
{$endif}
{$endif}
{$ifndef ACME_array_type}
{$define ACME_array_type:=byte}
{$endif}
{$ifdef ACME_bitconst}
// we want to keep the X_bits constant
const ACME_bitconst = ACME_bits; //X_bits
{$ifdef ACME_high}
// we want to keep the X_high constant
const ACME_high = pred(1 shl ACME_bitconst); //X_high
type ACME_type = 0..ACME_high; //X
{$else}
// we don't care about keeping the X_high constant
type ACME_type = 0..pred(1 shl ACME_bitconst); //X
{$endif}
{$else}
{$ifdef ACME_high}
// we don't care about keeping the X_bits constant
const ACME_high = pred(1 shl ACME_bits); //X_high
type ACME_type = 0..ACME_high; //X
{$else}
// we don't care about keeping the X_high or X_bits constants
type ACME_type = 0..pred(1 shl ACME_bits); //X
{$endif}
{$endif}
{$ifdef ACME_array}
type ACME_array = ACME_array_decl [ACME_type] of ACME_array_type;
{$ifdef ACME_array_length}
const ACME_array_length = sizeof(ACME_array);
{$endif}
{$ifdef ACME_array_pointer}
type ACME_array_pointer=^ACME_array;
{$endif}
{$undef ACME_array}
{$endif}
{$undef ACME_type}
{$undef ACME_bitconst}
{$undef ACME_high}
{$undef ACME_bits}
{$undef ACME_packed_array}
{$undef ACME_bitpacked_array}
{$undef ACME_array}
{$undef ACME_array_pointer}
{$undef ACME_array_type}
{$undef ACME_array_decl}
{$undef ACME_array_length}
somefile.pas
{$macro on}
{$define ACME_type:=TSha256IndexSliceMagic}
{$define ACME_bitconst:=TSha256IndexSliceMagic_bits}
{$define ACME_high:=TSha256IndexSliceMagic_high}
{$define ACME_bits:=17}
{$Include ACME_Integer.inc}
{$define ACME_type:=TSha256DataBufferIndex}
{$define ACME_bitconst:=TSha256DataBufferIndex_bits}
{$define ACME_high:=TSha256DataBufferIndex_high}
{$define ACME_bits:=9}
{$define ACME_packed_array:=TSha256DataBuffer}
{$define ACME_array_pointer:=PSha256DataBuffer}
{$Include ACME_Integer.inc}
扩展到
const TSha256IndexSliceMagic_bits = 17;
const TSha256IndexSliceMagic_high = pred(1 shl TSha256IndexSliceMagic_bits);
type TSha256IndexSliceMagic= 0..TSha256IndexSliceMagic_high;
const TSha256DataBufferIndex_bits = 9;
const TSha256DataBufferIndex_high = pred(1 shl TSha256DataBufferIndex_bits);
type TSha256DataBufferIndex= 0..TSha256DataBufferIndex_high;
type TSha256DataBuffer = packed array [TSha256DataBufferIndex] of byte;
type PSha256DataBuffer = ^TSha256DataBuffer;