📄 type.cpp
字号:
/* u1comp type.c
*
* History:
* 04.11.2000 - created
*/
#include "stdafx.h"
#include "type.h"
#include "error.h"
#include "symbol.h"
#include "memory.h"
#include <string.h>
#include "tree.h"
#include "typedef.h"
TYPE *undefinedTYPE;
static TYPE *voidTYPE, *boolTYPE, *intTYPE, *stringTYPE;
void initTypes()
{
undefinedTYPE = NULL;
voidTYPE = makeTYPEvoid();
boolTYPE = makeTYPEbool();
intTYPE = makeTYPEint();
stringTYPE = makeTYPEstring();
}
char *typeToString(TYPE *t)
{
switch(t->kind) {
case boolK:
return "bool";
case intK:
return "int";
case stringK:
return "string";
case voidK:
return "void";
}
return "N/A";
}
/* Create a string with the function signature - ie. 'int myfunc(int a, int b)' */
char *functionToSignatureString(FUNCTION *f)
{
DECL *formal;
int stringLength=1;
char *signature;
/* Count length of formal types: */
formal = f->formals;
while (formal != NULL) {
stringLength += strlen(typeToString(formal->type));
/* Possibly add length of separating comma and space: */
if (formal->next != NULL)
stringLength += 2;
formal = formal->next;
}
/* Add length of return type, function name and parantheses: */
stringLength += strlen(typeToString(f->type)) + 1 + strlen(f->name) + 2;
/* Construct string: */
signature = (char*)Malloc(stringLength);
signature[0] = 0; /* make empty string */
strcat(signature, typeToString(f->type));
strcat(signature, " ");
strcat(signature, f->name);
strcat(signature, "(");
formal = f->formals;
while (formal != NULL) {
strcat(signature, typeToString(formal->type));
/* Possibly add separating comma and space: */
if (formal->next != NULL)
strcat(signature, ", ");
formal = formal->next;
}
strcat(signature, ")");
return signature;
}
/* The 'greatest' type of the two */
TYPE *greaterType(TYPE *l, TYPE *r)
{
/* Pass on undefinedTYPE: */
if (l == undefinedTYPE || r == undefinedTYPE)
return undefinedTYPE;
/*bool*/
if(l->kind == boolK && r->kind == boolK)
return boolTYPE;
/*int*/
if(l->kind == intK && r->kind == intK)
return intTYPE;
/*string*/
if(l->kind == stringK && ( r->kind == stringK || r->kind == intK || r->kind == boolK))
return stringTYPE;
/* l is not greater than or equal to r */
return undefinedTYPE;
}
TYPE *greatestCommonType(TYPE *t1, TYPE *t2)
{
TYPE *type;
if((type = greaterType(t1,t2)) != undefinedTYPE)
return type;
else if((type = greaterType(t2,t1)) != undefinedTYPE)
return type;
return undefinedTYPE;
}
/* Can we assign right type to left? */
bool assignable(TYPE *left, TYPE *right)
{
/* undefinedTYPE always yields success: */
if (left == undefinedTYPE || right == undefinedTYPE)
return true;
if (greaterType(left, right) != undefinedTYPE)
return true;
else
return false;
}
/* Small function to retrieve the type of a given symbol (from the symbol check phase)*/
TYPE *symbolType(SYMBOL *symbol)
{
switch(symbol->kind) {
case functionSym:
return symbol->val.functionS->type;
case programSym:
return voidTYPE;
case declSym:
return symbol->val.declS->type;
}
/* Should not be possible: */
return undefinedTYPE;
}
/* Is the given type a void type? */
bool voidType(TYPE *type)
{
/* undefinedTYPE always yields success: */
if (type == undefinedTYPE)
return true;
if (type->kind == voidK)
return true;
return false;
}
/* Is the given type a boolean type? */
bool boolType(TYPE *type)
{
/* undefinedTYPE always yields success: */
if (type == undefinedTYPE)
return true;
if (type->kind == boolK)
return true;
return false;
}
/* Is the given type a numeric type? (note: in pxdscript this means int) */
bool numericType(TYPE *type)
{
/* undefinedTYPE always yields success: */
if (type == undefinedTYPE)
return true;
if (type->kind == intK)
return true;
return false;
}
/* Is the given type a int type? */
bool intType(TYPE *type)
{
/* undefinedTYPE always yields success: */
if (type == undefinedTYPE)
return true;
if (type->kind == intK)
return true;
return false;
}
/* Is the given type a string type? */
bool stringType(TYPE *type)
{
/* undefinedTYPE always yields success: */
if (type == undefinedTYPE)
return true;
if (type->kind == stringK)
return true;
return false;
}
/* Here you define the casting rules of your language.
Remember that what you deside here you have to pay for later
by coding the code needed to maintain these rules ;) */
bool validCast(TYPE *source, TYPE *dest) {
/* rules for cast int -> ?? */
if (source->kind == intK)
if (dest->kind == stringK || dest->kind == intK)
return true;
/* rules for cast string -> ?? */
if (source->kind == stringK)
if (dest->kind == intK || dest->kind == stringK )
return true;
/* rules for cast bool -> ?? */
if (source->kind == boolK)
if (dest->kind == stringK || dest->kind == boolK)
return true;
return false;
}
void typeSCRIPTCOLLECTION(SCRIPTCOLLECTION *s)
{
/* Initialize the type structures we'll use to compare with in this phase */
initTypes();
/* Check all toplevels */
if(s->toplevels != NULL)
typeTOPLEVEL(s->toplevels);
}
void typeTOPLEVEL(TOPLEVEL *t)
{
/* Which kind of toplevel? */
switch(t->kind){
case functionK:
typeFUNCTION(t->val.functionT);
break;
case programK:
typePROGRAM(t->val.programT);
break;
case simpledeclK: /* chenhongyu, 2004-9-17. */
typeSIMPLEDECL(t->val.decl);
break;
}
if(t->next != NULL)
typeTOPLEVEL(t->next);
}
void typeFUNCTION(FUNCTION *f)
{
if(f->formals != NULL)
typeDECL(f->formals);
if(f->stms != NULL)
typeSTM(f->stms, f->type);
}
void typePROGRAM(PROGRAM *s)
{
if(s->stms != NULL)
typeSTM(s->stms, voidTYPE);
}
/* chenhongyu, 2004-9-17. */
void typeSIMPLEDECL(DECL *d)
{
if(d->val.simplevarD.initialization != NULL) {
typeEXP(d->val.simplevarD.initialization);
if (!assignable(d->type, d->val.simplevarD.initialization->type))
reportError(d->lineno, "Cannot assign %s value to %s lvalue",
typeToString(d->val.simplevarD.initialization->type),
typeToString(d->type));
if (d->type != undefinedTYPE && d->val.simplevarD.initialization->type != undefinedTYPE) {
/* make implicit casts explicit */
if (d->val.simplevarD.initialization->type->kind != d->type->kind){
d->val.simplevarD.initialization = makeEXPcast(d->type, d->val.simplevarD.initialization);
d->val.simplevarD.initialization->type = d->type;
}
}
}
}
/* Note that at this point the two variable types are treated identically. Originally the differences were
that the simplevar could not have any modifiers (const) and you could not declare a list of variables
(int x,t,b;).
The 'const' issue is not to be checked here (in the initialization) and in the weeding phase we translated
a declaration like above into a bunch of single declarations... */
void typeDECL(DECL *d)
{
switch(d->kind){
case formalK:
break;
case variableK:
if(d->val.variableD.initialization != NULL){
typeEXP(d->val.variableD.initialization);
if (!assignable(d->type, d->val.variableD.initialization->type))
reportError(d->lineno, "Cannot assign %s value to %s lvalue",
typeToString(d->val.variableD.initialization->type),
typeToString(d->type));
if (d->type != undefinedTYPE && d->val.variableD.initialization->type != undefinedTYPE) {
/* make implicit casts explicit */
if (d->val.variableD.initialization->type->kind != d->type->kind){
d->val.variableD.initialization = makeEXPcast(d->type, d->val.variableD.initialization);
d->val.variableD.initialization->type = d->type;
}
}
}
break;
case simplevarK:
if(d->val.simplevarD.initialization != NULL) {
typeEXP(d->val.simplevarD.initialization);
if (!assignable(d->type, d->val.simplevarD.initialization->type))
reportError(d->lineno, "Cannot assign %s value to %s lvalue",
typeToString(d->val.simplevarD.initialization->type),
typeToString(d->type));
if (d->type != undefinedTYPE && d->val.simplevarD.initialization->type != undefinedTYPE) {
/* make implicit casts explicit */
if (d->val.simplevarD.initialization->type->kind != d->type->kind){
d->val.simplevarD.initialization = makeEXPcast(d->type, d->val.simplevarD.initialization);
d->val.simplevarD.initialization->type = d->type;
}
}
}
break;
}
if(d->next != NULL)
typeDECL(d->next);
}
void typeFORINIT(FORINIT *f)
{
switch(f->kind){
case declforinitK:
typeDECL(f->val.declforinitF);
break;
case expforinitK:
typeEXP(f->val.expforinitF);
break;
}
if(f->next != NULL)
typeFORINIT(f->next);
}
void typeSTM(STM *s, TYPE *returnType)
{
switch(s->kind){
case skipK:
break;
case expK:
typeEXP(s->val.expS);
break;
case declstmK:
typeDECL(s->val.declstmS);
break;
case returnK:
if(s->val.returnS.exp != NULL){
typeEXP(s->val.returnS.exp);
if(!assignable(returnType, s->val.returnS.exp->type))
reportError(s->lineno, "Function must return expression of type %s",
typeToString(returnType));
}
else if(!voidType(returnType))
reportError(s->lineno, "Function must return expression of type %s",
typeToString(returnType));
break;
case ifK:
typeEXP(s->val.ifS.condition);
typeSTM(s->val.ifS.body, returnType);
if (!boolType(s->val.ifS.condition->type))
reportError(s->lineno, "Condition in if statement must be of type bool");
break;
case ifelseK:
typeEXP(s->val.ifelseS.condition);
typeSTM(s->val.ifelseS.thenpart, returnType);
typeSTM(s->val.ifelseS.elsepart, returnType);
if (!boolType(s->val.ifelseS.condition->type))
reportError(s->lineno, "Condition in if statement must be of type bool");
break;
case whileK:
typeEXP(s->val.whileS.condition);
typeSTM(s->val.whileS.body, returnType);
if (!boolType(s->val.whileS.condition->type))
reportError(s->lineno, "Condition in while statement must be of type bool");
break;
case forK:
typeFORINIT(s->val.forS.inits);
typeEXP(s->val.forS.condition);
typeEXP(s->val.forS.updates);
typeSTM(s->val.forS.body, returnType);
if (!boolType(s->val.forS.condition->type))
reportError(s->lineno, "Condition in for statement must be of type bool");
break;
case sequenceK:
typeSTM(s->val.sequenceS.first, returnType);
typeSTM(s->val.sequenceS.second, returnType);
break;
case scopeK:
typeSTM(s->val.scopeS.stm, returnType);
break;
case setintK:
typeEXP(s->val.setintS.modelname);
typeEXP(s->val.setintS.nr);
typeEXP(s->val.setintS.val);
if (!intType(s->val.setintS.nr->type) || !intType(s->val.setintS.val->type) ||
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -