转自: http://www.cnblogs.com/BlackWalnut/p/4559717.html
这一章,就虎书而言,理论知识点是及其少的,就介绍了为什么要有一个中间表示树。看下面这张图就能理解为什么了。
由以上可以知道,中间表达式树可以看成是一种简化过的汇编语言组成的树。在这个阶段,我们已经抛弃了所有的变量名称和函数名称,使用标号以及变量以及临时变量(temp_newtemp)来代替来代替。,而且所有的变量都存储在frame中,也就是说,我们是使用frame来分割代码的,一个frame就代表了一个函数。
这章的代码量却是挺多的。在写代码之前,如果不懂整个代码的布局,是很难了解书上那写代码是对应那些功能,以及书上没有给出的代码,我应该这么完善。那么,我就我自己的理解来说一下到目前为止(翻译成中间表示树以后,编译器的前端就算基本完成了),整个代码的布局是什么样。
首先我们从外部读取tiger语言编写的源代码,经过由flex和bison生成的lex.yy.cpp tiger.tab.cpp tiger.tab.h的处理(词法分析,语法分析),生成了抽象语法树,这个语法树的数据结构是在absyn,table,symbol这些文件中定义的。然后我们要抽象语法树转化为中间表示树,这个转化过程都是由 semant 文件中的函数完成(语义分析)。semant主要完成了两个任务:对类型检测(类型检测)以及生成中间表达树(中间表达树)。类型检测过程中使用到了evn,table,symbol,type中定义的一些东西。而转化为中间表示树使用了translate文件中的函数,之所以使用这translate文件 ,是为了将树的具体构建过程和语义分析过程分离,这样如果想要用另一种方式表示中间表示树,可以不动原来semant的代码。因为在semant定义的函数只能看到以Tr_开头的函数,而看不到关于树的任何信息。一棵中间表示树是由frame(F开头),tree(T开头)两部文件分组成的,并且这两部分只被translate使用。
值得注意的是,前一章我们介绍的活动记录的时候提到,一个活动记录里面包含局部变量,临时变量,寄存器,静态链等信息。但是在frame里面,我们没有记录临时变量。临时变量的信息是在中间表示树中记录的(就是调用temp_newtemp),并且在生成frame的时候,我们也并不是真的取内存中分配一块地址然后记录他的位置,我们只是记录一个变量的相对位移。对于寄存器来说,frame中可以申请无数个寄存器。但是在最终翻译成汇编的时候,我们会根据实际寄存器的数量,将没有办法得到的寄存器的变量放入内存中。而temp_newlabel则是生成各种标签,因为汇编语言中是可以直接goto到一个标签位置的。
也就是说,frame中记录在任何目标机器上都要用到的信息,这个信息是一个理想化的信息,在最终翻译成代码的时候,还有根据机器的不同来进行调整。
也要注意到,中间代码多是面向汇编的,所以在translate中将抽象与法树对应的语句和表达式(还是高级语言)转换成中间语法树的节点(面向汇编)。
知道了以上信息,剩下的就是根据具体的要求来写相应的代码了。可以看出,tiger作者给出的代码框架还是很值得学习的。
好了,一下就是一部分关键代码。
/* * tree.h - Definitions for intermediate representation (IR) trees. * */ #ifndef TREE_H_ #define TREE_H_ typedef struct T_stm_ *T_stm; typedef struct T_exp_ *T_exp; typedef struct T_expList_ *T_expList; struct T_expList_ {T_exp head; T_expList tail;}; typedef struct T_stmList_ *T_stmList; struct T_stmList_ {T_stm head; T_stmList tail;}; typedef enum {T_plus, T_minus, T_mul, T_div, T_and, T_or, T_lshift, T_rshift, T_arshift, T_xor} T_binOp ; typedef enum {T_eq, T_ne, T_lt, T_gt, T_le, T_ge, T_ult, T_ule, T_ugt, T_uge} T_relOp; struct T_stm_ {enum {T_SEQ, T_LABEL, T_JUMP, T_CJUMP, T_MOVE, T_EXP} kind; union {struct {T_stm left, right;} SEQ; Temp_label LABEL; struct {T_exp exp; Temp_labelList jumps;} JUMP; struct {T_relOp op; T_exp left, right; Temp_label trues, falses;} CJUMP; struct {T_exp dst, src;} MOVE; T_exp EXP; } u; }; struct T_exp_ {enum {T_BINOP, T_MEM, T_TEMP, T_ESEQ, T_NAME, T_CONST, T_CALL} kind; union {struct {T_binOp op; T_exp left, right;} BINOP; T_exp MEM; Temp_temp TEMP; struct {T_stm stm; T_exp exp;} ESEQ; Temp_label NAME; int CONST; struct {T_exp fun; T_expList args;} CALL; } u; }; T_expList T_ExpList (T_exp head, T_expList tail); T_stmList T_StmList (T_stm head, T_stmList tail); T_stm T_Seq(T_stm left, T_stm right); T_stm T_Label(Temp_label); T_stm T_Jump(T_exp exp, Temp_labelList labels); T_stm T_Cjump(T_relOp op, T_exp left, T_exp right, Temp_label trues, Temp_label falses); T_stm T_Move(T_exp, T_exp); T_stm T_Exp(T_exp); T_exp T_Binop(T_binOp, T_exp, T_exp); T_exp T_Mem(T_exp); T_exp T_Temp(Temp_temp); T_exp T_Eseq(T_stm, T_exp); T_exp T_Name(Temp_label); T_exp T_Const(int); T_exp T_Call(T_exp, T_expList); T_relOp T_notRel(T_relOp); /* a op b == not(a notRel(op) b) */ T_relOp T_commute(T_relOp); /* a op b == b commute(op) a */ #endif
#include#include "util.h" #include "symbol.h" #include "temp.h" #include "tree.h" T_expList T_ExpList(T_exp head, T_expList tail) {T_expList p = (T_expList) checked_malloc (sizeof *p); p->head=head; p->tail=tail; return p; } T_stmList T_StmList(T_stm head, T_stmList tail) {T_stmList p = (T_stmList) checked_malloc (sizeof *p); p->head=head; p->tail=tail; return p; } T_stm T_Seq(T_stm left, T_stm right) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_SEQ; p->u.SEQ.left=left; p->u.SEQ.right=right; return p; } T_stm T_Label(Temp_label label) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_LABEL; p->u.LABEL=label; return p; } T_stm T_Jump(T_exp exp, Temp_labelList labels) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_JUMP; p->u.JUMP.exp=exp; p->u.JUMP.jumps=labels; return p; } T_stm T_Cjump(T_relOp op, T_exp left, T_exp right, Temp_label trues, Temp_label falses) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_CJUMP; p->u.CJUMP.op=op; p->u.CJUMP.left=left; p->u.CJUMP.right=right; p->u.CJUMP.trues=trues; p->u.CJUMP.falses=falses; return p; } T_stm T_Move(T_exp dst, T_exp src) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_MOVE; p->u.MOVE.dst=dst; p->u.MOVE.src=src; return p; } T_stm T_Exp(T_exp exp) {T_stm p = (T_stm) checked_malloc(sizeof *p); p->kind= T_stm_::T_EXP; p->u.EXP=exp; return p; } T_exp T_Binop(T_binOp op, T_exp left, T_exp right) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_BINOP; p->u.BINOP.op=op; p->u.BINOP.left=left; p->u.BINOP.right=right; return p; } T_exp T_Mem(T_exp exp) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_MEM; p->u.MEM=exp; return p; } T_exp T_Temp(Temp_temp temp) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_TEMP; p->u.TEMP=temp; return p; } T_exp T_Eseq(T_stm stm, T_exp exp) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_ESEQ; p->u.ESEQ.stm=stm; p->u.ESEQ.exp=exp; return p; } T_exp T_Name(Temp_label name) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_NAME; p->u.NAME=name; return p; } T_exp T_Const(int consti) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_CONST; p->u.CONST=consti; return p; } T_exp T_Call(T_exp fun, T_expList args) {T_exp p = (T_exp) checked_malloc(sizeof *p); p->kind= T_exp_::T_CALL; p->u.CALL.fun=fun; p->u.CALL.args=args; return p; } T_relOp T_notRel(T_relOp r) { switch(r) {case T_eq: return T_ne; case T_ne: return T_eq; case T_lt: return T_ge; case T_ge: return T_lt; case T_gt: return T_le; case T_le: return T_gt; case T_ult: return T_uge; case T_uge: return T_ult; case T_ule: return T_ugt ; case T_ugt: return T_ule; } assert(0); } T_relOp T_commute(T_relOp r) {switch(r) { case T_eq: return T_eq; case T_ne: return T_ne; case T_lt: return T_gt; case T_ge: return T_le; case T_gt: return T_lt ; case T_le: return T_ge; case T_ult: return T_ugt; case T_uge: return T_ule; case T_ule: return T_uge ; case T_ugt: return T_ult; } assert(0); }
#ifndef TRANSLATE_H_ #define TRANSLATE_H_ #include "frame.h" #include "absyn.h" //frame œ‡πÿ typedef struct Tr_level_ * Tr_level ; typedef struct Tr_accesslist_ * Tr_accesslist ; typedef struct Tr_access_ * Tr_access ; struct Tr_accesslist_ { Tr_access head ; Tr_accesslist tial ; }; struct Tr_level_ { Tr_level parent ; F_frame frame; }; //≤„µƒ◊˜”√ «Œ™¡À±£¥Êæ≤è¡¥ struct Tr_access_ { Tr_level level ; F_access access ; };//º«¬º¡À“ª∏ˆ≤„∫Õ≤„÷–µƒŒª÷√ ’‚—˘ ∑Ω±„“ª∏ˆ«∂Ã◊≤„»•≤È—Ø“˝”√µƒÕ‚≤ø±‰¡ø À¸ «E_varEntry÷–µƒ“ª∏ˆ±‰¡ø //frame œ‡πÿ Tr_accesslist Tr_Accesslist(Tr_access head , Tr_accesslist tial) ; Tr_access Tr_Access(Tr_level level , F_access access ) ; Tr_level Tr_outermorst() ; Tr_level Tr_newLevel(Tr_level parent , Temp_label name , U_boolList formals ) ; Tr_accesslist Tr_formals(Tr_level level) ; Tr_access Tr_allocLocal(Tr_level level , bool escape ) ; void Tr_ClearAcces(Tr_accesslist list) ; //Ω´list Õ∑≈ µ´ « ≤ª Õ∑≈∆‰÷–µƒhead // IR Tree œ‡πÿ #define GetExpEx Tr_exp_::Tr_ex #define GetExpNx Tr_exp_::Tr_nx #define GetExpCx Tr_exp_::Tr_cx typedef struct Tr_exp_* Tr_exp ; typedef struct Tr_expList_ * Tr_expList ; typedef struct patchList_ * patchList ; struct Cx { patchList trues ; patchList falses ; T_stm stm ; }; struct patchList_ { Temp_label *head ; patchList tail ; }; struct Tr_exp_ { enum{Tr_ex , Tr_nx , Tr_cx } kind; union { T_exp ex ; T_stm nx ; Cx cx ; }u; }; struct Tr_expList_ { Tr_exp head ; Tr_expList tail ; }; //IR Treeœ‡πÿ Tr_exp Tr_Ex(T_exp exp ) ; Tr_exp Tr_Nx(T_stm stm ) ; Tr_exp Tr_Cx(patchList trues , patchList falses , T_stm stm ) ; T_exp Tr_unEx(Tr_exp exp) ; T_stm Tr_unNx(Tr_exp exp) ; Cx Tr_unCx(Tr_exp exp) ; patchList PatchList(Temp_label *head , patchList patchlist ) ; void doPatch(patchList patchlist , Temp_label label) ; Tr_expList Tr_ExpList(Tr_exp head , Tr_expList tail) ; Tr_exp Tr_nilExp() ; Tr_exp Tr_intExp(int i) ; Tr_exp Tr_stringExp(string str) ; Tr_exp Tr_simpleVar(Tr_access acc , Tr_level level ); Tr_exp Tr_subscriptVar(Tr_exp base, Tr_exp index); Tr_exp Tr_fieldVar(Tr_exp base, int offset); Tr_exp Tr_binopExp(Tr_exp left , Tr_exp right ,A_oper oper ); Tr_exp Tr_relopExp(Tr_exp left , Tr_exp right , A_oper oper) ; Tr_exp Tr_ifExp( Tr_exp test , Tr_exp then , Tr_exp elses ) ; Tr_exp Tr_recordExp( Tr_expList explist , int num) ; Tr_exp Tr_arryExp(Tr_exp index , Tr_exp init) ; Tr_exp Tr_seqExp(Tr_expList explist) ; Tr_exp Tr_assignExp(Tr_exp exp1 , Tr_exp exp2) ; Tr_exp Tr_whileExp( Tr_exp test , Tr_exp body , bool isbreak) ; Tr_exp Tr_forExp(Tr_access acc , Tr_exp hi , Tr_exp low , Tr_exp body) ; Tr_exp Tr_breakExp() ; Tr_exp Tr_letExp(Tr_expList declist , Tr_exp exp ) ; Tr_exp Tr_callExp(Temp_label label ,Tr_level funleve , Tr_level level ,Tr_expList explist ) ; Tr_exp Tr_StaticLink(Tr_level now, Tr_level def); Tr_exp Tr_varDec(Tr_access acc , Tr_exp init) ; Tr_exp Tr_typeDec(); Tr_exp Tr_funDec(Tr_expList bodylist) ; void Tr_procEntryExit(Tr_level level , Tr_exp body , Tr_accesslist formals) ; F_fragList Tr_getResult() ; #endif
#include "translate.h" #include "util.h" #include "env.h" #include#include Tr_access Tr_allocLocal(Tr_level level , bool escape ) { F_access acc ; acc = F_allocLoacl(level->frame , escape) ; return Tr_Access(level , acc) ; } Tr_access Tr_Access(Tr_level level , F_access access ) { Tr_access acc = (Tr_access)checked_malloc(sizeof(*acc)); acc->level = level; acc->access = access; return acc; } Tr_accesslist Tr_Accesslist(Tr_access head , Tr_accesslist tial) { Tr_accesslist tmp = (Tr_accesslist)checked_malloc(sizeof(*tmp)); tmp->head = head ; tmp->tial = tial ; return tmp ; } Tr_level Tr_newLevel(Tr_level parent , Temp_label name , U_boolList formals ) { Tr_level level = (Tr_level)checked_malloc(sizeof(*level)); level->parent = parent ; level->frame = F_newframe(name , U_BoolList(true , formals) ) ; // ’‚¿Ôº”µƒtrue¥˙±Ì¡Àæ≤è¡¥ return level ; } Tr_accesslist Tr_formals(Tr_level level) { F_accesslist f_acc = level->frame->formals ; f_acc = f_acc->tail ;//µ⁄“ª∏ˆ¥˙±Ì¡Àæ≤è¡¥ À˘“‘“™ÃÙ≥ˆ¿¥ Tr_accesslist tmp = NULL ; while(f_acc) { tmp = Tr_Accesslist(Tr_Access(level , f_acc->head), tmp) ; f_acc = f_acc->tail ; } return tmp ; } Tr_level Tr_outermorst() { static Tr_level tmp = NULL ; if (!tmp) { tmp = (Tr_level)checked_malloc(sizeof(*tmp)); U_boolList b = U_BoolList(true , NULL) ; tmp->frame = F_newframe(Temp_newlabel() , b) ; tmp->parent = NULL ; } return tmp ; } void Tr_ClearAcces(Tr_accesslist list) { Tr_accesslist tmp ; tmp = list ; while(list) { list = list->tial ; tmp->head = NULL ; tmp->tial = NULL ; free(tmp) ; tmp = list ; } } Tr_exp Tr_Ex(T_exp exp ) { Tr_exp tmp = (Tr_exp)checked_malloc(sizeof(*tmp)); tmp->kind = GetExpEx ; tmp->u.ex = exp ; return tmp ; } Tr_exp Tr_Nx(T_stm stm ) { Tr_exp tmp = (Tr_exp)checked_malloc(sizeof(*tmp)); tmp->kind = GetExpNx ; tmp->u.nx = stm ; return tmp ; } Tr_exp Tr_Cx(patchList trues , patchList falses , T_stm stm ) { Tr_exp tmp = (Tr_exp)checked_malloc(sizeof(*tmp)); tmp->kind = GetExpCx ; tmp->u.cx.falses = falses ; tmp->u.cx.trues = trues ; tmp->u.cx.stm = stm ; return tmp ; } T_stm Tr_unNx(Tr_exp exp) { switch (exp->kind) { case GetExpEx: return T_Exp(exp->u.ex); case GetExpCx: return T_Exp(Tr_unEx(exp)); case GetExpNx: return exp->u.nx; } assert(0); } Cx Tr_unCx(Tr_exp exp) { switch (exp->kind) { case GetExpCx : return exp->u.cx; case GetExpEx: { T_stm stm = T_Cjump(T_ne, exp->u.ex, T_Const(0), NULL , NULL); Cx cx; cx.stm = stm; cx.falses = PatchList(&stm->u.CJUMP.falses, NULL); cx.trues = PatchList(&stm->u.CJUMP.trues, NULL); return cx; } } assert(0); } T_exp Tr_unEx(Tr_exp exp) { switch(exp->kind) { case GetExpEx : return exp->u.ex ; case GetExpCx : { Temp_temp tmp = Temp_newtemp() ; Temp_label t = Temp_newlabel() , f = Temp_newlabel() ; doPatch(exp->u.cx.falses , f) ; doPatch(exp->u.cx.trues , t) ; return T_Eseq(T_Move(T_Temp(tmp) , T_Const(1)), T_Eseq( exp->u.cx.stm , T_Eseq( T_Label(f) , T_Eseq(T_Move(T_Temp(tmp) , T_Const(0)) , T_Eseq(T_Label(t) , T_Temp(tmp)))))) ; } case GetExpNx : { return T_Eseq(exp->u.nx, T_Const(0));// Œ™ ≤√¥“™∑µªÿ0 ’‚∏ˆnx≤ª «Œfi÷µ”Ôæ‰√¥ } } assert(0); } void doPatch( patchList patchlist , Temp_label lable) { for ( ; patchlist ; patchlist = patchlist->tail) { (*patchlist->head) = lable ; } } patchList PatchList(Temp_label *head , patchList patchlist ) { patchList tmp = (patchList)checked_malloc(sizeof(*tmp)); tmp->head = head ; tmp->tail = patchlist ; return tmp ; } Tr_expList Tr_ExpList(Tr_exp head , Tr_expList tail) { Tr_expList tmp = (Tr_expList)checked_malloc(sizeof(*tmp)) ; tmp->head = head ; tmp->tail = tail ; return tmp ; } Tr_exp Tr_nilExp() { static Temp_temp temp = NULL ; if ( !temp ) { temp = Temp_newtemp() ; T_stm alloc = T_Move(T_Temp(temp), T_Call(T_Name(Temp_namedlabel("initRecord")), T_ExpList(T_Const(0), NULL))); return Tr_Ex(T_Eseq(alloc, T_Temp(temp))); } return Tr_Ex(T_Temp(temp)) ; } Tr_exp Tr_intExp(int i) { return Tr_Ex(T_Const(i)) ; } static F_fragList stringFragList = NULL; Tr_exp Tr_stringExp(string s) { Temp_label slabel = Temp_newlabel(); F_frag fragment = F_StringFrag(slabel, s); stringFragList = F_FragList(fragment, stringFragList); return Tr_Ex(T_Name(slabel)); } Tr_exp Tr_simpleVar(Tr_access acc, Tr_level level) { T_exp tmp = T_Temp(F_FP()); while ( level && level != acc->level->parent ) { tmp = T_Mem(T_Binop(T_plus, T_Const(level->frame->formals->head->u.offset), tmp)); level = level->parent; } return Tr_Ex(F_Exp(acc->access, tmp)); } Tr_exp Tr_subscriptVar(Tr_exp base, Tr_exp index ) { return Tr_Ex(T_Mem(T_Binop(T_plus, Tr_unEx(base), T_Binop(T_mul, Tr_unEx(index), T_Const(F_wordSize))))); } Tr_exp Tr_fieldVar(Tr_exp base, int offset) { return Tr_Ex(T_Mem(T_Binop(T_plus, Tr_unEx(base), T_Const(offset * F_wordSize)))); } Tr_exp Tr_binopExp(Tr_exp left , Tr_exp right ,A_oper oper ) { T_binOp op ; switch(oper) { case A_plusOp : { op = T_binOp::T_plus ; break ; } case A_minusOp : { op = T_binOp::T_minus ; break ; } case A_timesOp : { op = T_binOp::T_mul ; break ; } case A_divideOp : { op = T_binOp::T_div ; break ; } default : { return NULL ; } } return Tr_Ex(T_Binop(op , Tr_unEx(left) , Tr_unEx(right))) ; } Tr_exp Tr_relopExp(Tr_exp left , Tr_exp right , A_oper oper) { T_relOp op ; switch(oper) { case A_ltOp : { op = T_relOp::T_lt ; break ; } case A_leOp : { op = T_relOp::T_le ; break ; } case A_gtOp : { op = T_relOp::T_gt ; break ; } case A_geOp : { op = T_relOp::T_ge ; break ; } case A_eqOp : { op = T_relOp::T_eq ; break ; } case A_neqOp : { op = T_relOp::T_ne ; break ; } default : return NULL ; } T_stm stm = T_Cjump(op ,Tr_unEx(left) , Tr_unEx(right) , NULL , NULL ); patchList trues = PatchList(&stm->u.CJUMP.trues , NULL) ; patchList falses = PatchList(&stm->u.CJUMP.falses , NULL) ; return Tr_Cx(trues , falses , stm) ; } Tr_exp Tr_ifExp( Tr_exp test , Tr_exp then , Tr_exp elses ) { Cx ctest = Tr_unCx(test) ; T_stm reslutstm , thenstm , elsestm ; reslutstm = thenstm = elsestm = NULL ; Temp_label t = Temp_newlabel() ; Temp_label f = Temp_newlabel() ; Temp_temp v = Temp_newtemp() ; doPatch(ctest.falses , f) ; doPatch(ctest.trues , t ) ; switch(then->kind) { case GetExpEx : { thenstm = T_Seq(ctest.stm , T_Seq(T_Label(t) , T_Move(T_Temp(v) , Tr_unEx(then)))) ; break ; } case GetExpNx : { thenstm = T_Seq(ctest.stm ,T_Seq(T_Label(t) , then->u.nx)) ; break ; } case GetExpCx : { thenstm = T_Seq(ctest.stm , T_Seq(T_Label(t) , Tr_unNx(then))) ; break ; } } if (elses) { switch(elses->kind) { case GetExpEx: { elsestm = T_Move(T_Temp(v), Tr_unEx(elses)) ; break ; } case GetExpNx : { elsestm = elses->u.nx ; break ; } case GetExpCx : { elsestm = Tr_unNx(elses) ; break ; } } } if (elsestm) { Temp_label jump = Temp_newlabel() ; return Tr_Nx(T_Seq( T_Seq( thenstm , T_Seq(T_Jump( T_Name(jump) , Temp_LabelList(jump , NULL)) ,T_Seq(T_Label(f) ,elsestm))) , T_Label(jump))) ; } return Tr_Nx( T_Seq(thenstm , T_Label(f))) ; } Tr_exp Tr_recordExp( Tr_expList explist , int num) //’‚¿Ô¥´Ω¯¿¥µƒexplist ∫Õ’Ê «µƒexplist «œ‡∑¥µƒ { T_stm stm ; Temp_temp t = Temp_newtemp(); T_exp callfun = T_Call(T_Name(Temp_namedlabel("initRecord")) ,T_ExpList(T_Const(num*F_wordSize) , NULL)) ; stm = T_Move(T_Mem(T_Binop(T_plus , T_Temp(t) , T_Const((num - 1)*F_wordSize))), Tr_unEx(explist->head)) ; num-- ; explist = explist->tail ; while(explist) { stm = T_Seq(T_Move(T_Mem(T_Binop(T_plus, T_Temp(t) , T_Const((num -1 ) * F_wordSize))), Tr_unEx(explist->head)),stm) ; explist = explist->tail ; num-- ; } stm = T_Seq(T_Move(T_Temp(t) , callfun) , stm) ; return Tr_Ex( T_Eseq( stm , T_Temp(t))) ; } Tr_exp Tr_arryExp(Tr_exp index , Tr_exp init) { Temp_temp t = Temp_newtemp() ; T_exp callfun = T_Call(T_Name(Temp_namedlabel("initArray")) ,T_ExpList( Tr_unEx(index),T_ExpList(Tr_unEx(init) ,NULL))) ; return Tr_Nx( T_Move( T_Temp(t) , callfun) ); } Tr_exp Tr_seqExp(Tr_expList explist) { if (!explist) { return NULL ; } T_stm stm = Tr_unNx(explist->head) ; explist = explist->tail ; while(explist) { stm = T_Seq( Tr_unNx(explist->head) , stm) ; explist = explist->tail ; } return Tr_Nx(stm) ; } Tr_exp Tr_assignExp(Tr_exp exp1 , Tr_exp exp2) { return Tr_Nx(T_Move(T_Mem( Tr_unEx(exp1)) , T_Mem(Tr_unEx(exp2)))) ; } Tr_exp Tr_letExp(Tr_expList declist , Tr_exp exp ) { if (!declist) { return NULL ; } T_stm stm = Tr_unNx(declist->head) ; declist = declist->tail ; while(declist) { stm = T_Seq(Tr_unNx(declist->head) , stm) ; declist = declist->tail ; } if (exp) { stm = T_Seq(stm , Tr_unNx(exp)) ; } return Tr_Nx(stm); } Tr_exp Tr_whileExp(Tr_exp test , Tr_exp body , bool isbreak) { Cx ctest = Tr_unCx(test) ; Temp_label t = Temp_newlabel() ; Temp_label done = Temp_namedlabel("done") ; doPatch(ctest.falses , done) ; doPatch(ctest.trues , t) ; T_stm stm ; Temp_label testlabel = Temp_newlabel(); stm = T_Seq(T_Label(t) , T_Seq(Tr_unNx(body) ,T_Jump(T_Name(testlabel),Temp_LabelList(testlabel,NULL)))) ; stm = T_Seq( T_Label(testlabel) , T_Seq(ctest.stm ,T_Seq(stm , T_Label(done)))) ; return Tr_Nx(stm); } Tr_exp Tr_breakExp() { Temp_label done = Temp_namedlabel("done") ; return Tr_Nx(T_Jump(T_Name(done) , Temp_LabelList(done , NULL))) ; } Tr_exp Tr_forExp(Tr_access acc , Tr_exp hi , Tr_exp low , Tr_exp body) { T_exp tmp = T_Temp(F_FP()); //tmp = T_Mem(T_Binop(T_plus ,tmp , T_Const(acc->level->frame->formals->head->u.offset))) ; T_exp memt = F_Exp(acc->access , tmp) ; T_stm stm = T_Move(memt , Tr_unEx(low)) ; Temp_temp h = Temp_newtemp() ; T_stm limit = T_Move(T_Temp(h) , Tr_unEx(hi)) ; Cx cx ; cx.stm = T_Cjump(T_lt ,memt ,T_Temp(h) , NULL , NULL) ; cx.falses = PatchList(&cx.stm->u.CJUMP.falses , NULL) ; cx.trues = PatchList(&cx.stm->u.CJUMP.trues , NULL) ; T_stm finalbody = T_Seq(T_Move(memt , T_Binop(T_plus , memt , T_Const(1))) , Tr_unNx(body)) ; Tr_exp tmpwhile = Tr_whileExp(Tr_Cx(cx.trues , cx.falses , cx.stm) , Tr_Nx(finalbody) , false) ; return Tr_Nx(T_Seq( stm , T_Seq( limit , Tr_unNx(tmpwhile)))) ; } Tr_exp Tr_StaticLink(Tr_level now, Tr_level def) { T_exp addr = T_Temp(F_FP()); while(now && (now != def->parent)) { F_access sl = F_formals(now->frame)->head; addr = F_Exp(sl, addr); now = now->parent; } return Tr_Ex(addr); } Tr_exp Tr_callExp(Temp_label label ,Tr_level funleve , Tr_level level ,Tr_expList explist ) { T_expList tmplist = NULL; while(explist) { tmplist = T_ExpList( Tr_unEx(explist->head) , tmplist) ; explist = explist->tail ; } tmplist = T_ExpList(Tr_unEx(Tr_StaticLink(funleve , level)) , tmplist) ; T_exp callfun = T_Call(T_Name(label) ,tmplist) ; return Tr_Ex(callfun) ; } Tr_exp Tr_callExp(E_enventry entry , Tr_level level , Tr_expList explist ) { T_expList tmplist = NULL; while(explist) { tmplist = T_ExpList( Tr_unEx(explist->head) , tmplist) ; explist = explist->tail ; } tmplist = T_ExpList(Tr_unEx(Tr_StaticLink(entry->u.fun.level , level)) , tmplist) ; T_exp callfun = T_Call(T_Name(entry->u.fun.label) ,tmplist) ; return Tr_Ex(callfun) ; } Tr_exp Tr_varDec(Tr_access acc , Tr_exp init) { T_exp tmp = T_Temp(F_FP()); T_exp memt = F_Exp(acc->access , tmp) ; return Tr_Nx(T_Move(memt , Tr_unEx(init))) ; } Tr_exp Tr_typeDec() { return Tr_Ex(T_Const(0)) ; } Tr_exp Tr_funDec(Tr_expList bodylist) { T_stm stm ; stm = T_Move(T_Temp(F_RV()) , Tr_unEx(bodylist->head)) ; bodylist = bodylist->tail ; while (bodylist) { stm = T_Seq(T_Move(T_Temp(F_RV()) , Tr_unEx(bodylist->head)) , stm); } return Tr_Nx(stm) ; }
#ifndef SENMANT_H_ #define SENMANT_H_ #include "types.h" #include "translate.h" #include "absyn.h" struct expty { Tr_exp exp ; Ty_ty ty; }; expty expTy(Tr_exp exp , Ty_ty ty) ; expty transVar(S_table venv , S_table tenv , A_var var , Tr_level level) ; expty transExp(S_table venv , S_table tenv , A_exp exp , Tr_level level ) ; //∑µªÿ÷µ÷–µƒtyty“ª∂® «◊ÓµÕ≤„µƒ¿‡–Õ Tr_exp transDec(S_table venv , S_table tenv , A_dec dec , Tr_level level ) ; Ty_ty transTy( S_table tenv , A_ty ty) ; //ƒ⁄÷√±Í æ∑˚ºÏ≤‚ int string ÷ª”√‘⁄œÚ÷µª∑æ≥ ‰»Î÷µµƒ ±∫Ú≤≈ºÏ≤‚ ¿‡–Õª∑æ≥‘⁄ tranTy÷–“—æ≠ºÏ≤‚ bool innerIdentifiers( S_symbol sym); #endif
#include "semant.h" #include#include "env.h" expty expTy(Tr_exp exp , Ty_ty ty) { expty e ; e.exp = exp ; e.ty = ty ; return e ; } expty transExp(S_table venv , S_table tenv , A_exp exp , Tr_level level ) // done «Œ™¡ÀºÏ≤‚break «∑Ò‘⁄’˝»∑µƒŒª÷√ { static bool done = false ; if (exp == NULL ) { assert(0); } switch(exp->kind) { case A_varExp : return transVar(venv , tenv , exp->u.var , level ) ; case A_nilExp : return expTy( Tr_nilExp() ,Ty_Nil()); case A_intExp : // ’‚¿Ôµƒint «Àµµƒ’˚–Õ≥£¡ø ∂¯≤ª «int¿‡–Õ return expTy( Tr_intExp(exp->u.intt) , Ty_Int()) ; case A_stringExp ://’‚¿Ôµƒstring «Àµµƒ◊÷∑˚¥Æ≥£¡ø ∂¯≤ª «string¿‡–Õ return expTy( Tr_stringExp(exp->u.stringg) , Ty_String()) ; case A_callExp : { E_enventry tmp = (E_enventry)S_look(venv, exp->u.call.func) ; if (tmp == NULL) { assert(0) ; } Ty_tyList tylist = tmp->u.fun.formals ; A_expList explist = exp->u.call.args ; Tr_expList trexplist = NULL ; while (tylist != NULL && explist != NULL) { expty exptyp = transExp(venv , tenv , explist->head , level) ; if (exptyp.ty->kind == Ty_ty_::Ty_nil) { continue ; } if (!isTyequTy(tylist->head , exptyp.ty)) { assert(0) ; } trexplist = Tr_ExpList(exptyp.exp , trexplist) ; tylist = tylist->tail ; explist = explist->tail ; } if (tylist != NULL || explist != NULL ) { assert(0); } return expTy(Tr_callExp(tmp->u.fun.label , tmp->u.fun.level , level , trexplist) , actrulyTy(tmp->u.fun.result)) ; } case A_opExp : { expty tmpleft = transExp(venv , tenv, exp->u.op.left , level ) ; expty tmpright = transExp(venv , tenv, exp->u.op.right , level ) ; switch(exp->u.op.oper) { case A_plusOp : case A_minusOp : case A_timesOp : case A_divideOp : { if (tmpleft.ty->kind != Ty_ty_::Ty_int) assert(0); if (tmpright.ty->kind != Ty_ty_::Ty_int) assert(0); return expTy(Tr_binopExp(tmpleft.exp , tmpright.exp ,exp->u.op.oper) , Ty_Int()) ; } case A_ltOp : case A_leOp : case A_gtOp : case A_geOp : { if (tmpleft.ty->kind != Ty_ty_::Ty_int) assert(0); if (tmpright.ty->kind != Ty_ty_::Ty_int) assert(0); return expTy(Tr_relopExp(tmpleft.exp , tmpright.exp , exp->u.op.oper) , Ty_Int()) ; } case A_eqOp : case A_neqOp: { if (tmpleft.ty->kind == Ty_ty_::Ty_int && tmpright.ty->kind == Ty_ty_::Ty_int) return expTy(Tr_relopExp(tmpleft.exp , tmpright.exp , exp->u.op.oper) , Ty_Int()) ; if (tmpleft.ty->kind == tmpright.ty->kind) { if (tmpleft.ty->kind == Ty_ty_::Ty_record || tmpleft.ty->kind == Ty_ty_::Ty_array) { if ( tmpleft.ty == tmpright.ty ) { return expTy(Tr_relopExp(tmpleft.exp , tmpright.exp , exp->u.op.oper) , Ty_Int()) ; } } } assert(0); } } assert(0); } case A_recordExp : { Ty_ty tmpty = (Ty_ty)S_look(tenv , exp->u.record.typ) ; tmpty = actrulyTy(tmpty) ; if (tmpty == NULL ) { assert(0) ; } if (tmpty->kind != Ty_ty_::Ty_record ) { assert(0) ; } A_efieldList tmpefield = exp->u.record.fields ; Ty_fieldList tmpfieldlist = tmpty->u.record ; Tr_expList trexplist = NULL ; int num = 0 ; while(tmpefield && tmpfieldlist) { expty tmp = transExp(venv , tenv , tmpefield->head->exp , level) ; if (tmpefield->head->name != tmpfieldlist->head->name ) { assert(0) ; } if (!isTyequTy(tmp.ty ,tmpfieldlist->head->ty)) { assert(0) ; } trexplist = Tr_ExpList(tmp.exp , trexplist) ; tmpefield = tmpefield->tail ; tmpfieldlist = tmpfieldlist->tail ; num ++; } if (tmpfieldlist!= NULL || tmpefield != NULL ) { assert(0) ; } expty tmp = expTy(Tr_recordExp(trexplist,num),tmpty));
Tr_FreeExplist(trexplist) ; // 只释放链表结构 不释放内容(hand) return tmp ; } case A_seqExp : { A_expList explist = exp->u.seq ; Tr_expList trexplist = NULL ; if (explist) { while(explist->tail) { trexplist = Tr_ExpList(transExp( venv , tenv , explist->head , level).exp , trexplist) ; explist = explist->tail ; } } else { return expTy( Tr_seqExp(trexplist) , Ty_Void()); } expty tmp = transExp(venv , tenv , explist->head , level) ; trexplist = Tr_ExpList(tmp.exp , trexplist) ;
Tr_FreeExplist(trexplist) ; //只释放链表结构 不是放内容(hand) return expTy(Tr_seqExp(trexplist) , tmp.ty); } case A_assignExp : { expty tmpV = transVar(venv , tenv , exp->u.assign.var , level) ; expty tmpE = transExp(venv , tenv , exp->u.assign.exp , level); if (tmpE.ty->kind != tmpV.ty->kind) { assert(0); } return expTy(Tr_assignExp(tmpV .exp , tmpE.exp) , Ty_Void()); } case A_ifExp : { expty tmptest = transExp(venv ,tenv , exp->u.iff.test , level) ; if(tmptest.ty->kind != Ty_ty_::Ty_int) { assert(0); } expty tmpthen = transExp(venv , tenv , exp->u.iff.then , level ) ; if (exp->u.iff.elsee != NULL) { expty tmpelse = transExp(venv , tenv , exp->u.iff.elsee , level) ; if ( tmpthen.ty != tmpelse.ty ) { assert(0); } return expTy( Tr_ifExp(tmptest.exp , tmpthen.exp , tmpelse.exp) , tmpelse.ty); } if (tmpthen.ty->kind != Ty_ty_::Ty_void) { assert(0); } return expTy(Tr_ifExp(tmptest.exp , tmpthen.exp , NULL) , Ty_Void()); } case A_whileExp : { expty test = transExp(venv , tenv , exp->u.whilee.test , level ); if (test.ty->kind != Ty_ty_::Ty_int) { assert(0) ; } expty body = transExp(venv , tenv , exp->u.whilee.body , level ); if ( done ) { // Àµ√˜’‚¿Ô√Ê”–break done = false ; } /* if (body.ty->kind != Ty_ty_::Ty_void) { assert(0); }*/ return expTy(Tr_whileExp(test.exp , body.exp , false) , Ty_Void()); } case A_forExp : { expty tmplo = transExp(venv , tenv , exp->u.forr.lo , level ); expty tmphi = transExp(venv , tenv , exp->u.forr.hi ,level ); S_beginScope(venv); Tr_access acc; acc = Tr_allocLocal(level , exp->u.forr.escape); // forŒ™ ≤√¥“™”–Ô“›£ø£ø£ø£ø£ø S_enter(venv , exp->u.forr.var , E_VarEntry( acc ,Ty_Int())); expty tmpbody = transExp(venv , tenv, exp->u.forr.body , level); if (tmplo.ty->kind != Ty_ty_::Ty_int || tmphi.ty->kind != Ty_ty_::Ty_int ) { assert(0); } S_endScope(venv); return expTy(Tr_forExp(acc, tmphi.exp , tmplo.exp , tmpbody.exp) , Ty_Void()); } case A_breakExp : { done = true ; return expTy(Tr_breakExp() , Ty_Void()); } case A_letExp : { S_beginScope(venv); S_beginScope(tenv); A_decList declist = exp->u.let.decs ; Tr_expList trexplist = NULL ; while(declist != NULL) { trexplist = Tr_ExpList(transDec(venv , tenv , declist->head , level) , trexplist) ; declist = declist->tail; } expty tmp ; if (exp->u.let.body) { tmp = transExp(venv , tenv , exp->u.let.body , level); tmp = expTy(Tr_letExp(trexplist , tmp.exp) , tmp.ty) ; } else { tmp = expTy(Tr_letExp(trexplist , NULL) , Ty_Void()) ; }
Tr_FreeExplist(trexplist) ;//只释放链表结构,不是放链表内容(hand) S_endScope(venv); S_endScope(tenv); return tmp ; } case A_arrayExp : { Ty_ty ty = (Ty_ty)S_look(tenv , exp->u.array.typ); ty = actrulyTy(ty); if (ty == NULL || ty->kind != Ty_ty_::Ty_array) { assert(0); } expty tynum = transExp(venv , tenv , exp->u.array.size , level ); if (tynum.ty->kind != Ty_ty_::Ty_int) { assert(0); } expty tyinit = transExp(venv , tenv, exp->u.array.init , level ) ; if (tyinit.ty != ty->u.array ) { assert(0) ; } return expTy(Tr_arryExp(tynum.exp, tyinit.exp) , ty); } } assert(0); } expty transVar(S_table venv , S_table tenv , A_var var , Tr_level level) { switch(var->kind) { case A_simpleVar : { E_enventry tmp = (E_enventry) S_look(venv , var->u.simple) ; if (tmp != NULL && tmp->kind == E_enventry_::E_varEntry) { return expTy(Tr_simpleVar(tmp->u.var.access , level), actrulyTy(tmp->u.var.ty)) ; } assert(0) ; } case A_fieldVar : { expty tmpty = transVar(venv , tenv , var->u.field.var , level) ; if (tmpty.ty->kind != Ty_ty_::Ty_record) { assert(0); } Ty_fieldList fieldList = tmpty.ty->u.record ; int num = 0; while( fieldList ) { if ( fieldList->head->name == var->u.field.sym ) { return expTy(Tr_fieldVar(tmpty.exp ,num) , actrulyTy(fieldList->head->ty)) ; } num ++ ; fieldList = fieldList->tail ; } assert(0); } case A_subscriptVar : { expty tmp = transVar(venv , tenv , var->u.subscript.var , level) ; if (tmp.ty->kind != Ty_ty_::Ty_array ) { assert(0) ; } expty tmpexp = transExp(venv , tenv , var->u.subscript.exp , level ) ; if (tmpexp.ty->kind != Ty_ty_::Ty_int) { assert(0) ; } return expTy(Tr_subscriptVar(tmp.exp ,tmpexp.exp) , tmp.ty) ; } } assert(0) ; } Tr_exp transDec(S_table venv , S_table tenv , A_dec dec , Tr_level level) { switch(dec->kind) { case A_functionDec : { A_fundecList tmpfun = dec->u.function ; Tr_level newlevel ; Tr_access acce ; U_boolList boollist = NULL ; Ty_ty reslut = NULL ; while(tmpfun) { A_fieldList tmpfeldList = tmpfun->head->params ; Ty_tyList tylist = NULL ; while(tmpfeldList) { Ty_ty ty = (Ty_ty)S_look(tenv,tmpfeldList->head->typ); if (ty == NULL ) { assert(0) ; } tylist = Ty_TyList(ty , tylist) ; tmpfeldList = tmpfeldList->tail ; boollist = U_BoolList(true , boollist) ; } if (innerIdentifiers(tmpfun->head->name)) { assert(0) ; } //¿‡À∆”⁄…˘√˜“ª∏ˆ∫Ø ˝ ªπ√ª”–∂®“ÂÀ¸ newlevel = Tr_newLevel(level ,Temp_newlabel() ,boollist); reslut = (Ty_ty)S_look(tenv ,tmpfun->head->result) ; if (reslut == NULL ) { reslut = Ty_Void() ; } S_enter(venv , tmpfun->head->name , E_FunEntry( newlevel, newlevel->frame->name , tylist , reslut)) ; tmpfun = tmpfun->tail ; U_ClearBoolList(boollist) ; // “ÚŒ™÷ª «”√¡Àbool ≤¢√ª”–±£¥ÊÀ¸ À˘“‘ªπ“™ Õ∑≈“ªœ¬ boollist = NULL ; } tmpfun = dec->u.function ; E_enventry funEntry; Tr_accesslist tr_acceselist , tmpacclist ; Tr_expList trexplist = NULL ; while(tmpfun) { S_beginScope(venv) ; funEntry = (E_enventry) S_look(venv , tmpfun->head->name) ; tmpacclist = tr_acceselist = Tr_formals(funEntry->u.fun.level) ; A_fieldList tmpfeldList = tmpfun->head->params ; // ’‚¿Ô“™øº¬«µΩparamsµƒ…˙≥…∑Ω Ω »Áπ˚∫Õtr_accesslist≤ª“ª÷¬“™∏ƒ“ªœ¬ while(tmpfeldList) { Ty_ty ty = (Ty_ty)S_look(tenv,tmpfeldList->head->typ); if (innerIdentifiers(tmpfeldList->head->name)) { assert(0); } S_enter(venv ,tmpfeldList->head->name, E_VarEntry(tmpacclist->head,ty)) ; tmpfeldList = tmpfeldList->tail ; tmpacclist = tmpacclist->tial ; } expty tmp = transExp(venv , tenv , tmpfun->head->body , newlevel) ; trexplist = Tr_ExpList(tmp.exp , trexplist) ; if (tmp.ty != actrulyTy(funEntry->u.fun.result)) { assert(0) ; } Tr_ClearAcces(tr_acceselist) ; //÷ª π”√¡Àhead tail≤ø∑÷«Â¿Ì∏…æª S_endScope(venv) ; tmpfun = tmpfun->tail ; } return Tr_funDec(trexplist) ; } case A_typeDec : { A_nametyList namelist = dec->u.type ; while(namelist) { if (innerIdentifiers(namelist->head->name)) { assert(0) ; } // ¥¶¿Ìµ›πÈ ¿‡À∆”⁄ …˘√˜“ª∏ˆ¿‡–Õ µ´ «ªπ√ª”–∂®“ÂÀ¸ S_enter(tenv , namelist->head->name ,Ty_Name(namelist->head->name , NULL)) ; namelist = namelist->tail ; } namelist = dec->u.type ; while(namelist) { // ¥¶¿Ìµ›πÈ Ty_ty tmp1 = transTy(tenv , namelist->head->ty ) ; Ty_ty tmp2 = (Ty_ty)S_look(tenv , namelist->head->name) ; if ( tmp1->kind == Ty_ty_::Ty_int || tmp1->kind == Ty_ty_::Ty_string || tmp1->kind == Ty_ty_::Ty_nil || tmp1->kind == Ty_ty_::Ty_void) { //ƒ⁄÷√¿‡–Õ π”√µƒ «Õ¨“ª«¯”Úƒ⁄¥Ê Œ™¡À±£≥÷ø…“‘æ≠––÷∏’僱»ΩœæÕ÷±Ω”»∑∂® «∑ÒŒ™Õ¨“ª∏ˆ¿‡–Õ ƒ«√¥æÕ“™÷±Ω”∞—∞Û∂®∏¯ªª¡À tmp2 = (Ty_ty)S_changeBind(tenv , namelist->head->name , tmp1); tmp2 = (Ty_ty)freeTy(tmp2) ; } else { //»Áπ˚≤ª «’‚Àƒ÷÷ƒ⁄÷√¿‡–Õ “™œ˙ªŸ tyCpy(tmp2 , tmp1) ; tmp1 = (Ty_ty)freeTy(tmp1) ; } namelist = namelist->tail ; } namelist = dec->u.type; while(namelist) { // ¥¶¿Ì —≠ª∑µ›πÈ ¿˝»Á type a = b type b = a Ty_ty tmp = (Ty_ty)S_look(tenv , namelist->head->name) ; if (!actrulyTy(tmp)) { assert(0) ; } namelist = namelist->tail ; } return Tr_typeDec(); } case A_varDec : { if(dec->u.var.init == NULL) { assert(0) ; } expty tmp = transExp(venv , tenv , dec->u.var.init , level ) ; if( (dec->u.var.typ != NULL) ) { if ( actrulyTy((Ty_ty)S_look(tenv ,dec->u.var.typ)) != tmp.ty) { assert(0) ; } } if (innerIdentifiers(dec->u.var.var)) { assert(0) ; } Tr_access acc = Tr_allocLocal(level , dec->u.var.escape) ; S_enter(venv , dec->u.var.var ,E_VarEntry( acc ,tmp.ty)) ; return Tr_varDec(acc , tmp.exp); } } assert(0) ; } Ty_ty transTy(S_table tenv , A_ty ty) { switch(ty->kind) { case A_nameTy : { if (S_Symbol("int") == ty->u.name) { return Ty_Int(); } if (S_Symbol("string") == ty->u.name) { return Ty_String(); } Ty_ty tmp = (Ty_ty)S_look(tenv , ty->u.name) ; if ( tmp == NULL ) { assert(0) ; } return Ty_Name(ty->u.name , tmp) ; } case A_recordTy : { A_fieldList tmpfeldList = ty->u.record ; Ty_fieldList tyfdlist = NULL ; while(tmpfeldList) { Ty_ty tmp = (Ty_ty)S_look(tenv , tmpfeldList->head->typ) ; if ( tmp == NULL ) { assert(0) ; } if (innerIdentifiers(tmpfeldList->head->name)) { assert(0); } tyfdlist = Ty_FieldList(Ty_Field( tmpfeldList->head->name , tmp) , tyfdlist) ; tmpfeldList = tmpfeldList->tail ; } return Ty_Record(tyfdlist); } case A_arrayTy : { Ty_ty tmp = (Ty_ty)S_look(tenv , ty->u.array); if ( tmp == NULL ) { assert(0); } return Ty_Array(tmp) ; } } assert(0) ; } bool innerIdentifiers( S_symbol sym) { if (sym == S_Symbol("int") || sym == S_Symbol("string") ) { return true ; } return false ; }