visitFuncDecl method
Implementation
@override
Uint8List visitFuncDecl(FuncDecl stmt) {
// final savedCurFunc = _curFunc;
final bytesBuilder = BytesBuilder();
final functionOptimization = _eligibleFunction(stmt);
final localFunction =
stmt.category != FunctionCategory.literal && stmt.id != null
? _localDeclaration(stmt.id!)
: null;
// TODO: generic param
if (stmt.category != FunctionCategory.literal) {
if (localFunction != null) {
bytesBuilder.addByte(OpCode.localFunctionDecl);
bytesBuilder.add(_uint16(localFunction.slot!));
} else {
bytesBuilder.addByte(OpCode.funcDecl);
}
final docs = stmt.documentation;
if (docs.isNotEmpty && !config.removeDocumentation) {
bytesBuilder.addByte(1); // bool: has doc
bytesBuilder.add(_utf8String(docs));
} else {
bytesBuilder.addByte(0); // bool: has doc
}
// funcBytesBuilder.addByte(HTOpCode.funcDecl);
bytesBuilder.add(_identifier(stmt.internalName));
if (stmt.id != null) {
bytesBuilder.addByte(1); // bool: hasId
bytesBuilder.add(_identifier(stmt.id!.id));
} else {
bytesBuilder.addByte(0); // bool: hasId
}
if (stmt.classId != null) {
bytesBuilder.addByte(1); // bool: hasClassId
bytesBuilder.add(_identifier(stmt.classId!));
} else {
bytesBuilder.addByte(0); // bool: hasClassId
}
if (stmt.explicityNamespaceId != null) {
bytesBuilder.addByte(1); // bool: hasExplicityNamespaceId
bytesBuilder.add(_identifier(stmt.explicityNamespaceId!));
} else {
bytesBuilder.addByte(0); // bool: hasExplicityNamespaceId
}
if (stmt.externalTypeId != null) {
bytesBuilder.addByte(1); // bool: hasExternalTypedef
bytesBuilder.add(_identifier(stmt.externalTypeId!));
} else {
bytesBuilder.addByte(0); // bool: hasExternalTypedef
}
bytesBuilder.addByte(stmt.category.index);
bytesBuilder.addByte(stmt.isPrivate ? 1 : 0);
bytesBuilder.addByte(stmt.isAsync ? 1 : 0);
bytesBuilder.addByte(stmt.isField ? 1 : 0);
bytesBuilder.addByte(stmt.isExternal ? 1 : 0);
bytesBuilder.addByte(stmt.isStatic ? 1 : 0);
bytesBuilder.addByte(stmt.isTopLevel ? 1 : 0);
bytesBuilder.addByte(stmt.isConstValue ? 1 : 0);
} else {
bytesBuilder.addByte(OpCode.local);
bytesBuilder.addByte(HTValueTypeCode.function);
bytesBuilder.add(_identifier(stmt.internalName));
if (stmt.externalTypeId != null) {
bytesBuilder.addByte(1);
bytesBuilder.add(_identifier(stmt.externalTypeId!));
} else {
bytesBuilder.addByte(0);
}
bytesBuilder.addByte(stmt.isAsync ? 1 : 0);
}
bytesBuilder.addByte(stmt.hasParamDecls ? 1 : 0);
bytesBuilder.addByte(stmt.isVariadic ? 1 : 0);
bytesBuilder.addByte(stmt.minArity);
bytesBuilder.addByte(stmt.maxArity);
bytesBuilder.addByte(stmt.paramDecls.length); // max 255
for (var param in stmt.paramDecls) {
final bytes = visitParamDecl(param);
bytesBuilder.add(bytes);
}
if (stmt.returnType != null) {
bytesBuilder.addByte(1); // bool: hasReturnType
// use compileAst here because there are multiple types of typeExpr
final bytes = compileAST(stmt.returnType!);
bytesBuilder.add(bytes);
} else {
bytesBuilder.addByte(0); // bool: hasReturnType
}
if (stmt.category == FunctionCategory.constructor) {
// referring to another constructor
if (stmt.redirectingConstructorCall != null) {
bytesBuilder.addByte(1); // bool: hasRefCtor
final bytes =
visitReferConstructCallExpr(stmt.redirectingConstructorCall!);
bytesBuilder.add(bytes);
} else {
bytesBuilder.addByte(0); // bool: hasRefCtor
}
}
// definition body
if (stmt.definition != null) {
bytesBuilder.addByte(1); // bool: has definition / isAbstract
bytesBuilder.add(_uint16(stmt.definition!.line));
bytesBuilder.add(_uint16(stmt.definition!.column));
final savedOptimization = _currentFunctionOptimization;
_currentFunctionOptimization = functionOptimization;
late final Uint8List body;
try {
body = compileAST(stmt.definition!);
} finally {
_currentFunctionOptimization = savedOptimization;
}
bytesBuilder.add(_uint16(body.length + 1)); // definition bytes length
bytesBuilder.add(body);
bytesBuilder.addByte(OpCode.endOfFunc);
} else {
bytesBuilder.addByte(0); // bool: has no definition
}
bytesBuilder.addByte(functionOptimization != null ? 1 : 0);
if (functionOptimization != null) {
bytesBuilder.add(_uint16(functionOptimization.localSlotCount));
for (var i = 0; i < functionOptimization.localSlotCount; ++i) {
bytesBuilder.add(_identifier(functionOptimization.slotNames[i] ?? ''));
}
final capturedSlots = functionOptimization.capturedVariables
.map((variable) => variable.slot!)
.toList()
..sort();
bytesBuilder.add(_uint16(capturedSlots.length));
for (final slot in capturedSlots) {
bytesBuilder.add(_uint16(slot));
}
bytesBuilder.add(_uint16(functionOptimization.upvalues.length));
for (final upvalue in functionOptimization.upvalues) {
bytesBuilder.add(_uint16(_captureDepth(functionOptimization, upvalue)));
bytesBuilder.add(_uint16(upvalue.slot!));
bytesBuilder.add(_identifier(upvalue.name));
}
}
// if (stmt.category != FunctionCategory.literal && !stmt.isField) {
// bytesBuilder.addByte(HTOpCode.endOfStmt);
// }
return bytesBuilder.toBytes();
}