static SymPtr LookupIdent(char **name) { SymPtr sym=NULL,parent; /* check this class only */ if( in_class && Token==tSELF ) { SkipToken(tSELF); SkipToken(tPERIOD); *name = GetIdent(); sym = SymFindLevel(*name,(SymGetScope()-1)); } /* check super class only */ else if( in_class && Token==tSUPER && base_class->super!=NULL ) { SkipToken(tSUPER); SkipToken(tPERIOD); *name = GetIdent(); sym = SymFindLocal(*name,base_class->super); if( sym!=NULL && sym->flags&SYM_PRIVATE ) { compileError("attempt to access private field '%s'",*name); NextToken(); return COMPILE_ERROR; } } /* check all super classes */ else if( in_class ) { *name = GetIdent(); parent=base_class->super; while(parent!=NULL) { sym = SymFindLocal(*name,parent); if(sym!=NULL) break; parent=parent->super; } if( sym!=NULL && sym->flags&SYM_PRIVATE ) { compileError("attempt to access private field '%s'",*name); NextToken(); return COMPILE_ERROR; } } /* check globals */ if( sym==NULL ) { *name = GetIdent(); sym = SymFind(*name); } return sym; }
SymEntry* FindSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table * entry that encodes the size of the symbol or NULL if there is no such entry. */ { return SymFindLocal (Sym, &SizeEntryName, SYM_FIND_EXISTING); }
SymEntry* GetSizeOfSymbol (SymEntry* Sym) /* Get the size of a symbol table entry. The function returns the symbol table * entry that encodes the size of the symbol and will create a new one if it * does not exist. */ { return SymFindLocal (Sym, &SizeEntryName, SYM_ALLOC_NEW); }
static SymPtr FieldReference(SymPtr clas) { SymPtr field,parent; char *fieldname; SkipToken(tPERIOD); fieldname = GetIdent(); /* lookup field in class and parents */ parent=clas; while( parent!=NULL ) { field = SymFindLocal(fieldname,parent); if( field!=NULL ) break; parent = parent->super; } if( field==NULL ) { compileError("field '%s' not found",fieldname); return NULL; } field->flags |= SYM_FIELD; /* MCC */ if( field->flags&SYM_PRIVATE ) { compileError("attempt to access private field '%s'",fieldname); return NULL; } if( field->flags&SYM_PROTECTED && !in_class ) { compileError("attempt to access protected field '%s'",fieldname); return NULL; } NextToken(); if( is_func_kind(field) ) { return field; } if( is_global_kind(clas) ) { vm_genI(op_getglobal,clas->num); } else if( is_local_kind(clas) ) { vm_genI(op_getlocal,clas->num); } return field; }
SymEntry* ParseAnySymName (SymFindAction Action) /* Parse a cheap local symbol or a a (possibly scoped) symbol name, search * for it in the symbol table and return the symbol table entry. */ { SymEntry* Sym; /* Distinguish cheap locals and other symbols */ if (CurTok.Tok == TOK_LOCAL_IDENT) { Sym = SymFindLocal (SymLast, &CurTok.SVal, Action); NextTok (); } else { Sym = ParseScopedSymName (Action); } /* Return the symbol found */ return Sym; }
static void AssignmentStatement(void) { Int32 type,count; SymPtr sym,clas_init=NULL; SymPtr parents[16]; sym = Lhs(); if( sym==NULL ) { return; } CheckClassMember(sym); SkipToken(tEQUALS); if(sym->flags&SYM_DEFINED) { compileError("cannot reassign constant"); return; } else if(sym->flags&SYM_CONSTANT) { sym->flags |= SYM_DEFINED; } /* CheckClassMember(sym); */ new_class=NULL; type=Expr(); sym->object.type = type; switch(sym->kind) { case LOCAL_KIND: vm_genI(op_setlocal,sym->num); break; case GLOBAL_KIND: vm_genI(op_setglobal,sym->num); break; case FIELD_KIND: vm_genI(op_setfield,sym->num); break; default: compileError("invalid assignment"); break; } if( type==CLASS_TYPE && new_class != NULL ) { sym->clas = new_class; sym->super = new_class->super; sym->locals = new_class->locals; /* First build a list of all super classes */ count=0; clas_init=sym; while( clas_init!=NULL ) { parents[count++] = clas_init; clas_init = clas_init->super; } /* Now call all constructors in reverse order */ count--; while( count>=0 ) { clas_init = SymFindLocal(NEW,parents[count]); FunctionCall(clas_init,sym); vm_gen0(op_pop); count--; } /* call user defined constructor */ clas_init=SymFindLocal("init",sym); if( clas_init!=NULL ) { if( (Token==tLPAREN && clas_init->nargs!=0) || (Token!=tLPAREN && clas_init->nargs==0) ) { FunctionCall(clas_init,sym); vm_gen0(op_pop); } } } }