📄 symbols.c
字号:
case O_SYM: p->nodetype = namenode(p); break; case O_LCON: p->nodetype = t_int; break; case O_FCON: p->nodetype = t_real; break; case O_SCON: p->value.scon = strdup(p->value.scon); s = mkstring(p->value.scon); if (s == t_char) { p->op = O_LCON; p->value.lcon = p->value.scon[0]; } p->nodetype = s; break; case O_INDIR: p1 = p->value.arg[0]; chkclass(p1, PTR); p->nodetype = rtype(p1->nodetype)->type; break; case O_DOT: p->nodetype = p->value.arg[1]->value.sym; break; case O_RVAL: p1 = p->value.arg[0]; p->nodetype = p1->nodetype; if (p1->op == O_SYM) { if (p1->nodetype->class == FUNC) { p->op = O_CALL; p->value.arg[1] = nil; } else if (p1->value.sym->class == CONST) { if (compatible(p1->value.sym->type, t_real)) { p->op = O_FCON; p->value.fcon = p1->value.sym->symvalue.fconval; p->nodetype = t_real; dispose(p1); } else { p->op = O_LCON; p->value.lcon = p1->value.sym->symvalue.iconval; p->nodetype = p1->value.sym->type; dispose(p1); } } else if (isreg(p1->value.sym)) { p->op = O_SYM; p->value.sym = p1->value.sym; dispose(p1); } } else if (p1->op == O_INDIR and p1->value.arg[0]->op == O_SYM) { s = p1->value.arg[0]->value.sym; if (isreg(s)) { p1->op = O_SYM; dispose(p1->value.arg[0]); p1->value.sym = s; p1->nodetype = s; } } break; /* * Perform a cast if the call is of the form "type(expr)". */ case O_CALL: p1 = p->value.arg[0]; p->nodetype = rtype(p1->nodetype)->type; break; case O_TYPERENAME: p->nodetype = p->value.arg[1]->nodetype; break; case O_ITOF: p->nodetype = t_real; break; case O_NEG: s = p->value.arg[0]->nodetype; if (not compatible(s, t_int)) { if (not compatible(s, t_real)) { beginerrmsg(); fprintf(stderr, "\""); prtree(stderr, p->value.arg[0]); fprintf(stderr, "\" is improper type"); enderrmsg(); } else { p->op = O_NEGF; } } p->nodetype = s; break; case O_ADD: case O_SUB: case O_MUL: binaryop(p, nil); break; case O_LT: case O_LE: case O_GT: case O_GE: case O_EQ: case O_NE: binaryop(p, t_boolean); break; case O_DIVF: convert(&(p->value.arg[0]), t_real, O_ITOF); convert(&(p->value.arg[1]), t_real, O_ITOF); p->nodetype = t_real; break; case O_DIV: case O_MOD: convert(&(p->value.arg[0]), t_int, O_NOP); convert(&(p->value.arg[1]), t_int, O_NOP); p->nodetype = t_int; break; case O_AND: case O_OR: chkboolean(p->value.arg[0]); chkboolean(p->value.arg[1]); p->nodetype = t_boolean; break; case O_QLINE: p->nodetype = t_int; break; default: p->nodetype = nil; break; }}/* * Process a binary arithmetic or relational operator. * Convert from integer to real if necessary. */private binaryop (p, t)Node p;Symbol t;{ Node p1, p2; Boolean t1real, t2real; Symbol t1, t2; p1 = p->value.arg[0]; p2 = p->value.arg[1]; t1 = rtype(p1->nodetype); t2 = rtype(p2->nodetype); t1real = compatible(t1, t_real); t2real = compatible(t2, t_real); if (t1real or t2real) { p->op = (Operator) (ord(p->op) + 1); if (not t1real) { p->value.arg[0] = build(O_ITOF, p1); } else if (not t2real) { p->value.arg[1] = build(O_ITOF, p2); } p->nodetype = t_real; } else { if (size(p1->nodetype) > sizeof(integer)) { beginerrmsg(); fprintf(stderr, "operation not defined on \""); prtree(stderr, p1); fprintf(stderr, "\""); enderrmsg(); } else if (size(p2->nodetype) > sizeof(integer)) { beginerrmsg(); fprintf(stderr, "operation not defined on \""); prtree(stderr, p2); fprintf(stderr, "\""); enderrmsg(); } p->nodetype = t_int; } if (t != nil) { p->nodetype = t; }}/* * Create a node for a name. The symbol for the name has already * been chosen, either implicitly with "which" or explicitly from * the dot routine. */private Symbol namenode(p)Node p;{ register Symbol r, s; register Node np; s = p->value.sym; if (s->class == REF) { np = new(Node); np->op = p->op; np->nodetype = s; np->value.sym = s; p->op = O_INDIR; p->value.arg[0] = np; }/* * Old way * if (s->class == CONST or s->class == VAR or s->class == FVAR) { r = s->type; } else { r = s; } * */ return s;}/* * Convert a tree to a type via a conversion operator; * if this isn't possible generate an error. * * Note the tree is call by address, hence the #define below. */private convert(tp, typeto, op)Node *tp;Symbol typeto;Operator op;{ Node tree; Symbol s, t; tree = *tp; s = rtype(tree->nodetype); t = rtype(typeto); if (compatible(t, t_real) and compatible(s, t_int)) { tree = build(op, tree); } else if (not compatible(s, t)) { beginerrmsg(); fprintf(stderr, "expected integer or real, found \""); prtree(stderr, tree); fprintf(stderr, "\""); enderrmsg(); } else if (op != O_NOP and s != t) { tree = build(op, tree); } *tp = tree;}/* * Construct a node for the dot operator. * * If the left operand is not a record, but rather a procedure * or function, then we interpret the "." as referencing an * "invisible" variable; i.e. a variable within a dynamically * active block but not within the static scope of the current procedure. */public Node dot(record, fieldname)Node record;Name fieldname;{ register Node p; register Symbol s, t; if (isblock(record->nodetype)) { find(s, fieldname) where s->block == record->nodetype and s->class != FIELD and s->class != TAG endfind(s); if (s == nil) { beginerrmsg(); fprintf(stderr, "\"%s\" is not defined in ", ident(fieldname)); printname(stderr, record->nodetype); enderrmsg(); } p = new(Node); p->op = O_SYM; p->value.sym = s; p->nodetype = namenode(p); } else { p = record; t = rtype(p->nodetype); if (t->class == PTR) { s = findfield(fieldname, t->type); } else { s = findfield(fieldname, t); } if (s == nil) { beginerrmsg(); fprintf(stderr, "\"%s\" is not a field in ", ident(fieldname)); prtree(stderr, record); enderrmsg(); } if (t->class == PTR and not isreg(record->nodetype)) { p = build(O_INDIR, record); } p = build(O_DOT, p, build(O_SYM, s)); } return p;}/* * Return a tree corresponding to an array reference and do the * error checking. */public Node subscript(a, slist)Node a, slist;{ Symbol t; t = rtype(a->nodetype); if (t->language == nil) { error("unknown language"); } else { return (Node) (*language_op(t->language, L_BUILDAREF))(a, slist); }}/* * Evaluate a subscript index. */public int evalindex(s, i)Symbol s;long i;{ Symbol t; t = rtype(s); if (t->language == nil) { error("unknown language"); } else { return ((*language_op(t->language, L_EVALAREF)) (s, i)); }}/* * Check to see if a tree is boolean-valued, if not it's an error. */public chkboolean(p)register Node p;{ if (p->nodetype != t_boolean) { beginerrmsg(); fprintf(stderr, "found "); prtree(stderr, p); fprintf(stderr, ", expected boolean expression"); enderrmsg(); }}/* * Check to make sure the given tree has a type of the given class. */private chkclass(p, class)Node p;Symclass class;{ struct Symbol tmpsym; tmpsym.class = class; if (rtype(p->nodetype)->class != class) { beginerrmsg(); fprintf(stderr, "\""); prtree(stderr, p); fprintf(stderr, "\" is not a %s", classname(&tmpsym)); enderrmsg(); }}/* * Construct a node for the type of a string. */private Symbol mkstring(str)String str;{ register char *p, *q; register Symbol s; integer len; p = str; q = str; while (*p != '\0') { if (*p == '\\') { ++p; } *q = *p; ++p; ++q; } *q = '\0'; len = p - str; if (len == 1) { s = t_char; } else { s = newSymbol(nil, 0, ARRAY, t_char, nil); s->language = primlang; s->chain = newSymbol(nil, 0, RANGE, t_int, nil); s->chain->language = s->language; s->chain->symvalue.rangev.lower = 1; s->chain->symvalue.rangev.upper = len + 1; } return s;}/* * Free up the space allocated for a string type. */public unmkstring(s)Symbol s;{ dispose(s->chain);}/* * Figure out the "current" variable or function being referred to, * this is either the active one or the most visible from the * current scope. */public Symbol which(n)Name n;{ register Symbol s, p, t, f; find(s, n) where s->class != FIELD and s->class != TAG endfind(s); if (s == nil) { s = lookup(n); } if (s == nil) { error("\"%s\" is not defined", ident(n)); } else if (s == program or isbuiltin(s)) { t = s; } else { /* * Old way * if (not isactive(program)) { f = program; } else { f = whatblock(pc); if (f == nil) { panic("no block for addr 0x%x", pc); } } * * Now start with curfunc. */ p = curfunc; do { find(t, n) where t->block == p and t->class != FIELD and t->class != TAG endfind(t); p = p->block; } while (t == nil and p != nil); if (t == nil) { t = s; } } return t;}/* * Find the symbol which is has the same name and scope as the * given symbol but is of the given field. Return nil if there is none. */public Symbol findfield(fieldname, record)Name fieldname;Symbol record;{ register Symbol t; t = rtype(record)->chain; while (t != nil and t->name != fieldname) { t = t->chain; } return t;}public Boolean getbound(s,off,type,valp)Symbol s;int off;Rangetype type;int *valp;{ Frame frp; Address addr; Symbol cur; if (not isactive(s->block)) { return(false); } cur = s->block; while (cur != nil and cur->class == MODULE) { /* WHY*/ cur = cur->block; } if(cur == nil) { cur = whatblock(pc); } frp = findframe(cur); if (frp == nil) { return(false); } if(type == R_TEMP) addr = locals_base(frp) + off; else if (type == R_ARG) addr = args_base(frp) + off; else return(false); dread(valp,addr,sizeof(long)); return(true);}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -