diff --git a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowBodyAnalyzer.java b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowBodyAnalyzer.java index 25ab6c74..c3c667c0 100644 --- a/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowBodyAnalyzer.java +++ b/prometeu-compiler/frontends/prometeu-frontend-pbs/src/main/java/p/studio/compiler/pbs/semantics/PbsFlowBodyAnalyzer.java @@ -31,70 +31,94 @@ final class PbsFlowBodyAnalyzer { final var model = Model.from(ast, supplementalTopDecls); for (final var topDecl : ast.topDecls()) { - if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { - validateCallableBody( - functionDecl.parameters(), - functionDecl.body(), - newCallableContext( - typeOps.callableReturnType( - functionDecl.returnKind(), - functionDecl.returnType(), - functionDecl.resultErrorType(), - model), - functionDecl.resultErrorType() == null ? null : functionDecl.resultErrorType().name(), - null, - model, - diagnostics)); - continue; - } - if (topDecl instanceof PbsAst.StructDecl structDecl) { - final var receiverType = TypeView.struct(structDecl.name()); - for (final var method : structDecl.methods()) { - validateCallableBody( - method.parameters(), - method.body(), - newCallableContext( - typeOps.callableReturnType( - method.returnKind(), - method.returnType(), - method.resultErrorType(), - model), - method.resultErrorType() == null ? null : method.resultErrorType().name(), - receiverType, - model, - diagnostics)); - } - for (final var ctor : structDecl.ctors()) { - validateCallableBody( - ctor.parameters(), - ctor.body(), - newCallableContext( - TypeView.unit(), - null, - receiverType, - model, - diagnostics)); - } - continue; - } - if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { - final var receiverType = TypeView.service(serviceDecl.name()); - for (final var method : serviceDecl.methods()) { - validateCallableBody( - method.parameters(), - method.body(), - newCallableContext( - typeOps.callableReturnType( - method.returnKind(), - method.returnType(), - method.resultErrorType(), - model), - method.resultErrorType() == null ? null : method.resultErrorType().name(), - receiverType, - model, - diagnostics)); - } - } + validateTopDecl(topDecl, model, diagnostics); + } + } + + private void validateTopDecl( + final PbsAst.TopDecl topDecl, + final Model model, + final DiagnosticSink diagnostics) { + if (topDecl instanceof PbsAst.FunctionDecl functionDecl) { + validateFunction(functionDecl, model, diagnostics); + return; + } + if (topDecl instanceof PbsAst.StructDecl structDecl) { + validateStruct(structDecl, model, diagnostics); + return; + } + if (topDecl instanceof PbsAst.ServiceDecl serviceDecl) { + validateService(serviceDecl, model, diagnostics); + } + } + + private void validateFunction( + final PbsAst.FunctionDecl functionDecl, + final Model model, + final DiagnosticSink diagnostics) { + validateCallableBody( + functionDecl.parameters(), + functionDecl.body(), + typeOps.callableReturnType( + functionDecl.returnKind(), + functionDecl.returnType(), + functionDecl.resultErrorType(), + model), + errorName(functionDecl.resultErrorType()), + null, + model, + diagnostics); + } + + private void validateStruct( + final PbsAst.StructDecl structDecl, + final Model model, + final DiagnosticSink diagnostics) { + final var receiverType = TypeView.struct(structDecl.name()); + for (final var method : structDecl.methods()) { + validateCallableBody( + method.parameters(), + method.body(), + typeOps.callableReturnType( + method.returnKind(), + method.returnType(), + method.resultErrorType(), + model), + errorName(method.resultErrorType()), + receiverType, + model, + diagnostics); + } + for (final var ctor : structDecl.ctors()) { + validateCallableBody( + ctor.parameters(), + ctor.body(), + TypeView.unit(), + null, + receiverType, + model, + diagnostics); + } + } + + private void validateService( + final PbsAst.ServiceDecl serviceDecl, + final Model model, + final DiagnosticSink diagnostics) { + final var receiverType = TypeView.service(serviceDecl.name()); + for (final var method : serviceDecl.methods()) { + validateCallableBody( + method.parameters(), + method.body(), + typeOps.callableReturnType( + method.returnKind(), + method.returnType(), + method.resultErrorType(), + model), + errorName(method.resultErrorType()), + receiverType, + model, + diagnostics); } } @@ -113,6 +137,29 @@ final class PbsFlowBodyAnalyzer { diagnostics); } + private void validateCallableBody( + final ReadOnlyList parameters, + final PbsAst.Block body, + final TypeView returnType, + final String resultErrorName, + final TypeView receiverType, + final Model model, + final DiagnosticSink diagnostics) { + validateCallableBody( + parameters, + body, + newCallableContext( + returnType, + resultErrorName, + receiverType, + model, + diagnostics)); + } + + private String errorName(final PbsAst.TypeRef errorType) { + return errorType == null ? null : errorType.name(); + } + private void validateCallableBody( final ReadOnlyList parameters, final PbsAst.Block body,