void getProcedureMonoTypes(ProcedureMono &mono, EnvPtr env, llvm::ArrayRef<FormalArgPtr> formalArgs, bool hasVarArg) { if (mono.monoState == Procedure_NoOverloads && !hasVarArg) { assert(mono.monoTypes.empty()); mono.monoState = Procedure_MonoOverload; for (size_t i = 0; i < formalArgs.size(); ++i) { if (formalArgs[i]->type == NULL) goto poly; LocationContext loc(formalArgs[i]->type->location); PatternPtr argPattern = evaluateOnePattern(formalArgs[i]->type, env); ObjectPtr argTypeObj = derefDeep(argPattern); if (argTypeObj == NULL) goto poly; TypePtr argType; if (!staticToType(argTypeObj, argType)) error(formalArgs[i], "expecting a type"); mono.monoTypes.push_back(argType); } } else goto poly; return; poly: mono.monoTypes.clear(); mono.monoState = Procedure_PolyOverload; return; }
static void initVariantInstance(InstancePtr x) { EnvPtr env = new Env(x->env); const vector<PatternVar> &pvars = x->patternVars; for (unsigned i = 0; i < pvars.size(); ++i) { if (pvars[i].isMulti) { MultiPatternCellPtr cell = new MultiPatternCell(NULL); addLocal(env, pvars[i].name, cell.ptr()); } else { PatternCellPtr cell = new PatternCell(NULL); addLocal(env, pvars[i].name, cell.ptr()); } } PatternPtr pattern = evaluateOnePattern(x->target, env); ObjectPtr y = derefDeep(pattern); if (y.ptr()) { if (y->objKind != TYPE) error(x->target, "not a variant type"); Type *z = (Type *)y.ptr(); if (z->typeKind != VARIANT_TYPE) error(x->target, "not a variant type"); VariantType *vt = (VariantType *)z; vt->variant->instances.push_back(x); } else { if (pattern->kind != PATTERN_STRUCT) error(x->target, "not a variant type"); PatternStruct *ps = (PatternStruct *)pattern.ptr(); if ((!ps->head) || (ps->head->objKind != VARIANT)) error(x->target, "not a variant type"); Variant *v = (Variant *)ps->head.ptr(); v->instances.push_back(x); } }
void getProcedureMonoTypes(ProcedureMono &mono, EnvPtr env, vector<FormalArgPtr> const &formalArgs, FormalArgPtr formalVarArg) { if (mono.monoState == Procedure_NoOverloads && formalVarArg == NULL) { assert(mono.monoTypes.empty()); mono.monoState = Procedure_MonoOverload; for (size_t i = 0; i < formalArgs.size(); ++i) { if (formalArgs[i]->type == NULL) goto poly; PatternPtr argPattern = evaluateOnePattern(formalArgs[i]->type, env); ObjectPtr argType = derefDeep(argPattern); if (argType == NULL) goto poly; if (argType->objKind != TYPE) error(formalArgs[i], "expecting a type"); mono.monoTypes.push_back((Type*)argType.ptr()); } } else goto poly; return; poly: mono.monoTypes.clear(); mono.monoState = Procedure_PolyOverload; return; }
static void initOverload(OverloadPtr x) { EnvPtr env = overloadPatternEnv(x); PatternPtr pattern = evaluateOnePattern(x->target, env); ObjectPtr obj = derefDeep(pattern); if (obj == NULL) { x->nameIsPattern = true; addPatternOverload(x); } else { switch (obj->objKind) { case PROCEDURE : { Procedure *proc = (Procedure *)obj.ptr(); addProcedureOverload(proc, env, x); break; } case RECORD_DECL : { RecordDecl *r = (RecordDecl *)obj.ptr(); r->overloads.insert(r->overloads.begin(), x); break; } case VARIANT_DECL : { VariantDecl *v = (VariantDecl *)obj.ptr(); v->overloads.insert(v->overloads.begin(), x); break; } case TYPE : { Type *t = (Type *)obj.ptr(); t->overloads.insert(t->overloads.begin(), x); break; } case PRIM_OP : { if (isOverloadablePrimOp(obj)) addPrimOpOverload((PrimOp *)obj.ptr(), x); else error(x->target, "invalid overload target"); break; } case GLOBAL_ALIAS : { GlobalAlias *a = (GlobalAlias*)obj.ptr(); if (!a->hasParams()) error(x->target, "invalid overload target"); a->overloads.insert(a->overloads.begin(), x); break; } case INTRINSIC : { error(x->target, "invalid overload target"); } default : { error(x->target, "invalid overload target"); } } } }
static void initializeVariantType(VariantTypePtr t) { assert(!t->initialized); EnvPtr variantEnv = new Env(t->variant->env); { const vector<IdentifierPtr> ¶ms = t->variant->params; IdentifierPtr varParam = t->variant->varParam; assert(params.size() <= t->params.size()); for (unsigned j = 0; j < params.size(); ++j) addLocal(variantEnv, params[j], t->params[j]); if (varParam.ptr()) { MultiStaticPtr ms = new MultiStatic(); for (unsigned j = params.size(); j < t->params.size(); ++j) ms->add(t->params[j]); addLocal(variantEnv, varParam, ms.ptr()); } else { assert(params.size() == t->params.size()); } } ExprListPtr defaultInstances = t->variant->defaultInstances; for (unsigned i = 0; i < defaultInstances->size(); ++i) { ExprPtr x = defaultInstances->exprs[i]; TypePtr memberType = evaluateType(x, variantEnv); t->memberTypes.push_back(memberType); } const vector<InstancePtr> &instances = t->variant->instances; for (unsigned i = 0; i < instances.size(); ++i) { InstancePtr x = instances[i]; vector<PatternCellPtr> cells; vector<MultiPatternCellPtr> multiCells; const vector<PatternVar> &pvars = x->patternVars; EnvPtr patternEnv = new Env(x->env); for (unsigned j = 0; j < pvars.size(); ++j) { if (pvars[j].isMulti) { MultiPatternCellPtr multiCell = new MultiPatternCell(NULL); multiCells.push_back(multiCell); cells.push_back(NULL); addLocal(patternEnv, pvars[j].name, multiCell.ptr()); } else { PatternCellPtr cell = new PatternCell(NULL); cells.push_back(cell); multiCells.push_back(NULL); addLocal(patternEnv, pvars[j].name, cell.ptr()); } } PatternPtr pattern = evaluateOnePattern(x->target, patternEnv); if (!unifyPatternObj(pattern, t.ptr())) continue; EnvPtr staticEnv = new Env(x->env); for (unsigned j = 0; j < pvars.size(); ++j) { if (pvars[j].isMulti) { MultiStaticPtr ms = derefDeep(multiCells[j].ptr()); if (!ms) error(pvars[j].name, "unbound pattern variable"); addLocal(staticEnv, pvars[j].name, ms.ptr()); } else { ObjectPtr v = derefDeep(cells[j].ptr()); if (!v) error(pvars[j].name, "unbound pattern variable"); addLocal(staticEnv, pvars[j].name, v.ptr()); } } if (x->predicate.ptr()) if (!evaluateBool(x->predicate, staticEnv)) continue; TypePtr memberType = evaluateType(x->member, staticEnv); t->memberTypes.push_back(memberType); } RecordPtr reprRecord = getVariantReprRecord(); vector<ObjectPtr> params; for (unsigned i = 0; i < t->memberTypes.size(); ++i) params.push_back(t->memberTypes[i].ptr()); t->reprType = recordType(reprRecord, params); t->initialized = true; }
MatchResultPtr matchInvoke(OverloadPtr overload, ObjectPtr callable, llvm::ArrayRef<TypePtr> argsKey) { initializePatterns(overload); PatternReseter reseter(overload); if (!unifyPatternObj(overload->callablePattern, callable)) return new MatchCallableError(overload->target, callable); CodePtr code = overload->code; if (code->hasVarArg) { if (argsKey.size() < code->formalArgs.size()-1) return new MatchArityError(unsigned(code->formalArgs.size()), unsigned(argsKey.size()), true); } else { if (code->formalArgs.size() != argsKey.size()) return new MatchArityError(unsigned(code->formalArgs.size()), unsigned(argsKey.size()), false); } llvm::ArrayRef<FormalArgPtr> formalArgs = code->formalArgs; unsigned varArgSize = unsigned(argsKey.size()-formalArgs.size()+1); for (unsigned i = 0, j = 0; i < formalArgs.size(); ++i) { FormalArgPtr x = formalArgs[i]; if (x->varArg) { if (x->type.ptr()) { MultiStaticPtr types = new MultiStatic(); for (; j < varArgSize; ++j) types->add(argsKey[i+j].ptr()); --j; MultiPatternPtr pattern = overload->varArgPattern; if (!unifyMulti(pattern, types)) return new MatchMultiArgumentError(unsigned(formalArgs.size()), types, x); } else { j = varArgSize-1; } } else { if (x->type.ptr()) { PatternPtr pattern = overload->argPatterns[i]; if (!unifyPatternObj(pattern, argsKey[i+j].ptr())) return new MatchArgumentError(i+j, argsKey[i+j], x); } } } EnvPtr staticEnv = new Env(overload->env); llvm::ArrayRef<PatternVar> pvars = code->patternVars; for (size_t i = 0; i < pvars.size(); ++i) { if (pvars[i].isMulti) { MultiStaticPtr ms = derefDeep(overload->multiCells[i].ptr()); if (!ms) error(pvars[i].name, "unbound pattern variable"); addLocal(staticEnv, pvars[i].name, ms.ptr()); } else { ObjectPtr v = derefDeep(overload->cells[i].ptr()); if (!v) error(pvars[i].name, "unbound pattern variable"); addLocal(staticEnv, pvars[i].name, v.ptr()); } } reseter.reset(); if (code->predicate.ptr()) if (!evaluateBool(code->predicate, staticEnv)) return new MatchPredicateError(code->predicate); MatchSuccessPtr result = new MatchSuccess( overload, staticEnv, callable, argsKey ); for (unsigned i = 0, j = 0; i < formalArgs.size(); ++i) { FormalArgPtr x = formalArgs[i]; if (x->varArg) { result->varArgName = x->name; result->varArgPosition = i; for (; j < varArgSize; ++j) { result->varArgTypes.push_back(argsKey[i+j]); } --j; } else { result->fixedArgNames.push_back(x->name); result->fixedArgTypes.push_back(argsKey[i+j]); } } if(!code->hasVarArg) result->varArgPosition = unsigned(result->fixedArgNames.size()); return result.ptr(); }
MatchResultPtr matchInvoke(OverloadPtr overload, ObjectPtr callable, const vector<TypePtr> &argsKey) { initializePatterns(overload); PatternReseter reseter(overload); if (!unifyPatternObj(overload->callablePattern, callable)) return new MatchCallableError(overload->target, callable); CodePtr code = overload->code; if (code->formalVarArg.ptr()) { if (argsKey.size() < code->formalArgs.size()) return new MatchArityError(code->formalArgs.size(), argsKey.size(), true); } else { if (code->formalArgs.size() != argsKey.size()) return new MatchArityError(code->formalArgs.size(), argsKey.size(), false); } const vector<FormalArgPtr> &formalArgs = code->formalArgs; for (unsigned i = 0; i < formalArgs.size(); ++i) { FormalArgPtr x = formalArgs[i]; if (x->type.ptr()) { PatternPtr pattern = overload->argPatterns[i]; if (!unifyPatternObj(pattern, argsKey[i].ptr())) return new MatchArgumentError(i, argsKey[i], x); } } if (code->formalVarArg.ptr() && code->formalVarArg->type.ptr()) { MultiStaticPtr types = new MultiStatic(); for (unsigned i = formalArgs.size(); i < argsKey.size(); ++i) types->add(argsKey[i].ptr()); if (!unifyMulti(overload->varArgPattern, types)) return new MatchMultiArgumentError(formalArgs.size(), types, code->formalVarArg); } EnvPtr staticEnv = new Env(overload->env); const vector<PatternVar> &pvars = code->patternVars; for (unsigned i = 0; i < pvars.size(); ++i) { if (pvars[i].isMulti) { MultiStaticPtr ms = derefDeep(overload->multiCells[i].ptr()); if (!ms) error(pvars[i].name, "unbound pattern variable"); addLocal(staticEnv, pvars[i].name, ms.ptr()); } else { ObjectPtr v = derefDeep(overload->cells[i].ptr()); if (!v) error(pvars[i].name, "unbound pattern variable"); addLocal(staticEnv, pvars[i].name, v.ptr()); } } reseter.reset(); if (code->predicate.ptr()) { if (!evaluateBool(code->predicate, staticEnv)) return new MatchPredicateError(code->predicate); } MatchSuccessPtr result = new MatchSuccess( overload->callByName, overload->isInline, code, staticEnv, callable, argsKey ); for (unsigned i = 0; i < formalArgs.size(); ++i) { FormalArgPtr x = formalArgs[i]; result->fixedArgNames.push_back(x->name); result->fixedArgTypes.push_back(argsKey[i]); } if (code->formalVarArg.ptr()) { result->varArgName = code->formalVarArg->name; for (unsigned i = formalArgs.size(); i < argsKey.size(); ++i) { result->varArgTypes.push_back(argsKey[i]); } } return result.ptr(); }