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)); } }
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; }
// Copied from namespace.h. static void kNameSpace_AppendArrayRef(KonohaContext *kctx, kNameSpace *ns, const kArray **arrayRef, kObject *o) { if(arrayRef[0] == NULL) { ((kArray**)arrayRef)[0] = new_(Array, 0, ns->NameSpaceConstList); } DBG_ASSERT(IS_Array(arrayRef[0])); KLIB kArray_Add(kctx, arrayRef[0], o); }
static void copyMethodList(KonohaContext *kctx, ktype_t cid, kArray *s, kArray *d) { size_t i; for(i = 0; i < kArray_size(s); i++) { kMethod *mtd = s->MethodItems[i]; if(mtd->typeId != cid) continue; KLIB kArray_Add(kctx, d, mtd); } }
static KMETHOD Array_Add1(KonohaContext *kctx, KonohaStack *sfp) { kArray *a = sfp[0].asArray; if(kArray_isUnboxData(a)) { UnboxArray_Add(kctx, a, sfp[1].unboxValue); } else { KLIB kArray_Add(kctx, a, sfp[1].asObject); } }
static void kStmt_appendBlock(KonohaContext *kctx, kStmt *stmt, kBlock *bk) { if(bk != NULL) { kBlock *block = SUGAR kStmt_GetBlock(kctx, stmt, Stmt_ns(stmt), KW_BlockPattern, NULL); size_t i; for(i = 0; i < kArray_size(bk->StmtList); i++) { KLIB kArray_Add(kctx, block->StmtList, bk->StmtList->StmtItems[i]); } } }
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; }
//## Expr Expr.addExpr(Expr expr, Expr o); static KMETHOD kExpr_AddExpr(KonohaContext *kctx, KonohaStack *sfp) { kExpr *expr = sfp[0].asExpr; kExpr *o = sfp[1].asExpr; if(IS_NULL(o) && IS_Array(expr->cons)) { kObject_set(NullObject, expr, 1); } if(IS_NOTNULL(expr)) { KLIB kArray_Add(kctx, expr->cons, o); } KReturn(expr); }
static KClass *CreateEnvClass(KonohaContext *kctx, kNameSpace *ns, kToken *typeTk, KClass **EnvObjectClass) { INIT_GCSTACK(); size_t i = 0, esize = ns->genv->localScope.varsize; size_t start = 0, end = esize; KGammaStackDecl *oldenv = ns->genv->localScope.varItems; kparamtype_t *p = ALLOCA(kparamtype_t, esize); char buf[256] = {'_', '_', '_', 'E', 'N', 'V', 0}, *text = buf + 6; if(ns->genv->thisClass == KClass_NameSpace) { start = 1; end = esize - 1; } assert(end < 256); for(i = start; i <= end; i++) { p[i-1].name = oldenv[i].name; p[i-1].attrTypeId = oldenv[i].attrTypeId; *(text++) = (KType_text(p[i-1].attrTypeId))[0]; } *EnvObjectClass = KLIB kNameSpace_GetClassByFullName(kctx, ns, buf, text - buf, NULL); if(*EnvObjectClass == NULL) { *EnvObjectClass = kNameSpace_DefineClassName(kctx, ns, buf, text - buf); } KClass *ct = KLIB KClass_Generics(kctx, KClass_Func, typeTk->resolvedTypeId, end, p); if(end >= 1) { ((KClassVar *)ct)->classMethodList = new_(MethodArray, end*2, OnGlobalConstList); for(i = start; i <= end; i++) { int n = i - 1; ksymbol_t sym = p[n].name; ktypeattr_t type = KTypeAttr_Unmask(p[n].attrTypeId); kMethod *getter = new_FunctionGetter(kctx, _GcStack, ct->typeId, sym, type, n); kMethod *setter = new_FunctionSetter(kctx, _GcStack, ct->typeId, sym, type, n); KLIB kArray_Add(kctx, ct->classMethodList, getter); KLIB kArray_Add(kctx, ct->classMethodList, setter); } } RESET_GCSTACK(); return ct; }
// ## Array[AprTableEntry] AprTable.getElts() static KMETHOD AprTable_getElts(KonohaContext *kctx, KonohaStack *sfp) { kAprTable *self = (kAprTable *) sfp[0].asObject; kArray *arr = (kArray *)KLIB new_kObject(kctx, OnStack, KClass_Array, 0); const apr_array_header_t *apr_arr = apr_table_elts(self->tbl); const apr_table_entry_t *entries = (apr_table_entry_t *)apr_arr->elts; int i=0; for (i=0; i<apr_arr->nelts; i++) { KLIB kArray_Add(kctx, arr, (kAprTableEntry *)KLIB new_kObject(kctx, OnStack, KClass_AprTableEntry, (uintptr_t)entries)); entries++; } KReturn(arr); }
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); }
//## Token[] Stmt.getTokenList(symbol keyword, Token[] def); static KMETHOD Stmt_getTokenList(KonohaContext *kctx, KonohaStack *sfp) { kStmt *stmt = sfp[0].asStmt; ksymbol_t keyword = (ksymbol_t)sfp[1].intValue; kArray *def = sfp[2].asArray; kTokenArray *tokenList = (kTokenArray *)kStmt_GetObject(kctx, stmt, keyword, def); kTokenArray *ret; if(!IS_Array(tokenList)) { ret = new_(TokenArray, 0, OnStack); KLIB kArray_Add(kctx, ret, tokenList); } else { ret = tokenList; } KReturn(ret); }
//## method Array<T> Array.concat(Array<T> a1); static KMETHOD Array_concat(KonohaContext *kctx, KonohaStack *sfp) { kArray *a0 = sfp[0].asArray; kArray *a1 = sfp[1].asArray; size_t i; if(kArray_isUnboxData(a1)) { for (i = 0; i < kArray_size(a1); i++){ UnboxArray_Add(kctx, a0, a1->unboxItems[i]); } } else { for (i = 0; i < kArray_size(a1); i++){ KLIB kArray_Add(kctx, a0, a1->ObjectItems[i]); } } KReturn(a0); }
static void MacroSet_setTokenAt(KonohaContext *kctx, MacroSet *macroSet, int index, kArray *tokenList, const char *symbol, ...) { DBG_ASSERT(macroSet[index].tokenList == NULL); macroSet[index].symbol = KLIB Ksymbol(kctx, symbol, strlen(symbol), StringPolicy_TEXT|StringPolicy_ASCII, _NEWID); macroSet[index].tokenList = tokenList; macroSet[index].beginIdx = kArray_size(tokenList); kToken *tk; va_list ap; va_start(ap , symbol); while((tk = va_arg(ap, kToken *)) != NULL) { DBG_ASSERT(IS_Token(tk)); KLIB kArray_Add(kctx, tokenList, tk); } va_end(ap); macroSet[index].endIdx = kArray_size(tokenList); }
static KMETHOD Statement_syntax(KonohaContext *kctx, KonohaStack *sfp) { kbool_t r = 0; VAR_Statement(stmt, gma); kTokenArray *tokenList = (kTokenArray *)kStmt_GetObject(kctx, stmt, KW_TokenPattern, NULL); if(tokenList == NULL) { SUGAR kStmt_Message2(kctx, stmt, NULL, ErrTag, "empty syntax"); } if(tokenList != NULL) { if(!IS_Array(tokenList)) { // create tokenList from a Token kTokenArray *a = new_(TokenArray, 0, OnGcStack); KLIB kArray_Add(kctx, a, tokenList); tokenList = a; } DBG_ASSERT(IS_Array(tokenList)); kNameSpace *ns = Stmt_ns(stmt); SugarSyntaxVar *syn = kNameSpace_guessSyntaxFromTokenList(kctx, ns, tokenList); if(syn != NULL) { if(syn->syntaxPatternListNULL_OnList != NULL) { SUGAR kStmt_Message2(kctx, stmt, NULL, InfoTag, "oveloading syntax: %s%s", PSYM_t(syn->keyword)); } else { syn->syntaxPatternListNULL_OnList = new_(TokenArray, 0, ns->NameSpaceConstList); } TokenSeq tokens = {ns, tokenList, 0, kArray_size(tokenList)}; // Referred to kNameSpace_ParseSyntaxPattern in ast.h. kArray *patternList = syn->syntaxPatternListNULL_OnList; size_t firstPatternIdx = kArray_size(patternList); SUGAR kArray_AddSyntaxRule(kctx, patternList, &tokens); if(firstPatternIdx < kArray_size(patternList)) { kToken *firstPattern = patternList->TokenItems[firstPatternIdx]; if(kToken_isFirstPattern(firstPattern)) { kNameSpace_AppendArrayRef(kctx, ns, &((kNameSpaceVar *)ns)->stmtPatternListNULL_OnList, UPCAST(firstPattern)); } } r = 1; } kStmt_done(kctx, stmt); } KReturnUnboxValue(r); }
static kObject *MiniVM_AddConstPool(KonohaContext *kctx, KBuilder *builder, kObject *o) { KLIB kArray_Add(kctx, builder->constPools, o); return o; }
static KMETHOD Expression_ExtendedTextLiteral(KonohaContext *kctx, KonohaStack *sfp) { VAR_Expression(expr, tokenList, beginIdx, opIdx, endIdx); kNameSpace *ns = kNode_ns(expr); kToken *tk = tokenList->TokenItems[opIdx]; INIT_GCSTACK(); kString *text = remove_escapes(kctx, tk); if(beginIdx != opIdx) { /* FIXME */ assert(0 && "FIXME"); KReturnUnboxValue(-1); } if(text == NULL) { /* text contain unsupported escape sequences */ RESET_GCSTACK(); KReturnUnboxValue(-1); } const char *str = kString_text(text); const char *end = NULL; const char *start = strstr(str, "${"); if(start == NULL) { /* text does not contain Interpolation expressions */ RESET_GCSTACK(); KReturnUnboxValue(beginIdx+1); } kSyntax *addSyntax = kSyntax_(ns, KSymbol_("+")); kTokenVar *opToken = tokenList->TokenVarItems[beginIdx]; opToken->symbol = KSymbol_("+"); opToken->text = KLIB new_kString(kctx, OnGcStack, "+", 1, 0); KFieldSet(opToken, opToken->resolvedSyntaxInfo, addSyntax); SUGAR kNode_Op(kctx, expr, opToken, 0); /* [before] "aaa${bbb}ccc" * [after] "" + "aaa" + bbb + "ccc" */ SUGAR kNode_AddNode(kctx, expr, new_ConstNode(kctx, ns, NULL, UPCAST(TS_EMPTY))); while(true) { start = strstr(str, "${"); if(start == NULL) break; if(start == strstr(str, "${}")) { str += 3; continue; } end = strchr(start, '}'); if(end == NULL) break; kNode *newexpr = ParseSource(kctx, ns, start+2, end-(start+2)); if(start - str > 0) { kNode *first = new_ConstNode(kctx, ns, NULL, UPCAST(KLIB new_kString(kctx, OnGcStack, str, (start - str), 0))); SUGAR kNode_AddNode(kctx, expr, first); } SUGAR kNode_AddNode(kctx, expr, newexpr); str = end + 1; } if((start == NULL) || (start != NULL && end == NULL)) { kNode *rest = new_ConstNode(kctx, ns, KClass_String, UPCAST(KLIB new_kString(kctx, OnGcStack, str, strlen(str), 0))); SUGAR kNode_AddNode(kctx, expr, rest); } /* (+ 1 2 3 4) => (+ (+ (+ 1 2) 3 ) 4) */ int i, size = kNode_GetNodeListSize(kctx, expr); assert(size > 2); 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); RESET_GCSTACK(); KReturnUnboxValue(beginIdx+1); }