static kbool_t MiniVM_VisitDoWhileNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { bblock_t HeadBB = new_BasicBlockLABEL(kctx); bblock_t BodyBB = new_BasicBlockLABEL(kctx); bblock_t MergeBB = new_BasicBlockLABEL(kctx); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), HeadBB); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"), MergeBB); MiniVMBuilder_JumpTo(kctx, builder, BodyBB); { /* Head */ MiniVMBuilder_setBlock(kctx, builder, HeadBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); CreateBranch(kctx, builder, MiniVM_getExpression(builder), MergeBB, BodyBB, true); } { /* Body */ MiniVMBuilder_setBlock(kctx, builder, BodyBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } MiniVMBuilder_setBlock(kctx, builder, MergeBB); return true; }
static kbool_t class_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("$ClassName"), SYNFLAG_CFunc, 0, 0, {SUGARFUNC PatternMatch_ClassName}, {NULL}}, { KSymbol_("class"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_class}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("class")), "\"class\" $ClassName [\"extends\" extends: $Type] [$Block]", 0, trace); return true; }
static kbool_t subtype_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("instanceof"), SYNFLAG_CTypeFunc, Precedence_CStyleMUL, 0, {SUGAR opParseFunc}, {SUGARFUNC TypeCheck_InstanceOf}}, { KSymbol_("as"), SYNFLAG_CTypeFunc, Precedence_CStyleMUL, 0, {SUGAR opParseFunc}, {SUGARFUNC TypeCheck_as}}, { KSymbol_("to"), SYNFLAG_CTypeFunc, Precedence_CStyleMUL, 0, {SUGAR opParseFunc}, {SUGARFUNC TypeCheck_to}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
static kbool_t namespace_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("namespace"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_namespace}}, { KSymbol_("const"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_ConstDecl}}, { KSymbol_("defined"), SYNFLAG_CFunc,0, Precedence_CStylePrefixOperator, {SUGARFUNC Expression_Defined}, {SUGARFUNC TypeCheck_Defined},}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("namespace")), "\"namespace\" $Expr", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("const")), "\"const\" $Symbol = $Expr", 0, trace); return true; }
static kbool_t cstyle_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { kFunc *nullTypeFunc = KSugarFunc(ns, TypeCheck_null); KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("null"), 0, 0, 0, {SUGAR termParseFunc}, {nullTypeFunc}, }, { KSymbol_("NULL"), 0, 0, 0, {SUGAR termParseFunc}, {nullTypeFunc}, }, { KSymbol_("=="), 0, Precedence_CStyleEquals, 0, {KSugarFunc(ns, Expression_isNull)}, {SUGAR methodTypeFunc}}, { KSymbol_("!="), 0, Precedence_CStyleEquals, 0, {KSugarFunc(ns, Expression_isNotNull)}, {SUGAR methodTypeFunc}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
static kshortflag_t kNode_ParseClassFlag(KonohaContext *kctx, kNode *stmt, kshortflag_t cflag) { static KFlagSymbolData ClassDeclFlag[] = { {KClassFlag_Private}, {KClassFlag_Singleton}, {KClassFlag_Immutable}, {KClassFlag_Prototype}, {KClassFlag_Interface}, }; if(ClassDeclFlag[0].symbol == 0) { // this is a tricky technique ClassDeclFlag[0].symbol = KSymbol_("@Private"); ClassDeclFlag[1].symbol = KSymbol_("@Singleton"); ClassDeclFlag[2].symbol = KSymbol_("@Immutable"); ClassDeclFlag[3].symbol = KSymbol_("@Prototype"); ClassDeclFlag[4].symbol = KSymbol_("@Interface"); } return (kshortflag_t)SUGAR kNode_ParseFlag(kctx, stmt, ClassDeclFlag, cflag); }
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 kbool_t ClosureModel_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("function"), SYNFLAG_CTypeFunc, 0, Precedence_CStyleAssign, {SUGAR patternParseFunc}, {SUGARFUNC TypeCheck_Closure}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("function")), "\"function\" $Param [$Type] $Block", 0, NULL); KDEFINE_METHOD MethodData[] = { _Public|_Hidden, _F(Func_Create), KType_Func, KType_Func, KMethodName_("_Create"), 2, KType_Object, KFieldName_("env"), KType_Method, KFieldName_("mtd"), DEND, }; KLIB kNameSpace_LoadMethodData(kctx, ns, MethodData, trace); return true; }
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 Expression_isNotNull(KonohaContext *kctx, KonohaStack *sfp) { VAR_Expression(stmt, tokenList, beginIdx, opIdx, endIdx); if(opIdx + 2 == endIdx) { DBG_P("checking .. x != null"); kTokenVar *tk = tokenList->TokenVarItems[opIdx+1]; if(tk->symbol == KSymbol_("null") || tk->symbol == KSymbol_("NULL")) { kNameSpace *ns = kNode_ns(stmt); tk->symbol = KSymbol_("IsNotNull"); tk->resolvedSyntaxInfo = tokenList->TokenVarItems[opIdx]->resolvedSyntaxInfo; SUGAR kNode_Op(kctx, stmt, tk, 1, SUGAR ParseNewNode(kctx, ns, tokenList, &beginIdx, opIdx, ParseExpressionOption, NULL)); KReturnUnboxValue(opIdx + 2); } } DBG_P("checking parent .. != .."); KReturnUnboxValue(-1); }
static kbool_t MiniVM_VisitForNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { kUntypedNode *initNode = kUntypedNode_GetNode(kctx, node, KSymbol_("init")); if(initNode != NULL) { KLIB VisitNode(kctx, builder, initNode, thunk); } return MiniVM_VisitLoopNode(kctx, builder, node, thunk, ForLoop); }
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 kbool_t field_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("."), SYNFLAG_CTypeFunc, -1, 0, {NULL}, {SUGARFUNC TypeCheck_Getter}}, { KSymbol_END, }, }; KLIB kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
//## @Public void NameSpace.AddMethodDecl(Node methodNode); static KMETHOD NameSpace_AddMethodDecl(KonohaContext *kctx, KonohaStack *sfp) { kNameSpace *ns = sfp[0].asNameSpace; kSyntax *syn = SUGAR kNameSpace_GetSyntax(kctx, ns, KSymbol_("$MethodDecl")); kFunc *fo = syn->TypeFuncNULL; kNode *methodNode = (kNode *) sfp[1].asObject; CallTypeFunc(kctx, fo, methodNode, ns, K_NULL); KReturnVoid(); }
static kbool_t dollar_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("$"), 0, NULL, 0, Precedence_CStyleSuffixCall, NULL, Expression_dollar, NULL, NULL, NULL, }, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
static kbool_t CollectLocalVar_VisitForNode(KVISITOR_PARAM) { kUntypedNode *initNode = kUntypedNode_GetNode(kctx, node, KSymbol_("init")); if(initNode != NULL) { KLIB VisitNode(kctx, builder, initNode, thunk); } CollectLocalVar_VisitWhileNode(kctx, builder, node, thunk); return true; }
static kbool_t MiniVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk, enum LoopType Loop) { kUntypedNode *ItrBlock; bblock_t HeadBB = new_BasicBlockLABEL(kctx); bblock_t BodyBB = new_BasicBlockLABEL(kctx); bblock_t ItrBB = new_BasicBlockLABEL(kctx); bblock_t MergeBB = new_BasicBlockLABEL(kctx); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("continue"), ItrBB); kUntypedNode_SetLabelBlock(kctx, node, KSymbol_("break"), MergeBB); ItrBlock = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_("Iterator"), NULL); if(ItrBlock != NULL) { assert(Loop == ForLoop); MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } else if(Loop == WhileLoop) { MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } else { MiniVMBuilder_JumpTo(kctx, builder, BodyBB); } { /* Head */ MiniVMBuilder_setBlock(kctx, builder, HeadBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); CreateBranch(kctx, builder, MiniVM_getExpression(builder), BodyBB, MergeBB, false); } { /* Body */ MiniVMBuilder_setBlock(kctx, builder, BodyBB); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); MiniVMBuilder_JumpTo(kctx, builder, ItrBB); /* Itr */ MiniVMBuilder_setBlock(kctx, builder, ItrBB); if(ItrBlock != NULL) { KLIB VisitNode(kctx, builder, ItrBlock, thunk); } MiniVMBuilder_JumpTo(kctx, builder, HeadBB); } MiniVMBuilder_setBlock(kctx, builder, MergeBB); return true; }
static KMETHOD PatternMatch_ForStmt(KonohaContext *kctx, KonohaStack *sfp) { VAR_PatternMatch(stmt, name, tokenList, beginIdx, endIdx); /* for(IniitExpr; CondExpr; IterateExpr) $Block */ kNameSpace *ns = kNode_ns(stmt); int i, start = beginIdx; /* InitExpression Part */ for(i = beginIdx; i < endIdx; i++) { kTokenVar *tk = tokenList->TokenVarItems[i]; if(tk->symbol == KSymbol_SEMICOLON) { if(start < i) { kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, i, ParseMetaPatternOption, NULL); SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_("init"), UPCAST(node)); } start = i + 1; break; } } if(start == beginIdx) { KReturnUnboxValue(-1); } /* CondExpression Part */ for(i = start; i < endIdx; i++) { kTokenVar *tk = tokenList->TokenVarItems[i]; if(tk->symbol == KSymbol_SEMICOLON) { if(start < i) { kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, i, ParseExpressionOption, NULL); KDump(node); SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_ExprPattern, UPCAST(node)); } start = i + 1; break; } } if(i == endIdx) { KReturnUnboxValue(-1); } /* IterExpression Part */ if(start < endIdx) { kNode *node = SUGAR ParseNewNode(kctx, ns, tokenList, &start, endIdx, ParseMetaPatternOption, NULL); SUGAR kNode_AddParsedObject(kctx, stmt, KSymbol_("Iterator"), UPCAST(node)); } KReturnUnboxValue(endIdx); }
static kbool_t CollectLocalVar_VisitWhileNode(KVISITOR_PARAM) { kUntypedNode *ItrBlock; KLIB VisitNode(kctx, builder, kUntypedNode_getFirstNode(kctx, node), thunk); KLIB VisitNode(kctx, builder, kUntypedNode_getFirstBlock(kctx, node), thunk); ItrBlock = KLIB kUntypedNode_GetNode(kctx, node, KSymbol_("Iterator"), NULL); if(ItrBlock != NULL) { KLIB VisitNode(kctx, builder, ItrBlock, thunk); } return true; }
static kbool_t untyped_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { KRequirePackage("Type.StaticVar", trace); kSyntax *assignSyntax = kSyntax_(KNULL(NameSpace), KSymbol_LET); KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("="), SYNFLAG_NodeLeftJoinOp2, assignSyntax->precedence_op2, assignSyntax->precedence_op1, {assignSyntax->ParseFuncNULL}, {KSugarFunc(ns, TypeCheck_UntypedAssign)}}, { KSymbol_END, }, /* sentinental */ }; KLIB kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
static kbool_t float_defineSyntax(KonohaContext *kctx, kNameSpace *ns, KTraceInfo *trace) { /* Use Syntax.Number package's Parser to parsing FloatLiteral */ KImportPackage(ns, "Syntax.Number", trace); kSyntax *numberSyntax = kSyntax_(ns, KSymbol_NumberPattern); KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("$Float"), SYNFLAG_CTypeFunc, 0, 0, {numberSyntax->ParseFuncNULL}, {SUGARFUNC TypeCheck_Float}, KonohaChar_Digit, {numberSyntax->TokenFuncNULL}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); return true; }
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 kbool_t cstyle_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("break"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_break}}, { KSymbol_("continue"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_continue}}, { KSymbol_("while"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_while} }, { KSymbol_("do"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_do} }, { KSymbol_END, }, /* sentinental */ }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("while")), "\"while\" \"(\" $Expr \")\" $Block", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("do")), "\"do\" $Block \"while\" \"(\" $Expr \")\"", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("break")), "\"break\"", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("continue")), "\"continue\"", 0, trace); return true; }
static const char *getThisFileName(KonohaContext *kctx) { static char shell[] = "shell"; kNameSpace *ns = (kNameSpace *)KLIB Knull(kctx, KClass_NameSpace); ksymbol_t sym = KSymbol_("SCRIPT_ARGV"); KKeyValue *kv = KLIB kNameSpace_GetConstNULL(kctx, ns, sym, false/*isLocalOnly*/); if(kv != NULL) { kArray *sa = (kArray *)kv->ObjectValue; if(sa->stringItems != NULL) { const char *file = kString_text(sa->stringItems[0]); return file; } } return shell; }
static kbool_t cstyle_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("$ForStmt"), SYNFLAG_CParseFunc, 0, 0, {SUGARFUNC PatternMatch_ForStmt}, }, { KSymbol_("for"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_CStyleFor} }, /* copied from CStyleWhile */ { KSymbol_("break"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_break}}, { KSymbol_("continue"), SYNFLAG_CTypeFunc, 0, Precedence_Statement, {SUGAR patternParseFunc}, {SUGARFUNC Statement_continue}}, { KSymbol_END, }, /* sentinental */ }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("for")), "\"for\" \"(\" $ForStmt \")\" $Block", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("break")), "\"break\"", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("continue")), "\"continue\"", 0, trace); return true; }
static kbool_t Exception_PackupNameSpace(KonohaContext *kctx, kNameSpace *ns, int option, KTraceInfo *trace) { KDEFINE_METHOD MethodData[] = { _Public, _F(Exception_new), KType_Exception, KType_Exception, KMethodName_("new"), 0, _Public|_Hidden, _F(System_throw), KType_void, KType_System, KMethodName_("throw"), 1, KType_Exception, KFieldName_("e"), _Public|_Hidden, _F(System_getThrownException), KType_Exception, KType_System, KMethodName_("getThrownException"), 0, DEND, }; KLIB kNameSpace_LoadMethodData(kctx, ns, MethodData, trace); KDEFINE_SYNTAX SYNTAX[] = { { KSymbol_("try"), SYNFLAG_CTypeFunc, 0, 0, {SUGAR patternParseFunc}, {SUGARFUNC Statement_try}}, { KSymbol_("catch"), SYNFLAG_CTypeFunc, 0, 0, {SUGAR patternParseFunc}, {SUGARFUNC Statement_catch}}, { KSymbol_("finally"), SYNFLAG_CTypeFunc, 0, 0, {SUGAR patternParseFunc}, {SUGARFUNC Statement_finally}}, { KSymbol_END, }, }; SUGAR kNameSpace_DefineSyntax(kctx, ns, SYNTAX, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("try")), "\"try\" $Node [ \"catch\" \"(\" $Type $Symbol \")\" catch: $Node ] [ \"finally\" finally: $Node ]", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("catch")), "\"catch\" \"(\" $Type $Symbol \")\" $Node", 0, trace); SUGAR kSyntax_AddPattern(kctx, kSyntax_(ns, KSymbol_("finally")), "\"finally\" $Node", 0, trace); return true; }
static KMETHOD TokenFunc_ExtendedIntLiteral(KonohaContext *kctx, KonohaStack *sfp) { kTokenVar *tk = (kTokenVar *)sfp[1].asObject; const char *source = kString_text(sfp[2].asString); const char *start = source, *end; int c = *source++; /* * DIGIT = 0-9 * DIGITS = DIGIT | DIGIT DIGITS * HEX = 0-9a-fA-F * HEXS = HEX | HEX HEXS * BIN = 0 | 1 * BINS = BIN | BIN BINS * TAG = "0x" | "0b" * HEXINT = ("0x" | "0X") HEXS * INT = DIGITS | HEXS | BINS */ int base = 10; bool isFloat = false; char (*parseDigit)(char) = parseDecimalDigit; if(c == '0') { c = *source++; switch (c) { case 'b': base = 2; parseDigit = parseBinaryDigit; break; case 'x': base = 16; parseDigit = parseHexDigit; break; case '0':case '1':case '2':case '3': case '4':case '5':case '6':case '7': base = 8; parseDigit = parseOctalDigit; break; default: source--; break; } } for (; (c = *source) != 0; ++source) { if(c == '_') continue; if(parseDigit(c) == -1) break; } /* * DIGIT = 0-9 * DIGITS = DIGIT | DIGIT DIGITS * INT = DIGIT | DIGIT1-9 DIGITS * FLOAT = INT * | INT FRAC * | INT EXP * | INT FRAC EXP * FRAC = "." digits * EXP = E digits * E = 'e' | 'e+' | 'e-' | 'E' | 'E+' | 'E-' */ if(base != 10 && c != '.' && c != 'e' && c != 'E') { goto L_emit; } if(c == '.') { isFloat = true; source++; for (; (c = *source) != 0; ++source) { if(c == '_') continue; if(parseDecimalDigit(c) == -1) break; } } if(c == 'e' || c == 'E') { isFloat = true; c = *(++source); if(!('0' <= c && c <= '9') && !(c == '+' || c == '-')) { source--; goto L_emit; } if(c == '+' || c == '-') { c = *source++; } for (; (c = *source) != 0; ++source) { if(c == '_') continue; if(parseDecimalDigit(c) == -1) break; } } L_emit:; if(IS_NOTNULL(tk)) { /* skip unit */ for (; (c = *source) != 0; ++source) { if(c == '_') continue; if(!isalpha(c)) break; } end = source; KFieldSet(tk, tk->text, KLIB new_kString(kctx, OnField, start, end - start, StringPolicy_ASCII)); tk->tokenType = isFloat ? KSymbol_("$Float") : TokenType_Number; } KReturnUnboxValue(source - start); }
static kbool_t FuelVM_VisitBreakNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk) { ksymbol_t label = KSymbol_("break"); return FuelVM_VisitJumpNode(kctx, builder, stmt, thunk, label); }
static kbool_t MiniVM_VisitBreakNode(KonohaContext *kctx, KBuilder *builder, kUntypedNode *node, void *thunk) { return MiniVM_VisitJumpNode(kctx, builder, node, thunk, KSymbol_("break")); }
static kbool_t FuelVM_VisitLoopNode(KonohaContext *kctx, KBuilder *builder, kNode *stmt, void *thunk, enum LoopType Loop) { Block *HeadBB = CreateBlock(BLD(builder)); Block *BodyBB = CreateBlock(BLD(builder)); Block *ItrBB = CreateBlock(BLD(builder)); Block *MergeBB = CreateBlock(BLD(builder)); kNode_SetLabelBlock(kctx, stmt, KSymbol_("continue"), ItrBB); kNode_SetLabelBlock(kctx, stmt, KSymbol_("break"), MergeBB); kNode *itrBlock = SUGAR kNode_GetNode(kctx, stmt, KSymbol_("Iterator"), NULL); if(itrBlock != NULL) { assert(Loop == ForLoop); IRBuilder_JumpTo(BLD(builder), HeadBB); } else if(Loop == WhileLoop) { /* [WhileStmt] * "Head" is Join Node * Head : if(COND) { goto Body } else {goto Merge } * Body : Body * ... * goto Itr * Itr : Body3 * goto Head * Merge : ... */ IRBuilder_JumpTo(BLD(builder), HeadBB); } else { /* [LoopStmt] (e.g. do-while loop) * "Body" is Join Node * Body : Body * ... * goto Itr * Itr : Body3 * goto Head * Head : if(COND) { goto Body } else {goto Merge } * Merge : ... */ IRBuilder_JumpTo(BLD(builder), BodyBB); } { /* Head */ IRBuilder_setBlock(BLD(builder), HeadBB); SUGAR VisitNode(kctx, builder, kNode_getFirstNode(kctx, stmt), thunk); CreateBranch(BLD(builder), FuelVM_getExpression(builder), BodyBB, MergeBB); } { /* Body */ IRBuilder_setBlock(BLD(builder), BodyBB); SUGAR VisitNode(kctx, builder, kNode_getFirstBlock(kctx, stmt), thunk); IRBuilder_JumpTo(BLD(builder), ItrBB); /* Itr */ IRBuilder_setBlock(BLD(builder), ItrBB); if(itrBlock != NULL) { SUGAR VisitNode(kctx, builder, itrBlock, thunk); } IRBuilder_JumpTo(BLD(builder), HeadBB); } IRBuilder_setBlock(BLD(builder), MergeBB); return true; }