Codex 또는 Claude로 설치 이 Prompt를 복사해 Codex, Claude 또는 다른 어시스턴트에 붙여 넣으면 Skill 페이지를 검토하고 설치를 진행할 수 있습니다.
직접 명령은 검토 Prompt를 거치지 않습니다. 실행하기 전에 소스를 확인하세요.
npx skills add https://github.com/GEOS-ESM/MAPL --skill mapl-error-handling명령은 한 줄로 유지됩니다. 복사하기 전에 가로로 스크롤해 전체 내용을 확인하세요.
로컬 사본을 원하시나요? SkillsMP에서 현재 제공할 수 있는 파일을 다운로드하세요.
SKILL.md 표시 중
SOC 직업 분류 기준
| name | mapl-error-handling |
| description | MAPL error handling macros and best practices |
| compatibility | opencode |
Provide comprehensive guidance on MAPL's error handling system, including:
Use this skill when:
All modules using MAPL error handling must include:
#include "MAPL_Generic.h"
module MyModule
use MAPL
implicit none
private
! Your code here
end module MyModule
This provides access to all MAPL error handling macros.
Standard convention:
_SUCCESS macro)MAPL uses ESMF return code constants:
ESMF_SUCCESS = 0ESMF_FAILURE = non-zeroMAPL macros:
_SUCCESS → ESMF_SUCCESS (0)_FAILURE → ESMF_FAILURE (non-zero)Usage: Compact call + verify pattern
call some_procedure(arg1, arg2, _RC)
Expands to:
rc=status); _VERIFY(status)
What it does:
status variable as rc argumentExample:
subroutine process_data(input, output, rc)
type(DataSet), intent(in) :: input
type(DataSet), intent(out) :: output
integer, optional, intent(out) :: rc
integer :: status
call read_configuration('config.yaml', _RC)
call allocate_workspace(n_items, _RC)
call transform_data(input, output, _RC)
_RETURN(_SUCCESS)
end subroutine process_data
Benefits:
Usage: Check return codes explicitly
call some_procedure(arg1, arg2, rc=status)
_VERIFY(status)
What it does:
status == _SUCCESSUse when:
Example:
call read_file(filename, data, rc=status)
if (status /= _SUCCESS) then
call log_error('Failed to read: ' // trim(filename))
end if
_VERIFY(status)
Usually _RC is preferred over this pattern.
Usage: Check logical conditions
_ASSERT(condition, "Error message")
What it does:
Examples:
_ASSERT(n_columns > 0, "Number of columns must be positive")
_ASSERT(allocated(workspace), "Workspace not allocated")
_ASSERT(size(input) == size(output), "Array size mismatch")
Use for:
Don't use for:
_VERIFY or _RC)_FAIL insteadUsage: Force procedure to fail with message
_FAIL("Error message describing the problem")
What it does:
_FAILURECommon use: SELECT CASE with invalid/unexpected values
Example:
select case(operation_type)
case(ADD)
result = a + b
case(SUBTRACT)
result = a - b
case(MULTIPLY)
result = a * b
case default
_FAIL("Unknown operation type")
end select
Also useful for:
Note: If you find yourself doing _ASSERT(.FALSE., "message"), use _FAIL("message") instead - it's clearer.
Usage: Return from procedure with given status
_RETURN(status_value)
What it does:
Standard pattern at end of successful procedure:
subroutine my_procedure(arg, rc)
integer, intent(in) :: arg
integer, optional, intent(out) :: rc
! ... procedure implementation ...
_RETURN(_SUCCESS) ! Always end successful procedures this way
end subroutine my_procedure
Can return with any value:
if (early_exit_condition) then
_RETURN(_SUCCESS) ! Early successful return
end if
Usage: Represents successful return code (0)
_RETURN(_SUCCESS)
if (status == _SUCCESS) then
! Success path
end if
Expands to: ESMF_SUCCESS (which is 0)
Use instead of: Literal 0 in code
Benefits:
Usage: Represents failure return code (non-zero)
if (status /= _SUCCESS) then
! This is a failure
end if
Expands to: ESMF_FAILURE
Note: Usually don't need this directly - macros handle it. Provided for completeness.
Usage: Check Fortran intrinsic STAT codes
allocate(array(n), _STAT)
deallocate(array, _STAT)
Expands to:
stat=status); _VERIFY(status)
Examples:
subroutine allocate_workspace(n, rc)
integer, intent(in) :: n
integer, optional, intent(out) :: rc
integer :: status
real, allocatable :: workspace(:)
allocate(workspace(n), _STAT)
! Use workspace
deallocate(workspace, _STAT)
_RETURN(_SUCCESS)
end subroutine
Usage: Check Fortran I/O IOSTAT codes
open(unit, file=filename, _IOSTAT)
read(unit, *, _IOSTAT) values
close(unit, _IOSTAT)
Expands to:
iostat=status); _VERIFY(status)
Example:
subroutine read_data(filename, values, rc)
character(len=*), intent(in) :: filename
real, intent(out) :: values(:)
integer, optional, intent(out) :: rc
integer :: status, unit
open(newunit=unit, file=filename, status='old', _IOSTAT)
read(unit, *, _IOSTAT) values
close(unit, _IOSTAT)
_RETURN(_SUCCESS)
end subroutine read_data
Usage: Debug print with file and line information
_HERE, "debug message", variables
Expands to:
print*, __FILE__, __LINE__, "debug message", variables
Examples:
_HERE, "n_columns:", n_columns
_HERE, "Entering iteration:", iteration_count
_HERE, "Checkpoint A"
Use for:
Note: Remember to remove or comment out after debugging!
#include "MAPL_Generic.h"
module MAPL_DataProcessor
use ESMF
use MAPL_BaseMod
implicit none
private
public :: process_dataset
contains
subroutine process_dataset(input_file, output_file, n_iterations, rc)
character(len=*), intent(in) :: input_file
character(len=*), intent(in) :: output_file
integer, intent(in) :: n_iterations
integer, optional, intent(out) :: rc
integer :: status
real, allocatable :: data(:)
integer :: i, n_points
! Validate inputs
_ASSERT(n_iterations > 0, "Iterations must be positive")
_ASSERT(len_trim(input_file) > 0, "Input filename cannot be empty")
! Read number of points from file
call read_file_size(input_file, n_points, _RC)
! Allocate workspace
allocate(data(n_points), _STAT)
! Read data
call read_data(input_file, data, _RC)
! Process
do i = 1, n_iterations
call apply_filter(data, _RC)
end do
! Write results
call write_data(output_file, data, _RC)
! Cleanup
deallocate(data, _STAT)
_RETURN(_SUCCESS)
end subroutine process_dataset
subroutine read_file_size(filename, n_points, rc)
character(len=*), intent(in) :: filename
integer, intent(out) :: n_points
integer, optional, intent(out) :: rc
integer :: status, unit
open(newunit=unit, file=filename, status='old', _IOSTAT)
read(unit, *, _IOSTAT) n_points
close(unit, _IOSTAT)
_ASSERT(n_points > 0, "File contains invalid point count")
_RETURN(_SUCCESS)
end subroutine read_file_size
subroutine apply_filter(data, rc)
real, intent(inout) :: data(:)
integer, optional, intent(out) :: rc
integer :: status, filter_type
! Get filter type from configuration
call get_filter_type(filter_type, _RC)
! Apply appropriate filter
select case(filter_type)
case(1)
call apply_gaussian_filter(data, _RC)
case(2)
call apply_median_filter(data, _RC)
case(3)
call apply_moving_average(data, _RC)
case default
_FAIL("Unknown filter type")
end select
_RETURN(_SUCCESS)
end subroutine apply_filter
end module MAPL_DataProcessor
DO:
call some_procedure(args, _RC)
DON'T:
call some_procedure(args) ! Ignoring potential errors!
Why: If something fails, you want to know immediately, not debug mysterious crashes later.
DO:
subroutine my_proc(rc)
integer, optional, intent(out) :: rc
! ... successful execution ...
_RETURN(_SUCCESS)
end subroutine
DON'T:
subroutine my_proc(rc)
integer, optional, intent(out) :: rc
! ... successful execution ...
! Missing return status!
end subroutine
subroutine process(n_items, tolerance, rc)
integer, intent(in) :: n_items
real, intent(in) :: tolerance
integer, optional, intent(out) :: rc
! Validate first
_ASSERT(n_items > 0, "n_items must be positive")
_ASSERT(tolerance > 0.0, "tolerance must be positive")
_ASSERT(tolerance < 1.0, "tolerance must be less than 1")
! Now proceed with validated inputs
! ...
_RETURN(_SUCCESS)
end subroutine
allocate(workspace(n), _STAT)
allocate(temporary(m), _STAT)
Never:
allocate(workspace(n)) ! Unchecked!
open(newunit=unit, file=filename, _IOSTAT)
read(unit, *, _IOSTAT) data
close(unit, _IOSTAT)
Good:
_ASSERT(n_rows == n_cols, "Matrix must be square for this operation")
_FAIL("Configuration file missing required 'output_dir' parameter")
Poor:
_ASSERT(n_rows == n_cols, "Error")
_FAIL("Bad input")
subroutine process_with_cleanup(rc)
integer, optional, intent(out) :: rc
integer :: status
real, allocatable :: temp(:)
logical :: file_open
file_open = .false.
allocate(temp(100), _STAT)
open(newunit=unit, file='data.txt', _IOSTAT)
file_open = .true.
call risky_operation(_RC)
! Cleanup
if (file_open) close(unit)
deallocate(temp)
_RETURN(_SUCCESS)
end subroutine
Note: Error macros return immediately, so cleanup after error is tricky. Consider Fortran block scope or finalization for robust cleanup.
call read_configuration(config_file, config, rc=status)
if (status /= _SUCCESS) then
call log_error("Failed reading config: " // trim(config_file))
end if
_VERIFY(status)
! Unusual case: want to continue despite errors
call optional_operation(rc=status)
if (status /= _SUCCESS) then
call log_warning("Optional operation failed, continuing")
! Don't call _VERIFY - continue execution
end if
Old macros ending with underscore: VERIFY_, ASSERT_, __RC__
Problem: Required IAM character variable with procedure name
! OLD STYLE - Don't do this!
character(len=*), parameter :: IAM = 'my_procedure'
call something(args, __RC__)
Issues:
Migration:
! OLD
character(len=*), parameter :: IAM = 'my_procedure'
call foo(args, __RC__)
! NEW
call foo(args, _RC)
If you see these in code review: Request update to new macros
Error: Macros not defined Solution:
#include "MAPL_Generic.h"
Must come before module statement.
Error: Macros try to set rc but procedure doesn't have it Solution: Add optional rc parameter
subroutine my_proc(arg, rc) ! Add rc parameter
integer, intent(in) :: arg
integer, optional, intent(out) :: rc
! WRONG - not standard conforming
if (flag == .true.) then
! CORRECT - but redundant
if (flag .eqv. .true.) then
! BEST - direct use
if (flag) then
#include "MAPL_Generic.h" present_RC)_STAT)_IOSTAT)_RETURN(_SUCCESS)VERIFY_, __RC__, etc.)fortran-style - General Fortran coding standardsgithub-workflow - Code review processKey Points:
MAPL_Generic.h in all modules_RC for compact call + check pattern_ASSERT for precondition validation_STAT and _IOSTAT for intrinsics_RETURN(_SUCCESS)Philosophy: Error handling everywhere in calling chain. If something can fail, check it. Your future self (and teammates) will thank you during debugging.