static KMETHOD Statement_try(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); DBG_P("try statement .. \n"); int ret = false; //kNode *tryNode, *catchNode, *finallyNode; //tryNode = SUGAR kNode_GetNode(kctx, stmt, NULL, KSymbol_NodePattern, K_NULLBLOCK); //ret = SUGAR TypeCheckBlock(kctx, tryNode, gma); //if(ret == false) { // KReturnUnboxValue(ret); //} //catchNode = SUGAR kNode_GetNode(kctx, stmt, NULL, KSymbol_("catch"), K_NULLBLOCK); //finallyNode = SUGAR kNode_GetNode(kctx, stmt, NULL, KSymbol_("finally"), K_NULLBLOCK); //ret = SUGAR TypeCheckBlock(kctx, tryNode, gma); //ret = SUGAR TypeCheckBlock(kctx, catchNode, gma); //if(ret == false) { // KReturnUnboxValue(ret); //} //if(finallyNode) { // ret = SUGAR TypeCheckBlock(kctx, finallyNode, gma); //} //if(ret) { // kNode_Type(stmt, TRY); //} KReturnUnboxValue(ret); }
static KMETHOD Statement_ConstDecl(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); kToken *symbolToken = SUGAR kNode_GetToken(kctx, stmt, KSymbol_SymbolPattern, NULL); ksymbol_t unboxKey = symbolToken->symbol; kNode *constNode = SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_ExprPattern, ns, KClass_INFER, TypeCheckPolicy_CONST); if(!kNode_IsError(constNode)) { KClass *constClass = KClass_(constNode->attrTypeId); ktypeattr_t type = constClass->typeId; uintptr_t unboxValue; kbool_t result = false; if(kNode_node(constNode) == KNode_Null) { // const C = String type = VirtualType_KClass; unboxValue = (uintptr_t)constClass; result = true; } else if(kNode_node(constNode) == KNode_Const) { // const C = "1" unboxValue = (uintptr_t)constNode->ObjectConstValue; result = true; } else if(kNode_node(constNode) == KNode_UnboxConst) { // const c = 1 unboxValue = constNode->unboxConstValue; result = true; } if(result) { KMakeTraceUL(trace, sfp, kNode_uline(stmt)); result = KLIB kNameSpace_SetConstData(kctx, ns, unboxKey, type, unboxValue, trace); } else { kNode_Message(kctx, stmt, ErrTag, "constant value is expected: %s%s", KSymbol_Fmt2(unboxKey)); } constNode = kNode_Type(kctx, stmt, KNode_Done, KType_void); } KReturn(constNode); }
static KMETHOD TypeCheck_Bracket(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); // [0] currentToken, [1] NULL, [2] .... size_t i; KonohaClass *requestClass = CT_(reqty); KonohaClass *paramType = (requestClass->baseTypeId == TY_Array) ? CT_(requestClass->p0) : CT_INFER; for(i = 2; i < kArray_size(expr->cons); i++) { kExpr *typedExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, i, gma, paramType, 0); if(typedExpr == K_NULLEXPR) { KReturn(typedExpr); } if(paramType->typeId == TY_var) { paramType = CT_(typedExpr->attrTypeId); } } if(requestClass->baseTypeId != TY_Array) { requestClass = (paramType->typeId == TY_var) ? CT_Array : CT_p0(kctx, CT_Array, paramType->typeId); } kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, Stmt_ns(stmt), CT_Array, MN_("[]"), -1, MethodMatch_NoOption); DBG_ASSERT(mtd != NULL); KFieldSet(expr, expr->cons->MethodItems[0], mtd); KFieldSet(expr, expr->cons->ExprItems[1], SUGAR kExpr_SetVariable(kctx, NULL, gma, TEXPR_NEW, requestClass->typeId, kArray_size(expr->cons) - 2)); KReturn(Expr_typed(expr, TEXPR_CALL, requestClass->typeId)); }
static KMETHOD TypeCheck_ExtendedIntLiteral(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(expr, gma, reqty); kToken *tk = expr->TermToken; long long n = kstrtoll(kString_text(tk->text)); KReturn(SUGAR kNode_SetUnboxConst(kctx, expr, KType_Int, (uintptr_t)n)); }
static KMETHOD TypeCheck_Float(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kToken *tk = expr->termToken; sfp[4].floatValue = strtod(S_text(tk->text), NULL); // just using tramsformation float KReturn(SUGAR kExpr_SetUnboxConstValue(kctx, expr, TY_float, sfp[4].unboxValue)); }
static KMETHOD TypeCheck_RegExp(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kToken *tk = expr->termToken; kRegExp *r = new_(RegExp, NULL, OnGcStack); DBG_ASSERT(kArray_size(tk->subTokenList) == 2); RegExp_set(kctx, r, tk->subTokenList->stringItems[0], tk->subTokenList->stringItems[1]); KReturn(SUGAR kExpr_setConstValue(kctx, expr, TY_RegExp, UPCAST(r))); }
static KMETHOD Statement_continue(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); kNode *p = stmt; while(p != NULL) { if(kNode_Is(CatchContinue, p)) { KLIB kObjectProto_SetObject(kctx, stmt, KSymbol_("continue"), KType_Node, p); KReturn(kNode_Type(kctx, stmt, KNode_Continue, KType_void)); } p = kNode_GetParentNULL(p); } KReturn(SUGAR MessageNode(kctx, stmt, NULL, ns, ErrTag, "continue statement not within a loop")); }
static KMETHOD Statement_do(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); //DBG_P("do statement .. "); kNode *exprNode = SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_ExprPattern, ns, KClass_Boolean, 0); if(kNode_IsError(exprNode)) { KReturn(exprNode); } kNode_Set(CatchContinue, stmt, true); // set before TypeCheck Block kNode_Set(CatchBreak, stmt, true); SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_BlockPattern, ns, KClass_void, 0); KReturn(kNode_Type(kctx, stmt, KNode_DoWhile, KType_void)); }
static KMETHOD TypeCheck_Getter(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kToken *tkN = expr->cons->TokenItems[0]; ksymbol_t fn = tkN->resolvedSymbol; kExpr *self = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, TY_var, 0); kNameSpace *ns = Stmt_ns(stmt); if(self != K_NULLEXPR) { kMethod *mtd = KLIB kNameSpace_GetGetterMethodNULL(kctx, ns, self->ty, fn, TY_var); if(mtd != NULL) { KFieldSet(expr->cons, expr->cons->MethodItems[0], mtd); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, reqty)); } SUGAR kStmt_Message2(kctx, stmt, tkN, ErrTag, "undefined field: %s", S_text(tkN->text)); } }
static KMETHOD Statement_CStyleFor(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); int KSymbol_InitNode = KSymbol_("init"), KSymbol_IteratorNode = KSymbol_("Iterator"); KDump(stmt); kNode *initNode = SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_InitNode, ns, KClass_void, TypeCheckPolicy_AllowEmpty); if(initNode != NULL) { kNode_Set(OpenBlock, initNode, true); } SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_IteratorNode, ns, KClass_void, TypeCheckPolicy_AllowEmpty); SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_ExprPattern, ns, KClass_Boolean, 0); kNode_Set(CatchContinue, stmt, true); // set before TypeCheckAll kNode_Set(CatchBreak, stmt, true); //kNode_Set(RedoLoop, stmt, true); SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_BlockPattern, ns, KClass_void, 0); KReturn(kNode_Type(kctx, stmt, KNode_For, KType_void)); }
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 KMETHOD TypeCheck_Defined(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); size_t i; kbool_t isDefined = true; SugarContext *sugarContext = GetSugarContext(kctx); int popIsBlockingErrorMessage = sugarContext->isBlockedErrorMessage; sugarContext->isBlockedErrorMessage = true; for(i = 1; i < kArray_size(expr->cons); i++) { kExpr *typedExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, i, gma, TY_var, TypeCheckPolicy_ALLOWVOID); if(typedExpr == K_NULLEXPR) { isDefined = false; break; } } sugarContext->isBlockedErrorMessage = popIsBlockingErrorMessage; KReturn(SUGAR kExpr_SetUnboxConstValue(kctx, expr, TY_boolean, isDefined)); }
static KMETHOD Statement_finally(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); DBG_P("finally statement .. \n"); int ret = false; //kNode *finallyNode = SUGAR kNode_GetNode(kctx, stmt, NULL, KSymbol_NodePattern, K_NULLBLOCK); //if(finallyNode != K_NULLBLOCK) { // kNode *tryNode = Node_LookupTryOrCatchNodeNULL(kctx, stmt); // if(tryNode != NULL) { // ret = SUGAR TypeCheckBlock(kctx, finallyNode, gma); // KLIB kObjectProto_SetObject(kctx, tryNode, KSymbol_("finally"), KType_Node, finallyNode); // kNode_Type(stmt, KNode_Done, KType_void); // } //} KReturnUnboxValue(ret); }
static KMETHOD Statement_namespace(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); kstatus_t result = K_CONTINUE; kToken *tk = SUGAR kNode_GetToken(kctx, stmt, KSymbol_BlockPattern, NULL); if(tk != NULL && tk->resolvedSyntaxInfo->keyword == TokenType_LazyBlock) { INIT_GCSTACK(); kNameSpace *ns = new_(NameSpace, kNode_ns(stmt), _GcStack); KTokenSeq range = {ns, KGetParserContext(kctx)->preparedTokenList}; KTokenSeq_Push(kctx, range); SUGAR Tokenize(kctx, ns, kString_text(tk->text), tk->uline, tk->indent, range.tokenList); KTokenSeq_End(kctx, range); result = SUGAR EvalTokenList(kctx, &range, NULL/*trace*/); KTokenSeq_Pop(kctx, range); RESET_GCSTACK(); kNode_Type(kctx, stmt, KNode_Done, KType_void); } KReturnUnboxValue(result == K_CONTINUE); }
static KMETHOD TypeCheck_as(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, targetExpr->ty, TypeCheckPolicy_NOCHECK); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(selfExpr->ty == targetExpr->ty || selfClass->isSubType(kctx, selfClass, targetClass)) { KReturn(selfExpr); } if(selfClass->isSubType(kctx, targetClass, selfClass)) { kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, TY_Object, MN_("as"), 0); DBG_ASSERT(mtd != NULL); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, targetClass->typeId)); } KReturn(kStmtExpr_Message(kctx, stmt, selfExpr, ErrTag, "unable to downcast: %s as %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty))); } }
static KMETHOD TypeCheck_InstanceOf(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, TY_var, 0); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(CT_is(Final, selfClass)) { kbool_t staticSubType = (selfClass == targetClass || selfClass->isSubType(kctx, selfClass, targetClass)); KReturn(SUGAR kExpr_SetUnboxConstValue(kctx, expr, TY_boolean, staticSubType)); } kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, TY_Object, MN_("<:"), 1); DBG_ASSERT(mtd != NULL); KFieldSet(expr->cons, expr->cons->MethodItems[0], mtd); kExpr *classValue = SUGAR kExpr_SetConstValue(kctx, expr->cons->ExprItems[2], targetExpr->ty, KLIB Knull(kctx, targetClass)); KFieldSet(expr->cons, expr->cons->ExprItems[2], classValue); KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, TY_boolean)); } }
static KMETHOD TypeCheck_to(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, expr, gma, reqty); kExpr *targetExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 2, gma, TY_var, 0); kExpr *selfExpr = SUGAR kStmt_TypeCheckExprAt(kctx, stmt, expr, 1, gma, targetExpr->ty, TypeCheckPolicy_NOCHECK); if(selfExpr != K_NULLEXPR && targetExpr != K_NULLEXPR) { KonohaClass *selfClass = CT_(selfExpr->ty), *targetClass = CT_(targetExpr->ty); if(selfExpr->ty == targetExpr->ty || selfClass->isSubType(kctx, selfClass, targetClass)) { kStmtExpr_Message(kctx, stmt, selfExpr, InfoTag, "no need: %s to %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty)); KReturn(selfExpr); } kNameSpace *ns = Stmt_ns(stmt); kMethod *mtd = KLIB kNameSpace_GetCoercionMethodNULL(kctx, ns, selfExpr->ty, targetExpr->ty); if(mtd == NULL) { mtd = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, selfExpr->ty, MN_("to"), 0); DBG_ASSERT(mtd != NULL); // because Object.to is found. if(mtd->typeId != selfExpr->ty) { KReturn(kStmtExpr_Message(kctx, stmt, selfExpr, ErrTag, "undefined coercion: %s to %s", TY_t(selfExpr->ty), TY_t(targetExpr->ty))); } } KReturn(SUGAR kStmtkExpr_TypeCheckCallParam(kctx, stmt, expr, mtd, gma, targetClass->typeId)); } }
/* ------------------------------------------------------------------------ */ static KMETHOD TypeCheck_Closure(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(expr, ns, reqc); kNode *texpr = K_NULLNODE; INIT_GCSTACK(); kToken *typeTk = SUGAR kNode_GetToken(kctx, expr, KSymbol_TypePattern, NULL); KClass *EnvObjectClass = NULL; KClass *envCt = CreateEnvClass(kctx, ns, typeTk, &EnvObjectClass); kMethod *mtd = CompileClosure(kctx, ns, expr, envCt, typeTk, &texpr); /* type check is OK */ if(texpr != K_NULLNODE) { /* * FunctionExpression * 0: Method * 1: EnvObject's Default Object * 2: Current LocalScope Variable * 3: ditto * 4: ... */ kNode_Type(texpr, KNode_Function, envCt->typeId); KFieldSet(expr, texpr->NodeList, new_(Array, 0, OnField)); KLIB kArray_Add(kctx, texpr->NodeList, mtd); KLIB kArray_Add(kctx, texpr->NodeList, KLIB Knull(kctx, EnvObjectClass)); size_t i = 0; struct KGammaLocalData *genv = ns->genv; if(genv->thisClass == KClass_NameSpace) { i = 1; } for(; i < genv->localScope.varsize; i++) { kNode *node = new_VariableNode(kctx, ns, KNode_Local, genv->localScope.varItems[i].attrTypeId, i); KLIB kArray_Add(kctx, texpr->NodeList, node); } } RESET_GCSTACK(); KReturn(texpr); }
static KMETHOD Statement_catch(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck(stmt, ns, reqc); DBG_P("catch statement .. \n"); int ret = false; //// check "catch(...)" ////ret = SUGAR TypeCheckNodeByName(kctx, stmt, KSymbol_NodePattern, ns, KClass_Exception, 0); //kNode *catchNode = SUGAR kNode_GetNode(kctx, stmt, NULL, KSymbol_NodePattern, K_NULLBLOCK); //kNode *parentNode = Node_LookupTryOrCatchNodeNULL(kctx, stmt); //if(catchNode != K_NULLBLOCK && parentNode != NULL) { // ret = SUGAR TypeCheckBlock(kctx, catchNode, gma); // kNode *expr = SUGAR kNode_GetNode(kctx, stmt, KSymbol_NodePattern, K_NULLNODE); // KLIB kObjectProto_SetObject(kctx, parentNode, KSymbol_NodePattern, KType_Exception, expr); // KLIB kObjectProto_SetObject(kctx, parentNode, KSymbol_("catch"), KType_Node, stmt); // kNode_Type(stmt, KNode_Done, KType_void); //} else { // kNode_Message(kctx, stmt, ErrTag, "upper stmt is not try/catch"); // KReturnUnboxValue(false); //} KReturnUnboxValue(ret); }