📄 mal_type.mx
字号:
@' The contents of this file are subject to the MonetDB Public License@' Version 1.1 (the "License"); you may not use this file except in@' compliance with the License. You may obtain a copy of the License at@' http://monetdb.cwi.nl/Legal/MonetDBLicense-1.1.html@'@' Software distributed under the License is distributed on an "AS IS"@' basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See the@' License for the specific language governing rights and limitations@' under the License.@'@' The Original Code is the MonetDB Database System.@'@' The Initial Developer of the Original Code is CWI.@' Portions created by CWI are Copyright (C) 1997-2007 CWI.@' All Rights Reserved.@a M. Kersten@v 0.0@+ Type implementationThe MAL type module overloads the atom structure managed in the GDKlibrary. For the time being, we assume GDK to support at most 127 differentatomic types. Type composition is limited to at most two builtin types to forma BAT. Furthermore, the polymorphic type @sc{any} can be qualifiedwith a type variable index @sc{any$I}, where I is a digit (1-9). Beware, the TYPE_any is a speudo type known within MAL only.@{Within the MAL layer types are encoded in 32-bit integers usingbit stuffing to save some space.The integer contains the following fields:anyHeadIndex (bit 25-22), anyTailIndex (bit 21-18),batType (bit 17) headType (16-9) and tailType(8-0)This encoding scheme permits a limited number of different bat types.@h#ifndef MAL_TYPE_H#define MAL_TYPE_H#include "mal.h"/* #define DEBUG_MAL_TYPE 1 */typedef int malType;#define malVARG " malVARG"#define TMPMARKER '_'#define REFMARKER 'X'#define newBatType(H,T) (1<<16 | (((H & 0377) <<8) | (T & 0377) ))#define newColType(T) (1<<25 | (((TYPE_void & 0377) <<8) | (T & 0377) ))#define getHeadType(X) ((X>>8) & 0377 )#define getTailType(X) ((X) & 0377 )#define isaBatType(X) ((1<<16) & (X) && (X)!= TYPE_any)#define setAnyHeadIndex(X,I) X |= ((I & 017)<<22);#define setAnyTailIndex(X,I) X |= ((I & 017)<<18);#define isAnyExpression(X) ((X) >> 17)#define isPolymorphic(X) (((X) >> 17) || (X)== TYPE_any)#define isPolyType(X) (isAnyExpression(X) && (getHeadIndex(X)>0 ||getTailIndex(X)>0))#define getHeadIndex(X) (((X)>>22) & 017)#define getTailIndex(X) (((X)>>18) & 017)@-The symbol/instruction kinds are introduced here instead of reusing the defines derived from the parser to avoid a loop in the define-structure.@h#define RAISEsymbol 21 /* flow of control modifiers */#define CATCHsymbol 22#define RETURNsymbol 23#define BARRIERsymbol 24#define REDOsymbol 25#define LEAVEsymbol 26#define YIELDsymbol 27#define EXITsymbol 29#define ASSIGNsymbol 40 /* interpreter entry points */#define ENDsymbol 41#define NOOPsymbol 43 /* no operation required */#define COMMANDsymbol 61 /* these tokens should be the last group !! */#define FUNCTIONsymbol 62 /* the designate the signature start */#define FACTORYsymbol 63 /* the co-routine infrastructure */#define PATTERNsymbol 64 /* the MAL self-reflection commands */#define FCNcall 50 /* internal symbols */#define FACcall 51#define CMDcall 52#define THRDcall 53#define PATcall 54 /* pattern call */#define REMsymbol 99 /* commentary to be retained */mal_export str getTypeName(malType tpe);mal_export malType coercion(malType t1, malType t2);mal_export int getTypeIndex(str nme, int len, int deftpe);mal_export malType reverseBatType(malType v);mal_export malType malAnyBatType(malType t1, malType t2);mal_export int idcmp(str n, str m);mal_export str newTmpName(char tag, int i);mal_export int isTmpName(str n);mal_export int isTypeName(str n);mal_export int isIdentifier(str s);mal_export int findGDKtype(int type); /* used in src/mal/mal_interpreter.c */#endif /* MAL_TYPE_H */@-At any point we should be able to construct an ascii representation ofthe type descriptor. Including the variable references.@c#include "mal_config.h"#include "mal_type.h"strgetTypeName(malType tpe){ char buf[PATHLENGTH], *s; int l = PATHLENGTH, k;#ifdef DEBUG_MAL_TYPE stream_printf(GDKout, "maltype: %d %d %d", tpe, getHeadType(tpe), getTailType(tpe)); stream_printf(GDKout, " [%d,%d]", getHeadIndex(tpe), getTailIndex(tpe)); stream_printf(GDKout, " : %s\n", (isaBatType(tpe) ? "bat" : ""));#endif if (tpe == TYPE_any) return GDKstrdup("any"); if (isaBatType(tpe)) { k = getHeadIndex(tpe); if (k) snprintf(buf, l, "bat[:any%c%d,", TMPMARKER, k); else if (getHeadType(tpe) == TYPE_any) snprintf(buf, l, "bat[:any,"); else snprintf(buf, l, "bat[:%s,", ATOMname(getHeadType(tpe))); l -= strlen(buf); s = buf + strlen(buf); k = getTailIndex(tpe); if (k) snprintf(s, l, ":any%c%d]",TMPMARKER, k); else if (getTailType(tpe) == TYPE_any) snprintf(s, l, ":any]"); else snprintf(s, l, ":%s]", ATOMname(getTailType(tpe)));#ifdef DEBUG_MAL_TYPE stream_printf(GDKout, "%s\n", buf);#endif return GDKstrdup(buf); } if (isAnyExpression(tpe)) { strncpy(buf, "any", 4); if (isAnyExpression(tpe)) snprintf(buf + 3, PATHLENGTH - 3, "%c%d", TMPMARKER, getTailIndex(tpe)); return GDKstrdup(buf); }#ifdef DEBUG_MAL_TYPE stream_printf(GDKout, "Rely on GDK atom %s\n", ATOMname(tpe));#endif return GDKstrdup(ATOMname(tpe));}@+ Type coercionThe coercion scheme below should at some point be added to the GDK kernel.@cint gdkCoercionTable[12][12] = {/* void bit chr sht bat int oid ptr flt dbl lng str *//* void */ {TYPE_void, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_str},/* bit */ {TYPE_any, TYPE_bit, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_str},/* chr */ {TYPE_any, TYPE_any, TYPE_chr, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_str},/* sht */ {TYPE_any, TYPE_any, TYPE_any, TYPE_sht, TYPE_any, TYPE_int, TYPE_any, TYPE_any, TYPE_flt, TYPE_dbl, TYPE_lng, TYPE_str},/* bat */ {TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_bat, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_str},/* int */ {TYPE_any, TYPE_any, TYPE_any, TYPE_int, TYPE_any, TYPE_int, TYPE_any, TYPE_any, TYPE_flt, TYPE_dbl, TYPE_lng, TYPE_str},/* oid */ {TYPE_any, TYPE_any, TYPE_any, TYPE_int, TYPE_any, TYPE_int, TYPE_oid, TYPE_any, TYPE_any, TYPE_int, TYPE_any, TYPE_str},/* ptr */ {TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_ptr, TYPE_any, TYPE_any, TYPE_any, TYPE_str},/* flt */ {TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_flt, TYPE_dbl, TYPE_any, TYPE_str},/* dbl */ {TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_any, TYPE_dbl, TYPE_dbl, TYPE_any, TYPE_str},/* lng */ {TYPE_any, TYPE_any, TYPE_any, TYPE_lng, TYPE_any, TYPE_lng, TYPE_any, TYPE_any, TYPE_flt, TYPE_dbl, TYPE_lng, TYPE_str},/* str */ {TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str, TYPE_str}};@-Coercion is defined in terms of malType structures, which meansthat we have to be prepared to deal with type variables as well.[This function is not used ]@cmalTypecoercion(malType t1, malType t2){ if (t1 == t2) return t1; if (t1 < 0 || t1 >= TYPE_str) return t1; if (t2 < 0 || t2 >= TYPE_str) return t2; return gdkCoercionTable[(int) t1][(int) t2];}@+ Some utilities In many places we need a confirmed type identifier.GDK returns the next available index when it can not find the type.This is not sufficient here, an error message may have to be generated.It is assumed that the type table does not change in the mean time.Use the information that identifiers are at least one characterand are terminated by a null to speedup comparison@cINLINE intidcmp(str n, str m){ if (* n == * m) return strcmp(n, m); return -1;}@-The ATOMindex routine is pretty slow, because it performs alinear search through the type table. This code should actuallybe integrated with the kernel. @c#define qt(x) (nme[1]==x[1] && nme[2]==x[2] )intgetTypeIndex(str nme, int len, int deftype){ int i,k=0; char old=0; if (len == 3) switch (*nme) { case 'a': if (qt("any")) return TYPE_any; break; case 'b': if (qt("bat")) return TYPE_bat; if (qt("bit")) return TYPE_bit; if (qt("bte")) return TYPE_bte; break; case 'c': if (qt("chr")) return TYPE_chr; break; case 'd': if (qt("dbl")) return TYPE_dbl; break; case 'i': if (qt("int")) return TYPE_int; break; case 'f': if (qt("flt")) return TYPE_flt; break; case 'l': if (qt("lng")) return TYPE_lng; break; case 'o': if (qt("oid")) return TYPE_oid; break; case 'p': if (qt("ptr")) return TYPE_ptr; break; case 's': if (qt("str")) return TYPE_str; if (qt("sht")) return TYPE_sht; break; case 'w': if (qt("wrd")) return TYPE_wrd; break; } if( nme[0]=='v' && qt("voi") && nme[3] == 'd') return TYPE_void; if( len > 0 ){ old= nme[k = MIN(IDLENGTH, len)]; nme[k] = 0; } for(i= TYPE_str; i< GDKatomcnt; i++) if( BATatoms[i].name[0]==nme[0] && strcmp(nme,BATatoms[i].name)==0) break; if( len > 0) nme[k]=old; /*stream_printf(GDKout,"getTypeIndex %s %d %d\n",nme,i, GDKatomcnt); */ if (i == GDKatomcnt) i = deftype; return i;}INLINE intfindGDKtype(int type){ if (type == TYPE_any || type== TYPE_void) return TYPE_void; if (isaBatType(type)) return TYPE_bat; return ATOMtype(type);}strnewTmpName(char tag, int i){ char buf[PATHLENGTH]; snprintf(buf, PATHLENGTH, "%c%d", tag, i); return GDKstrdup(buf);}INLINE intisTmpName(str n){ return n && *n == TMPMARKER;}intisTypeName(str n){ int i = ATOMindex(n); return i >= 0;}intisIdentifier(str s){ if (!isalpha((int) *s)) return -1; for (; s && *s; s++) if (!isalnum((int) *s) && *s != '_') return -1; return 0;}@}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -