最后还剩下一个, 声明语句的翻译. 因为符号表API已经很完善了, 所以声明语句的翻译不会太困难. 将一些小地方处理好了就行. 难对付的部分是设定初始值, 需要考虑到类型转换. OK, 代码说明一切.
struct List* insDeclarationNode(void* node) { struct DeclarationNode* self = (struct DeclarationNode*)node; // 节点指令 struct List* insList = (struct List*)newArrayList(); AcceptType type = self->dectype; int i; // 如果有初值, 这些变量会派上用场 struct IntParamInstruction* loadAddr; struct AbstractValueNode* initialVal; // 如果初值需要转型, 就用这个 InstructionCode castCode = (INTEGER == type) ? REAL_2_INT : INT_2_REAL; InstructionCode assignCode = (INTEGER == type) ? INT_ASSIGN : REAL_ASSIGN; struct NoParamInstruction* initAssign; // 赋值结束需要弹出初始值, 这两个留作备用. int popSize = (INTEGER == type) ? INT_SIZE : REAL_SIZE; struct IntParamInstruction* popInitVal; for (i = 0; i < self->vars->length(self->vars); ++i) { // 一次可能声明多个变量 // 调用符号表 int addr = declare((struct VariableNode*) (self->vars->peekAt(self->vars, i)), type); if (NULL != (initialVal = (struct AbstractValueNode*) // 如果有初始化 (self->initVals->peekAt(self->initVals, i)))) { struct List* insInitVal = initialVal->createInstruction(initialVal); // load 刚刚声明的变量 loadAddr = (struct IntParamInstruction*) allocate(sizeof(struct IntParamInstruction)); loadAddr->code = CONST_INT; loadAddr->param = addr; appendInsList(appendIns(insList, loadAddr), insInitVal); // 类型不匹配 if (initialVal->typeOf(initialVal) != type) { struct NoParamInstruction* cast = (struct NoParamInstruction*) allocate(sizeof(struct NoParamInstruction)); cast->code = castCode; appendIns(insList, cast); } initAssign = (struct NoParamInstruction*) allocate(sizeof(struct NoParamInstruction)); initAssign->code = assignCode; popInitVal = (struct IntParamInstruction*) allocate(sizeof(struct IntParamInstruction)); popInitVal->code = POP; popInitVal->param = popSize; appendIns(appendIns(insList, initAssign), popInitVal); } } return insList; }
接下来, 就要进入... 测试环节了. 这么多指令生成代码, 不测试, 能放心吗?