Metaprogramming: Difference between revisions

m
→‎{{header|Wren}}: Changed to Wren S/H
m (→‎{{header|Wren}}: Changed to Wren S/H)
 
(8 intermediate revisions by one other user not shown)
Line 343:
</syntaxhighlight>
<p>Note: the "Free_secure()" and "Str_init()" macros are preprocessed before entering the compile cycle.</p>
 
<p>Other interesting macros that can extend the C language are the "Assert" and "Exception" macros, which use the "hated GOTO":</p>
 
<syntaxhighlight lang="c">
#define Throw(_X_) if( !Is_ok ) { goto _X_; }
#define Exception(_H_) _H_: if( !Is_ok++ )
#define Assert(_X_,_Y_) if( !(_X_) ) { Is_ok=0; goto _Y_; }
</syntaxhighlight>
<p>Example:</p>
<syntaxhighlight lang="c">
#include <gadget/gadget.h>
LIB_GADGET_START
 
Main
int retVal=0;
Assert( Arg_count == 2, fail_input );
Get_arg_str( filename, 0 );
Get_arg_float( number, 1 );
 
Print "First argument (filename) = %s\n", filename;
Print "Second argument (a number) = %f\n", number;
 
Free secure filename;
 
Exception( fail_input ){
Msg_yellow("Use:\n ./prog <number>\n");
retVal=1;
}
Return( retVal );
</syntaxhighlight>
<p>There are also macros that, in combination with functions, allow you to extend the C language and simplify its programming:</p>
<syntaxhighlight lang="c">
/* declara un array vacío */
#define New_mt_array(_X_) \
MT_CELL *_X_ = NULL;\
Define_New_Array(_X_)\
_X_##_data.type = MULTI_TYPE;
....
/* acceso a celdas string */
#define sCell(_X_,...) CONCAT2(Cell_mtstr, COUNT_ARGUMENTS(__VA_ARGS__))(_X_, ##__VA_ARGS__)
 
#define Cell_mtstr1(_X_,ARG1) (_X_[ ARG1 ].value)
#define Cell_mtstr2(_X_,ARG1,ARG2) (_X_[ ( ARG1 ) * ( _X_##_data.cols ) + ( ARG2 ) ].value)
#define Cell_mtstr3(_X_,ARG1,ARG2,ARG3) (_X_[ ( ( ARG1 ) * ( _X_##_data.cols ) + ( ARG2 ) ) + \
( ARG3 ) * ( _X_##_data.cols * _X_##_data.rows ) ].value)
...
/* acceso a celdas long */
#define lCell(_X_,...) CONCAT2(Cell_mtlng, COUNT_ARGUMENTS(__VA_ARGS__))(_X_, ##__VA_ARGS__)
 
#define Cell_mtlng1(_X_,ARG1) *((long *)(_X_[ ARG1 ].value))
#define Cell_mtlng2(_X_,ARG1,ARG2) *((long *)(_X_[ ( ARG1 ) * ( _X_##_data.cols ) + ( ARG2 ) ].value))
#define Cell_mtlng3(_X_,ARG1,ARG2,ARG3) *((long *)(_X_[ ( ( ARG1 ) * ( _X_##_data.cols ) + ( ARG2 ) ) + \
( ARG3 ) * ( _X_##_data.cols * _X_##_data.rows ) ].value))
 
...
/* RANGOS para acceso iterado */
#define Range_for(_X_, ...) CONCAT2(Range_for, COUNT_ARGUMENTS(__VA_ARGS__))(_X_, ##__VA_ARGS__)
 
/* para un array 1D */
#define Range_for3(_X_,A1,A2,A3) \
_X_##_data.rowi=A1;_X_##_data.rowinc=A2;_X_##_data.rowe=A3;
 
/* para un array 2D */
#define Range_for6(_X_,A1,A2,A3,B1,B2,B3) \
_X_##_data.rowi=A1;_X_##_data.rowinc=A2;_X_##_data.rowe=A3; \
_X_##_data.coli=B1;_X_##_data.colinc=B2;_X_##_data.cole=B3;
....
</syntaxhighlight>
<p>Example:</p>
<syntaxhighlight lang="c">
#include <gadget/gadget.h>
 
LIB_GADGET_START
 
void Muestra_archivo_original();
 
Main
Assert (Exist_file("load_matrix.txt"), file_not_found);
 
/* recupero informacion del archivo para su apertura segura */
F_STAT dataFile = Stat_file("load_matrix.txt");
Assert (dataFile.is_matrix, file_not_matrixable) // tiene forma de matriz???
New multitype test;
/* The data range to be read is established.
It is possible to read only part of the file using these ranges. */
Range for test [0:1:dataFile.total_lines-1, 0:1:dataFile.max_tokens_per_line-1];
/* cargamos el array detectando números enteros como long */
test = Load_matrix_mt( pSDS(test), "load_matrix.txt", dataFile, DET_LONG);
/* modifica algunas cosas del archivo */
Let( $s-test[0,1], "Columna 1");
$l-test[2,1] = 1000;
$l-test[2,2] = 2000;
/* inserto filas */
/* preparo la fila a insertar */
New multitype nueva_fila;
sAppend_mt(nueva_fila,"fila 3.1"); /* sAppend_mt() and Append_mt() are macros */
Append_mt(nueva_fila,float,0.0);
Append_mt(nueva_fila,int,0);
Append_mt(nueva_fila,double,0.0);
Append_mt(nueva_fila,long, 0L);
/* insertamos la misma fila en el array, 3 veces */
test = Insert_row_mt(pSDS(test),pSDS(nueva_fila), 4);
test = Insert_row_mt(pSDS(test),pSDS(nueva_fila), 4);
test = Insert_row_mt(pSDS(test),pSDS(nueva_fila), 4);
Free multitype nueva_fila;
Print "\nGuardando archivo en \"save_matrix.txt\"...\n";
DEC_PREC = 20; /* establece precision decimal */
All range for test;
Save_matrix_mt(SDS(test), "save_matrix.txt" );
 
Free multitype test;
Print "\nArchivo original:\n";
Muestra_archivo_original();
Exception( file_not_found ){
Msg_red("File not found\n");
}
Exception( file_not_matrixable ){
Msg_red("File is not matrixable\n");
}
 
End
 
void Muestra_archivo_original(){
String csys;
csys = `cat load_matrix.txt`;
Print "\n%s\n", csys;
Free secure csys;
}
</syntaxhighlight>
<p>Note: "Range_for()", "sCell()", "lCell()", "v=`...`", and "New_mt_array()" macros are preprocessed before entering the compile cycle.</p>
<pre>GADGET has been designed to encapsulate the complicated (and basically utilitarian, that is, what will always be programmed in the same way) without losing the spirit of the C language (the possibility of working at a low level).
 
From Chile with love,
 
Mr Dalien.</pre>
 
=={{header|C sharp|C#}}==
Line 2,050 ⟶ 2,195:
=={{header|Wren}}==
Analogous to D's mixins, Wren has an optional Meta module which enables strings to be compiled to regular Wren code or expressions and inserted into the script. The D example looks like this in Wren.
<syntaxhighlight lang="ecmascriptwren">import "meta" for Meta
 
var genericClass = Fn.new { |cname, fname|
9,482

edits