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 void kNode_AddMethodDeclNode(KonohaContext *kctx, kNode *bk, kToken *tokenClassName, kNode *classNode) { if(bk == NULL) { return; } size_t i; kNameSpace *ns = kNode_ns(classNode); kMethod *AddMethod = KLIB kNameSpace_GetMethodByParamSizeNULL(kctx, ns, KClass_NameSpace, KMethodName_("AddMethodDecl"), 1, KMethodMatch_NoOption); for(i = 0; i < kNode_GetNodeListSize(kctx, bk); i++) { kNode *stmt = bk->NodeList->NodeItems[i]; if(stmt->syn->keyword == KSymbol_TypeDeclPattern) continue; if(stmt->syn->keyword == KSymbol_MethodDeclPattern) { KLIB kObjectProto_SetObject(kctx, stmt, KSymbol_("ClassName"), KType_Token, tokenClassName); kNodeVar *classParentBlock = kNode_GetParentNULL(classNode); if(classParentBlock == NULL) { classParentBlock = KNewNode(ns); SUGAR kNode_AddNode(kctx, classParentBlock, classNode); kNode_Type(kctx, classParentBlock, KNode_Block, KType_void); } /* Create 'NameSpace.AddMethodDecl(stmt)' */ kNode *arg0 = new_ConstNode(kctx, ns, NULL, UPCAST(ns)); kNode *arg1 = new_ConstNode(kctx, ns, NULL, UPCAST(stmt)); kNode *callNode = SUGAR new_MethodNode(kctx, ns, KClass_NameSpace, AddMethod, 2, arg0, arg1); SUGAR kNode_AddNode(kctx, classParentBlock, callNode); } else { SUGAR MessageNode(kctx, stmt, NULL, NULL, WarnTag, "%s is not available within the class clause", KSymbol_Fmt2(stmt->syn->keyword)); } } }
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 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 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 Expression_LispOperator(KonohaContext *kctx, KonohaStack *sfp) { VAR_Expression(expr, tokenList, beginIdx, currentIdx, endIdx); kNameSpace *ns = kNode_ns(expr); if(beginIdx == currentIdx && beginIdx + 1 < endIdx) { kTokenVar *opToken = tokenList->TokenVarItems[beginIdx]; kNode_Type(kctx, expr, KNode_Block, KType_var); int i = beginIdx + 1; SUGAR kNode_Op(kctx, expr, opToken, 0); while(i < endIdx) { int orig = i; kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &i, i+1, ParseExpressionOption, "("); SUGAR kNode_AddNode(kctx, expr, node); assert(i != orig); } int size = kNode_GetNodeListSize(kctx, expr); if(size == 1) { /* case (+) */ assert(0 && "(+) is not supported"); } else if(size == 2) { /* case (+ 1) */ KReturnUnboxValue(endIdx); } /* (+ 1 2 3 4) => (+ (+ (+ 1 2) 3 ) 4) */ kNode *leftNode = kNode_At(expr, 1), *rightNode; for(i = 2; i < size-1; i++) { kNode *node = KNewNode(ns); rightNode = kNode_At(expr, i); SUGAR kNode_Op(kctx, node, opToken, 2, leftNode, rightNode); leftNode = node; } rightNode = kNode_At(expr, i); KLIB kArray_Clear(kctx, expr->NodeList, 1); KLIB kArray_Add(kctx, expr->NodeList, leftNode); KLIB kArray_Add(kctx, expr->NodeList, rightNode); KDump(expr); KReturnUnboxValue(endIdx); } }
/* ------------------------------------------------------------------------ */ 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); }
//## void Node.done(); static KMETHOD Node_done(KonohaContext *kctx, KonohaStack *sfp) { kNode_Type(kctx, sfp[0].asNode, KNode_Done, KType_void); KReturnVoid(); }
//## void Node.SetType(int type); static KMETHOD Node_SetType(KonohaContext *kctx, KonohaStack *sfp) { kNode_Type(kctx, sfp[0].asNode, sfp[1].intValue, KType_void); KReturnVoid(); }