29 const std::shared_ptr<yoi::IRModule> &irModule,
41 irModule->functionTable.put(L
"yoimiya_glob_initializer", globInitializer);
53 for (
auto &stmt :
module->stmts) {
114 }
catch (std::out_of_range &e) {
118 auto index = irModule->globalVariables.getIndex(
id);
119 auto valType = irModule->globalVariables[index];
127 }
catch (std::out_of_range &e) {
135 case primary::primaryKind::memberExpr:
138 case primary::primaryKind::basicLiterals:
141 case primary::primaryKind::rExpr:
144 case primary::primaryKind::typeIdExpression: {
148 case primary::primaryKind::dynCastExpression: {
152 case primary::primaryKind::newExpression: {
156 case primary::primaryKind::lambdaExpr: {
157 auto lambdaStructIndex = createLambdaUnnamedStruct(
primary->
lambda);
158 auto [lambdaCallableIndex, callableInterface] =
159 createCallableImplementationForLambda(irModule->structTable[lambdaStructIndex], lambdaStructIndex, currentModuleIndex);
164 case primary::primaryKind::funcExpr: {
168 case primary::primaryKind::bracedInitalizerList: {
189 yoi_assert(rhs.type == IRValueType::valueType::interfaceObject,
192 "RHS of 'impl' operator must be an interface type");
193 auto interfaceImplName = getInterfaceImplName({rhs.typeAffiliateModule, rhs.typeIndex}, lhs);
197 ->getImportedModule(lhs->typeAffiliateModule)
198 ->interfaceImplementationTable.contains(interfaceImplName)) {
204 yoi_assert(lhs->type == IRValueType::valueType::interfaceObject,
207 "LHS of 'interfaceof' operator must be an interface type");
209 auto key = std::make_tuple(rhs.type, rhs.typeAffiliateModule, rhs.typeIndex);
212 if (std::find(
vec.begin(),
vec.end(), key) !=
vec.end()) {
237 case lexer::token::tokenKind::incrementSign: {
241 if (lhs->isBasicType()) {
244 handleUnaryOperatorOverload(L
"operator++");
248 case lexer::token::tokenKind::decrementSign: {
251 if (lhs->isBasicType()) {
254 handleUnaryOperatorOverload(L
"operator--");
258 case lexer::token::tokenKind::binaryNot: {
261 if (lhs->isBasicType()) {
264 handleUnaryOperatorOverload(L
"operator~");
268 case lexer::token::tokenKind::minus: {
270 if (lhs->isBasicType()) {
273 handleUnaryOperatorOverload(L
"operator-");
277 case lexer::token::tokenKind::unknown: {
291 case lexer::token::tokenKind::assignSign: {
297 case lexer::token::tokenKind::directAssignSign: {
308 case lexer::token::tokenKind::additionAssignment: {
315 if (lhs->isBasicType() && rhs->isBasicType()) {
322 handleBinaryOperatorOverload(L
"operator+=",
leftExpr->
rhs);
326 case lexer::token::tokenKind::subtractionAssignment: {
332 if (lhs->isBasicType() && rhs->isBasicType()) {
339 handleBinaryOperatorOverload(L
"operator-=",
leftExpr->
rhs);
343 case lexer::token::tokenKind::multiplicationAssignment: {
349 if (lhs->isBasicType() && rhs->isBasicType()) {
356 handleBinaryOperatorOverload(L
"operator*=",
leftExpr->
rhs);
360 case lexer::token::tokenKind::divisionAssignment: {
366 if (lhs->isBasicType() && rhs->isBasicType()) {
373 handleBinaryOperatorOverload(L
"operator/=",
leftExpr->
rhs);
393 auto lhsPos = visit(*term);
396 auto rhsPos = visit(*++term);
400 if (lhsType->isBasicType() && rhsType->isBasicType()) {
402 case lexer::token::tokenKind::asterisk:
403 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
406 case lexer::token::tokenKind::slash:
407 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
410 case lexer::token::tokenKind::percentSign:
414 panic(op->line, op->col,
"Unexpected multiplication expression operator");
419 case lexer::token::tokenKind::asterisk:
420 handleBinaryOperatorOverload(L
"operator*", *term);
422 case lexer::token::tokenKind::slash:
423 handleBinaryOperatorOverload(L
"operator/", *term);
425 case lexer::token::tokenKind::percentSign:
426 handleBinaryOperatorOverload(L
"operator%", *term);
429 panic(op->line, op->col,
"Unexpected multiplication expression operator");
441 auto lhsPos = visit(*term);
444 auto rhsPos = visit(*++term);
448 if (lhsType->isBasicType() && rhsType->isBasicType()) {
450 case lexer::token::tokenKind::plus:
451 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
454 case lexer::token::tokenKind::minus:
455 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
459 panic(op->line, op->col,
"Unexpected addition expression operator");
464 case lexer::token::tokenKind::plus:
465 handleBinaryOperatorOverload(L
"operator+", *term);
467 case lexer::token::tokenKind::minus:
468 handleBinaryOperatorOverload(L
"operator-", *term);
471 panic(op->line, op->col,
"Unexpected addition expression operator");
495 if (lhsType->isBasicType() && rhsType->type == IRValueType::valueType::integerObject) {
497 case lexer::token::tokenKind::binaryShiftLeft:
500 case lexer::token::tokenKind::binaryShiftRight:
504 panic(op->line, op->col,
"Unexpected shift expression operator");
510 case lexer::token::tokenKind::binaryShiftLeft:
511 handleBinaryOperatorOverload(L
"operator<<", *term);
513 case lexer::token::tokenKind::binaryShiftRight:
514 handleBinaryOperatorOverload(L
"operator>>", *term);
517 panic(op->line, op->col,
"Unexpected shift expression operator");
528 auto lhsPos = visit(*term);
531 auto rhsPos = visit(*++term);
535 if (lhsType->isBasicType() && rhsType->isBasicType()) {
537 case lexer::token::tokenKind::lessThan:
538 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
541 case lexer::token::tokenKind::greaterThan:
542 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
545 case lexer::token::tokenKind::lessEqual:
546 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
549 case lexer::token::tokenKind::greaterEqual:
550 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
554 panic(op->line, op->col,
"Unexpected relational expression operator");
559 case lexer::token::tokenKind::lessThan:
560 handleBinaryOperatorOverload(L
"operator<", *term);
562 case lexer::token::tokenKind::greaterThan:
563 handleBinaryOperatorOverload(L
"operator>", *term);
565 case lexer::token::tokenKind::lessEqual:
566 handleBinaryOperatorOverload(L
"operator<=", *term);
568 case lexer::token::tokenKind::greaterEqual:
569 handleBinaryOperatorOverload(L
"operator>=", *term);
572 panic(op->line, op->col,
"Unexpected relational expression operator");
584 auto lhsPos = visit(*term);
587 auto rhsPos = visit(*++term);
591 if (lhsType->isBasicType() && rhsType->isBasicType() || lhsType->type == IRValueType::valueType::pointerObject ||
592 rhsType->type == IRValueType::valueType::pointerObject) {
594 case lexer::token::tokenKind::equal:
595 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
598 case lexer::token::tokenKind::notEqual:
599 emitBasicCastInBasicArithOpByLhsAndRhs(lhsPos, rhsPos);
603 panic(op->line, op->col,
"Unexpected equality expression operator");
609 case lexer::token::tokenKind::equal:
610 handleBinaryOperatorOverload(L
"operator==", *term);
612 case lexer::token::tokenKind::notEqual:
613 handleBinaryOperatorOverload(L
"operator!=", *term);
616 panic(op->line, op->col,
"Unexpected equality expression operator");
628 auto lhsPos = visit(*term);
631 auto rhsPos = visit(*++term);
635 if (lhsType->isBasicType() && rhsType->isBasicType()) {
637 case lexer::token::tokenKind::binaryAnd: {
638 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
641 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
649 panic(op->line, op->col,
"Unexpected and expression operator");
656 case lexer::token::tokenKind::binaryAnd: {
657 handleBinaryOperatorOverload(L
"operator&", *term);
661 panic(op->line, op->col,
"Unexpected and expression operator");
675 auto lhs = visit(*term);
678 auto rhs = visit(*++term);
682 if (lhsType->isBasicType() && rhsType->isBasicType()) {
684 case lexer::token::tokenKind::binaryXor: {
685 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
688 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
696 panic(op->line, op->col,
"Unexpected exclusive expression operator");
703 case lexer::token::tokenKind::binaryXor: {
704 handleBinaryOperatorOverload(L
"operator^", *term);
708 panic(op->line, op->col,
"Unexpected exclusive expression operator");
720 auto lhs = visit(*term);
722 auto rhs = visit(*++term);
726 if (lhsType->isBasicType() && rhsType->isBasicType()) {
728 case lexer::token::tokenKind::binaryOr: {
729 if (lhsType->isBasicType() && lhsType->type != IRValueType::valueType::integerObject) {
732 if (rhsType->isBasicType() && rhsType->type != IRValueType::valueType::integerObject) {
740 panic(op->line, op->col,
"Unexpected inclusive expression operator");
746 case lexer::token::tokenKind::binaryOr: {
747 handleBinaryOperatorOverload(L
"operator|", *term);
751 panic(op->line, op->col,
"Unexpected inclusive expression operator");
774 if (termType->type != IRValueType::valueType::booleanObject) {
788 if (termType->type != IRValueType::valueType::booleanObject) {
809 auto lhs = visit(*term);
825 .
insert({IR::Opcode::jump,
826 {
IROperand{IROperand::operandType::codeBlock, exitBlock}},
831 .
insert({IR::Opcode::push_boolean,
839 case lexer::token::tokenKind::logicOr: {
840 yoi_assert(lhsType->isBasicType(), op->line, op->col,
"Not basic type for logical or");
841 if (lhsType->type != IRValueType::valueType::booleanObject) {
851 auto rhs = visit(*++term);
853 yoi_assert(rhsType->isBasicType(), op->line, op->col,
"Not basic type for logical or");
854 if (rhsType->type != IRValueType::valueType::booleanObject) {
869 panic(op->line, op->col,
"Unexpected logical or expression operator");
888 if (!notEmitNewBlockInstruction) {
907 while (it + 1 !=
memberExpr->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
909 lastModule = targetModule;
915 if ((*it)->isIdentifier() && !(*it)->id->hasTemplateArg() && (*(it + 1))->isIdentifier() && !(*(it + 1))->id->hasTemplateArg() &&
916 targetedModule->enumerationTable.contains((*it)->id->id->node.strVal)) {
918 auto v = targetedModule->enumerationTable[(*it)->id->id->node.strVal]->valueToIndexMap[(*(it + 1))->id->id->node.strVal];
921 switch (targetedModule->enumerationTable[(*it)->id->id->node.strVal]->getUnderlyingType()) {
922 case IREnumerationType::UnderlyingType::I8: {
923 op = IR::Opcode::push_character;
924 operand = {IROperand::operandType::character, (
yoi::wchar)v};
927 case IREnumerationType::UnderlyingType::I16: {
928 op = IR::Opcode::push_short;
929 operand = {IROperand::operandType::character, (short)v};
932 case IREnumerationType::UnderlyingType::I64: {
933 op = IR::Opcode::push_unsigned;
934 operand = {IROperand::operandType::unsignedInt, (
yoi::indexT)v};
942 }
catch (std::out_of_range &e) {
943 panic((*(it + 1))->getLine(),
944 (*(it + 1))->getColumn(),
952 std::shared_ptr<IRValueType> staticTypeBase{};
955 staticTypeBase =
managedPtr(parseTypeSpecExtern(*it, targetModule == -1 ? currentModuleIndex : targetModule));
957 }
catch (std::runtime_error &) {
959 }
catch (std::out_of_range &) {
963 if (staticTypeBase) {
964 auto memberNameNode = *(++it);
965 yoi_assert(!memberNameNode->getSubscript().empty() && memberNameNode->getSubscript().front()->isInvocation(),
966 memberNameNode->getLine(),
967 memberNameNode->getColumn(),
968 "Static member access must be a method call.");
969 auto &invocation = memberNameNode->getSubscript().front();
971 switch (staticTypeBase->type) {
972 case IRValueType::valueType::structObject: {
973 if (!handleInvocationExtern(
974 memberNameNode->id->getId().node.strVal, invocation->args, staticTypeBase->typeAffiliateModule, staticTypeBase,
true,
975 memberNameNode->id->hasTemplateArg() ? &memberNameNode->id->getArg() :
nullptr))
976 panic(memberNameNode->getLine(),
977 memberNameNode->getColumn(),
978 "No matching static method found for: " +
wstring2string(memberNameNode->id->getId().get().strVal));
982 case IRValueType::valueType::datastructObject: {
983 constructDataStruct(staticTypeBase->typeIndex, staticTypeBase->typeAffiliateModule, invocation->args);
987 panic(memberNameNode->getLine(),
988 memberNameNode->getColumn(),
989 "Static member access must be a method call.");
994 if (targetModule == -1) {
995 visit(*it, isStoreOp && isFinalTerm);
997 visitExtern(*it, targetModule, isStoreOp && isFinalTerm);
1008 auto currentTermNode = *it;
1017 if (currentTermNode->getSubscript().empty()) {
1019 if (objectType->isArrayType() || objectType->isDynamicArrayType()) {
1020 if (currentTermNode->id->getId().get().strVal == L
"length") {
1023 panic(currentTermNode->getLine(), currentTermNode->getColumn(),
"Only 'length' member is valid on array types.");
1025 }
else if (objectType->type == IRValueType::valueType::structObject) {
1028 auto &memberName = currentTermNode->id->getId().get().strVal;
1029 bool isResolved =
false;
1031 auto nameInfo = structDef->lookupName(memberName);
1032 if (nameInfo.type != IRStructDefinition::nameInfo::nameType::field) {
1033 panic(currentTermNode->getLine(),
1034 currentTermNode->getColumn(),
1035 "Cannot access method '" +
wstring2string(memberName) +
"' as a field.");
1037 auto fieldType = structDef->fieldTypes[nameInfo.index];
1040 if (isStoreOp && isFinalTerm) {
1042 tryCastTo(fieldType);
1049 }
catch (std::out_of_range &) {
1053 if (
auto methodName = structDef->name + L
"::" + memberName; !isResolved &&
moduleContext->
getCompilerContext()->getImportedModule(objectType->typeAffiliateModule)->functionOverloadIndexies.contains(methodName)) {
1056 yoi_assert(funcIndexies.size() == 1, (*it)->getLine(), (*it)->getColumn(),
"Multiple overloads found for method: " +
wstring2string(methodName));
1058 auto impl = createCallableImplementationForFunction(funcDef, funcIndexies.front(), objectType->typeAffiliateModule,
true);
1059 createCallableInstanceForFunction(impl.first, impl.second, objectType->typeAffiliateModule,
true);
1062 yoi_assert(isResolved, currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on unknown struct fields or methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1063 }
else if (objectType->type == IRValueType::valueType::datastructObject) {
1065 yoi_assert(structDef->fields.contains(currentTermNode->id->getId().get().strVal), currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on unknown data struct fields or methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1066 auto fieldIndex = structDef->fields[currentTermNode->id->getId().get().strVal];
1067 if (accessors.empty()) {
1073 accessors.emplace_back(IROperand::operandType::index, fieldIndex);
1080 tryCastTo(fieldType);
1090 currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on a non-struct or non-array type is not allowed.");
1095 auto firstOp = currentTermNode->getSubscript().front();
1096 bool isMethodCall = firstOp->isInvocation();
1099 if (objectType->type == IRValueType::valueType::structObject) {
1100 bool isResolved =
false;
1102 isResolved = handleInvocationExtern(
1103 currentTermNode->id->getId().get().strVal, firstOp->args, objectType->typeAffiliateModule, objectType,
false,
1104 currentTermNode->id->hasTemplateArg() ? ¤tTermNode->id->getArg() :
nullptr);
1108 ->getImportedModule(objectType->typeAffiliateModule)
1109 ->structTable[objectType->typeIndex];
1112 auto info = structDef->lookupName(currentTermNode->id->getId().get().strVal);
1114 structDef->fieldTypes[info.index]);
1116 yoi_assert(structDef->fieldTypes[info.index]->type == IRValueType::valueType::structObject ||
1117 structDef->fieldTypes[info.index]->type == IRValueType::valueType::interfaceObject,
1118 currentTermNode->getLine(),
1119 currentTermNode->getColumn(),
1120 "Cannot invoke basic types as methods: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1121 if (!handleInvocationExtern(L
"operator()",
1123 structDef->fieldTypes[info.index]->typeAffiliateModule,
1124 structDef->fieldTypes[info.index]))
1125 panic(currentTermNode->getLine(),
1126 currentTermNode->getColumn(),
1127 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal) +
1131 }
catch (std::out_of_range &) {
1136 panic(currentTermNode->getLine(),
1137 currentTermNode->getColumn(),
1138 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1140 }
else if (objectType->type == IRValueType::valueType::interfaceObject) {
1142 if (!handleInvocationExtern(
1143 currentTermNode->id->getId().get().strVal, firstOp->args, objectType->typeAffiliateModule, objectType))
1144 panic(currentTermNode->getLine(),
1145 currentTermNode->getColumn(),
1146 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal));
1151 if (objectType->type == IRValueType::valueType::structObject) {
1153 ->getImportedModule(objectType->typeAffiliateModule)
1154 ->structTable[objectType->typeIndex];
1155 auto &fieldName = currentTermNode->id->getId().get().strVal;
1157 auto nameInfo = structDef->lookupName(fieldName);
1158 if (nameInfo.type != IRStructDefinition::nameInfo::nameType::field) {
1159 panic(currentTermNode->getLine(),
1160 currentTermNode->getColumn(),
1163 auto fieldType = structDef->fieldTypes[nameInfo.index];
1165 }
catch (std::out_of_range &) {
1166 panic(currentTermNode->getLine(),
1167 currentTermNode->getColumn(),
1171 panic(currentTermNode->getLine(), currentTermNode->getColumn(),
"Member access on a non-struct type is not allowed here.");
1176 auto subIt = isMethodCall ? std::next(currentTermNode->getSubscript().begin()) : currentTermNode->getSubscript().begin();
1177 for (; subIt != currentTermNode->getSubscript().end(); ++subIt) {
1179 bool isFinalOperation = isFinalTerm && (std::next(subIt) == currentTermNode->getSubscript().end());
1182 if (sub->isInvocation()) {
1185 if (!handleInvocationExtern(L
"operator()", sub->args, currentObjectType->typeAffiliateModule, currentObjectType))
1186 panic(sub->getLine(),
1188 "No matching method found for: " +
wstring2string(currentTermNode->id->getId().get().strVal) +
".operator()");
1189 }
else if (sub->isSubscript()) {
1190 if (currentObjectType->isArrayType() || currentObjectType->isDynamicArrayType()) {
1194 yoi_assert(indexType->type == IRValueType::valueType::unsignedObject,
1197 "Array/subscript index must be an integer or unsigned integer.");
1199 if (isStoreOp && isFinalOperation) {
1208 if (isFinalOperation && isStoreOp) {
1219 if (array->type == IRValueType::valueType::structObject)
1220 overload = resolveOverloadExtern(L
"operator[]",
1221 {value, array, index},
1222 array->typeAffiliateModule,
1224 ->getImportedModule(array->typeAffiliateModule)
1225 ->structTable[array->typeIndex]);
1227 yoi_assert(overload.
found(), sub->getLine(), sub->getColumn(),
"No matching overload found for operator[].");
1229 !overload.
isVariadic, sub->getLine(), sub->getColumn(),
"Variadic operator[] overloading is not supported.");
1235 tryCastTo(overload.
function->argumentTypes.back());
1247 handleBinaryOperatorOverload(L
"operator[]", sub->expr);
1266 case inCodeBlockStmt::vKind::ifStmt:
1269 case inCodeBlockStmt::vKind::whileStmt:
1272 case inCodeBlockStmt::vKind::forStmt:
1275 case inCodeBlockStmt::vKind::forEachStmt:
1278 case inCodeBlockStmt::vKind::returnStmt:
1281 case inCodeBlockStmt::vKind::continueStmt:
1284 case inCodeBlockStmt::vKind::breakStmt:
1287 case inCodeBlockStmt::vKind::letStmt:
1290 case inCodeBlockStmt::vKind::codeBlock:
1293 case inCodeBlockStmt::vKind::yieldStmt:
1296 case inCodeBlockStmt::vKind::rExpr:
1316 auto &first_term = *it;
1318 bool isType =
false;
1319 std::shared_ptr<IRValueType> baseType;
1323 }
catch (
const std::runtime_error &) {
1327 bool firstTermHandled =
false;
1330 if (isType && first_term->isSubscript()) {
1334 while (dim_it != end && (*dim_it)->isSubscript()) {
1335 yoi_assert((*dim_it)->expr->getToken().kind == lexer::token::tokenKind::integer,
1336 (*dim_it)->expr->getLine(),
1337 (*dim_it)->expr->getColumn(),
1338 "Array dimension must be an integer.");
1339 dimensions.push_back((*dim_it)->expr->getToken().basicVal.vInt);
1340 size = size * dimensions.back();
1344 if (dim_it != end && (*dim_it)->isInvocation()) {
1345 for (
auto &val : (*dim_it)->args->get()) {
1347 tryCastTo(baseType);
1358 else if (first_term->isInvocation()) {
1359 firstTermHandled =
true;
1361 auto args = first_term->args;
1362 bool resolved =
false;
1367 if (irModule->funcTemplateAsts.contains(baseName)) {
1368 auto astNode = irModule->funcTemplateAsts.at(baseName);
1369 specializeFunctionTemplate(astNode, concreteTemplateArgs, currentModuleIndex);
1373 switch (baseType->type) {
1374 case IRValueType::valueType::structObject:
1376 ->getImportedModule(baseType->typeAffiliateModule)
1377 ->structTable.getKey(baseType->typeIndex);
1379 case IRValueType::valueType::interfaceObject:
1381 ->getImportedModule(baseType->typeAffiliateModule)
1382 ->interfaceTable.getKey(baseType->typeIndex);
1387 "Cannot specialize type: except structObject or interfaceObject but got: " +
1391 }
catch (
const std::runtime_error &e) {
1394 "Could not resolve template specialization for function '" +
wstring2string(baseName) +
": \n" + e.what());
1404 bool isAccessible =
false;
1407 isAccessible =
true;
1409 }
catch (
const std::runtime_error &) {
1414 if (
structObject->type == IRValueType::valueType::structObject ||
structObject->type == IRValueType::valueType::interfaceObject) {
1415 if (!handleInvocationExtern(L
"operator()", args, currentModuleIndex,
structObject))
1427 if (irModule->structTable.contains(baseName)) {
1428 auto structIndex = irModule->structTable.getIndex(baseName);
1429 auto structType = irModule->structTable[structIndex];
1432 if (handleInvocationExtern(L
"constructor", args, currentModuleIndex, rhs)) {
1438 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1446 if (irModule->dataStructTable.contains(baseName)) {
1447 constructDataStruct(irModule->dataStructTable.getIndex(baseName), irModule->identifier, args);
1454 resolved = handleInvocationExtern(baseName, args, currentModuleIndex);
1459 if (irModule->interfaceTable.contains(baseName)) {
1462 auto interfaceIndex = irModule->interfaceTable.getIndex(baseName);
1463 auto argTypes = evaluateArguments(args);
1467 "Interface constructor expects exactly one argument.");
1469 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1471 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1473 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1476 }
catch (
const std::out_of_range &) {
1484 if (irModule->externTable.contains(baseName)) {
1487 auto importedFunctionIndex = irModule->externTable.getIndex(baseName);
1488 yoi_assert(irModule->externTable[importedFunctionIndex]->type == IRExternEntry::externType::importedFunction,
1491 "This is not an imported function.");
1494 ->importedLibraries[irModule->externTable[importedFunctionIndex]->affiliateModule]
1495 .importedFunctionTable[irModule->externTable[importedFunctionIndex]->itemIndex];
1497 auto desiredArgTypes = importedFunc->argumentTypes;
1498 yoi_assert(desiredArgTypes.size() == args->arg.size(),
1501 "Number of arguments does not match the function signature.");
1502 for (
yoi::indexT i = 0; i < args->arg.size(); i++) {
1503 visit(args->arg[i]);
1507 irModule->externTable[importedFunctionIndex]->itemIndex,
1508 desiredArgTypes.size(),
1509 importedFunc->returnType);
1512 }
catch (
const std::out_of_range &) {
1519 if (
auto it = irModule->typeAliases.find(baseName); it != irModule->typeAliases.end()) {
1520 if (it->second.type == IRValueType::valueType::structObject) {
1522 auto structIndex = it->second.typeIndex;
1523 auto structType = targetModule->structTable[structIndex];
1526 if (handleInvocationExtern(L
"constructor", args, targetModule->identifier, rhs)) {
1532 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1534 }
else if (it->second.type == IRValueType::valueType::interfaceObject) {
1539 auto interfaceIndex = it->second.typeIndex;
1540 auto argTypes = evaluateArguments(args);
1544 "Interface constructor expects exactly one argument.");
1546 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1548 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1550 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1553 }
catch (
const std::out_of_range &) {
1557 panic(first_term->getLine(), first_term->getColumn(),
"invalid type alias type");
1565 "'. No matching function, constructor, or template found for the given arguments.");
1573 if (firstTermHandled) {
1579 auto currentTerm = *it;
1580 bool isLastTerm = (std::next(it) == end);
1583 if (currentTerm->isSubscript()) {
1584 if (handleSubscript(it, end, isStoreOp, isLastTerm))
1588 }
else if (currentTerm->isInvocation()) {
1589 if (objectOnStackType->type == IRValueType::valueType::structObject ||
1590 objectOnStackType->type == IRValueType::valueType::interfaceObject) {
1591 if (!handleInvocationExtern(L
"operator()", currentTerm->args, currentModuleIndex, objectOnStackType))
1592 panic(currentTerm->getLine(),
1593 currentTerm->getColumn(),
1596 panic(currentTerm->getLine(), currentTerm->getColumn(),
"Cannot call operator() on non-struct object or interface object.");
1615 auto &firstTerm = *it;
1619 bool isType =
false;
1620 std::shared_ptr<IRValueType> baseType;
1624 }
catch (
const std::out_of_range &) {
1628 bool firstTermHandled =
false;
1631 if (isType && firstTerm->isSubscript()) {
1635 while (dim_it != end && (*dim_it)->isSubscript()) {
1636 yoi_assert((*dim_it)->expr->getToken().kind == lexer::token::tokenKind::integer,
1637 (*dim_it)->expr->getLine(),
1638 (*dim_it)->expr->getColumn(),
1639 "Array dimension must be an integer.");
1640 dimensions.push_back((*dim_it)->expr->getToken().basicVal.vInt);
1641 size = size * dimensions.back();
1645 if (dim_it != end && (*dim_it)->isInvocation()) {
1646 for (
auto &val : (*dim_it)->args->get()) {
1648 tryCastTo(baseType);
1659 else if (firstTerm->isInvocation()) {
1660 firstTermHandled =
true;
1662 auto args = firstTerm->args;
1663 bool resolved =
false;
1668 if (targetedModule->funcTemplateAsts.contains(baseName)) {
1669 auto astNode = targetedModule->funcTemplateAsts.at(baseName);
1670 specializeFunctionTemplate(astNode, concreteTemplateArgs, targetModule);
1674 switch (baseType->type) {
1675 case IRValueType::valueType::structObject:
1677 ->getImportedModule(baseType->typeAffiliateModule)
1678 ->structTable.getKey(baseType->typeIndex);
1680 case IRValueType::valueType::interfaceObject:
1682 ->getImportedModule(baseType->typeAffiliateModule)
1683 ->interfaceTable.getKey(baseType->typeIndex);
1688 "Cannot specialize type: except structObject or interfaceObject but got: " +
1692 }
catch (
const std::runtime_error &e) {
1695 "Could not resolve template specialization for function '" +
wstring2string(baseName) +
"'" +
": \n" + e.what() +
"\n");
1696 }
catch (
const std::out_of_range &e) {
1703 if (targetedModule->structTable.contains(baseName)) {
1706 externStructEntry = getExternEntry(targetModule, baseName);
1707 }
catch (
const std::out_of_range &) {
1711 auto targetedStruct = targetedModule->structTable[baseName];
1715 if (handleInvocationExtern(L
"constructor", args, targetModule, rhs)) {
1724 if (targetedModule->dataStructTable.contains(baseName)) {
1725 constructDataStruct(targetedModule->dataStructTable.getIndex(baseName), targetedModule->identifier, args);
1732 resolved = handleInvocationExtern(baseName, args, targetModule);
1737 if (targetedModule->interfaceTable.contains(baseName)) {
1740 auto argTypes = evaluateArguments(args);
1744 "Interface constructor expects exactly one argument.");
1748 auto externInterface = getExternEntry(targetModule, baseName);
1751 auto interfaceImplName = getInterfaceImplName({externInterface.affiliateModule, externInterface.itemIndex}, argTypes[0]);
1753 ->getImportedModule(concreteThis->typeAffiliateModule)
1754 ->interfaceImplementationTable.getIndex(interfaceImplName);
1757 concreteThis->typeAffiliateModule != currentModuleIndex,
1758 concreteThis->typeAffiliateModule);
1762 }
catch (
const std::out_of_range &e) {
1765 "Could not find matched extern interface constructor for " +
wstring2string(baseName));
1775 if (targetedModule->externTable.contains(baseName)) {
1778 auto argTypes = evaluateArguments(args);
1779 auto externEntry = targetedModule->externTable[baseName];
1782 ->importedLibraries[externEntry->affiliateModule]
1783 .importedFunctionTable[externEntry->itemIndex];
1785 externEntry->affiliateModule, externEntry->itemIndex, argTypes.size(), externFunc->returnType);
1789 }
catch (
const std::exception &) {
1796 if (
auto it = targetedModule->typeAliases.find(baseName); it != targetedModule->typeAliases.end()) {
1797 if (it->second.type == IRValueType::valueType::structObject) {
1799 auto structIndex = it->second.typeIndex;
1800 auto structType = targetModule->structTable[structIndex];
1803 if (handleInvocationExtern(L
"constructor", args, targetModule->identifier, rhs)) {
1809 "Could not resolve constructor for struct '" +
wstring2string(baseName) +
"'.");
1811 }
else if (it->second.type == IRValueType::valueType::interfaceObject) {
1816 auto interfaceIndex = it->second.typeIndex;
1817 auto argTypes = evaluateArguments(args);
1821 "Interface constructor expects exactly one argument.");
1823 auto interfaceImplName = getInterfaceImplName({currentModuleIndex, interfaceIndex}, argTypes[0]);
1825 auto interfaceImplIndex = targetModule->interfaceImplementationTable.getIndex(interfaceImplName);
1827 {currentModuleIndex, interfaceIndex}, interfaceImplIndex,
true, targetModule->identifier);
1830 }
catch (
const std::exception &) {
1834 panic(firstTerm->getLine(), firstTerm->getColumn(),
"invalid type alias type: " +
wstring2string(baseName));
1841 "Could not find extern function, struct constructor, or interface in module: " +
wstring2string(baseName));
1847 if (firstTermHandled) {
1853 auto currentTerm = *it;
1854 bool isLastTerm = (std::next(it) == end);
1857 if (currentTerm->isSubscript()) {
1858 if (handleSubscript(it, end, isStoreOp, isLastTerm))
1862 }
else if (currentTerm->isInvocation()) {
1863 if (objectOnStackType->type == IRValueType::valueType::structObject ||
1864 objectOnStackType->type == IRValueType::valueType::interfaceObject) {
1865 handleInvocationExtern(L
"operator()", currentTerm->args, currentModuleIndex, objectOnStackType);
1867 panic(currentTerm->getLine(), currentTerm->getColumn(),
"Cannot call operator() on non-struct object or interface object.");
1896 return irModule->typeAliases.at(typeName);
1897 }
catch (std::out_of_range &e) {
1901 auto typeIndex = irModule->structTable.getIndex(typeName);
1902 return IRValueType{IRValueType::valueType::structObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1903 }
catch (std::out_of_range &e) {
1907 auto typeIndex = irModule->dataStructTable.getIndex(typeName);
1908 return IRValueType{IRValueType::valueType::datastructObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1909 }
catch (std::out_of_range &e) {
1913 auto typeIndex = irModule->interfaceTable.getIndex(typeName);
1914 return IRValueType{IRValueType::valueType::interfaceObject,
static_cast<yoi::indexT>(currentModuleIndex), typeIndex};
1915 }
catch (std::out_of_range &e) {
1919 auto incompleteType = getIncompleteType(typeName);
1920 return *incompleteType;
1921 }
catch (std::out_of_range &e) {
1924 if (typeName == L
"int") {
1926 }
else if (typeName == L
"bool") {
1928 }
else if (typeName == L
"deci") {
1930 }
else if (typeName == L
"string") {
1932 }
else if (typeName == L
"none") {
1934 }
else if (typeName == L
"char") {
1936 }
else if (typeName == L
"int32") {
1938 }
else if (typeName == L
"float") {
1940 }
else if (typeName == L
"ptr") {
1942 }
else if (typeName == L
"unsigned") {
1944 }
else if (typeName == L
"short") {
1954 if (funcName.hasDefTemplateArg()) {
1956 irModule->funcTemplateAsts[actualName] =
funcDefStmt;
1958 bool isVaridic =
false;
1967 std::vector<std::shared_ptr<IRValueType>> argTypes;
1969 if (&i == &
funcDefStmt->
getArgs().
get().back() && i->spec->kind == typeSpec::typeSpecKind::Elipsis ) {
1971 builder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
1972 auto argName = i->getId().node.strVal;
1973 auto argType =
managedPtr(i->spec->elipsis ? parseTypeSpec(i->spec->elipsis).getDynamicArrayType()
1976 argTypes.push_back(argType);
1980 auto argName = i->getId().node.strVal;
1981 auto argType =
managedPtr(parseTypeSpec(i->spec));
1982 argTypes.push_back(argType);
1986 if (builder.
attrs.contains(IRFunctionDefinition::FunctionAttrs::Generator)) {
1988 std::to_wstring(irModule->identifier) + L
"_" + funcName.getId().node.strVal + getFuncUniqueNameStr(argTypes),
1995 builder.
setName(funcName.getId().node.strVal + getFuncUniqueNameStr(argTypes));
1997 auto func = builder.
yield();
1999 auto funcIndex = irModule->functionTable.put(builder.
name, func);
2000 irModule->functionOverloadIndexies[funcName.getId().node.strVal].push_back(funcIndex);
2003 if (builder.
attrs.contains(IRFunctionDefinition::FunctionAttrs::Generator)) {
2025 auto interfaceIndex = irModule->interfaceTable.put(interfaceName, {});
2028 builder.
setName(interfaceName);
2030 bool isVaridic =
false;
2031 yoi_assert(i->isMethod(), i->getLine(), i->getColumn(),
"Interface member must be a method");
2033 auto methodName = i->getMethod().getName().getId().get().strVal;
2034 auto methodResultType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
2038 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2041 for (
auto &arg : i->getMethod().getArgs().get()) {
2042 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis ) {
2044 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2045 auto argName = arg->getId().node.strVal;
2047 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2050 argTypes.push_back(argType);
2054 auto argName = arg->getId().get().strVal;
2055 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2057 argTypes.push_back(argType);
2059 auto methodFuncName = L
"interface#" + interfaceName + L
"#" + methodName;
2060 auto uniq = getFuncUniqueNameStr(argTypes);
2061 methodBuilder.
setName(methodFuncName + uniq);
2063 auto func = methodBuilder.
yield();
2064 builder.
addMethod(methodName, methodName + uniq, func);
2066 auto interfaceType = builder.
yield();
2067 irModule->interfaceTable[interfaceIndex] = interfaceType;
2077 auto structIndex = irModule->structTable.put(structName, {});
2079 generateNullInterfaceImplementation(
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex}));
2086 auto memberName = i->getVar().getId().get().strVal;
2087 auto memberType =
managedPtr(parseTypeSpec(i->getVar().spec));
2088 if (i->modifier == structDefInnerPair::Modifier::DataField) {
2089 memberType->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
2091 if (i->modifier == structDefInnerPair::Modifier::Weak) {
2092 memberType->addAttribute(IRValueType::ValueAttr::WeakRef);
2094 builder.
addField(memberName, memberType);
2098 bool isVaridic =
false;
2101 constructorBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2102 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
2105 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2107 constructorBuilder.
addArgument(L
"this", thisType);
2108 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
2109 for (
auto &arg : i->getConstructor().getArgs().get()) {
2110 if (&arg == &i->getConstructor().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2112 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2113 auto argName = arg->getId().node.strVal;
2115 ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2118 argTypes.push_back(argType);
2121 auto argName = arg->getId().get().strVal;
2122 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2124 argTypes.push_back(argType);
2126 auto uniq = getFuncUniqueNameStr(argTypes);
2127 auto mangledName = L
"constructor" + uniq;
2128 constructorBuilder.
setName(structName + L
"::" + mangledName);
2130 auto func = constructorBuilder.
yield();
2131 auto funcIndex = irModule->functionTable.put_create(func->name, func);
2132 builder.
addMethod(mangledName, funcIndex);
2133 irModule->functionOverloadIndexies[structName + L
"::constructor"].push_back(funcIndex);
2137 bool isVaridic =
false;
2138 auto methodName = i->getMethod().getName().getId().get().strVal;
2140 if (i->getMethod().getName().hasDefTemplateArg()) {
2146 auto methodType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
2149 methodBuilder.
attrs = getFunctionAttributes(i->getMethod().attrs);
2150 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2155 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2157 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
2158 methodBuilder.
attrs.end())
2161 for (
auto &arg : i->getMethod().getArgs().get()) {
2162 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2164 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2165 auto argName = arg->getId().node.strVal;
2167 ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2170 argTypes.push_back(argType);
2173 auto argName = arg->getId().get().strVal;
2174 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2176 argTypes.push_back(argType);
2179 auto uniq = getFuncUniqueNameStr(argTypes);
2180 auto mangledName = methodName + uniq;
2181 methodBuilder.
setName(structName + L
"::" + mangledName);
2182 auto func = methodBuilder.
yield();
2183 auto funcIndex = irModule->functionTable.put_create(func->name, func);
2184 builder.
addMethod(mangledName, funcIndex);
2185 irModule->functionOverloadIndexies[structName + L
"::" + methodName].push_back(funcIndex);
2191 finalizerBuilder.
setName(structName + L
"::finalizer");
2192 finalizerBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2193 finalizerBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Finalizer);
2194 finalizerBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
2195 auto thisType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
2198 auto func = finalizerBuilder.
yield();
2199 auto funcIndex = irModule->functionTable.put_create(structName + L
"::finalizer", func);
2200 builder.
addMethod(L
"finalizer", funcIndex);
2206 auto structType = builder.
yield();
2207 irModule->structTable[structIndex] = structType;
2215 auto it = structIdNode.
getTerms().begin();
2217 while (it + 1 != structIdNode.getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2219 lastModule = targetModule;
2221 if (targetModule == -1) {
2222 targetModule = currentModuleIndex;
2224 yoi_assert(it + 1 == structIdNode.getTerms().end(), structIdNode.getLine(), structIdNode.getColumn(),
"Invalid interface name");
2227 auto structBaseName = (*it)->getId().get().strVal;
2229 if ((*it)->hasTemplateArg()) {
2231 yoi_assert(targetedModule->structTemplateAsts.contains(structBaseName),
2234 "Impl for undefined struct template: " +
wstring2string(structBaseName));
2240 if (concreteTemplateArgs.empty()) {
2241 targetedModule->templateInterfaceImplAsts[structBaseName].push_back(
implStmt);
2244 auto interfaceTemplateAst = targetedModule->templateInterfaceAsts[structBaseName];
2245 auto concreteStructName = getMangledTemplateName(structBaseName, concreteTemplateArgs);
2247 yoi_assert(concreteStructType->type == IRValueType::valueType::structObject,
2250 "Invalid struct name for struct specialization: " +
wstring2string(concreteStructName) +
2251 " (except structObject but got " +
wstring2string(concreteStructType->to_string()) +
")");
2253 specializeInterfaceImplementation(
implStmt, concreteStructType, concreteStructName, concreteTemplateArgs, targetModule);
2256 if (concreteTemplateArgs.empty()) {
2258 targetedModule->templateImplAsts[structBaseName] =
implStmt;
2261 auto structTemplateAst = targetedModule->structTemplateAsts[structBaseName];
2262 specializeStructTemplate(structBaseName, concreteTemplateArgs,
implStmt, targetModule);
2271 std::shared_ptr<IRValueType> srcType;
2274 targetModule = srcType->typeAffiliateModule;
2276 }
catch (std::runtime_error &e) {
2280 auto targetInterface =
2282 targetInterface->implementations.emplace_back(srcType->type, srcType->typeAffiliateModule, srcType->typeIndex);
2283 auto interfaceImplName = getInterfaceImplName(interfaceName.first, srcType);
2287 interfaceImplIndex = targetedModule->interfaceImplementationTable.getIndex(interfaceImplName);
2288 if (targetedModule->interfaceImplementationTable[interfaceImplIndex]) {
2292 }
catch (std::out_of_range &e) {
2293 interfaceImplIndex = targetedModule->interfaceImplementationTable.put(interfaceImplName, {});
2297 builder.
setName(interfaceImplName);
2298 builder.
setImplStructIndex({srcType->type, srcType->typeAffiliateModule, srcType->typeIndex});
2301 std::map<yoi::wstr, std::pair<yoi::wstr, std::shared_ptr<IRValueType>>> virtualMethodMap;
2307 "impl-for statement only allows method definition, not constructor or finalizer");
2309 bool isVaridic =
false;
2311 auto methodName = i->getMethod().getName().getId().get().strVal;
2314 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
2315 methodBuilder.
attrs = getFunctionAttributes(i->getMethod().attrs);
2316 methodBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
2320 const auto &thisType = srcType;
2321 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
2322 methodBuilder.
attrs.end())
2325 for (
auto &arg : i->getMethod().getArgs().get()) {
2326 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2328 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
2329 auto argName = arg->getId().node.strVal;
2331 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
2334 argTypes.push_back(argType);
2337 auto argName = arg->getId().get().strVal;
2338 auto argType =
managedPtr(parseTypeSpec(arg->spec));
2340 argTypes.push_back(argType);
2342 auto uniq = getFuncUniqueNameStr(argTypes);
2344 methodBuilder.
setName(structBaseName + L
"::" + methodName + uniq + L
"interfaceImpl#" + interfaceImplName);
2346 auto func = methodBuilder.
yield();
2347 auto funcIndex = targetedModule->functionTable.put_create(func->name, func);
2348 targetedModule->functionOverloadIndexies[structBaseName + L
"::" + methodName + L
"interfaceImpl#" + interfaceImplName].push_back(
2353 virtualMethodMap[methodName + getFuncUniqueNameStr(argTypes,
true)] = {
2354 methodName + uniq,
managedPtr(
IRValueType{IRValueType::valueType::virtualMethod, targetModule, funcIndex})};
2359 visit(i->getMethod().block,
true);
2364 for (
auto &method : targetInterface->methodMap) {
2365 yoi_assert(virtualMethodMap.contains(method.first),
2368 "Method '" +
wstring2string(method.first) +
"' not implemented for interface '" +
2370 builder.
addVirtualMethod(virtualMethodMap[method.first].first, virtualMethodMap[method.first].second);
2373 targetedModule->interfaceImplementationTable[interfaceImplIndex] = builder.
yield();
2380 structIndex = targetedModule->structTable.getIndex(structBaseName);
2381 }
catch (std::runtime_error &e) {
2388 if (i->isConstructor()) {
2389 bool isVaridic =
false;
2391 for (
auto &arg : i->getConstructor().getArgs().get()) {
2392 if (&arg == &i->getConstructor().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2395 argTypes.push_back(argType);
2398 argTypes.push_back(
managedPtr(parseTypeSpec(arg->spec)));
2400 mangledName = structBaseName + L
"::constructor" + getFuncUniqueNameStr(argTypes);
2401 block = i->getConstructor().block;
2402 }
else if (i->isFinalizer()) {
2403 mangledName = structBaseName + L
"::finalizer";
2404 block = i->getFinalizer().block;
2406 if (i->getMethod().getName().hasTemplateArg()) {
2408 auto structDef = targetedModule->structTable[structIndex];
2409 structDef->templateMethodDefs[i->getMethod().getName().getId().get().strVal] = i;
2413 bool isVaridic =
false;
2415 for (
auto &arg : i->getMethod().getArgs().get()) {
2416 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
2420 auto argType =
managedPtr(type.getDynamicArrayType());
2421 argTypes.push_back(argType);
2424 argTypes.push_back(
managedPtr(parseTypeSpec(arg->spec)));
2426 mangledName = structBaseName + L
"::" + i->getMethod().getName().getId().get().strVal + getFuncUniqueNameStr(argTypes);
2427 block = i->getMethod().block;
2431 auto funcIndex = targetedModule->functionTable.getIndex(mangledName);
2432 auto func = targetedModule->functionTable[funcIndex];
2439 }
catch (std::out_of_range &e) {
2441 i->getLine(), i->getColumn(),
"No matched constructor or method declaration found for impl: " +
wstring2string(mangledName));
2452 if (i->lhs->kind == letAssignmentPairLHS::vKind::identifier) {
2453 if (isVisitingGlobalScope()) {
2456 auto index = irModule->globalVariables.put(i->lhs->id->node.strVal, type);
2464 }
else if (i->lhs->kind == letAssignmentPairLHS::vKind::list) {
2466 if (type->isArrayType() || type->isDynamicArrayType()) {
2469 ? IRBuilder::ExtractType::First
2470 : IRBuilder::ExtractType::Last};
2471 bool isFull = i->lhs->list.back().kind != lexer::token::tokenKind::kThreeDots &&
2472 i->lhs->list.front().kind != lexer::token::tokenKind::kThreeDots;
2473 auto elementCount = i->lhs->list.size() - !isFull;
2475 auto bindType =
managedPtr(type->getElementType());
2476 for (
yoi::indexT curPos = extractType == IRBuilder::ExtractType::First && !isFull; curPos < elementCount; curPos++) {
2477 if (isVisitingGlobalScope()) {
2479 auto index = irModule->globalVariables.put(i->lhs->list[i->lhs->list.size() - 1 - curPos].strVal, bindType);
2484 i->lhs->list[i->lhs->list.size() - 1 - curPos].strVal, bindType);
2488 }
else if (type->type == IRValueType::valueType::structObject) {
2491 ? IRBuilder::ExtractType::First
2492 : IRBuilder::ExtractType::Last};
2493 bool isFull = i->lhs->list.back().kind != lexer::token::tokenKind::kThreeDots &&
2494 i->lhs->list.front().kind != lexer::token::tokenKind::kThreeDots;
2495 yoi::indexT elementCount = i->lhs->list.size() - !isFull;
2496 yoi::indexT startPos = extractType == IRBuilder::ExtractType::First ? elementCount - 1 : i->lhs->list.size() - 1;
2497 yoi::indexT endPos = extractType == IRBuilder::ExtractType::First ? -1 : 0 - isFull;
2499 for (
yoi::indexT curPos = startPos; curPos != endPos; curPos -= 1) {
2501 if (isVisitingGlobalScope()) {
2503 auto index = irModule->globalVariables.put(i->lhs->list[curPos].strVal, fieldType);
2504 tryCastTo(fieldType);
2510 tryCastTo(fieldType);
2515 panic(i->getLine(), i->getColumn(),
"Unsupported structured binding");
2526 case globalStmt::vKind::useStmt: {
2530 case globalStmt::vKind::implStmt: {
2534 case globalStmt::vKind::letStmt: {
2538 case globalStmt::vKind::funcDefStmt: {
2542 case globalStmt::vKind::structDefStmt: {
2546 case globalStmt::vKind::interfaceDefStmt: {
2550 case globalStmt::vKind::importDecl: {
2554 case globalStmt::vKind::exportDecl: {
2558 case globalStmt::vKind::typeAliasStmt: {
2562 case globalStmt::vKind::enumerationDef: {
2566 case globalStmt::vKind::dataStructDefStmt: {
2570 case globalStmt::vKind::conceptDef: {
2583 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2586 "The type in if-condition must be boolean");
2600 yoi_assert(elifCondType->type == IRValueType::valueType::booleanObject,
2602 i.cond->getColumn(),
2603 "The type in elif-condition must be boolean");
2608 visit(i.block,
true);
2634 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2637 "The type in while-condition must be boolean");
2672 yoi_assert(condType->type == IRValueType::valueType::booleanObject,
2675 "The type in for-condition must be boolean");
2706 "Generator function cannot return a value");
2710 tryCastTo(returnType);
2734 if (irModule->structTemplateAsts.contains(baseName)) {
2736 auto pureTemplateAst = irModule->templateImplAsts.at(baseName);
2737 auto specializedIndex = specializeStructTemplate(baseName, concreteTypes, pureTemplateAst, currentModuleIndex);
2738 return {IRValueType::valueType::structObject, currentModuleIndex, specializedIndex};
2739 }
catch (std::out_of_range &e) {
2742 "No implementation block found for struct template: " +
wstring2string(baseName));
2744 }
else if (irModule->templateInterfaceAsts.contains(baseName)) {
2745 auto specializedIndex = specializeInterfaceTemplate(baseName, concreteTypes, currentModuleIndex);
2746 return {IRValueType::valueType::interfaceObject, currentModuleIndex, specializedIndex};
2761 yoi_assert(sub->isSubscript() && sub->expr->getToken().kind == lexer::token::tokenKind::integer,
2764 "Expected dimension size for array type.");
2765 dimensions.push_back(sub->expr->getToken().basicVal.vInt);
2767 return baseType.getArrayType(dimensions);
2775 if (
auto it = mod->typeAliases.find(
identifier->
get().
strVal); it != mod->typeAliases.end()) {
2779 if (ex.
type == IRExternEntry::externType::structType)
2781 if (ex.
type == IRExternEntry::externType::datastructType)
2783 else if (ex.
type == IRExternEntry::externType::interfaceType)
2796 if (targetedModule->structTemplateAsts.contains(baseName)) {
2798 auto pureTemplateAst = targetedModule->templateImplAsts.at(baseName);
2799 auto specializedIndex = specializeStructTemplate(baseName, concreteTypes, pureTemplateAst, targetModule);
2800 return {IRValueType::valueType::structObject, targetModule, specializedIndex};
2801 }
catch (std::out_of_range &e) {
2804 "No implementation block found for struct template: " +
wstring2string(baseName));
2806 }
else if (targetedModule->templateInterfaceAsts.contains(baseName)) {
2807 auto specializedIndex = specializeInterfaceTemplate(baseName, concreteTypes, targetModule);
2808 return {IRValueType::valueType::interfaceObject, targetModule, specializedIndex};
2822 return {IRValueType::valueType::null};
2830 case typeSpec::typeSpecKind::Member: {
2834 while (it + 1 !=
typeSpec->
member->
getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2836 lastModule = targetModule;
2839 IRValueType lhs{IRValueType::valueType::integerObject};
2841 if (targetModule == -1) {
2842 lhs = parseTypeSpec(*it);
2844 lhs = parseTypeSpecExtern(*it, targetModule);
2846 }
catch (std::out_of_range &e) {
2853 return lhs.getDynamicArrayType();
2861 case typeSpec::typeSpecKind::Func: {
2865 case typeSpec::typeSpecKind::Null: {
2867 return {IRValueType::valueType::null};
2869 case typeSpec::typeSpecKind::DecltypeExpr: {
2876 case typeSpec::typeSpecKind::Elipsis: {
2882 return {IRValueType::valueType::null};
2892 res += parseTypeSpec(i->spec).to_string();
2898 return std::move(res);
2901 yoi::wstr visitor::getInterfaceImplName(
const std::pair<yoi::indexT, yoi::indexT> &interfaceSrc,
const std::shared_ptr<IRValueType> &typeSrc) {
2902 return L
"interfaceImpl#" + std::to_wstring(interfaceSrc.first) + L
"#" + std::to_wstring(interfaceSrc.second) + L
"#" + typeSrc->to_string();
2905 std::pair<std::pair<yoi::indexT, yoi::indexT>, std::shared_ptr<IRInterfaceInstanceDefinition>>
2908 auto it = structDef->
getTerms().begin();
2910 while (it + 1 != structDef->
getTerms().end() && (targetModule = isModuleName(*it, targetModule)) != lastModule) {
2912 lastModule = targetModule;
2914 if (targetModule == -1) {
2915 targetModule = currentModuleIndex;
2918 auto interfaceName = parseIdentifierWithTemplateArg(*it);
2921 auto interfaceIndex = target->interfaceTable.getIndex(interfaceName);
2922 return std::make_pair(std::make_pair(targetModule, interfaceIndex), target->interfaceTable[interfaceIndex]);
2923 }
catch (std::out_of_range &) {
2930 return isModuleName(it->
id, currentModule);
2932 return currentModule;
2939 return {IRExternEntry::externType::globalVar,
identifier, moduleIndex, res};
2940 }
catch (std::out_of_range &) {
2944 return {IRExternEntry::externType::function,
identifier, moduleIndex, res};
2945 }
catch (std::out_of_range &) {
2949 return {IRExternEntry::externType::structType,
identifier, moduleIndex, res};
2950 }
catch (std::out_of_range &) {
2954 return {IRExternEntry::externType::datastructType,
identifier, moduleIndex, res};
2955 }
catch (std::out_of_range &) {
2959 return {IRExternEntry::externType::interfaceType,
identifier, moduleIndex, res};
2960 }
catch (std::out_of_range &) {
2964 return {IRExternEntry::externType::interfaceImplType,
identifier, moduleIndex, res};
2965 }
catch (std::out_of_range &) {
2968 throw std::out_of_range(
"undefined identifier: not known global variable, function, struct or interface type: " +
2972 bool visitor::isVisitingGlobalScope()
const {
2980 if (lhsType->isForeignBasicType()) {
2981 lhsType =
managedPtr(lhsType->getNormalizedForeignBasicType());
2983 if (rhsType->isForeignBasicType()) {
2984 rhsType =
managedPtr(rhsType->getNormalizedForeignBasicType());
2988 if (lhsType->is1ByteType() && !rhsType->is1ByteType()) {
2990 }
else if (!lhsType->is1ByteType() && rhsType->is1ByteType()) {
2994 if (lhsType->type == IRValueType::valueType::shortObject && rhsType->type != IRValueType::valueType::shortObject) {
2996 }
else if (lhsType->type != IRValueType::valueType::shortObject && rhsType->type == IRValueType::valueType::shortObject) {
3000 else if (lhsType->type == IRValueType::valueType::integerObject && rhsType->type == IRValueType::valueType::decimalObject) {
3002 }
else if (lhsType->type == IRValueType::valueType::decimalObject && rhsType->type == IRValueType::valueType::integerObject) {
3006 else if (lhsType->type == IRValueType::valueType::unsignedObject && rhsType->type == IRValueType::valueType::integerObject) {
3008 }
else if (lhsType->type == IRValueType::valueType::integerObject && rhsType->type == IRValueType::valueType::unsignedObject) {
3012 else if (lhsType->type == IRValueType::valueType::unsignedObject && rhsType->type == IRValueType::valueType::decimalObject) {
3014 }
else if (lhsType->type == IRValueType::valueType::decimalObject && rhsType->type == IRValueType::valueType::unsignedObject) {
3018 else if (lhsType->type == IRValueType::valueType::pointerObject) {
3020 }
else if (rhsType->type == IRValueType::valueType::pointerObject) {
3025 void visitor::emitBasicCastTo(
const std::shared_ptr<IRValueType> &toType) {
3028 if (rhs->type == toType->type) {
3035 yoi::wstr visitor::getInterfaceNameStr(
const std::pair<yoi::indexT, yoi::indexT> &interfaceSrc) {
3036 return L
"interface#" + std::to_wstring(interfaceSrc.first) + L
"#" + std::to_wstring(interfaceSrc.second);
3039 yoi::wstr visitor::getTypeSpecUniqueNameStr(
const std::shared_ptr<IRValueType> &type) {
3041 switch (type->type) {
3042 case IRValueType::valueType::integerObject:
3045 case IRValueType::valueType::decimalObject:
3048 case IRValueType::valueType::booleanObject:
3051 case IRValueType::valueType::stringObject:
3054 case IRValueType::valueType::characterObject:
3057 case IRValueType::valueType::shortObject:
3060 case IRValueType::valueType::unsignedObject:
3063 case IRValueType::valueType::structObject:
3064 res = L
"struct#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3066 case IRValueType::valueType::null:
3069 case IRValueType::valueType::virtualMethod:
3070 res = L
"virtual_method#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3072 case IRValueType::valueType::incompleteTemplateType:
3073 res = L
"incomplete_template_type#" + std::to_wstring(type->typeIndex);
3075 case IRValueType::valueType::interfaceObject:
3076 res = L
"interfaceObject#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3078 case IRValueType::valueType::pointerObject:
3079 res = L
"pointerObject";
3081 case IRValueType::valueType::none:
3084 case IRValueType::valueType::datastructObject:
3085 res += L
"datastructObject#" + std::to_wstring(type->typeAffiliateModule) + L
"#" + std::to_wstring(type->typeIndex);
3093 if (type->isArrayType()) {
3095 for (
auto &dim : type->dimensions) {
3098 res += L
"[" + std::to_wstring(arraySize) + L
"]";
3099 }
else if (type->isDynamicArrayType()) {
3105 yoi::wstr visitor::getFuncUniqueNameStr(
const std::vector<std::shared_ptr<IRValueType>> &argumentTypes,
bool whetherIgnoreFirstParam) {
3108 for (
auto &arg : argumentTypes) {
3109 if (whetherIgnoreFirstParam && !first || !whetherIgnoreFirstParam)
3110 res += getTypeSpecUniqueNameStr(arg) + L
"#";
3114 if (!argumentTypes.empty()) {
3117 res.shrink_to_fit();
3127 "Invalid type specifier, expected global variable");
3139 }
catch (std::runtime_error &) {
3142 }
catch (std::out_of_range &) {
3158 std::shared_ptr<IRValueType> visitor::getIncompleteType(
const yoi::wstr &typeName)
const {
3161 throw std::out_of_range(
"No template builder found");
3164 auto res = templateBuilder.templateArguments[typeName];
3165 return res.templateType;
3166 }
catch (std::out_of_range &e) {
3173 for (
auto &arg : templateArgs.
spec) {
3174 yoi::wstr name = arg->getId().get().strVal;
3176 res[index].templateType =
managedPtr(
IRValueType{IRValueType::valueType::incompleteTemplateType, currentModuleIndex, index});
3183 for (
auto &arg : templateArgs.
spec) {
3184 res.push_back(
managedPtr(parseTypeSpec(arg->spec)));
3190 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3204 auto paramName = astNode->
id->
arg->
get()[i]->id->get().strVal;
3206 for (
auto &c : astNode->
id->
arg->
get()[i]->satisfyCondition->emaes) {
3207 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3213 pushModuleContext(moduleIndex);
3218 for (
const auto &argPair : astNode->
getArgs().
get()) {
3219 auto argName = argPair->getId().get().strVal;
3220 auto argType =
managedPtr(parseTypeSpec(&argPair->getSpec()));
3222 paramTypes.push_back(argType);
3225 if (targetedModule->functionTable.contains(specializedName + getFuncUniqueNameStr(paramTypes))) {
3226 auto result = targetedModule->functionTable.getIndex(specializedName + getFuncUniqueNameStr(paramTypes));
3233 builder.
setName(specializedName + getFuncUniqueNameStr(paramTypes));
3236 auto specializedFunc = builder.
yield();
3237 auto funcIndex = targetedModule->functionTable.put_create(specializedName + getFuncUniqueNameStr(paramTypes), specializedFunc);
3238 targetedModule->functionOverloadIndexies[specializedName].push_back(funcIndex);
3246 }
catch (std::runtime_error &e) {
3249 std::string(
"Exception occurred while specializing method: ") +
yoi::wstring2string(specializedName) +
": " + e.what());
3250 }
catch (std::exception &e) {
3253 std::string(
"Unknown exception occurred while specializing method: ") +
yoi::wstring2string(specializedName) +
": " + e.what());
3267 for (
size_t i = 0; i < templateArgs.size(); ++i) {
3268 mangled += getTypeSpecUniqueNameStr(templateArgs[i]);
3269 if (i < templateArgs.size() - 1) {
3281 for (
auto &spec : templateArgs->
get()) {
3286 if (!term->hasTemplateArg()) {
3287 params.push_back(term->id->get().strVal);
3292 panic(templateArgs->
getLine(), templateArgs->
getColumn(),
"Invalid template parameter definition. Expected identifier.");
3301 for (
auto &spec : templateArgs->
get()) {
3302 params.push_back(spec->getId().get().strVal);
3308 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3314 yoi::wstr specializedName = getMangledTemplateName(templateName, concreteTemplateArgs);
3316 if (targetedModule->structTable.contains(specializedName)) {
3317 return targetedModule->structTable.getIndex(specializedName);
3320 auto structAst = targetedModule->structTemplateAsts.at(templateName);
3323 yoi_assert(concreteTemplateArgs.size() == structAst->id->getArg().get().size(),
3326 "Template argument count mismatch for struct " +
wstring2string(templateName));
3327 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3328 auto paramName = structAst->id->getArg().get()[i]->getId().get().strVal;
3330 if (structAst->id->hasDefTemplateArg() && structAst->id->getArg().get()[i]->satisfyCondition) {
3331 for (
auto &c : structAst->id->getArg().get()[i]->satisfyCondition->emaes) {
3332 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3338 auto specializedStructIndex = targetedModule->structTable.put_create(specializedName,
nullptr);
3340 generateNullInterfaceImplementation(
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, specializedStructIndex}));
3341 auto selfType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, specializedStructIndex});
3344 pushModuleContext(moduleIndex);
3348 builder.
setName(specializedName);
3350 for (
yoi::indexT i = 0; i < structAst->id->getArg().get().size(); ++i) {
3351 paramNames.push_back(structAst->id->getArg().get()[i]->getId().get().strVal);
3354 for (
auto &field : structAst->getInner().getInner()) {
3355 if (field->kind == 0) {
3356 auto memberName = field->getVar().getId().get().strVal;
3357 auto memberType =
managedPtr(parseTypeSpec(field->getVar().spec));
3358 if (field->modifier == structDefInnerPair::Modifier::DataField) {
3359 memberType->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
3361 if (field->modifier == structDefInnerPair::Modifier::Weak) {
3362 memberType->addAttribute(IRValueType::ValueAttr::WeakRef);
3364 builder.
addField(memberName, memberType);
3365 }
else if (field->kind == 2 && field->getMethod().getName().hasDefTemplateArg()) {
3369 auto [funcIndex, funcName] =
3370 specializeStructMethodDeclaration(specializationContext, field, specializedName, concreteTemplateArgs, moduleIndex);
3376 if (pureTemplateImplAst) {
3378 if (methodAst->isMethod() && methodAst->getMethod().getName().hasTemplateArg()) {
3379 builder.
addTemplateMethodDef(methodAst->getMethod().getName().getId().get().strVal, methodAst);
3384 auto specializedStruct = builder.
yield();
3385 targetedModule->structTable[specializedStructIndex] = specializedStruct;
3388 if (pureTemplateImplAst) {
3390 if (methodAst->isMethod() && methodAst->getMethod().getName().hasTemplateArg()) {
3394 specializeStructMethodDefinition(
3395 specializationContext, specializedStruct, methodAst, specializedName, concreteTemplateArgs, moduleIndex);
3400 if (targetedModule->templateInterfaceImplAsts.count(templateName)) {
3401 for (
auto &implAst : targetedModule->templateInterfaceImplAsts.at(templateName)) {
3402 specializeInterfaceImplementation(
3403 implAst, selfType, specializedName, concreteTemplateArgs, currentModuleIndex);
3410 return specializedStructIndex;
3413 yoi::indexT visitor::specializeStructMethodTemplate(
const std::shared_ptr<IRStructDefinition> &structDef,
3417 const yoi::vec<std::shared_ptr<IRValueType>> &methodTemplateArgs,
3424 for (
size_t i = 0; i < structDef->templateParamNames.size(); ++i) {
3425 combinedContext.
addTemplateArgument(structDef->templateParamNames[i], structDef->storedTemplateArgs[i]);
3436 yoi_assert(methodParams.size() == methodTemplateArgs.size(), 0, 0,
"Method template argument count mismatch");
3437 for (
size_t i = 0; i < methodParams.size(); ++i) {
3443 checkConceptSatisfaction(c, paramName, methodTemplateArgs[i]);
3449 yoi::wstr specializedMethodName = getMangledTemplateName(baseMethodName, methodTemplateArgs);
3451 pushModuleContext(moduleIndex);
3458 auto selfType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(structDef->name)});
3464 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) == funcBuilder.
attrs.end()) {
3468 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3469 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3470 specializedArgTypes.push_back(specializedType);
3476 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) == funcBuilder.
attrs.end()) {
3480 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3481 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3482 specializedArgTypes.push_back(specializedType);
3487 yoi::wstr fullMangledName = structDef->
name + L
"::" + specializedMethodName + getFuncUniqueNameStr(specializedArgTypes);
3489 if (targetedModule->functionTable.contains(fullMangledName)) {
3490 auto res = targetedModule->functionTable.getIndex(fullMangledName);
3496 funcBuilder.
setName(fullMangledName);
3497 auto specializedFunc = funcBuilder.
yield();
3498 auto funcIndex = targetedModule->functionTable.put_create(fullMangledName, specializedFunc);
3499 targetedModule->functionOverloadIndexies[structDef->name + L
"::" + baseMethodName].push_back(funcIndex);
3508 }
catch (std::exception &e) {
3521 std::pair<yoi::indexT, yoi::wstr> visitor::specializeStructMethodDeclaration(
IRTemplateBuilder &structTemplate,
3524 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3540 if (methodAstNode->
kind == 1) {
3541 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3546 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3551 baseMethodName = L
"constructor";
3553 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3555 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3556 }
else if (methodAstNode->
kind == 2) {
3557 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
3562 checkConceptSatisfaction(c, paramName, concreteTemplateArgs[i]);
3569 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3571 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3572 }
else if (methodAstNode->
kind == 3) {
3574 baseMethodName = L
"finalizer";
3575 genericMethodKey = baseMethodName;
3581 for (
size_t i = 0; i < concreteTemplateArgs.size(); ++i) {
3586 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(specializedStructName)});
3596 if (methodAstNode->
kind == 1) {
3597 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
3600 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3601 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3602 specializedArgTypes.push_back(specializedType);
3605 }
else if (methodAstNode->
kind == 2) {
3607 if (std::find(funcBuilder.
attrs.begin(), funcBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
3608 funcBuilder.
attrs.end()) {
3612 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3613 funcBuilder.
addArgument(arg->getId().get().strVal, specializedType);
3614 specializedArgTypes.push_back(specializedType);
3617 }
else if (methodAstNode->
kind == 3) {
3618 funcBuilder.
setName(specializedStructName + L
"::finalizer");
3619 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Finalizer);
3620 funcBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
3625 yoi::wstr specializedMethodName = specializedStructName + L
"::" + baseMethodName;
3626 funcBuilder.
setName(specializedMethodName + getFuncUniqueNameStr(specializedArgTypes));
3628 auto specializedFunc = funcBuilder.
yield();
3629 auto funcIndex = targetedModule->functionTable.put_create(specializedMethodName + getFuncUniqueNameStr(specializedArgTypes), specializedFunc);
3630 targetedModule->functionOverloadIndexies[specializedMethodName].push_back(funcIndex);
3633 return {funcIndex, baseMethodName + getFuncUniqueNameStr(specializedArgTypes)};
3637 const std::shared_ptr<IRStructDefinition> &specializedStruct,
3640 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
3657 baseMethodName = L
"constructor";
3659 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3661 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3663 baseMethodName = L
"finalizer";
3665 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3667 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3671 genericArgTypes.push_back(
managedPtr(parseTypeSpec(&arg->getSpec())));
3673 genericMethodKey = baseMethodName + getFuncUniqueNameStr(genericArgTypes);
3679 for (
size_t i = 0; i < concreteTemplateArgs.size(); ++i) {
3684 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(specializedStructName)});
3692 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3693 specializedArgTypes.push_back(specializedType);
3699 auto specializedType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3700 specializedArgTypes.push_back(specializedType);
3704 yoi::wstr specializedMethodName = specializedStructName + L
"::" + baseMethodName + getFuncUniqueNameStr(specializedArgTypes);
3706 auto funcIndex = targetedModule->functionTable.getIndex(specializedMethodName);
3713 }
catch (std::exception &e) {
3714 set_current_file_path(moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().sourceFile);
3715 panic(moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().line,
3716 moduleContextStack.top().first->getIRBuilder().getCurrentDebugInfo().column,
3717 std::string(
"Exception occurred while specializing method: ") +
yoi::wstring2string(specializedMethodName) +
": " + e.what() +
3728 const yoi::vec<std::shared_ptr<IRValueType>> &specializedArgTypes) {
3729 auto res = baseMethodName;
3730 for (
yoi::indexT i = 0; i < specializedArgTypes.size(); ++i) {
3731 auto &arg = templateArgs[i];
3732 auto strRepl1 = templateArgs[i].templateType->to_string();
3733 auto strRepl2 = specializedArgTypes[i]->to_string();
3746 }
catch (std::runtime_error &e) {
3755 lastModule = targetModule;
3760 "Expected a identifier after modules but this is not the final term of expression.");
3761 targetModule = targetModule == -1 ? currentModuleIndex : targetModule;
3765 if (!(*it)->hasTemplateArg()) {
3769 if (funcIt->first.starts_with((*it)->id->get().strVal + L
"#")) {
3777 if (funcIndex != -1) {
3783 auto templateName = (*it)->id->get().strVal;
3785 throw std::out_of_range(
"Cannot find the template: " +
wstring2string(templateName));
3791 "Expected template arguments for template: " +
wstring2string(templateName));
3793 auto templateArgs = parseTemplateArgs((*it)->getArg());
3795 auto funcIndex = specializeFunctionTemplate(
3803 }
catch (std::out_of_range &e) {
3821 }
catch (std::runtime_error &e) {
3839 auto argType =
managedPtr(parseTypeSpec(&arg->getSpec()));
3840 builder.
addArgument(arg->getId().get().strVal, argType);
3843 auto importedFunc = builder.
yield();
3847 irModule->externTable.put_create(
3857 void visitor::tryCastTo(
const std::shared_ptr<IRValueType> &toType) {
3859 if (rhs->isForeignBasicType()) {
3860 rhs =
managedPtr(rhs->getNormalizedForeignBasicType());
3863 if (*rhs == *toType) {
3865 }
else if (rhs->type == IRValueType::valueType::pointerObject || rhs->type == IRValueType::valueType::pointer ||
3866 rhs->type == IRValueType::valueType::null || toType->type == IRValueType::valueType::pointerObject ||
3867 toType->type == IRValueType::valueType::pointer) {
3870 }
else if (rhs->isBasicType() && toType->isBasicType() && !rhs->isDynamicArrayType() && !toType->isDynamicArrayType() &&
3871 !rhs->isArrayType() && !toType->isArrayType() &&
3872 (rhs->type != IRValueType::valueType::stringObject || toType->type == IRValueType::valueType::pointerObject)) {
3873 emitBasicCastTo(toType);
3874 }
else if ((toType->isArrayType() || toType->isDynamicArrayType()) && rhs->type == IRValueType::valueType::bracedInitalizerList) {
3875 auto elementType =
managedPtr(toType->getElementType());
3876 auto elementCount = rhs->bracedTypes.size();
3877 if (toType->isArrayType()) {
3884 }
else if (toType->type == IRValueType::valueType::interfaceObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3887 auto implName = getInterfaceImplName({toType->typeAffiliateModule, toType->typeIndex}, rhs);
3895 rhs->typeAffiliateModule != currentModuleIndex,
3896 rhs->typeAffiliateModule);
3897 }
catch (std::out_of_range &e) {
3901 ": no implementation found.");
3903 }
else if (toType->type == IRValueType::valueType::structObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3906 auto result = resolveOverloadExtern(L
"constructor", {rhs}, toType->typeAffiliateModule, structType);
3907 if (result.found()) {
3908 if (result.isCastRequired) {
3909 tryCastTo(result.function->argumentTypes.back());
3913 result.functionIndex, 2, result.function->returnType,
true, toType->typeAffiliateModule);
3918 ": no viable conversion found.");
3924 ": no viable conversion found.");
3928 bool visitor::canCastTo(
const std::shared_ptr<IRValueType> &fromType,
const std::shared_ptr<IRValueType> &toType) {
3929 auto rhs = fromType;
3930 if (fromType->isForeignBasicType()) {
3931 rhs =
managedPtr(rhs->getNormalizedForeignBasicType());
3933 if (*rhs == *toType) {
3935 }
else if (rhs->isBasicType() && toType->isBasicType() && !rhs->isDynamicArrayType() && !toType->isDynamicArrayType() &&
3936 !rhs->isArrayType() && !toType->isArrayType() && (toType->type != IRValueType::valueType::stringObject) &&
3937 (rhs->type != IRValueType::valueType::stringObject || toType->type == IRValueType::valueType::pointerObject)) {
3939 }
else if ((toType->isArrayType() || toType->isDynamicArrayType()) && fromType->type == IRValueType::valueType::bracedInitalizerList) {
3940 auto e = toType->getElementType();
3941 for (
auto &i : fromType->bracedTypes) {
3947 }
else if (rhs->type == IRValueType::valueType::pointerObject) {
3950 }
else if (toType->type == IRValueType::valueType::interfaceObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3953 auto implName = getInterfaceImplName({toType->typeAffiliateModule, toType->typeIndex}, rhs);
3957 }
catch (std::out_of_range &e) {
3960 }
else if (toType->type == IRValueType::valueType::structObject && !toType->isArrayType() && !toType->isDynamicArrayType()) {
3963 auto result = resolveOverloadExtern(L
"constructor", {rhs}, toType->typeAffiliateModule, structType);
3964 return result.found();
3988 yoi_assert(rhs->type == IRValueType::valueType::interfaceObject,
3991 "dynamic cast can only be applied to interface objects to struct objects. Type: " +
yoi::wstring2string(rhs->to_string()));
3996 if (
auto it = std::find(impls.begin(), impls.end(), std::make_tuple(toType->type, toType->typeAffiliateModule, toType->typeIndex));
4003 ": no implementation found.");
4008 yoi::indexT visitor::generateNullInterfaceImplementation(
const std::shared_ptr<IRValueType> &structType) {
4010 auto nullImplName = getInterfaceImplName(nullInterface, structType);
4013 ->getImportedModule(structType->typeAffiliateModule)
4014 ->interfaceImplementationTable.getIndex(nullImplName);
4015 }
catch (std::out_of_range &e) {
4019 ->implementations.emplace_back(structType->type, structType->typeAffiliateModule, structType->typeIndex);
4021 {structType->type, structType->typeAffiliateModule, structType->typeIndex},
4026 ->getImportedModule(structType->typeAffiliateModule)
4027 ->interfaceImplementationTable.put_create(nullImplName, nullImpl);
4032 std::set<IRFunctionDefinition::FunctionAttrs> res;
4033 for (
auto &attr : attrs) {
4034 switch (attr.kind) {
4035 case lexer::token::tokenKind::kAlwaysInline:
4036 res.insert(IRFunctionDefinition::FunctionAttrs::AlwaysInline);
4038 case lexer::token::tokenKind::kNoFFI:
4039 res.insert(IRFunctionDefinition::FunctionAttrs::NoFFI);
4041 case lexer::token::tokenKind::kStatic:
4042 res.insert(IRFunctionDefinition::FunctionAttrs::Static);
4044 case lexer::token::tokenKind::kIntrinsic:
4045 res.insert(IRFunctionDefinition::FunctionAttrs::Intrinsic);
4047 case lexer::token::tokenKind::kGenerator:
4048 res.insert(IRFunctionDefinition::FunctionAttrs::Generator);
4054 return std::move(res);
4073 std::shared_ptr<yoi::IRModule> target =
4075 if (
auto x = target->moduleImports.find(it->
node.
strVal); x != target->moduleImports.end()) {
4078 return currentModule;
4083 auto it = emaExpression->
getTerms().begin();
4085 while (it + 1 != emaExpression->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
4087 lastModule = targetModule;
4090 bool whetherLastTerm = it + 1 == emaExpression->
getTerms().end();
4091 if (targetModule == -1 || targetModule == currentModuleIndex)
4092 return parseTypeSpec((*it));
4094 return parseTypeSpecExtern((*it), targetModule);
4097 bool visitor::OverloadResult::found()
const {
4098 return functionIndex != -1;
4103 for (
auto &arg : args->
get()) {
4111 const yoi::vec<std::shared_ptr<IRValueType>> &argTypes,
4113 const std::shared_ptr<IRStructDefinition> &structContext) {
4118 auto exactMangledName = baseName + getFuncUniqueNameStr(argTypes);
4119 yoi::wstr lookupName = structContext ? structContext->name + L
"::" + exactMangledName : exactMangledName;
4121 if (targetedModule->functionTable.contains(lookupName)) {
4122 result.
functionIndex = targetedModule->functionTable.getIndex(lookupName);
4125 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4135 auto findVariadicMatch = [&](
const yoi::wstr &funcKey,
bool skipFirstParam =
false) {
4136 auto func = targetedModule->functionTable[funcKey];
4137 const auto ¶mTypes = func->argumentTypes;
4138 size_t fixedParamCount = paramTypes.size() - 1 - (skipFirstParam && paramTypes.size() > 1 ? 1 : 0);
4139 if (std::find(func->attrs.begin(), func->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) != func->attrs.end()) {
4140 if (argTypes.size() >= fixedParamCount) {
4141 bool fixedMatch =
true;
4142 for (
size_t i = 0; i < fixedParamCount; ++i) {
4143 if (!canCastTo(argTypes[i], paramTypes[i + skipFirstParam])) {
4149 result.
functionIndex = targetedModule->functionTable.getIndex(funcKey);
4158 if (argTypes.size() != fixedParamCount + 1 ||
4159 paramTypes.size() != fixedParamCount + 1 + skipFirstParam)
4162 for (
size_t i = 0; i < fixedParamCount + 1; ++i) {
4163 if (!canCastTo(argTypes[i], paramTypes[i + skipFirstParam])) {
4168 result.
functionIndex = targetedModule->functionTable.getIndex(funcKey);
4179 yoi::wstr prefix = structContext ? structContext->name + L
"::" + baseName : baseName;
4180 for (
const auto it : targetedModule->functionOverloadIndexies[prefix]) {
4181 const auto &key = targetedModule->functionTable.getKey(it);
4182 if (key.starts_with(prefix)) {
4183 if (findVariadicMatch(key,
4184 structContext !=
nullptr &&
4185 !targetedModule->functionTable[it]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static)))
4190 if (!structContext && targetedModule->funcTemplateAsts.contains(baseName)) {
4192 auto astNode = targetedModule->funcTemplateAsts.at(baseName);
4193 auto templateArgs = getTemplateArgs(astNode->id->getArg());
4197 for (
yoi::indexT i = 0; i < argTypes.size(); i++) {
4198 if (i < templateArgs.size() && templateArgs[i].templateType->type == IRValueType::valueType::incompleteTemplateType) {
4199 auto &srcTypeToPlace = argTypes[i];
4200 auto incompleteTypeIndex = templateArgs[i].templateType->typeIndex;
4201 if (deducedArgs[incompleteTypeIndex] && *deducedArgs[incompleteTypeIndex] != *srcTypeToPlace) {
4202 throw std::runtime_error(
"Template argument type mismatch during deduction.");
4204 deducedArgs[incompleteTypeIndex] = srcTypeToPlace;
4207 for (
yoi::indexT i = 0; i < deducedArgs.size(); i++) {
4208 if (deducedArgs[i] ==
nullptr) {
4209 throw std::runtime_error(
"Cannot deduce all template arguments for: " +
yoi::wstring2string(baseName));
4213 auto specializedFuncIndex = specializeFunctionTemplate(astNode, deducedArgs, targetModule);
4215 result.
function = targetedModule->functionTable[specializedFuncIndex];
4218 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4225 }
catch (
const std::out_of_range &) {
4233 bool visitor::handleInvocationExtern(
const yoi::wstr &baseName,
4236 const std::shared_ptr<IRValueType> &structContext,
4240 auto argTypes = evaluateArguments(args);
4242 if (structContext && structContext->type == IRValueType::valueType::structObject) {
4245 overload = resolveOverloadExtern(baseName, argTypes, targetModule, structType);
4247 if (!overload.
found()) {
4249 if (structType->templateMethodDecls.contains(baseName) || structType->templateMethodDefs.contains(baseName)) {
4251 structType->templateMethodDecls.contains(baseName) ? structType->templateMethodDecls.at(baseName) :
nullptr;
4253 structType->templateMethodDefs.contains(baseName) ? structType->templateMethodDefs.at(baseName) :
nullptr;
4258 concreteMethodTemplateArgs = parseTemplateArgs(*templateArgs);
4267 concreteMethodTemplateArgs.resize(methodTemplateParams.size());
4269 for (
size_t i = 0; i < astArgs.size() && i < argTypes.size(); ++i) {
4270 auto &spec = *astArgs[i]->spec;
4271 if (spec.kind == typeSpec::typeSpecKind::Member && spec.member && spec.member->getTerms().size() == 1) {
4272 auto term = spec.member->getTerms()[0];
4273 yoi::wstr typeName = term->id->get().strVal;
4274 for (
size_t j = 0; j < methodTemplateParams.size(); ++j) {
4275 if (methodTemplateParams[j] == typeName) {
4276 concreteMethodTemplateArgs[j] = argTypes[i];
4284 bool allDeduced =
true;
4285 for (
auto &arg : concreteMethodTemplateArgs) {
4292 if (allDeduced && !concreteMethodTemplateArgs.empty()) {
4295 auto specializedFuncIndex =
4296 specializeStructMethodTemplate(structType, decl, def, baseName, concreteMethodTemplateArgs, targetModule);
4298 overload.
function = targetedModule->functionTable[specializedFuncIndex];
4302 }
else if (structContext && structContext->type == IRValueType::valueType::interfaceObject) {
4303 auto interfaceType =
4305 overload = resolveOverloadInterface(baseName, argTypes, targetModule, interfaceType);
4307 overload = resolveOverloadExtern(baseName, argTypes, targetModule,
nullptr);
4310 if (!overload.
found()) {
4315 auto fullMangledName = overload.
function->name;
4316 bool skipFirstParam = structContext !=
nullptr && !noThisCall && structContext->type != IRValueType::valueType::interfaceObject;
4321 visit(args->
get()[i]);
4322 tryCastTo(overload.
function->argumentTypes[i + skipFirstParam]);
4324 auto variadicArgCount = argTypes.size() - overload.
fixedArgCount;
4325 if (variadicArgCount > 0) {
4326 for (
size_t i = 0; i < variadicArgCount; ++i) {
4331 overload.
variadicElementType, {static_cast<yoi::indexT>(variadicArgCount)}, variadicArgCount);
4338 visit(args->
get()[i]);
4339 tryCastTo(overload.
function->argumentTypes[i + skipFirstParam]);
4345 size_t finalParamCount = overload.
function->argumentTypes.size();
4346 if (structContext && structContext->type == IRValueType::valueType::structObject) {
4347 IRExternEntry externEntry = getExternEntry(targetModule, fullMangledName);
4348 auto isStaticMethod =
4349 std::find(overload.
function->attrs.begin(), overload.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4351 bool usePureStaticLogic = noThisCall && isStaticMethod;
4353 if (usePureStaticLogic) {
4358 finalParamCount - !isStaticMethod,
4364 }
else if (structContext && structContext->type == IRValueType::valueType::interfaceObject) {
4366 structContext->typeIndex,
4370 structContext->typeAffiliateModule);
4372 auto externEntry = getExternEntry(targetModule, fullMangledName);
4374 externEntry.itemIndex, finalParamCount, overload.
function->returnType,
true, externEntry.affiliateModule);
4379 template <
typename T>
yoi::indexT visitor::handleBinaryOperatorOverload(
const yoi::wstr &overloadName, T *rhsAST) {
4382 bool isResolved =
false;
4384 if (lhs->type == IRValueType::valueType::structObject) {
4386 resolveOverloadExtern(overloadName,
4388 lhs->typeAffiliateModule,
4390 if (resolved.found()) {
4391 yoi_assert(resolved.isVariadic ==
false, 0, 0,
"Binary operator overloading with variadic functions is not supported.");
4392 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4393 resolved.function->attrs.end(),
4396 "Binary operator overloading with non-static functions is not supported.");
4398 if (resolved.isCastRequired) {
4400 tryCastTo(resolved.function->argumentTypes.front());
4402 tryCastTo(resolved.function->argumentTypes.back());
4409 resolved.functionIndex, 1, resolved.function->returnType,
false,
true, lhs->typeAffiliateModule);
4413 if (!isResolved && rhs->type == IRValueType::valueType::structObject) {
4415 resolveOverloadExtern(overloadName,
4417 rhs->typeAffiliateModule,
4419 if (resolved.found()) {
4423 "Binary operator overloading with variadic functions is not supported.");
4424 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4425 resolved.function->attrs.end(),
4428 "Binary operator overloading with non-static functions is not supported.");
4430 if (resolved.isCastRequired) {
4432 tryCastTo(resolved.function->argumentTypes.front());
4434 tryCastTo(resolved.function->argumentTypes.back());
4444 resolved.functionIndex, 1, resolved.function->returnType,
false,
true, rhs->typeAffiliateModule);
4449 if (!isResolved && lhs->type == IRValueType::valueType::interfaceObject) {
4450 const auto &baseName = overloadName;
4451 auto mangledName = getFuncUniqueNameStr({rhs});
4453 auto resolved = resolveOverloadInterface(
4456 lhs->typeAffiliateModule,
4459 if (resolved.found()) {
4460 if (resolved.isCastRequired) {
4462 tryCastTo(resolved.function->argumentTypes.front());
4464 tryCastTo(resolved.function->argumentTypes.back());
4470 resolved.functionIndex, lhs->typeIndex, 1, resolved.function->returnType,
true, lhs->typeAffiliateModule);
4489 bool isResolved =
false;
4491 if (rhs->type == IRValueType::valueType::structObject) {
4493 resolveOverloadExtern(overloadName,
4495 rhs->typeAffiliateModule,
4497 if (resolved.found()) {
4501 "Unary operator overloading with variadic functions is not supported.");
4502 yoi_assert(std::find(resolved.function->attrs.begin(), resolved.function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) !=
4503 resolved.function->attrs.end(),
4506 "Unary operator overloading with non-static functions is not supported.");
4509 resolved.functionIndex, 0, resolved.function->returnType,
false,
true, rhs->typeAffiliateModule);
4513 if (rhs->type == IRValueType::valueType::interfaceObject) {
4514 const auto &baseName = overloadName;
4515 auto mangledName = getFuncUniqueNameStr({});
4518 ->getImportedModule(rhs->typeAffiliateModule)
4519 ->interfaceTable[rhs->typeIndex]
4520 ->methodMap.getIndex(baseName + mangledName);
4522 ->getImportedModule(rhs->typeAffiliateModule)
4523 ->interfaceTable[rhs->typeIndex]
4524 ->methodMap[methodIdx];
4525 yoi_assert(method->argumentTypes.size() == 1,
4528 "Argument count does not match");
4541 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
4544 yoi::wstr specializedName = getMangledTemplateName(templateName, concreteTemplateArgs);
4545 if (targetedModule->interfaceTable.contains(specializedName)) {
4546 return targetedModule->interfaceTable.getIndex(specializedName);
4549 yoi_assert(targetedModule->templateInterfaceAsts.contains(templateName), 0, 0,
"Unknown interface template: " +
wstring2string(templateName));
4551 auto interfaceAst = targetedModule->templateInterfaceAsts.at(templateName);
4554 yoi_assert(concreteTemplateArgs.size() == interfaceAst->id->arg->get().size(),
4557 "Template argument count mismatch for interface " +
wstring2string(templateName));
4558 for (
yoi::indexT i = 0; i < concreteTemplateArgs.size(); ++i) {
4559 auto paramName = interfaceAst->id->arg->get()[i]->getId().get().strVal;
4563 pushModuleContext(moduleIndex);
4567 builder.
setName(specializedName);
4569 for (
auto &i : interfaceAst->getInner().getInner()) {
4570 bool isVaridic =
false;
4571 yoi_assert(i->isMethod(), i->getLine(), i->getColumn(),
"Interface member must be a method");
4572 auto methodName = i->getMethod().getName().getId().get().strVal;
4573 auto methodResultType =
managedPtr(parseTypeSpec(i->getMethod().resultType));
4576 methodBuilder.
setDebugInfo({irModule->modulePath, i->getLine(), i->getColumn()});
4578 for (
auto &arg : i->getMethod().getArgs().get()) {
4579 if (&arg == &i->getMethod().getArgs().get().back() && arg->spec->kind == typeSpec::typeSpecKind::Elipsis) {
4581 methodBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Variadic);
4582 auto argName = arg->getId().node.strVal;
4584 managedPtr(arg->spec->elipsis ? parseTypeSpec(arg->spec->elipsis).getDynamicArrayType()
4587 argTypes.push_back(argType);
4590 auto argName = arg->getId().get().strVal;
4591 auto argType =
managedPtr(parseTypeSpec(arg->spec));
4593 argTypes.push_back(argType);
4595 auto uniq = getFuncUniqueNameStr(argTypes);
4596 methodBuilder.
setName(L
"interface#" + specializedName + L
"#" + methodName + uniq);
4597 builder.
addMethod(methodName, methodName + uniq, methodBuilder.
yield());
4600 auto specializedInterface = builder.
yield();
4601 auto interfaceIndex = irModule->interfaceTable.put_create(
4602 specializedName, specializedInterface);
4606 return interfaceIndex;
4610 const std::shared_ptr<IRValueType> &concreteStructType,
4612 const yoi::vec<std::shared_ptr<IRValueType>> &concreteTemplateArgs,
4618 "Expected 'impl for' AST node for interface implementation specialization.");
4624 yoi_assert(concreteInterfaceType->type == IRValueType::valueType::interfaceObject,
4627 "Expected an interface type.");
4631 auto interfaceSrcPair = std::make_pair(concreteInterfaceType->typeAffiliateModule, concreteInterfaceType->typeIndex);
4633 auto targetInterface =
4636 targetInterface->implementations.emplace_back(
4637 concreteStructType->type, concreteStructType->typeAffiliateModule, concreteStructType->typeIndex);
4639 auto implName = getInterfaceImplName(interfaceSrcPair, concreteStructType);
4640 if (irModule->interfaceImplementationTable.contains(implName)) {
4646 implIndex = targetedModule->interfaceImplementationTable.getIndex(implName);
4647 if (targetedModule->interfaceImplementationTable[implIndex]) {
4650 }
catch (std::out_of_range &e) {
4651 implIndex = targetedModule->interfaceImplementationTable.put_create(implName,
nullptr);
4654 if (implAst->
inner) {
4657 builder.
setImplStructIndex({concreteStructType->type, concreteStructType->typeAffiliateModule, concreteStructType->typeIndex});
4660 std::map<yoi::wstr, std::pair<yoi::wstr, std::shared_ptr<IRValueType>>> virtualMethodMap;
4664 methodNode->getLine(),
4665 methodNode->getColumn(),
4666 "Only methods are allowed in interface implementations.");
4667 auto &methodAst = methodNode->getMethod();
4670 methodBuilder.
setDebugInfo({irModule->modulePath, methodAst.getLine(), methodAst.getColumn()});
4671 methodBuilder.
attrs = getFunctionAttributes(methodAst.attrs);
4672 methodBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
4676 if (std::find(methodBuilder.
attrs.begin(), methodBuilder.
attrs.end(), IRFunctionDefinition::FunctionAttrs::Static) ==
4677 methodBuilder.
attrs.end()) {
4678 methodBuilder.
addArgument(L
"this", concreteStructType);
4681 for (
auto &arg : methodAst.getArgs().get()) {
4682 auto specializedArgType =
managedPtr(parseTypeSpec(arg->spec));
4683 methodBuilder.
addArgument(arg->getId().get().strVal, specializedArgType);
4684 specializedArgTypes.push_back(specializedArgType);
4687 auto uniq = getFuncUniqueNameStr(specializedArgTypes);
4688 auto baseMethodName = methodAst.getName().getId().get().strVal;
4691 methodBuilder.
setName(specializedStructName + L
"::" + baseMethodName + uniq);
4693 auto func = methodBuilder.
yield();
4694 auto funcIndex = irModule->functionTable.put_create(func->name, func);
4695 irModule->functionOverloadIndexies[specializedStructName + L
"::" + baseMethodName].emplace_back(funcIndex);
4700 visit(methodAst.block,
true);
4703 virtualMethodMap[baseMethodName + getFuncUniqueNameStr(specializedArgTypes,
true)] = {
4704 baseMethodName + uniq,
managedPtr(
IRValueType{IRValueType::valueType::virtualMethod, currentModuleIndex, funcIndex})};
4706 for (
auto &method : targetInterface->methodMap) {
4707 yoi_assert(virtualMethodMap.contains(method.first),
4710 "Interface method not found in implementation: " +
wstring2string(method.first));
4711 builder.
addVirtualMethod(virtualMethodMap[method.first].first, virtualMethodMap[method.first].second);
4716 targetedModule->interfaceImplementationTable[implIndex] = builder.
yield();
4723 const yoi::vec<std::shared_ptr<IRValueType>> &argTypes,
4725 const std::shared_ptr<IRInterfaceInstanceDefinition> &interfaceContext) {
4729 auto exactMangledName = baseName + getFuncUniqueNameStr(argTypes);
4731 if (interfaceContext->methodMap.contains(exactMangledName)) {
4733 result.
functionIndex = interfaceContext->methodMap.getIndex(exactMangledName);
4735 if (std::find(result.
function->attrs.begin(), result.
function->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) !=
4744 auto findVariadicMatch = [&](
const yoi::wstr &funcKey) {
4745 auto func = interfaceContext->methodMap[funcKey];
4746 const auto ¶mTypes = func->argumentTypes;
4747 size_t fixedParamCount = paramTypes.size() - 1;
4748 if (std::find(func->attrs.begin(), func->attrs.end(), IRFunctionDefinition::FunctionAttrs::Variadic) != func->attrs.end()) {
4749 if (argTypes.size() >= fixedParamCount) {
4750 bool fixedMatch =
true;
4751 for (
size_t i = 0; i < fixedParamCount; ++i) {
4752 if (*paramTypes[i] != *argTypes[i]) {
4758 result.
functionIndex = interfaceContext->methodMap.getIndex(funcKey);
4768 if (argTypes.size() != fixedParamCount + 1)
4771 for (
size_t i = 0; i < fixedParamCount; ++i) {
4772 if (!canCastTo(argTypes[i], paramTypes[i])) {
4777 result.
functionIndex = interfaceContext->methodMap.getIndex(funcKey);
4789 if (!interfaceContext->functionOverloadIndexies.contains(baseName))
4792 for (
const auto &it : interfaceContext->functionOverloadIndexies[baseName]) {
4793 if (findVariadicMatch(interfaceContext->methodMap.getKey(it)))
4802 moduleContextStack.emplace(
moduleContext, currentModuleIndex);
4805 currentModuleIndex = moduleIndex;
4808 void visitor::popModuleContext() {
4811 currentModuleIndex = moduleContextStack.top().second;
4813 moduleContextStack.pop();
4820 auto currentTerm = *it;
4822 if (objectOnStackType->isArrayType() || objectOnStackType->isDynamicArrayType()) {
4823 const auto &dimensions = objectOnStackType->dimensions;
4826 for (
long long i =
static_cast<long long>(dimensions.size()) - 2; i >= 0; --i) {
4827 strides[i] = strides[i + 1] * dimensions[i + 1];
4834 while (it != end && (*it)->isSubscript()) {
4835 yoi_assert(currentDim < dimensions.size(), (*it)->getLine(), (*it)->getColumn(),
"Too many indices for array dimension.");
4841 "Array subscript index must be an integer or unsigned integer.");
4849 yoi_assert(currentDim == dimensions.size() || (isStoreOp && isLastTerm),
4850 currentTerm->getLine(),
4851 currentTerm->getColumn(),
4852 "Partial array access is not a loadable value. Not enough indices provided.");
4854 if (isStoreOp && isLastTerm) {
4858 auto elementType =
managedPtr(objectOnStackType->getElementType());
4863 if (isLastTerm && isStoreOp) {
4868 visit(currentTerm->expr);
4872 if (array->type == IRValueType::valueType::structObject)
4873 overload = resolveOverloadExtern(
4875 {value, array, index},
4876 array->typeAffiliateModule,
4879 yoi_assert(overload.
found(), currentTerm->getLine(), currentTerm->getColumn(),
"No matching overload found for operator[].");
4881 !overload.
isVariadic, currentTerm->getLine(), currentTerm->getColumn(),
"Variadic operator[] overloading is not supported.");
4885 tryCastTo(overload.
function->argumentTypes.back());
4887 tryCastTo(overload.
function->argumentTypes.front());
4901 visit(currentTerm->expr);
4902 handleBinaryOperatorOverload(L
"operator[]", currentTerm->expr);
4910 for (
auto &arg :
typeSpec->args->types) {
4911 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
4919 const std::shared_ptr<IRValueType> &returnType) {
4920 auto callableInterfaceName = L
"callable" + getFuncUniqueNameStr(parameterTypes);
4921 callableInterfaceName += getTypeSpecUniqueNameStr(returnType);
4924 ->interfaceTable.contains(callableInterfaceName)) {
4927 ->interfaceTable.getIndex(callableInterfaceName);
4932 ->interfaceTable.put_create(callableInterfaceName, {});
4935 for (
auto &arg : parameterTypes) {
4936 argTypes.emplace_back(L
"arg", arg);
4939 builder.
setName(callableInterfaceName);
4941 L
"operator()" + getFuncUniqueNameStr(parameterTypes),
4946 return interfaceIndex;
4952 if (irModule->structTable.contains(structName)) {
4955 auto index = irModule->structTable.getIndex(structName);
4956 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, index});
4960 visit(i->identifier);
4963 case structDefInnerPair::Modifier::DataField:
4965 argTypes.back()->addAttribute(IRValueType::ValueAttr::Raw);
4966 case structDefInnerPair::Modifier::Weak:
4969 case structDefInnerPair::Modifier::None:
4973 auto funcName = structName + L
"::constructor" + getFuncUniqueNameStr(argTypes);
4975 irModule->functionTable.getIndex(funcName), argTypes.size(), structType,
false,
true, currentModuleIndex);
4979 auto structIndex = irModule->structTable.put_create(structName,
nullptr);
4981 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, currentModuleIndex, structIndex});
4990 callableBuilder.
attrs.insert(IRFunctionDefinition::FunctionAttrs::Preserve);
4993 auto argType =
managedPtr(parseTypeSpec(i->spec));
4994 callableBuilder.
addArgument(i->id->node.strVal, argType);
4995 argTypes.push_back(argType);
4999 callableBuilder.
setName(structName + L
"::operator()" + getFuncUniqueNameStr(argTypes));
5000 auto callableFunc = callableBuilder.
yield();
5001 auto callableFuncIndex = irModule->functionTable.put_create(callableFunc->name, callableFunc);
5002 irModule->functionOverloadIndexies[structName + L
"::operator()"].push_back(callableFuncIndex);
5003 builder.addMethod(L
"operator()" + getFuncUniqueNameStr(argTypes), callableFuncIndex);
5012 visit(i->identifier);
5016 case structDefInnerPair::Modifier::DataField:
5018 argTypes.back()->addAttribute(IRValueType::ValueAttr::Raw);
5019 case structDefInnerPair::Modifier::Weak:
5020 capturedVar->addAttribute(IRValueType::ValueAttr::Nullable);
5021 fieldType->addAttribute(IRValueType::ValueAttr::WeakRef);
5023 case structDefInnerPair::Modifier::None:
5024 capturedVar->addAttribute(IRValueType::ValueAttr::Nullable);
5028 argTypes.push_back(
managedPtr(*capturedVar));
5029 builder.addField(i->identifier->node.strVal, fieldType);
5035 constructorBuilder.
addArgument(L
"this", structType);
5036 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Constructor);
5037 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::NoRawAndNullOptimization);
5038 for (
yoi::indexT i = 0; i < argTypes.size(); ++i) {
5042 constructorBuilder.
setName(structName + L
"::constructor" + getFuncUniqueNameStr(argTypes));
5043 auto constructorFunc = constructorBuilder.
yield();
5044 auto constructorFuncIndex = irModule->functionTable.put_create(constructorFunc->name, constructorFunc);
5045 irModule->functionOverloadIndexies[structName + L
"::constructor"].push_back(constructorFuncIndex);
5046 builder.addMethod(L
"constructor" + getFuncUniqueNameStr(argTypes), constructorFuncIndex);
5049 irModule->structTable[structIndex] = builder.yield();
5069 {IROperand::operandType::localVar, i + 1},
5086 std::pair<yoi::indexT, std::pair<yoi::indexT, yoi::indexT>> visitor::createCallableImplementationForLambda(
5087 const std::shared_ptr<IRStructDefinition> &lambda,
yoi::indexT lambdaStructIndex,
yoi::indexT moduleIndex) {
5091 for (
auto &[key, value] : lambda->nameIndexMap) {
5092 if (key.starts_with(L
"operator()")) {
5094 callableIndex = value.index;
5100 for (
yoi::indexT i = 1; i < callableFunc->argumentTypes.size(); ++i) {
5101 argTypes.push_back(callableFunc->argumentTypes[i]);
5103 auto returnType = callableFunc->returnType;
5109 if (irModule->interfaceImplementationTable.contains(interfaceImpl)) {
5111 return {irModule->interfaceImplementationTable.getIndex(interfaceImpl), interfaceSrc};
5116 .
setImplStructIndex({IRValueType::valueType::structObject, moduleIndex, lambdaStructIndex})
5117 .setName(interfaceImpl)
5119 auto implIndex = irModule->interfaceImplementationTable.put_create(interfaceImpl, builder.
yield());
5120 interfaceDef->implementations.emplace_back(std::tuple{IRValueType::valueType::structObject, currentModuleIndex, implIndex});
5122 return {implIndex, interfaceSrc};
5128 bool satisfied =
true;
5132 case lexer::token::tokenKind::integer:
5134 case lexer::token::tokenKind::integer:
5136 case lexer::token::tokenKind::decimal:
5139 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5141 case lexer::token::tokenKind::decimal:
5143 case lexer::token::tokenKind::integer:
5144 return {lhs,
lexer::token{0, 0, lexer::token::tokenKind::decimal,
static_cast<double>(rhs.basicVal.vUint)}};
5145 case lexer::token::tokenKind::decimal:
5148 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5150 case lexer::token::tokenKind::string:
5152 case lexer::token::tokenKind::string:
5154 case lexer::token::tokenKind::boolean:
5155 return {
lexer::token{0, 0, lexer::token::tokenKind::integer,
static_cast<uint64_t
>(lhs.
strVal == rhs.strVal)}, rhs};
5157 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5159 case lexer::token::tokenKind::boolean:
5161 case lexer::token::tokenKind::string:
5162 return {
lexer::token{0, 0, lexer::token::tokenKind::integer,
static_cast<uint64_t
>(lhs.
strVal == rhs.strVal)}, rhs};
5163 case lexer::token::tokenKind::boolean:
5166 panic(lhs.
line, lhs.
col,
"Cannot convert marco value to comparable type.");
5173 auto [lhsTok, rhsTok] = convertToSameType(lhs, rhs);
5175 case lexer::token::tokenKind::equal:
5176 return lhsTok.basicVal.vUint == rhsTok.basicVal.vUint && lhsTok.strVal == rhsTok.strVal;
5177 case lexer::token::tokenKind::notEqual:
5178 return lhsTok.basicVal.vUint != rhsTok.basicVal.vUint || lhsTok.strVal != rhsTok.strVal;
5179 case lexer::token::tokenKind::greaterThan:
5180 switch (lhsTok.kind) {
5181 case lexer::token::tokenKind::integer:
5182 return lhsTok.basicVal.vUint > rhsTok.basicVal.vUint;
5183 case lexer::token::tokenKind::decimal:
5184 return lhsTok.basicVal.vDeci > rhsTok.basicVal.vDeci;
5186 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5188 case lexer::token::tokenKind::greaterEqual:
5189 switch (lhsTok.kind) {
5190 case lexer::token::tokenKind::integer:
5191 return lhsTok.basicVal.vUint >= rhsTok.basicVal.vUint;
5192 case lexer::token::tokenKind::decimal:
5193 return lhsTok.basicVal.vDeci >= rhsTok.basicVal.vDeci;
5195 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5197 case lexer::token::tokenKind::lessThan:
5198 switch (lhsTok.kind) {
5199 case lexer::token::tokenKind::integer:
5200 return lhsTok.basicVal.vUint < rhsTok.basicVal.vUint;
5201 case lexer::token::tokenKind::decimal:
5202 return lhsTok.basicVal.vDeci < rhsTok.basicVal.vDeci;
5204 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5206 case lexer::token::tokenKind::lessEqual:
5207 switch (lhsTok.kind) {
5208 case lexer::token::tokenKind::integer:
5209 return lhsTok.basicVal.vUint <= rhsTok.basicVal.vUint;
5210 case lexer::token::tokenKind::decimal:
5211 return lhsTok.basicVal.vDeci <= rhsTok.basicVal.vDeci;
5213 panic(lhs.
line, lhs.
col,
"Cannot compare marco value.");
5221 for (
auto &i : desc->
pairs) {
5222 bool currentSatisfied =
false;
5223 auto &marco = i->identifier.strVal;
5225 auto &value = marcos[marco];
5226 auto tok =
lexer(std::wstringstream(value)).
scan();
5227 tok.
kind = tok.kind == lexer::token::tokenKind::identifier ? lexer::token::tokenKind::string : tok.kind;
5229 auto &targetValue = i->rhs;
5230 switch (i->constraint.kind) {
5231 case lexer::token::tokenKind::equal: {
5232 currentSatisfied = tok.basicVal.vUint == targetValue.basicVal.vUint && tok.strVal == targetValue.strVal;
5235 case lexer::token::tokenKind::notEqual: {
5236 currentSatisfied = tok.basicVal.vUint != targetValue.basicVal.vUint || tok.strVal != targetValue.strVal;
5239 case lexer::token::tokenKind::greaterThan:
5240 case lexer::token::tokenKind::greaterEqual:
5241 case lexer::token::tokenKind::lessThan:
5242 case lexer::token::tokenKind::lessEqual: {
5243 currentSatisfied = compare(tok, targetValue, i->constraint.kind);
5249 "Unsupported marco constraint kind: " + std::string{magic_enum::enum_name(i->constraint.kind)});
5253 if (!currentSatisfied) {
5266 auto rhs = parseTypeSpec(typeAlias->
rhs);
5267 if (irModule->typeAliases.contains(aliasName)) {
5270 irModule->typeAliases[aliasName] = rhs;
5277 switch (enumDef->getUnderlyingType()) {
5278 case IREnumerationType::UnderlyingType::I8:
5280 case IREnumerationType::UnderlyingType::I16:
5282 case IREnumerationType::UnderlyingType::I64:
5294 idx = node->value.kind != lexer::token::tokenKind::unknown ? node->value.basicVal.vInt : idx;
5295 builder.
addValue(node->name->get().strVal, idx++);
5297 auto enumType = builder.
yield();
5298 auto enumIndex = irModule->enumerationTable.put_create(enumType->name, enumType);
5299 auto underlyingEnumType = mapEnumTypeToBasicType(currentModuleIndex, enumIndex);
5307 while (it + 1 != func->
name->
getTerms().end() && (targetModule = isModuleName((*it)->id, lastModule)) != lastModule) {
5309 lastModule = targetModule;
5313 enum class CreateStrategy { Plain, IncludeThis } strategy{CreateStrategy::Plain};
5318 auto nameNode = *(it);
5319 auto funcNameNode = *(it + 1);
5320 std::shared_ptr<IRStructDefinition> structType;
5322 if (nameNode->hasTemplateArg() && targetedModule->structTemplateAsts.contains(nameNode->getId().node.strVal)) {
5323 auto concreteTypes = parseTemplateArgs(nameNode->getArg());
5324 auto specializedIndex = specializeStructTemplate(
5325 nameNode->id->node.strVal, concreteTypes, targetedModule->templateImplAsts[nameNode->getId().node.strVal], targetModule);
5326 structType = targetedModule->structTable[specializedIndex];
5328 }
else if (targetedModule->structTable.contains(nameNode->getId().node.strVal)) {
5329 structType = targetedModule->structTable[nameNode->getId().node.strVal];
5331 panic(nameNode->getLine(), nameNode->getColumn(),
"Undefined struct: " +
yoi::wstring2string(nameNode->getId().node.strVal));
5334 yoi::wstr baseName = structType->name + L
"::" + funcNameNode->getId().node.strVal;
5336 yoi_assert(targetedModule->functionOverloadIndexies.contains(baseName),
5337 funcNameNode->getLine(),
5338 funcNameNode->getColumn(),
5345 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
5347 yoi::wstr fullFuncName = baseName + getFuncUniqueNameStr(argTypes);
5348 yoi_assert(targetedModule->functionTable.contains(fullFuncName),
5349 funcNameNode->getLine(),
5350 funcNameNode->getColumn(),
5351 "No matching function overload found with explicit param types: " +
yoi::wstring2string(fullFuncName));
5352 yoi_assert(targetedModule->functionTable[fullFuncName]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static),
5353 funcNameNode->getLine(),
5354 funcNameNode->getColumn(),
5356 funcIndex = targetedModule->functionTable.getIndex(fullFuncName);
5357 strategy = CreateStrategy::Plain;
5360 yoi_assert(targetedModule->functionOverloadIndexies[baseName].size() == 1,
5361 funcNameNode->getLine(),
5362 funcNameNode->getColumn(),
5363 "Inplicit specification on multiple overloads of method: " +
yoi::wstring2string(baseName));
5364 auto candidateIndex = targetedModule->functionOverloadIndexies[baseName][0];
5365 yoi_assert(targetedModule->functionTable[candidateIndex]->hasAttribute(IRFunctionDefinition::FunctionAttrs::Static),
5366 funcNameNode->getLine(),
5367 funcNameNode->getColumn(),
5369 funcIndex = candidateIndex;
5370 strategy = CreateStrategy::Plain;
5374 auto funcNameNode = *(it);
5375 yoi_assert(targetedModule->functionOverloadIndexies.contains(funcNameNode->getId().node.strVal),
5376 funcNameNode->getLine(),
5377 funcNameNode->getColumn(),
5383 argTypes.push_back(
managedPtr(parseTypeSpec(arg)));
5385 yoi::wstr fullFuncName = funcNameNode->getId().node.strVal + getFuncUniqueNameStr(argTypes);
5386 yoi_assert(targetedModule->functionTable.contains(fullFuncName),
5387 funcNameNode->getLine(),
5388 funcNameNode->getColumn(),
5389 "No matching function overload found with explicit param types: " +
yoi::wstring2string(fullFuncName));
5390 funcIndex = targetedModule->functionTable.getIndex(fullFuncName);
5391 strategy = CreateStrategy::Plain;
5394 yoi_assert(targetedModule->functionOverloadIndexies[funcNameNode->getId().node.strVal].size() == 1,
5395 funcNameNode->getLine(),
5396 funcNameNode->getColumn(),
5397 "Inplicit specification on multiple overloads of function: " +
yoi::wstring2string(funcNameNode->getId().node.strVal));
5398 funcIndex = targetedModule->functionOverloadIndexies[funcNameNode->getId().node.strVal][0];
5399 strategy = CreateStrategy::Plain;
5407 case CreateStrategy::Plain: {
5408 auto funcDef = targetedModule->functionTable[funcIndex];
5409 auto impl = createCallableImplementationForFunction(funcDef, funcIndex, targetModule == -1 ? currentModuleIndex : targetModule,
false);
5410 createCallableInstanceForFunction(impl.first, impl.second, targetModule == -1 ? currentModuleIndex : targetModule,
false);
5413 case CreateStrategy::IncludeThis: {
5426 std::pair<yoi::indexT, std::pair<yoi::indexT, yoi::indexT>> visitor::createCallableImplementationForFunction(
5427 const std::shared_ptr<IRFunctionDefinition> &func,
yoi::indexT funcIndex,
yoi::indexT moduleIndex,
bool hasThis) {
5429 auto objectType = hasThis ? func->argumentTypes[0] :
nullptr;
5432 for (
auto index = hasThis ? 1 : 0; index < func->argumentTypes.size(); index++) {
5433 argTypes.push_back(func->argumentTypes[index]);
5438 auto uniqueName = L
"callableWrapper#" + func->name + getFuncUniqueNameStr(argTypes);
5439 if (targetedModule->structTable.contains(uniqueName)) {
5440 auto interfaceImplName = getInterfaceImplName(
5442 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(uniqueName)}));
5443 return {targetedModule->interfaceImplementationTable.getIndex(interfaceImplName), callableInterface};
5446 yoi::indexT structTypeIndex = targetedModule->structTable.put_create(uniqueName, {});
5447 yoi::wstr constructorName = hasThis ? uniqueName + L
"::constructor#" + getTypeSpecUniqueNameStr(objectType) : uniqueName + L
"::constructor#";
5448 yoi::indexT constructorIndex = targetedModule->functionTable.put_create(constructorName, {});
5449 yoi::wstr callableName = uniqueName + L
"::operator()" + getFuncUniqueNameStr(func->argumentTypes);
5450 yoi::indexT callableIndex = targetedModule->functionTable.put_create(callableName, {});
5455 builder.
addField(L
"object_this", objectType);
5458 auto constructorUniqueName = hasThis ? L
"constructor#" + getTypeSpecUniqueNameStr(objectType) : L
"constructor#";
5459 builder.
setName(uniqueName).
addMethod(constructorUniqueName, constructorIndex);
5460 builder.
setName(uniqueName).
addMethod(L
"operator()" + getFuncUniqueNameStr(func->argumentTypes), callableIndex);
5461 targetedModule->structTable[structTypeIndex] = builder.
yield();
5463 auto structType =
managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, structTypeIndex});
5466 constructorBuilder.
setName(constructorName);
5467 constructorBuilder.
addArgument(L
"this", structType);
5469 constructorBuilder.
addArgument(L
"object_this", objectType);
5472 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::NoRawAndNullOptimization);
5473 constructorBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
5475 targetedModule->functionTable[constructorIndex] = constructorBuilder.
yield();
5477 callableBuilder.
setName(callableName);
5479 for (
yoi::indexT argIndex = hasThis ? 1 : 0; argIndex < func->argumentTypes.size(); argIndex++) {
5481 callableBuilder.
addArgument(L
"param" + std::to_wstring(argIndex), arg);
5484 callableBuilder.
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve);
5486 targetedModule->functionTable[callableIndex] = callableBuilder.
yield();
5513 for (
yoi::indexT argIndex = hasThis ? 1 : 0; argIndex < func->argumentTypes.size(); argIndex++) {
5514 auto arg = func->argumentTypes[argIndex];
5516 IR::Opcode::load_local, {IROperand::operandType::index, (
yoi::indexT)(argIndex + 1)}, arg, moduleIndex);
5523 auto interfaceImplName = getInterfaceImplName(
5525 managedPtr(
IRValueType{IRValueType::valueType::structObject, moduleIndex, targetedModule->structTable.getIndex(uniqueName)}));
5527 auto interfaceImplIndex = targetedModule->interfaceImplementationTable.put_create(
5530 .setName(interfaceImplName)
5531 .addVirtualMethod(L
"operator()" + getFuncUniqueNameStr(func->argumentTypes),
5533 .setImplInterfaceIndex(callableInterface)
5534 .setImplStructIndex({IRValueType::valueType::structObject, moduleIndex, structTypeIndex})
5537 return {interfaceImplIndex, callableInterface};
5540 void visitor::createCallableInstanceForFunction(
yoi::indexT implIndex,
5541 std::pair<yoi::indexT, yoi::indexT> callableInterfaceIndex,
5544 auto implDef = targetedModule->interfaceImplementationTable[implIndex];
5545 auto structIndex = implDef->implStructIndex;
5551 auto constructorIndex = targetedModule->structTable[std::get<2>(structIndex)]->nameIndexMap.at(L
"constructor#" + getTypeSpecUniqueNameStr(objectPtrOnStack));
5577 auto &
id = i->getVar().id->get().strVal;
5578 auto spec = parseTypeSpec(i->getVar().spec);
5582 irModule->dataStructTable[placeholder] = builder.yield();
5588 auto datastructDef = targetedModule->dataStructTable[datastructIndex];
5592 if (args->
arg.empty()) {
5596 yoi_assert(args->
arg.size() == datastructDef->fieldTypes.size(), args->
getLine(), args->
getColumn(),
"expected " + std::to_string(datastructDef->fields.size()) +
" arguments to construct data struct " +
yoi::wstring2string(datastructDef->name) +
", got " + std::to_string(args->
arg.size()));
5598 visit(args->
arg[i]);
5599 tryCastTo(datastructDef->fieldTypes[i]);
5622 std::shared_ptr<IRValueType> visitor::getGeneratorContext(
const yoi::wstr &funcName,
const std::shared_ptr<IRValueType> &yieldType) {
5624 auto generatorContextName = L
"GeneratorContext#" + funcName;
5625 auto generatorContextIndex = builtinModule->structTable.put_create(generatorContextName, {});
5627 IRValueType::valueType::structObject,
5629 generatorContextIndex
5633 auto generatorConstructorIndex = builtinModule->functionTable.put_create(generatorContextName + L
"::" + generatorConstructorName, {});
5634 auto generatorNextName = L
"next#";
5635 auto generatorNextIndex = builtinModule->functionTable.put_create(generatorContextName + L
"::" + generatorNextName, {});
5638 unsignedDataField->metadata.setMetadata(L
"STRUCT_DATAFIELD",
true);
5641 .
setName(generatorContextName)
5642 .
addField(L
"raw_ctx", unsignedDataField)
5644 .
addMethod(generatorConstructorName, generatorConstructorIndex)
5645 .
addMethod(generatorNextName, generatorNextIndex);
5647 builtinModule->structTable[generatorContextIndex] = builder.
yield();
5650 .
setName(generatorContextName + L
"::" + generatorConstructorName)
5654 .
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve)
5659 .
setName(generatorContextName + L
"::" + generatorNextName)
5662 .
addAttr(IRFunctionDefinition::FunctionAttrs::Preserve)
5666 builtinModule->functionOverloadIndexies[generatorContextName + L
"::constructor"].push_back(generatorConstructorIndex);
5667 builtinModule->functionOverloadIndexies[generatorContextName + L
"::next"].push_back(generatorNextIndex);
5672 builtinModule->functionTable[generatorConstructorIndex]
5686 builtinModule->functionTable[generatorNextIndex]
5706 irModule->identifier,
5711 void visitor::setupTemporaryConceptEvaluationEnvironment(
yoi::indexT moduleIndex,
const yoi::wstr &conceptName,
const std::vector<std::shared_ptr<IRValueType>> &args) {
5716 "Concept type parameter count does not match the number of arguments."
5720 for (
yoi::indexT i = 0; i < args.size(); i += 1) {
5733 node->id->node.strVal,
5753 void visitor::ejectTemporaryConceptEvaluationEnvironment() {
5759 switch (stmt->
kind) {
5767 }
catch (std::runtime_error &e) {
5768 panic(currentDebugInfo.
line, currentDebugInfo.
column,
"Constraint evaluation failed: " + std::string(e.what()));
5778 yoi::indexT currentModIndex = conceptName->
getTerms().size() > 1 ? -1 : currentModuleIndex;
5780 auto term = conceptName->
getTerms()[i];
5781 yoi_assert(!term->hasTemplateArg(), term->getLine(), term->getColumn(),
"template arguments is not allowed except in the last term");
5785 auto name = conceptName->
getTerms().back()->id->node.strVal;
5790 conceptName->
getTerms().back()->arg
5795 auto [conceptDef, parsedTemplateArg] = parseConceptName(stmt);
5799 for (
auto &i : parsedTemplateArg->spec) {
5800 args.push_back(
managedPtr(parseTypeSpec(i->spec)));
5803 setupTemporaryConceptEvaluationEnvironment(currentModuleIndex, conceptDef->name, args);
5805 for (
auto constraint : conceptDef->def->conceptBlock) {
5806 evaluateConstraint(constraint, {
5813 ejectTemporaryConceptEvaluationEnvironment();
5818 const std::shared_ptr<IRValueType> &args) {
5822 checkConceptSatisfaction(stmt);
#define HOSHI_COMPILER_CTX_GLOB_ID_CONST
void pushLoopContext(yoi::indexT breakTarget, yoi::indexT continueTarget)
void invokeOp(yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
Invoke a function with the given arguments.
std::shared_ptr< IRValueType > & getLhsFromTempVarStack()
void newDataStructOp(yoi::indexT structIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
const IRDebugInfo & getCurrentDebugInfo()
void yieldOp(bool yieldNone=false)
void invokeVirtualOp(yoi::indexT funcIndex, yoi::indexT interfaceIndex, yoi::indexT methodArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
void pushOp(IR::Opcode op, const yoi::IROperand &constV)
IRCodeBlock & getCodeBlock(yoi::indexT index)
void storeOp(IR::Opcode op, const yoi::IROperand &operand, yoi::indexT moduleIndex=-1)
void basicCast(const std::shared_ptr< IRValueType > &valType, yoi::indexT insertionPoint, bool lhs=false)
yoi::indexT createCodeBlock()
void constructInterfaceImplOp(const std::pair< yoi::indexT, yoi::indexT > &interfaceId, yoi::indexT interfaceImplIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
void loadFieldOp(yoi::vec< yoi::IROperand > &accessors, const std::shared_ptr< IRValueType > &expectedType)
std::shared_ptr< IRFunctionDefinition > irFuncDefinition()
void pushTempVar(const std::shared_ptr< IRValueType > &type)
void newArrayOp(const std::shared_ptr< IRValueType > &elementType, const yoi::vec< yoi::indexT > &dimensions, yoi::indexT onstackElementCount)
void loadOp(IR::Opcode op, const yoi::IROperand &source, const std::shared_ptr< IRValueType > &expectedType, yoi::indexT moduleIndex=-1)
void storeFieldOp(yoi::vec< yoi::IROperand > &accessors)
void typeIdOp(const std::shared_ptr< IRValueType > &type)
void invokeImportedOp(yoi::indexT libIndex, yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType)
void newStructOp(yoi::indexT structIndex, bool isExternal=false, yoi::indexT moduleIndex=-1)
yoi::indexT switchCodeBlock(yoi::indexT index)
void discardStateUntil(yoi::indexT stateIndex)
void bindElementsOp(yoi::indexT extractElementCount, ExtractType extractType)
void insert(const IR &ir, yoi::indexT insertionPoint=0xffffffff)
void invokeMethodOp(yoi::indexT funcIndex, yoi::indexT methodArgsCount, const std::shared_ptr< IRValueType > &returnType, bool isStatic, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
void uniqueArithmeticOp(IR::Opcode op)
void loadMemberOp(const yoi::IROperand &memberIndex, const std::shared_ptr< IRValueType > &memberType)
void initializeFieldsOp(yoi::indexT parameterCount)
void jumpOp(yoi::indexT target)
void bindFieldsOp(yoi::indexT extractFieldCount, ExtractType extractType)
void jumpIfOp(IR::Opcode op, yoi::indexT target)
yoi::indexT getCurrentInsertionPoint()
void restoreStateTemporarily()
void invokeDanglingOp(yoi::indexT funcIndex, yoi::indexT funcArgsCount, const std::shared_ptr< IRValueType > &returnType, bool externalInvocation=false, yoi::indexT moduleIndex=-1)
invoke a function with the given arguments, but the last param will be taken as the first param.
void newDynamicArrayOp(const std::shared_ptr< IRValueType > &elementType, yoi::indexT initializerSize=0)
void popFromTempVarStack()
void storeMemberOp(const yoi::IROperand &memberIndex)
void arithmeticOp(IR::Opcode op)
void dynCastOp(const std::shared_ptr< IRValueType > &type)
std::shared_ptr< IRValueType > & getRhsFromTempVarStack()
void retOp(bool returnWithNone=false)
void setDebugInfo(const IRDebugInfo &debugInfo)
void insert(const IR &ir)
Builder & addValue(const yoi::wstr &valueName, yoi::indexT valueIndex)
std::shared_ptr< IREnumerationType > yield()
Builder & setName(const yoi::wstr &name)
yoi::indexT affiliateModule
enum yoi::IRExternEntry::externType type
yoi::indexTable< yoi::wstr, Argument > templateArguments
IRTemplateBuilder & addTemplateArgument(const yoi::wstr &templateName, const std::shared_ptr< IRValueType > &templateType, const yoi::vec< externModuleAccessExpression * > &satisfyConditions={})
externModuleAccessExpression * rhs
vec< mulExpr * > & getTerms()
vec< lexer::token > & getOp()
vec< equalityExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< yoi::rExpr * > exprs
vec< inCodeBlockStmt * > & getStmts()
union yoi::conceptStmt::ConceptStmtValue value
enum yoi::conceptStmt::Kind kind
defTemplateArg * tempArgs
definitionArguments & getArgs()
definitionArguments & getArgs()
structDefInner & getInner()
vec< defTemplateArgSpec * > & get()
vec< defTemplateArgSpec * > spec
vec< identifierWithTypeSpec * > spec
vec< identifierWithTypeSpec * > & get()
vec< enumerationPair * > values
vec< relationalExpr * > & getTerms()
vec< lexer::token > & getOp()
vec< andExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< lexer::token > attrs
vec< identifierWithTemplateArg * > & getTerms()
inCodeBlockStmt * afterStmt
inCodeBlockStmt * initStmt
typeSpec & getResultType()
identifierWithDefTemplateArg * id
definitionArguments & getArgs()
identifierWithDefTemplateArg & getId()
yoi::vec< lexer::token > attrs
externModuleAccessExpression * name
unnamedDefinitionArguments * args
union yoi::globalStmt::vValue value
enum yoi::globalStmt::vKind kind
defTemplateArg & getArg() const
bool hasDefTemplateArg() const
identifier & getId() const
identifier & getId() const
bool hasTemplateArg() const
templateArg & getArg() const
bool hasElseBlock() const
innerMethodDef & getMethod()
constructorDef & getConstructor()
bool isConstructor() const
vec< implInnerPair * > & getInner()
externModuleAccessExpression & getStructId()
externModuleAccessExpression * structName
externModuleAccessExpression * interfaceName
vec< lexer::token > & getOp()
vec< exclusiveExpr * > & getTerms()
yoi::indexT put_create(const A &a, const B &b)
typeSpec & getResultType()
definitionArguments & getArgs()
yoi::vec< lexer::token > attrs
identifierWithDefTemplateArg * name
definitionArguments * args
identifierWithDefTemplateArg & getName()
typeSpec & getResultType()
identifierWithTemplateArg & getName()
definitionArguments & getArgs()
yoi::vec< lexer::token > attrs
vec< interfaceDefInnerPair * > & getInner()
identifierWithDefTemplateArg * id
interfaceDefInner & getInner()
vec< yoi::lambdaCapture * > captures
definitionArguments * args
vec< letAssignmentPair * > terms
vec< lexer::token > & getOp()
vec< inclusiveExpr * > & getTerms()
vec< logicalAndExpr * > & getTerms()
vec< lexer::token > & getOp()
yoi::vec< marcoPair * > pairs
vec< subscriptExpr * > & getTerms()
yoi::IRBuilder & getIRBuilder()
void pushIRBuilder(const yoi::IRBuilder &builder)
yoi::hoshiModule & getModuleAST()
void pushTemplateBuilder(IRTemplateBuilder &builder)
std::vector< IRTemplateBuilder > & getTemplateBuilders()
void popTemplateBuilder()
std::shared_ptr< yoi::compilerContext > getCompilerContext()
vec< lexer::token > & getOp()
vec< leftExpr * > & getTerms()
invocationArguments * args
externModuleAccessExpression * type
enum yoi::primary::primaryKind kind
bracedInitalizerList * bracedInitalizer
typeIdExpression * typeId
dynCastExpression * dynCast
logicalOrExpr & getExpr() const
vec< shiftExpr * > & getTerms()
vec< lexer::token > & getOp()
externModuleAccessExpression * emae
vec< lexer::token > & getOp()
vec< addExpr * > & getTerms()
innerMethodDecl & getMethod()
constructorDecl & getConstructor()
vec< structDefInnerPair * > & getInner()
identifierWithDefTemplateArg * id
identifierWithDefTemplateArg & getId()
structDefInner & getInner()
vec< subscript * > & getSubscript()
identifierWithTemplateArg * id
vec< templateArgSpec * > spec
vec< templateArgSpec * > & get()
yoi::identifierWithDefTemplateArg * lhs
decltypeExpr * decltypeExpression
yoi::vec< uint64_t > * arraySubscript
externModuleAccessExpression * member
enum yoi::typeSpec::typeSpecKind kind
std::shared_ptr< yoi::IRModule > visit()
visitor(const std::shared_ptr< yoi::moduleContext > &moduleContext, const std::shared_ptr< yoi::IRModule > &irModule, yoi::indexT moduleIndex)
std::shared_ptr< yoi::IRModule > irModule
std::string wstring2string(const std::wstring &v)
std::shared_ptr< T > managedPtr(const T &v)
yoi::wstr realpath(const std::wstring &path)
thread_local yoi::wstr __current_file_path
void yoi_assert(bool condition, yoi::indexT line, yoi::indexT col, const std::string &msg)
Asserts a condition that would be true and throws a runtime_error if it is false.
void set_current_file_path(const std::wstring &path)
void panic(yoi::indexT line, yoi::indexT col, const std::string &msg)
std::string replace_all(std::string str, const std::string &from, const std::string &to)
Builder & setName(const yoi::wstr &name)
Builder & setDebugInfo(const IRDebugInfo &debugInfo)
yoi::vec< std::pair< yoi::wstr, std::shared_ptr< IRValueType > > > argumentTypes
std::shared_ptr< IRFunctionDefinition > yield()
Builder & setName(const yoi::wstr &name)
Builder & addArgument(const yoi::wstr &argumentName, const std::shared_ptr< IRValueType > &argumentType)
Builder & setReturnType(const std::shared_ptr< IRValueType > &returnType)
Builder & addAttr(FunctionAttrs attr)
std::set< FunctionAttrs > attrs
std::shared_ptr< IRInterfaceImplementationDefinition > yield()
Builder & setImplStructIndex(std::tuple< IRValueType::valueType, yoi::indexT, yoi::indexT > implStructIndex)
Builder & setImplInterfaceIndex(const std::pair< yoi::indexT, yoi::indexT > &implInterfaceIndex)
Builder & addVirtualMethod(const yoi::wstr &methodName, const std::shared_ptr< IRValueType > &methodType)
Builder & setName(const yoi::wstr &name)
std::shared_ptr< IRInterfaceInstanceDefinition > yield()
Builder & setName(const yoi::wstr &name)
Builder & addMethod(const yoi::wstr &methodNameOri, const yoi::wstr &methodName, const std::shared_ptr< IRFunctionDefinition > &methodSignature)
std::shared_ptr< IRStructDefinition > yield()
Builder & setStoredTemplateArgs(const yoi::vec< yoi::wstr > ¶mNames, const yoi::vec< std::shared_ptr< IRValueType > > &args)
Builder & addMethod(const yoi::wstr &methodName, yoi::indexT index)
Builder & addTemplateMethodDef(const yoi::wstr &name, yoi::implInnerPair *def)
Builder & addField(const yoi::wstr &fieldName, const std::shared_ptr< IRValueType > &fieldType)
Builder & addTemplateMethodDecl(const yoi::wstr &name, yoi::structDefInnerPair *decl)
Builder & setName(const yoi::wstr &name)
enum yoi::lexer::token::tokenKind kind
union yoi::lexer::token::vBasicValue basicVal
yoi::indexT functionIndex
std::shared_ptr< IRValueType > variadicElementType
yoi::indexT fixedArgCount
std::shared_ptr< IRFunctionDefinition > function
satisfyStmt * satisfyStmt
dataStructDefStmt * dataStructDefStmtVal
enumerationDefinition * enumerationDefVal
interfaceDefStmt * interfaceDefStmtVal
conceptDefinition * conceptDefVal
funcDefStmt * funcDefStmtVal
typeAliasStmt * typeAliasStmtVal
exportDecl * exportDeclVal
structDefStmt * structDefStmtVal
importDecl * importDeclVal
forEachStmt * forEachStmtVal
returnStmt * returnStmtVal
continueStmt * continueStmtVal