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_Getter(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kToken *fieldToken = expr->NodeList->TokenItems[0]; ksymbol_t fn = fieldToken->symbol; kNode *self = KLIB TypeCheckNodeAt(kctx, expr, 1, ns, KClass_INFER, 0); if(self != K_NULLNODE) { kMethod *mtd = KLIB kNameSpace_GetGetterMethodNULL(kctx, ns, KClass_(self->typeAttr), fn); if(mtd != NULL) { KFieldSet(expr->NodeList, expr->NodeList->MethodItems[0], mtd); KReturn(KLIB TypeCheckMethodParam(kctx, mtd, expr, ns, reqc)); } else { // dynamic field o.name => o.get(name) kparamtype_t p[1] = {{KType_Symbol}}; kparamId_t paramdom = KLIB Kparamdom(kctx, 1, p); mtd = KLIB kNameSpace_GetMethodBySignatureNULL(kctx, ns, KClass_(self->typeAttr), KMethodNameAttr_Getter, paramdom, 1, p); if(mtd != NULL) { KFieldSet(expr->NodeList, expr->NodeList->MethodItems[0], mtd); KLIB kArray_Add(kctx, expr->NodeList, new_UnboxConstNode(kctx, ns, KType_Symbol, KSymbol_Unmask(fn))); KReturn(KLIB TypeCheckMethodParam(kctx, mtd, expr, ns, reqc)); } } KLIB MessageNode(kctx, stmt, fieldToken, ns, ErrTag, "undefined field: %s", kString_text(fieldToken->text)); } }
// @Public @Hidden Func[T] Func[T].Create(Object env, Method mtd) static KMETHOD Func_Create(KonohaContext *kctx, KonohaStack *sfp) { kFuncVar *fo = (kFuncVar *) sfp[0].asFunc; kObject *env = sfp[1].asObject; kMethod *mtd = sfp[2].asMethod; KFieldSet(fo, fo->env, env); KFieldSet(fo, fo->method, mtd); KReturn(fo); }
//## eventCBArg eventCBArg.new(Func[void, int, Object arg] cb, Object cbArg); static KMETHOD eventCBArg_new(KonohaContext *kctx, KonohaStack *sfp) { struct eventCBArg *cbarg = (struct eventCBArg *) sfp[0].asObject; kFunc *cb = sfp[1].asFunc; kObjectVar *cbArg = sfp[2].asObjectVar; //deliver callback method cbarg->kctx = kctx; KFieldSet(cbarg, cbarg->kcb, cb); KFieldSet(cbarg, cbarg->arg, cbArg); KReturn(cbarg); }
//## void Token.setSubArray(String[] sub); static KMETHOD Token_setSubArray(KonohaContext *kctx, KonohaStack *sfp) { kTokenVar *tk = (kTokenVar *) sfp[0].asToken; kArray *sub = sfp[1].asArray; KFieldSet(tk, tk->subTokenList, sub); KReturnVoid(); }
//## void Token.setText(String text); static KMETHOD Token_setText(KonohaContext *kctx, KonohaStack *sfp) { kTokenVar *tk = (kTokenVar *) sfp[0].asToken; kString *text = sfp[1].asString; KFieldSet(tk, tk->text, text); KReturnVoid(); }
static KMETHOD KMethodFunc_ObjectFieldSetter(KonohaContext *kctx, KonohaStack *sfp) { size_t delta = sfp[K_MTDIDX].calledMethod->delta; kObjectVar *o = sfp[0].asObjectVar; KFieldSet(o, o->fieldObjectItems[delta], sfp[1].asObject); KReturn(sfp[1].asObject); }
static kToken* new_ParsedExprToken(KonohaContext *kctx, kNameSpace *ns, kExpr *expr) { kTokenVar *ParsedExprToken = new_(TokenVar, 0, OnGcStack); ParsedExprToken->resolvedSyntaxInfo = SYN_(ns, KW_ExprPattern); KFieldSet(ParsedExprToken, ParsedExprToken->parsedExpr, expr); return (kToken *)ParsedExprToken; }
static kBlock* kStmt_ParseClassBlockNULL(KonohaContext *kctx, kStmt *stmt, kToken *tokenClassName) { kBlock *bk = NULL; kToken *blockToken = (kToken *)kStmt_GetObject(kctx, stmt, KW_BlockPattern, NULL); if(blockToken != NULL && blockToken->resolvedSyntaxInfo->keyword == KW_BlockPattern) { const char *cname = S_text(tokenClassName->text); TokenSeq range = {Stmt_ns(stmt), GetSugarContext(kctx)->preparedTokenList}; TokenSeq_Push(kctx, range); SUGAR TokenSeq_Tokenize(kctx, &range, S_text(blockToken->text), blockToken->uline); { TokenSeq sourceRange = {range.ns, range.tokenList, range.endIdx}; kToken *prevToken = blockToken; int i; for(i = range.beginIdx; i < range.endIdx; i++) { kToken *tk = range.tokenList->TokenItems[i]; if(tk->hintChar == '(' && prevToken->unresolvedTokenType == TokenType_SYMBOL && strcmp(cname, S_text(prevToken->text)) == 0) { kTokenVar *newToken = new_(TokenVar, TokenType_SYMBOL, sourceRange.tokenList); KFieldSet(newToken, newToken->text, SYM_s(MN_new)); } KLIB kArray_Add(kctx, sourceRange.tokenList, tk); prevToken = tk; } TokenSeq_end(kctx, (&sourceRange)); bk = SUGAR new_kBlock(kctx, stmt/*parent*/, NULL, &sourceRange); KLIB kObject_setObject(kctx, stmt, KW_BlockPattern, TY_Block, bk); } TokenSeq_Pop(kctx, range); } return bk; }
static struct KVirtualCode *FuelVM_GenerateVirtualCode(KonohaContext *kctx, kMethod *mtd, kNode *block, int option) { if(unlikely(AbstractMethodPtr == 0)) { AbstractMethodPtr = mtd->invokeKMethodFunc; } kNameSpace *ns = kNode_ns(block); KBuilder builderbuf = {}, *builder = &builderbuf; FuelIRBuilder Builder = {}; INIT_GCSTACK(); IRBuilder_Init(&Builder, kctx, ns); builder->builder = &Builder; builder->common.api = ns->builderApi; Block *EntryBlock = CreateBlock(BLD(builder)); IRBuilder_setBlock(BLD(builder), EntryBlock); INode *Self = SetUpArguments(kctx, &Builder, mtd); SUGAR VisitNode(kctx, builder, block, NULL); if(!Block_HasTerminatorInst(BLD(builder)->Current)) { if(mtd->mn == MN_new) { INode *Ret = CreateReturn(BLD(builder), Self); INode_setType(Ret, ConvertToTypeId(kctx, mtd->typeId)); } else { ktypeattr_t retTy = kMethod_GetReturnType(mtd)->typeId; if(retTy == KType_void) { CreateReturn(BLD(builder), 0); } else { enum TypeId Type = ConvertToTypeId(kctx, retTy); INode *Ret; if(KType_Is(UnboxType, retTy)) { SValue V; V.bits = 0; Ret = CreateConstant(BLD(builder), Type, V); } else { kObject *obj = KLIB Knull(kctx, KClass_(retTy)); Ret = CreateObject(BLD(builder), Type, (void *)obj); } Ret = CreateReturn(BLD(builder), Ret); INode_setType(Ret, Type); CreateReturn(BLD(builder), 0); } } } RESET_GCSTACK(); IMethod Mtd = {kctx, mtd, EntryBlock, ns}; BLD(builder)->Method = &Mtd; bool JITCompiled = false; union ByteCode *code = IRBuilder_Compile(BLD(builder), &Mtd, option, &JITCompiled); if(mtd->invokeKMethodFunc == FuelVM_RunVirtualMachine) { mtd->virtualCodeApi_plus1[-1]->FreeVirtualCode(kctx, mtd->vcode_start); } KLIB kMethod_SetFunc(kctx, mtd, 0); if(JITCompiled) { KLIB kMethod_SetFunc(kctx, mtd, (KMethodFunc) code); } KFieldSet(mtd, ((kMethodVar *)mtd)->CompiledNode, block); IRBuilder_Exit(&Builder); return (struct KVirtualCode *) code; }
static KMETHOD String_toIterator(KonohaContext *kctx, KonohaStack *sfp) { kIterator *itr = (kIterator *)KLIB new_kObject(kctx, OnStack, CT_StringIterator, 0); KFieldSet(itr, itr->source, sfp[0].asObject); itr->hasNext = String_hasNext; itr->setNextResult = String_setNextResult; KReturn(itr); }
//## void cbufferevent.setcb(buffereventCBArg cbarg); static KMETHOD cbufferevent_setcb(KonohaContext *kctx, KonohaStack *sfp) { kcbufferevent *bev = (kcbufferevent *)sfp[0].asObject; kbuffereventCBArg *cbArg = (kbuffereventCBArg *)sfp[1].asObject; KFieldSet(cbArg, cbArg->cbev, bev); bufferevent_setcb(bev->bev, Cbev_readCB_1st, Cbev_writeCB_1st, Cbev_eventCB_1st, cbArg); KReturnVoid(); }
//## buffereventCBArg buffereventCBArg.new(Func[void, int, Object arg] cb, Object cbArg); static KMETHOD buffereventCBArg_new(KonohaContext *kctx, KonohaStack *sfp) { struct buffereventCBArg *bcbarg = (struct buffereventCBArg *) sfp[0].asObject; kObjectVar *cbArg = sfp[4].asObjectVar; //deliver callback method bcbarg->kctx = kctx; enum e_buffereventCB i; for (i = BEV_ReadCB; i < NUM_BuffereventCB; i++){ kFunc *cb = sfp[i + 1].asFunc; KFieldSet(bcbarg, bcbarg->kcb[i], cb); } /* !!ATTENTION!! 'bcbarg->cbev' will be set in cbufferevent_setcb() function */ KFieldSet(bcbarg, bcbarg->arg, cbArg); KReturn(bcbarg); }
static KMETHOD Array_toIterator(KonohaContext *kctx, KonohaStack *sfp) { kArray *a = sfp[0].asArray; KonohaClass *cIterator = CT_p0(kctx, CT_Iterator, O_ct(a)->p0); kIterator *itr = (kIterator *)KLIB new_kObject(kctx, OnStack, cIterator, 0); KFieldSet(itr, itr->arrayList, a); itr->hasNext = Array_hasNext; itr->setNextResult = TY_isUnbox(O_ct(a)->p0) ? Array_setNextResultUnbox : Array_setNextResult; KReturn(itr); }
static KMETHOD Array_toIterator(KonohaContext *kctx, KonohaStack *sfp) { kArray *a = sfp[0].asArray; KClass *cIterator = KClass_p0(kctx, KClass_Iterator, kObject_class(a)->p0); kIterator *itr = (kIterator *)KLIB new_kObject(kctx, OnStack, cIterator, 0); KFieldSet(itr, itr->arrayList, a); itr->hasNext = Array_hasNext; itr->setNextResult = KType_Is(UnboxType, kObject_class(a)->p0) ? Array_SetNextResultUnbox : Array_SetNextResult; KReturn(itr); }
static kbool_t KClass_SetClassFieldObjectValue(KonohaContext *kctx, KClassVar *definedClass, ksymbol_t sym, kObject *ObjectValue) { int i; for(i = definedClass->fieldsize - 1; i >= 0; i--) { if(definedClass->fieldItems[i].name == sym && kObject_class(definedClass->defaultNullValueVar->fieldObjectItems[i]) == kObject_class(ObjectValue)) { kObjectVar *o = definedClass->defaultNullValueVar; KFieldSet(o, o->fieldObjectItems[i], ObjectValue); return true; } } return false; }
//## method void Array.set(Int n, T0 v); static KMETHOD Array_set(KonohaContext *kctx, KonohaStack *sfp) { kArray *a = sfp[0].asArray; size_t n = (size_t)sfp[1].intValue; KCheckIndex(n, kArray_size(a)); if(kArray_isUnboxData(a)) { a->unboxItems[n] = sfp[2].unboxValue; } else { KFieldSet(a, a->ObjectItems[n], sfp[2].asObject); } }
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 kbool_t KonohaClass_setClassFieldObjectValue(KonohaContext *kctx, KonohaClassVar *definedClass, ksymbol_t sym, kObject *ObjectValue) { int i; for(i = definedClass->fieldsize - 1; i >= 0; i--) { if(definedClass->fieldItems[i].fn == sym && O_ct(definedClass->defaultNullValueVar_OnGlobalConstList->fieldObjectItems[i]) == O_ct(ObjectValue)) { kObjectVar *o = definedClass->defaultNullValueVar_OnGlobalConstList; KFieldSet(o, o->fieldObjectItems[i], ObjectValue); return true; } } return false; }
//## @Native Thread Thread.create(Func f) static KMETHOD Thread_create(KonohaContext *kctx, KonohaStack *sfp) { INIT_GCSTACK(); kFunc *f = sfp[1].asFunc; KLIB kMethod_DoLazyCompilation(kctx, (f)->mtd, NULL, HatedLazyCompile); kThread *thread = (kThread *)KLIB new_kObject(kctx, _GcStack, KGetReturnType(sfp), 0); thread->rootCtx = kctx; //TODO getRootContext thread->kctx = KLIB KonohaContext_Init(kctx, kctx->platApi); KFieldSet(thread, thread->func, f); pthread_create(&(thread->thread), NULL, spawn_start, thread); RESET_GCSTACK(); // FIXME?? Not sure this is okay?? KReturn(thread); }
//## Person Person.new(String name, int age); static KMETHOD Person_new(KonohaContext *kctx, KonohaStack *sfp) { /* You do not need to allocate object because * object is allocated by Runtime. */ struct Person *p = (struct Person *) sfp[0].asObject; kString *name = sfp[1].asString; kint_t age = sfp[2].intValue; /* If you want to determine the type of the return value, * please check KGetReturnType(sfp) . */ KFieldSet(p, p->name, name); p->age = age; KReturn(p); }
static KMETHOD Array_reverse(KonohaContext *kctx, KonohaStack *sfp) { kArray *a = sfp[0].asArray; size_t asize = kArray_size(a); size_t asize_half = asize / 2; size_t i; if(kArray_isUnboxData(a)) { for(i = 0; i != asize_half; ++i) { uintptr_t temp = a->unboxItems[asize - 1 - i]; a->unboxItems[asize - 1 - i] = a->unboxItems[i]; a->unboxItems[i] = temp; } } else { for(i = 0; i != asize_half; ++i){ kObject *temp = a->ObjectItems[asize - 1 - i]; KFieldSet(a, a->ObjectItems[asize - 1 - i], a->ObjectItems[i]); KFieldSet(a, a->ObjectItems[i], temp); } } KReturn(a); }
static void RegExp_set(KonohaContext *kctx, kRegExp *re, kString *ptns, kString *opts) { const char *ptn = S_text(ptns); const char *opt = S_text(opts); kRegExp_setOptions(re, opt); KFieldSet(re, re->pattern, ptns); re->reg = pcre_regmalloc(kctx, ptns); int cflags = pcre_ParseComplflags(kctx, opt); if(!kString_is(ASCII, ptns)) { /* Add 'u' option when the pattern is multibyte string. */ cflags |= PCRE_UTF8; } pcre_regcomp(kctx, re->reg, ptn, cflags); re->eflags = pcre_ParseExecflags(kctx, opt); }
//## int Token.parse(symbol keyword, String s, int begin, int end); static KMETHOD Token_Parse(KonohaContext *kctx, KonohaStack *sfp) { kTokenVar *tk = (kTokenVar *) sfp[0].asToken; if(IS_NOTNULL(tk)) { kString *text = sfp[2].asString; size_t len = S_size(text); size_t beginIdx = (size_t)sfp[3].intValue; size_t endIdx = (size_t)sfp[4].intValue; if(beginIdx <= endIdx && endIdx < len) { ksymbol_t keyword = (ksymbol_t)sfp[1].intValue; tk->unresolvedTokenType = keyword; KFieldSet(tk, tk->text, KLIB new_kString(kctx, OnField, S_text(text) + beginIdx, endIdx - beginIdx, 0)); } } KReturnUnboxValue(sfp[4].intValue); }
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 Array_newArray(KonohaContext *kctx, KonohaStack *sfp) { kArrayVar *a = (kArrayVar *)sfp[0].asObject; size_t asize = (size_t)sfp[1].intValue; a->bytemax = asize * sizeof(uintptr_t); kArray_SetSize(a, asize); a->ObjectItems = (kObject**)KCalloc_UNTRACE(a->bytemax, 1); if(!kArray_isUnboxData(a)) { size_t i; kObject *null = KLIB Knull(kctx, CT_(O_p0(a))); for(i = 0; i < asize; i++) { KFieldSet(a, a->ObjectItems[i], null); } } KReturn(a); }
static KMETHOD TypeCheck_UntypedAssign(KonohaContext *kctx, KonohaStack *sfp) { VAR_TypeCheck2(stmt, expr, ns, reqc); kNodeVar *leftHandNode = (kNodeVar *)kNode_At(expr, 1); if(kNode_isSymbolTerm(leftHandNode)) { kNode *texpr = KLIB TypeVariableNULL(kctx, leftHandNode, ns, KClass_INFER); if(texpr == NULL) { kNode *rightHandNode = KLIB TypeCheckNodeAt(kctx, expr, 2, ns, KClass_INFER, 0); if(rightHandNode != K_NULLNODE) { DeclVariable(kctx, stmt, ns, rightHandNode->typeAttr, leftHandNode); } } else { KFieldSet(expr->NodeList, expr->NodeList->NodeItems[1], texpr); } } }
static KMETHOD Array_newList(KonohaContext *kctx, KonohaStack *sfp) { kArrayVar *a = (kArrayVar *)sfp[0].asObject; size_t i = 0; KonohaStack *p = sfp+1; if(kArray_isUnboxData(a)) { for(i = 0; p + i < kctx->esp; i++) { a->unboxItems[i] = p[i].unboxValue; } } else { for(i = 0; p + i < kctx->esp; i++) { KFieldSet(a, a->ObjectItems[i], p[i].asObject); } } kArray_SetSize(a, i); DBG_ASSERT(a->bytesize <= a->bytemax); KReturn(a); }
static kbool_t KClass_AddField(KonohaContext *kctx, KClass *ct, ktypeattr_t typeattr, ksymbol_t sym) { kuhalfword_t pos = ct->fieldsize; if(unlikely(ct->classMethodList == K_EMPTYARRAY)) { ((KClassVar *)ct)->classMethodList = new_(MethodArray, 8, OnGlobalConstList); /*FIXME WriteBarrier */ } INIT_GCSTACK(); if(pos < ct->fieldAllocSize) { KClassVar *definedClass = (KClassVar *)ct; definedClass->fieldsize += 1; definedClass->fieldItems[pos].name = sym; if(KType_Is(UnboxType, typeattr)) { definedClass->defaultNullValueVar->fieldUnboxItems[pos] = 0; definedClass->fieldItems[pos].typeAttr = typeattr; } else { kObjectVar *o = definedClass->defaultNullValueVar; KFieldSet(o, o->fieldObjectItems[pos], KLIB Knull(kctx, KClass_(typeattr))); definedClass->fieldItems[pos].typeAttr = typeattr | KTypeAttr_Boxed; } if(1/*KHalfFlag_Is(flag, kField_Getter)*/) { kMethod *mtd = new_FieldGetter(kctx, _GcStack, definedClass->typeId, sym, KTypeAttr_Unmask(typeattr), pos); KLIB kArray_Add(kctx, ct->classMethodList, mtd); } if(!KTypeAttr_Is(ReadOnly, typeattr)/*KHalfFlag_Is(flag, kField_Setter)*/) { kMethod *mtd = new_FieldSetter(kctx, _GcStack, definedClass->typeId, sym, KTypeAttr_Unmask(typeattr), pos); KLIB kArray_Add(kctx, ct->classMethodList, mtd); } } else { if(1/*KHalfFlag_Is(flag, kField_Getter)*/) { kMethod *mtd = new_PrototypeGetter(kctx, _GcStack, ct->typeId, sym, KTypeAttr_Unmask(typeattr)); KLIB kArray_Add(kctx, ct->classMethodList, mtd); } if(!KTypeAttr_Is(ReadOnly, typeattr)/*KHalfFlag_Is(flag, kField_Setter)*/) { kMethod *mtd = new_PrototypeSetter(kctx, _GcStack, ct->typeId, sym, KTypeAttr_Unmask(typeattr)); KLIB kArray_Add(kctx, ct->classMethodList, mtd); } } RESET_GCSTACK(); return true; }
//## DIR System.opendir(String path) static KMETHOD System_opendir(KonohaContext *kctx, KonohaStack *sfp) { KMakeTrace(trace, sfp); char buffer[K_PATHMAX]; kString *path = sfp[1].asString; const char *systemPath = PLATAPI I18NModule.formatSystemPath(kctx, buffer, sizeof(buffer), kString_text(path), kString_size(path), trace); DIR *d = opendir(systemPath); if(d == NULL) { int fault = KLIB DiagnosisFaultType(kctx, kString_GuessUserFault(path)|SystemError, trace); KTraceErrorPoint(trace, fault, "opendir", LogText("dirname", kString_text(path)), LogErrno); KLIB KRuntime_raise(kctx, KException_("IO"), fault, NULL, sfp); } kDir *dir = (kDir *)KLIB new_kObject(kctx, OnStack, KGetReturnType(sfp), (uintptr_t)d); KFieldSet(dir, dir->PathInfoNULL, path); if(!PLATAPI I18NModule.isSystemCharsetUTF8(kctx)) { dir->readerIconv = PLATAPI I18NModule.iconvSystemCharsetToUTF8(kctx, trace); } KReturn(dir); }