




已阅读5页,还剩95页未读, 继续免费阅读
版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领
文档简介
第六章类型检查,内容,类型系统类型表达式的等价类型转换函数和运算符的重载多态函数一致化算法,静态检查(staticchecking),类型检查(typecheck)操作对象必须与操作符匹配:函数名相加控制流检查(flow-of-controlcheck)break必须退出while、for、switch唯一性检查(uniquenesscheck)对象(变量、标号)定义必须唯一名字关联检查(name-relatedcheck)相同名字在不同位置,类型检查,检查语法结构的类型与上下文匹配简单的类型检查两个类型的匹配代码生成要利用类型信息重载,多态,6.1类型系统,语法结构、类型、将类型赋予语法结构+,-,*的两个运算数均为整数,结果为整数array(0,9,integer)笛卡儿积:T1、T2为类型表达式,则T1T2为类型表达式,类型表达式(续),记录:与笛卡儿积的不同之处仅在于记录的域有名字。元组typedefstructintaddress;charlexeme15;row;rowtable101;类型表达式为:record(addressinteger)(lexemearray(0,15,char),类型表达式(续),指针:T为类型表达式,则pointer(T)为类型表达式,表示“指向类型为T的对象的指针”类型row*p;pointer(row)函数:数学上,一个集合“定义域”到另一个集合“值域”的映射。程序语言,定义域类型D到值域类型R的映射:DR。%运算符(intint)intint*f(chara,charb);(charchar)pointer(integer)不考虑函数返回数组、函数类型的情况(integerinteger)(integerinteger)可使用类型表达式变量,图表示类型表达式,(charchar)pointer(integer),6.1.2类型系统,typesystem:规则的集合规则将类型表达式赋予程序的不同部分类型检查程序:实现一个类型系统语法制导方式实现嵌入语义规则,6.1.2静态/动态检查,静态编译器进行动态运行时进行可靠类型系统,强类型语言编译器无type_error运行时无类型错误inta10,i;b=ai;需动态检查安全领域也涉及类型检查(缓冲溢出问题),6.1.4错误恢复,最低要求:报告类型错误位置错误处理应融入规则中错误修正比描述正确程序更困难根据错误的程序、处理缺失信息,来推测正确类型在变量使用之前无需定义它类型变量可用来处理这种问题,6.2一个简单的类型检查器,6.2.1一种简单语言用综合属性type保存类型表达式PD;EDD;D|id:TTchar|integer|arraynumofT|TEliteral|num|id|EmodE|EE|E基本类型:char、integer、type_error例CODESomeTypesExpressionskey:integer;array256ofchararray(1.256,char)keymod1999integerpointer(integer),翻译模式,PD;EDD;DDid:Taddtype(id.entry,T.type)TcharT.type=charTintegerT.type=integerTarraynumofTT.type=array(1.num.val,T.type)TTT.type=pointer(T.type)Did:T的规则在符号表保存标识符类型T.type由后几个产生式语义规则计算PD;E,D在E之前,保证在检查表达式类型之前类型已经保存入符号表,6.2.2表达式类型检查,EliteralE.type=charEnumE.type=integerEidE.type=lookup(id.entry)EE1modE2E.type=if(E1.type=integer)and(E2.type=integer)thenintegerelsetype_errorEE1E2E.type=if(E2.type=integer)and(E1.type=array(s,t)thentelsetype_errorEE1E.type=if(E1.type=pointer(t)thentelsetype_error可添加其他类型和运算,6.2.3语句的类型检查,赋值、条件、while无错误,void;错误,type_errorSid:=ES.type=if(lookup(id.entry)=E.type)thenvoidelsetype_errorSifEthenS1S.type=if(E.type=boolean)thenS1.typeelsetype_errorSwhileEdoS1S.type=if(E.type=boolean)thenS1.typeelsetype_errorSS1;S2S.type=if(S1.type=void)and(S2.type=void)thenvoidelsetype_error,6.2.4函数的类型检查,函数定义TT1T2T.type=T1.typeT2.type函数调用EE1(E2)E.type=if(E2.type=s)and(E1.type=st)thentelsetype_error多参数:T1,TnT1Tn更复杂例子:root:(realreal)realrealfunctionroot(functionf(real):real;x:real):real,6.3类型表达式的等价,两个类型表达式等价的精确定义?用类型表示方式可快速确定等价性结构等价和名字等价类型表达式的图表示不同叶结点为基本类型或类型名递归定义类型会导致回路,6.3.1类型表达式的结构等价,结构等价(structuralequivalence)相同的基本类型对子表达式施加的类型构造符相同两个类型表达式结构等价dag中对应相同结点有时要放松条件数组参数忽略界限等价性检查算法稍做修改,等价性检查算法,boolsequiv(s,t)if(s和t为相同基本类型)returntrue;elseif(s=array(s1,s2)andt=array(t1,t2)returnsequiv(s1,t1)andsequiv(s2,t2);elseif(s=s1s2andt=t1t2)returnsequiv(s1,t1)andsequiv(s2,t2);elseif(s=pointer(s1)andt=pointer(t1)returnsequiv(s1,t1);elseif(s=s1s2andt=t1t2)returnsequiv(s1,t1)andsequiv(s2,t2);elsereturnfalse;,例6.1:编码类型表达式,用二进制码表示类型和构造符节省内存,加速检测二进制码不同的类型表达式肯定不等价D.M.Ritchie,C编译器忽略数组界限和函数参数charfreturns(char)pointer(freturns(char)array(pointer(freturns(char),例6.1(续),构造符的编码pointer01array10freturns11基本类型编码boolean0000char0001integer0010real0011,例6.1(续),编码方法最右端四位二进制位表示基本类型它前面两位表示第一个构造符再前面两位表示第二个构造符类型表达式编码char0000000001freturns(char)0000110001pointer(freturns(char)0001110001array(pointer(freturns(char)1001110001,例6.1(续),加速等价性检查不同二进制串不可能表示相同类型不同类型可能表示为相同二进制串数组界限、函数参数记录的编码在类型表达式中记录作为基本类型用另一个二进制串编码它的域,6.3.2名字等价,typelink=cell;varnext:link;last:link;p:cell;q,r:cell;5个变量类型是否都相同?依赖实现允许类型表达式命名,但不允许回路名字等价:完全相同结构等价:名字被替换后完全相同,例6.2,变量类型表达式nextlinklastlinkppointer(cell)qpointer(cell)rpointer(cell)名字等价:next,last类型相同,p,q,r类型相同,p,next类型不同结构等价:5个变量类型都相同,例6.3,许多Pascal编译器会隐含地为每条标识符定义语句涉及到的类型关联一个类型名typelink=cell;np=cell;nqr=cell;varnext:link;last:link;p:np;q,r:nqr;名字等价:next,last类型相同,q,r类型相同,p,next,q类型不同,例6.3(续),实现方式构造类型图对基本类型和类型构造符创建新结点对新类型名创建叶结点,保存与类型表达式的链接名字等价相同结点,6.3.3回路问题,链表、树:递归定义实现:记录数据、指向同一记录类型的指针回路typelink=cell;cell=recordinfo:integer;next:link;end;,回路问题(续),将递归定义的类型名替换为类型表达式,类型图中会产生回路,例6.4C语言避免回路,对除记录之外的类型使用结构等价structcellintinfo;structcell*next;C语言要求类型名在使用前声明例外:未定义记录类型的指针回路:只可能是记录指针引起结构等价判定遇到记录类型停止:只有名字相同的记录才认为类型相同,6.4类型转换,x+i,x为实型,i为整型不同保存格式,不同加法指令转换为相同类型进行运算语言定义指定转换方法赋值:转换为左部类型表达式:intreal类型检查器完成转换操作的生成xiinttorealreal+类型转换与重载紧密相连,强制类型转换(coercion),编译器自动进行的隐含的类型转换一般要求:不能丢失信息显式(explicit)类型转换:程序员C:(float)10Pascal:ord(a)字符型整型chr(65)整型字符型常量类型转换编译时进行,提高性能forI:=1toNdoXI:=148.4NmsforI:=1toNdoXI:=1.05.4Nms,例6.5,EnumE.type=integerEnum.numE.type=realEidE.type=lookup(id.entry)EE1opE2E.type=if(E1.type=integer)and(E2.type=integer)thenintegerelseif(E1.type=integer)and(E2.type=real)thenrealelseif(E1.type=real)and(E2.type=integer)thenrealelseif(E1.type=real)and(E2.type=real)thenrealelsetype_error,lcc的类型,typedefstructtype*Type;structtypeintop;Typetype;intalign;intsize;unionSymbolsym;structunsignedoldstyle:1;Type*proto;f;u;Xtypex;,类型构造符(基本类型),子类型表达式(用链表保存类型表达式),类型构造,staticTypetype(intop,Typety,intsize,intalign,void*sym)unsignedh=(op(unsignedlong)ty3),函数类型和不完全数组类型无重复概念,总是创建新类型,重复类型检查,类型构造,NEW0(tn,PERM);tn-type.op=op;tn-type.type=ty;tn-type.size=size;tn-type.align=align;tn-type.u.sym=sym;tn-link=typetableh;typetableh=tn;return,指针,Typeptr(Typety)returntype(POINTER,ty,IR-ptrmetric.size,IR-ptrmetric.align,pointersym);Typederef(Typety)if(isptr(ty)ty=ty-type;elseerror(typeerror:%sn,pointerexpected);returnisenum(ty)?unqual(ty)-type:ty;,脱掉指针,数组,Typearray(Typety,intn,inta)assert(ty);if(isfunc(ty)error(illegaltypearrayof%tn,ty);returnarray(inttype,n,0);if(isarray(ty),不允许函数数组,数组的数组,低维必须大小已知,数组,elseif(nINT_MAX/ty-size)error(sizeofarrayof%texceeds%dbytesn,ty,INT_MAX);n=1;returntype(ARRAY,ty,n*ty-size,a?a:ty-align,NULL);,结构和联合,Typenewstruct(intop,char*tag)Symbolp;assert(tag);if(*tag=0)tag=stringd(genlabel(1);elseif(p=lookup(tag,types)!=NULL,创建一个结构类型,但只是一个空架子,结构和联合,p=install(tag,结构和联合,Fieldnewfield(char*name,Typety,Typefty)Fieldp,*q=,结构和联合,if(xref)/*omit*/if(ty-u.sym-u.s.ftab=NULL)/*omit*/ty-u.sym-u.s.ftab=table(NULL,level);/*omit*/install(name,结构和联合,staticTypestructdcl(intop)ty=newstruct(op,tag);fields(ty);staticvoidfields(Typety)p=newfield(id,ty,fty);,类型等价,inteqtype(Typety1,Typety2,intret)if(ty1=ty2)return1;if(ty1-op!=ty2-op)return0;switch(ty1-op)caseENUM:caseUNION:caseSTRUCT:caseUNSIGNED:caseINT:caseFLOAT:return0;casePOINTER:returneqtype(ty1-type,ty2-type,1);caseVOLATILE:caseCONST+VOLATILE:caseCONST:returneqtype(ty1-type,ty2-type,1);,类型等价,caseARRAY:if(eqtype(ty1-type,ty2-type,1)if(ty1-size=ty2-size)return1;if(ty1-size=0|ty2-size=0)returnret;return0;,类型等价,caseFUNCTION:if(eqtype(ty1-type,ty2-type,1)Type*p1=to,*p2=to;if(p1=p2)return1;if(p1,类型等价,elseif(variadic(p1?ty1:ty2)return0;if(p1=NULL)p1=p2;for(;*p1;p1+)Typety=unqual(*p1);if(promote(ty)!=(isenum(ty)?ty-type:ty)return0;return1;return0;assert(0);return0;,TinyC的类型检查,voidtypeCheck(TreeNode*syntaxTree)traverse(syntaxTree,nullProc,checkNode);staticvoidtraverse(TreeNode*t,void(*preProc)(TreeNode*),void(*postProc)(TreeNode*)if(t!=NULL)preProc(t);inti;for(i=0;ichildi,preProc,postProc);postProc(t);traverse(t-sibling,preProc,postProc);,TinyC的类型检查,staticvoidcheckNode(TreeNode*t)switch(t-nodekind)caseExpK:switch(t-kind.exp)caseOpK:if(t-child0-type!=Integer)|(t-child1-type!=Integer)typeError(t,Opappliedtonon-integer);if(t-attr.op=EQ)|(t-attr.op=LT)t-type=Boolean;elset-type=Integer;break;caseConstK:caseIdK:t-type=Integer;break;,TinyC的类型检查,default:break;break;caseStmtK:switch(t-kind.stmt)caseIfK:if(t-child0-type=Integer)typeError(t-child0,iftestisnotBoolean);break;caseAssignK:if(t-child0-type!=Integer)typeError(t-child0,assignmentofnon-integervalue);break;,TinyC的类型检查,caseWriteK:if(t-child0-type!=Integer)typeError(t-child0,writeofnon-integervalue);break;caseRepeatK:if(t-child1-type=Integer)typeError(t-child1,repeattestisnotBoolean);break;default:break;break;default:break;,6.5函数和操作符重载,重载(overloaded)符号:根据上下文,具有不同的意义+:整型加法,浮点型加法A(I):数组A的第I个元素,以参数I调用A,将I转换为类型A的显式类型转换重载的解析(resolved):在某个特定上下文,确定符号的唯一意义1+2:+为整型加法运算符识别,operatoridentification,6.5.1子表达式可能类型集合,例6.6Ada允许对乘法运算符“*”进行重载function“*”(i,j:integer)returncomplex;function“*”(x,y:complex)returncomplex;*具有三种可能类型integerintegerintegerintegerintegercomplexcomplexcomplexcomplex2*(3*5)3*5类型1z*(3*5),z为复数类型3*5类型2,可能类型集合情况的处理,EidE.types=lookup(id.entry)EE1(E2)E.types=t|E2.types中存在s使得st属于E1.types单一类型运算类型集合运算,例6.7,6.5.2确定唯一类型,完整表达式须有唯一类型确定每个子表达式的唯一类型,或type_error自顶向下E.types中每个类型t均为可行(feasible)类型确定E中重载标识符的类型,某种情况下,E的类型为t对标识符成立,id.types中类型均可行归纳法:E为E1(E2),s为E2可行类型,st为E1可行类型,因此t为E可行类型,确定唯一类型的语义规则,EEE.types=E.typesE.unique=ifE.types=tthentelsetype_errorE.code=E.codeEidE.types=lookup(id.entry)E.code=gen(id.lexeme:E.unique)EE1(E2)E.types=s|E2.types中存在s使得ss属于E1.typest=E.uniqueS=s|sE2.typesandstE1.typesE2.unique=ifS=sthenselsetype_errorE1.unique=ifS=sthenstelsetype_errorE.code=E1.code|E2.code|gen(apply:E.unique),6.6多态(polymorphic)函数,普通函数:参数类型固定多态函数:不同调用参数可为不同类型某些内置操作符多态操作符数组索引符,函数调用符(),指针操作符cell=recordinfo:integer;next:linkend;functionlength(lptr:link):integer;varlen:integer;beginlen:=0;whilelptrnildobeginlen:=len+1;lptr:=lptr.next;end;length:=lenend;,求任何类型列表长度的ML程序,funlength(lptr)=ifnull(lptr)then0elselength(tl(lptr)+1;可应用于任何类型的列表length(“sun”,“mon”,“tue”);length(10,9,8);,递归函数,列表为空?,列表剩余部分,6.6.2类型变量,a,b,,表示未知类型重要应用:不要求标识符先声明后使用的语言中,检查标识符使用的一致性类型变量表示未声明标识符的类型若类型变量发生变化,不一致!若一直未变化,一致!同时得到标识符类型类型推断,typeinference根据语言结构的使用方式判定其类型,例6.8,typelink=cell;proceduremlist(lptr:link;procedurep);beginwhilelptrnildobeginp(lptr);lptr:=lptr.nextendend;p:参数情况未知,不完整的过程类型由p(lptr)p参数为link类型,p的类型为linkvoid其他使用方式均会导致type_error,例6.9,functionderef(p);beginreturnp;end;扫描第一行,p的类型未知,用b表示第三行,应作用于指针,因此p为某未知基本类型a的指针类型,b=pointer(a)因此函数deref类型为:pointer(a)a,6.6.3包含多态函数的语言,用表示“对所有类型”deref类型的精确描述:length:list(integer)integerlist(list(char)integer:全称量词(universalquantifier)它所施用的类型变量称为由它约束(bound),文法定义,PD;EDD;D|id:QQtype_varible.Q|TTTT|TT|unary_constructor(T)|basic_type|type_varible|(T)EE(E)|E,E|id程序例:deref:q:pointer(pointer(integer);deref(deref(q),多态函数类型检查,每个结点两个标签:子表达式和类型表达式下标o:外层deref,i:内存deref,类型检查规则的特点,不同位置出现的同一多态函数可具有不同类型的参数。derefo参数为二重指针,而derefi的参数为一重指针。关键在于的解释,对不同deref,约束的类型变量a所代表的意义是不同的。对多态函数的每次出现,都赋予不同的类型变量,而不再使用上例中用ao、ai分别对应外层和内层deref,类型检查规则的特点(二),类型表达式中存在变量,因此要重新考虑类型等价的概念类型为ss的函数E1施用于类型为t的E2,仅判定s和t是否等价是不够的,要对它们进行“一致化”(unify)适当替换类型变量,检查是否有可能达到结构等价上例:将ai替换为pointer(integer),则pointer(ai)与pointer(pointer(integer)等价,类型检查规则的特点(三),需要某种机制记录一致化的影响一个类型变量可出现在表达式的多个位置若s和s的一致化使得变量a表示类型t,则在整个类型表达式中,它都应表示t上例:ai作用域为derefi(q),因此可用来一致化derefi和q而ao为不同类型变量,因此表示不同类型不违反本规则,6.6.4代换,实例和合一,变量表示实际类型的形式化定义类型变量类型表达式的映射,称为替换,substitutionsubst(t:type_expression):type_expression/利用代换(映射)S将类型表达式t中变量代换if(t为基本类型)returnt;elseif(t为类型变量)returnS(t);elseif(t为t1t2)returnsubst(t1)subst(t2);S(t)表示代换t的类型表达式,称为t的实例,instance若无法代换,S(a)=a,恒等映射,例6.10,st表示s是t的一个实例pointer(integer)pointer(a)pointer(real)pointer(a)integerintegeraapointer(a)bab不是实例的情况integerrealintegerrealaaintegeraaa,合一方法,类型表达式t1和t2能合一的条件存在代换S,S(t1)=S(t2)最一般的合一代换,mostgeneralunifier最少变量约束的代换类型表达式t1和t2的最一般的合一代换是一个代换S,它满足以下条件S(t1)=S(t2)对任何其他代换S,S(t1)=S(t2),S是S的一个实例,即,对任意t,S(t)是S(t)的一个实例,6.6.5多态函数类型检查,检查规则由下列对类型图的操作构成fresh(t)将类型表达式t中约束变量代换为新变量,返回代换后类型表达式结点指针消除unify(m,n)将结点m、n表示的类型表达式合一,会修改、保存对应的代换。若失败,则整个类型检查过程失败图的创建仍可用mkleaf、mknode完成每个类型变量创建不同结点,unify操作,合一、代换基于图论的方法m、n为类型图结点,分别表示表达式e、f,若S(e)=S(f),称m、n在代换S下等价求最一般的合一代换转化为在S下必须等价的结点的集合划分问题类型表达式等价根必须等价m、n等价表示相同操作且孩子结点等价,类型检查规则,EE1(E2)p=mkleaf(newtypevar);unify(E1.type,mknode(,E2.type,p);E.type=p;EE1,E2E.type=mknode(,E1.type,E2.type);EidE.type=fresh(id.type);E1.type=a,E2.type=b,都是类型变量前者是函数,寻求两者等价,必有类型变量g,使得a=bg,例,表达式类型代换qpointer(pointer(integer)derefipointer(ai)aiderefi(q)pointer(integer)ai=pointer(integer)derefopointer(ao)aoderefo(derefi(q)integerao=integer,例6.11,例6.11(续),derefi的合一过程,例6.12ML语言多态函数检查,funid0(id1,idk)=E;id0:函数名,id1,idk:参数,E遵从前面定义的用于多态函数类型检查的文法,其中的标识符只可能是函数名、参数或内置函数方法:例6.9方法的形式化为函数名和参数创建新类型变量多态函数的类型变量由约束检查id0(id1,idk)和E类型是否匹配若成功,则推断出函数类型,例6.12(续),funlength(lptr)=ifnull(lptr)then0elselength(tl(lptr)+1;类型变量:lengthb,lptrg为匹配函数体:b=按多态函数类型检查语言重写程序length:b;lptr:g;if:,例6.12(续),null:tl:0:integer;1:integer;+:match:match(length(lptr),if(null(lptr),0,length(tl(lptr)+1),检查length(lptr)与函数体匹配,例6.12(续),表达式:lptr:length:length(lptr):lptr:null:null(lptr):0:lptr:tl:tl(lptr):,类型gbdglist(an)booleanbooleanintegerlist(an)list(at)list(at)list(an),替换b=gdg=list(an)at=an,length参数为lptrg返回类型为d,null参数类型为list(an)lptr类型g=list(an)length类型为list(an)d,例6.12(续),表达式:length:length(tl(lptr):1:+:length(tl(lptr)+1:if:if():match:match():,类型list(an)ddintegerintegerintegerintegerintegerbooleanaiaiaiintegeramamaminteger,替换d=integerai=integeram=integer,length的返回类型,因此d=integer,an最终未被替代,length类型为,6.7合一算法,合一:类型表达式e、f通过变量代换,是否可达到类型等价特殊情况:等价性检查,无变量本节算法适用类型图有回路情况算法寻找最一般的合一代换S,例6.13,e、f:两个合一代换S,S:xS(x)S(x)a1a3a1a2a2a1a3a3a1a4a2a1a5list(a2)list(a1)代换结果:,最一般的合一代换S(e)是S(e)的实例,反之不成立,算法思想,用树表示表达式S(e)的结点数目可能与e、f的结点数目呈指数关系图表示图论方法:在最一般的合一代换下必须等价的结点,进行集合划分,算法6.1合一算法,输入:一个类型图和要进行合一的结点m、n输出:若一致,返回true;否则,返回false。本算法的函数可修改为前面给出的多态函数类型检查规则所需的unify函数方法:结点用上图所示记录实现set域维护等价结点集合每个等价类选出一个代表结点set域为空指针等价类内其他结点指向代表
温馨提示
- 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
- 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
- 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
- 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
- 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
- 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
- 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。
最新文档
- 临床医学基础试题及答案回顾
- 民用航空器维修行业前景试题及答案
- 2025年入团考试专题试题及答案
- 2025年注册会计师《会计》全真模拟试题及答案解析
- 时效性拓展的高级会计试题及答案
- 会计实务中新技术的运用及试题答案
- 多维度分析中级会计试题及答案
- 民用航空器维修人员考试的行业展望及试题及答案启发
- 2025年建造师考试通过秘籍和试题及答案
- 2025年消防环境评估试题及答案
- 计划生育选择试题及答案
- 法律文化-形考作业3-国开(ZJ)-参考资料
- 家校共育“心”模式:青少年心理健康教育家长会
- 2025届东北三省四市高三第二次联考英语试卷含答案
- 2025-2030中国振动监测系统行业市场发展趋势与前景展望战略研究报告
- 《中华茶艺文化》课件
- 华为系统面试题及答案
- 主题班会:高中男女生正常交往课件
- 2025年第33批 欧盟REACH SVHC高度关注物质清单247项
- 漳州市城市规划管理技术规定
- 机械工程设备维护与保养手册
评论
0/150
提交评论