static void trace_dynamic_nominal(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { // Skip if a primitive. ast_t* def = (ast_t*)ast_data(type); if(ast_id(def) == TK_PRIMITIVE) return; // If it's not possible to use match or as to extract this type from the // original type, there's no need to trace as this type. if(tuple != NULL) { // We are a tuple element. Our type is in the correct position in the // tuple, everything else is TK_DONTCARE. if(is_matchtype(orig, tuple) != MATCHTYPE_ACCEPT) return; } else { // We aren't a tuple element. if(is_matchtype(orig, type) != MATCHTYPE_ACCEPT) return; } // We aren't always this type. We need to check dynamically. LLVMValueRef desc = gendesc_fetch(c, object); LLVMValueRef test = gendesc_isnominal(c, desc, type); LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); LLVMBuildCondBr(c->builder, test, is_true, is_false); // Trace as this type. LLVMPositionBuilderAtEnd(c->builder, is_true); gentrace(c, ctx, object, type); // If we have traced as known, unknown or actor, we're done with this // element. Otherwise, continue tracing this as if the match had been // unsuccessful. switch(trace_type(type)) { case TRACE_KNOWN: case TRACE_UNKNOWN: case TRACE_KNOWN_VAL: case TRACE_UNKNOWN_VAL: case TRACE_ACTOR: LLVMBuildBr(c->builder, next_block); break; default: LLVMBuildBr(c->builder, is_false); break; } // Carry on, whether we have traced or not. LLVMPositionBuilderAtEnd(c->builder, is_false); }
static bool check_nominal(compile_t* c, LLVMValueRef desc, ast_t* pattern_type, LLVMBasicBlockRef next_block) { LLVMValueRef test = gendesc_isnominal(c, desc, pattern_type); if(test == GEN_NOVALUE) return false; LLVMBasicBlockRef continue_block = codegen_block(c, "pattern_continue"); LLVMBuildCondBr(c->builder, test, continue_block, next_block); LLVMPositionBuilderAtEnd(c->builder, continue_block); return true; }
static void trace_dynamic_nominal(compile_t* c, LLVMValueRef ctx, LLVMValueRef object, ast_t* type, ast_t* orig, ast_t* tuple, LLVMBasicBlockRef next_block) { pony_assert(ast_id(type) == TK_NOMINAL); // Skip if a primitive. ast_t* def = (ast_t*)ast_data(type); if(ast_id(def) == TK_PRIMITIVE) return; int mutability = trace_cap_nominal(c->opt, type, orig, tuple); // If we can't extract the element from the original type, there is no need to // trace the element. if(mutability == -1) return; token_id dst_cap = TK_TAG; switch(mutability) { case PONY_TRACE_MUTABLE: dst_cap = TK_ISO; break; case PONY_TRACE_IMMUTABLE: dst_cap = TK_VAL; break; default: {} } ast_t* dst_type = ast_dup(type); ast_t* dst_cap_ast = cap_fetch(dst_type); ast_setid(dst_cap_ast, dst_cap); ast_t* dst_eph = ast_sibling(dst_cap_ast); if(ast_id(dst_eph) == TK_EPHEMERAL) ast_setid(dst_eph, TK_NONE); // We aren't always this type. We need to check dynamically. LLVMValueRef desc = gendesc_fetch(c, object); LLVMValueRef test = gendesc_isnominal(c, desc, type); LLVMBasicBlockRef is_true = codegen_block(c, ""); LLVMBasicBlockRef is_false = codegen_block(c, ""); LLVMBuildCondBr(c->builder, test, is_true, is_false); // Trace as this type. LLVMPositionBuilderAtEnd(c->builder, is_true); gentrace(c, ctx, object, object, type, dst_type); ast_free_unattached(dst_type); // If we have traced as mut or val, we're done with this element. Otherwise, // continue tracing this as if the match had been unsuccessful. if(mutability != PONY_TRACE_OPAQUE) LLVMBuildBr(c->builder, next_block); else LLVMBuildBr(c->builder, is_false); // Carry on, whether we have traced or not. LLVMPositionBuilderAtEnd(c->builder, is_false); }