diff --git a/src/builtins/guts.pir b/src/builtins/guts.pir index e3a0a138939..e84def3ee0f 100644 --- a/src/builtins/guts.pir +++ b/src/builtins/guts.pir @@ -1679,6 +1679,37 @@ Creates whatever closures (*.foo => { $_.foo }) 'die'("You used handles on attribute ", attrname, ", but nothing in the array can do method ", methodname) .end + +=item !make_type_fail_message + +Makes a type check failure error message, so we don't have to be doing so all +over the rest of the code base. + +=cut + +.sub '!make_type_fail_message' + .param string what_failed + .param pmc got_type + .param pmc wanted_type + + # Initial bit. + .local string output + output = concat what_failed, " type check failed; expected " + + # Work out what we were looking for and show that. + $P0 = wanted_type.'WHAT'() + $S0 = $P0.'perl'() + output = concat $S0 + + # Report what we actually got. + output = concat ", but got " + $P0 = got_type.'WHAT'() + $S0 = $P0.'perl'() + output = concat $S0 + + .return (output) +.end + =back =cut diff --git a/src/classes/Array.pir b/src/classes/Array.pir index b3091fe327e..027ab2c1401 100644 --- a/src/classes/Array.pir +++ b/src/classes/Array.pir @@ -350,7 +350,8 @@ Store things into an Array (e.g., upon assignment) splice self, array, 0, $I0 .return (self) type_error: - 'die'("Type mismatch in assignment to Array.") + $S0 = '!make_type_fail_message'('Array assignment', $P0, type) + 'die'($S0) .end =back diff --git a/src/classes/Hash.pir b/src/classes/Hash.pir index 58abaeb6e3d..71f90ef723b 100644 --- a/src/classes/Hash.pir +++ b/src/classes/Hash.pir @@ -236,7 +236,8 @@ Store a value into a hash. err_odd_list: die "Odd number of elements found where hash expected" type_error: - 'die'("Type mismatch in assignment to Hash.") + $S0 = '!make_type_fail_message'('Hash assignment', value, type) + 'die'($S0) .end diff --git a/src/classes/Object.pir b/src/classes/Object.pir index a55457d0623..7e0cbe8adb5 100644 --- a/src/classes/Object.pir +++ b/src/classes/Object.pir @@ -574,10 +574,8 @@ in the future.) .return (self) err_type: - $S0 = type.'perl'() - $S1 = source.'WHAT'() - 'die'("Type mismatch in assignment; expected something matching type ", $S0, " but got something of type ", $S1) - .return (self) + $S0 = '!make_type_fail_message'('Assignment', source, type) + 'die'($S0) .end diff --git a/src/classes/Signature.pir b/src/classes/Signature.pir index 39217a4015f..6cf2335ddbe 100644 --- a/src/classes/Signature.pir +++ b/src/classes/Signature.pir @@ -344,8 +344,6 @@ Gets a perl representation of the signature. concat s, ':' no_trailing_colon: - # XXX TODO: Return type, once we support those. - # Done. concat s, ')' .return (s) @@ -455,14 +453,8 @@ lexicals as needed and performing type checks. $P0 = '!DISPATCH_JUNCTION_SINGLE'(callersub, callerlex, callersig) 'return'($P0) not_junctional: - .local string errmsg - errmsg = 'Parameter type check failed; expected something matching ' - $S0 = type.'WHAT'() - concat errmsg, $S0 - concat errmsg, ' but got something of type ' - $S0 = orig.'WHAT'() - concat errmsg, $S0 - .local string callername + .local string errmsg, callername + errmsg = '!make_type_fail_message'('Parameter', orig, type) callername = callersub if callername goto have_callername callername = '' diff --git a/src/parser/actions.pm b/src/parser/actions.pm index e134b0ff288..1c819027d9c 100644 --- a/src/parser/actions.pm +++ b/src/parser/actions.pm @@ -3127,7 +3127,8 @@ sub return_handler_past() { :name('ACCEPTS'), PAST::Op.new( :inline(" %r = interpinfo .INTERPINFO_CURRENT_SUB", " %r = getprop '$!real_self', %r", - " %r = %r.'of'()") ), + " %r = %r.'of'()", + " $P0 = %r") ), PAST::Var.new( :name('exception'), :scope('register') ) ), PAST::Op.new( @@ -3137,7 +3138,13 @@ sub return_handler_past() { PAST::Op.new( :pasttype('call'), :name('die'), - 'Type check failed on return value' + PAST::Op.new( + :pasttype('call'), + :name('!make_type_fail_message'), + 'Return value', + PAST::Var.new( :name('exception'), :scope('register') ), + PAST::Var.new( :name('$P0'), :scope('register') ) + ) ) ) )