Además, necesitaremos según el tipo:
- UNUSED: Un puntero a la siguiente celda sin usar. De esta manera mantenemos una lista simplemente enlazada de las celdas sin usar.
- EMPTY_LIT: La lista vacía no requiere ningún valor adicional.
- INT_LIT: Un literal entero requiere el valor entero que almacena.
- STRING_LIT: Un literal de cadena requiere la cadena que almacena.
- LAMBDA_VAL: Un valor de función definida por el usuario requiere tres cosas: el código a ejecutar, los parámetros que tiene la función y la clausura léxica del código. Usaremos una lista para agrupar el código con los parámetros por lo que sólo requeriremos dos valores.
- NATIVE_VAL: Un puntero a la función nativa.
- ENVIR_VAL: Un puntero a la tabla hash o árbol de búsqueda que relaciona los nombres de las variables con sus valores. Además, otro puntero a el entorno padre (si existe) donde se buscarán los nombres que no se encuentren en la tabla de éste.
- BOOL_VAL: El valor verdadero o falso del booleano.
- NAME_CODE: Un puntero a la cadena con el nombre de la variable.
- COMBINE_CODE: El operador y sus operandos en una lista.
- CONS_CTOR: La cabeza y el resto de la lista.
Con todas estos campos en la cabeza, la estructura de una celda queda así:
struct CELL { CELL_TYPE type; bool mark; //Garbage collection mark union { CELL* next_unused; //UNUSED int int_val; //INT_LIT bool bool_val; //BOOL_VAL STRING const* string_val; //STRING_LIT CELL* head; //CONS. CELL* code; //LAMBDA_VAL. The cell must be a CONS_CTOR with parameters and body NATIVE native; //NATIVE_VAL ENVIR_TABLE* envir_table; //ENVIR_VAL CELL* op; //COMBINE_CODE. The cell must be code (Any *_CODE type or CONS or EMPTY) }; union { CELL* tail; //CONS. Must be CONS or EMPTY. CELL* closure; //LAMBDA_VAL. The cell must be an environment (ENVIR_VAL) CELL* parent_envir; //ENVIR_VAL. The pointer may be NULL or an environment cell (ENVIR_VAL) CELL* operands; //COMBINE_CODE. The cell must be a list of code. }; };
La mayoría de los tipos de C++ que hemos usado han quedado por definir. En principio dependerán de la plataforma.
typedef std::wstring STRING; typedef std::wistream ISTREAM; typedef std::wostream OSTREAM; typedef std::map<STRING, CELL*> STRING_MAP; typedef std::map<CELL*, CELL*> ENVIR_TABLE; typedef std::deque<CELL> CELL_STORAGE; typedef CELL& (*NATIVE) (Script& script, CELL& args, CELL& envir);
En la siguiente entrada hablaremos con más tranquilidad de STRING_MAP y ENVIR_TABLE; en otra posterior hablaremos de CELL_STORAGE y, mucho después, de NATIVE, ISTREAM y OSTREAM.
0 comentarios:
Publicar un comentario