// @SmartReturn Object Prototype.get(Symbol symbol) static KMETHOD Prototype_get(KonohaContext *kctx, KonohaStack *sfp) { KClass *targetClass = KGetReturnType(sfp); DBG_P("requesting type=%s", KClass_text(targetClass)); ksymbol_t symbol = sfp[1].intValue; KKeyValue *kvs = KLIB kObjectProto_GetKeyValue(kctx, sfp[0].asObject, symbol); if(kvs != NULL) { KClass *c = KClass_(kvs->attrTypeId); if(targetClass == c) { if(KClass_Is(UnboxType, targetClass)) { KReturnUnboxValue(kvs->unboxValue); } else { KReturnField(kvs->ObjectValue); } } DBG_P("requesting type=%s instanceof %s ? %d", KClass_text(c), KClass_text(targetClass), c->isSubType(kctx, c, targetClass)); if(c->isSubType(kctx, c, targetClass)) { if(KClass_Is(UnboxType, c)) { if(KClass_Is(UnboxType, targetClass)) { KReturnUnboxValue(kvs->unboxValue); } else { DBG_P("boxing type=%s instanceof %s ? %d", KClass_text(c), KClass_text(targetClass), c->isSubType(kctx, c, targetClass)); KReturn(KLIB new_kObject(kctx, OnStack, c, kvs->unboxValue)); } } KReturnField(kvs->ObjectValue); } } KReturnUnboxValue(0); // return default value }
static void KStackReturnTypeCheck(KonohaContext *kctx, KonohaStack *sfp, kMethod *mtd, KClass *reqType, KClass *thisClass) { if(!kMethod_Is(SmartReturn, mtd)) { KClass *returnType = kMethod_GetReturnType(mtd); returnType = returnType->realtype(kctx, returnType, thisClass); if(reqType == returnType || returnType->isSubType(kctx, returnType, reqType)) { if(KClass_Is(UnboxType, returnType) && !KClass_Is(UnboxType, reqType)) { KReturn(KLIB new_kObject(kctx, OnStack, returnType, sfp[K_RTNIDX].unboxValue)); } } else { ThrowTypeError(kctx, sfp, -1); } } }
static KMETHOD Statement_class(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); kToken *tokenClassName = SUGAR kNode_GetToken(kctx, stmt, KSymbol_("$ClassName"), NULL); int isNewlyDefinedClass = false; KClassVar *definedClass = (KClassVar *)KLIB kNameSpace_GetClassByFullName(kctx, ns, kString_text(tokenClassName->text), kString_size(tokenClassName->text), NULL); if(definedClass == NULL) { // Already defined kshortflag_t cflag = kNode_ParseClassFlag(kctx, stmt, KClassFlag_Virtual); KMakeTraceUL(trace, sfp, kNode_uline(stmt)); definedClass = kNameSpace_DefineClassName(kctx, ns, cflag, tokenClassName->text, trace); isNewlyDefinedClass = true; } kNode *block = kNode_ParseClassNodeNULL(kctx, stmt, tokenClassName); size_t declsize = kNode_countFieldSize(kctx, block); if(isNewlyDefinedClass) { // Already defined KClass *superClass = KClass_Object; kToken *tokenSuperClass= SUGAR kNode_GetToken(kctx, stmt, KSymbol_("extends"), NULL); if(tokenSuperClass != NULL) { DBG_ASSERT(Token_isVirtualTypeLiteral(tokenSuperClass)); superClass = KClass_(Token_typeLiteral(tokenSuperClass)); if(KClass_Is(Final, superClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s is final", KClass_text(superClass))); } if(KClass_Is(Virtual, superClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s is still virtual", KClass_text(superClass))); } } size_t initsize = (block != NULL) ? declsize : initFieldSizeOfVirtualClass(superClass); KClass_InitField(kctx, definedClass, superClass, initsize); } else { if(declsize > 0 && !KClass_Is(Virtual, definedClass)) { KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "%s has already defined", KClass_text(definedClass))); } } if(block != NULL) { if(!kNode_declClassField(kctx, block, ns, definedClass)) { KReturnUnboxValue(false); } KClass_Set(Virtual, definedClass, false); } kToken_SetTypeId(kctx, tokenClassName, ns, definedClass->typeId); kNode_AddMethodDeclNode(kctx, block, tokenClassName, stmt); KReturn(kNode_Type(kctx, stmt, KNode_Done, KType_void)); }
static void KBuffer_WriteValue(KonohaContext *kctx, KBuffer *wb, KClass *c, KonohaStack *sfp) { if(KClass_Is(UnboxType, c)) { c->p(kctx, sfp, 0, wb); } else { KLIB kObject_WriteToBuffer(kctx, sfp[0].asObject, false/*delim*/, wb, NULL, 0); } }
//## Node Node.setConstValue(Object value); static KMETHOD Node_setConstValue(KonohaContext *kctx, KonohaStack *sfp) { kNodeVar *expr = (kNodeVar *)sfp[0].asNode; KClass *ct = kObject_class(sfp[1].asObject); if(KClass_Is(UnboxType, (ct))) { KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, ct->typeId, sfp[1].unboxValue)); } KReturn(SUGAR kNode_SetConst(kctx, expr, ct, sfp[1].asObject)); }
// @SmartReturn void Object.set(Symbol symbol, Object value) static KMETHOD Prototype_SetObject(KonohaContext *kctx, KonohaStack *sfp) { ksymbol_t symbol = (ksymbol_t)sfp[1].intValue; KClass *c = kObject_class(sfp[2].asObject); if(KClass_Is(UnboxType, c)) { KLIB kObjectProto_SetUnboxValue(kctx, sfp[0].asObject, symbol, c->typeId, kObject_Unbox(sfp[2].asObject)); } else { KLIB kObjectProto_SetObject(kctx, sfp[0].asObject, symbol, c->typeId, sfp[2].asObject); } }
static void KStackDynamicTypeCheck(KonohaContext *kctx, KonohaStack *sfp, kMethod *mtd, KClass *thisClass) { kushort_t i; kParam *pa = kMethod_GetParam(mtd); for(i = 0; i < pa->psize; i++) { KClass *objectType = kObject_class(sfp[i+1].asObject); KClass *paramType = KClass_(pa->paramtypeItems[i].attrTypeId); paramType = paramType->realtype(kctx, paramType, thisClass); if(objectType == paramType || objectType->isSubType(kctx, objectType, paramType)) { if(KClass_Is(UnboxType, paramType)) { KStackSetUnboxValue(sfp[i+1].unboxValue, kObject_Unbox(sfp[i+1].asObject)); } continue; // OK } ThrowTypeError(kctx, sfp, i + 1); } }
static KMETHOD TypeCheck_InstanceOf(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); /* selfNode and targetNode allow void type * e.g. "'a' instanceof void" */ kNode *selfNode = SUGAR TypeCheckNodeAt(kctx, expr, 1, ns, KClass_INFER, TypeCheckPolicy_AllowVoid); kNode *targetNode = SUGAR TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, TypeCheckPolicy_AllowVoid); if(selfNode != K_NULLNODE && targetNode != K_NULLNODE) { KClass *selfClass = KClass_(selfNode->attrTypeId), *targetClass = KClass_(targetNode->attrTypeId); if(KClass_Is(Final, selfClass)) { kbool_t staticSubType = (selfClass == targetClass || selfClass->isSubType(kctx, selfClass, targetClass)); KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, KType_Boolean, staticSubType)); } kNameSpace *ns = kNode_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_Object, KMethodName_("instanceof"), 1, KMethodMatch_NoOption); DBG_ASSERT(mtd != NULL); kNode *classValue = SUGAR kNode_SetConst(kctx, expr->NodeList->NodeVarItems[2], NULL, KLIB Knull(kctx, targetClass)); KFieldSet(expr->NodeList, expr->NodeList->NodeItems[2], classValue); KReturn(SUGAR TypeCheckMethodParam(kctx, mtd, expr, ns, KClass_Boolean)); } }