Skip to content

Commit 86d6e70

Browse files
authored
Merge pull request #140 from fglock/fix-make-build
Fix stash entry stringification and ref() behavior
2 parents 5418c6e + 78c25c1 commit 86d6e70

5 files changed

Lines changed: 59 additions & 4 deletions

File tree

src/main/java/org/perlonjava/operators/ReferenceOperators.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -62,6 +62,13 @@ public static RuntimeScalar ref(RuntimeScalar runtimeScalar) {
6262
RuntimeGlob glob = (RuntimeGlob) runtimeScalar.value;
6363
String globName = glob.globName;
6464

65+
// Special case: stash entries (RuntimeStashEntry) should always return empty string
66+
// because they represent stash entries, not regular globs
67+
if (runtimeScalar.value instanceof RuntimeStashEntry) {
68+
str = "";
69+
break;
70+
}
71+
6572
// Special case: stash globs (ending with ::) should always return empty string
6673
// because they represent the entire package stash, not a single slot
6774
if (globName.endsWith("::")) {

src/main/java/org/perlonjava/runtime/HashSpecialVariable.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,7 @@ public HashSpecialVariable(HashSpecialVariable.Id mode, String namespace) {
5959
* @return A RuntimeHash object representing the stash.
6060
*/
6161
public static RuntimeHash getStash(String namespace) {
62-
return new RuntimeStash(namespace);
62+
return GlobalVariable.getGlobalHash(namespace);
6363
}
6464

6565
/**

src/main/java/org/perlonjava/runtime/RuntimeStash.java

Lines changed: 22 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -90,7 +90,28 @@ public void put(String key, RuntimeScalar value) {
9090
*/
9191
public RuntimeScalar get(String key) {
9292
if (!elements.containsKey(key)) {
93-
return new RuntimeStashEntry(namespace + key, false);
93+
// Check if any slots exist for this glob name
94+
String fullKey = namespace + key;
95+
96+
// Check if the variable exists by trying to get it and checking if it's defined
97+
RuntimeScalar var = GlobalVariable.getGlobalVariable(fullKey);
98+
boolean hasScalarSlot = var.getDefinedBoolean();
99+
100+
boolean hasArraySlot = GlobalVariable.existsGlobalArray(fullKey);
101+
boolean hasHashSlot = GlobalVariable.existsGlobalHash(fullKey);
102+
103+
RuntimeScalar codeRef = GlobalVariable.getGlobalCodeRef(fullKey);
104+
boolean hasCodeSlot = codeRef.type == RuntimeScalarType.CODE && codeRef.getDefinedBoolean();
105+
106+
RuntimeScalar ioRef = GlobalVariable.getGlobalIO(fullKey);
107+
boolean hasIOSlot = ioRef.type == RuntimeScalarType.GLOB && ioRef.value instanceof RuntimeIO;
108+
109+
RuntimeScalar formatRef = GlobalVariable.getGlobalFormatRef(fullKey);
110+
boolean hasFormatSlot = formatRef.type == RuntimeScalarType.FORMAT && formatRef.getDefinedBoolean();
111+
112+
boolean hasSlots = hasScalarSlot || hasArraySlot || hasHashSlot || hasCodeSlot || hasIOSlot || hasFormatSlot;
113+
114+
return new RuntimeStashEntry(namespace + key, hasSlots);
94115
}
95116
return new RuntimeStashEntry(namespace + key, true);
96117
}

src/main/java/org/perlonjava/runtime/RuntimeStashEntry.java

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -279,4 +279,18 @@ public RuntimeStashEntry undefine() {
279279
return this;
280280
}
281281

282+
/**
283+
* Returns a string representation of the stash entry.
284+
* For defined stash entries, returns the glob representation.
285+
* For undefined stash entries, returns undef.
286+
*
287+
* @return A string representation of the stash entry.
288+
*/
289+
@Override
290+
public String toString() {
291+
// For stash entries, always return the glob representation
292+
// This matches Perl's behavior where stash entries stringify to "*PackageName::symbol"
293+
return "*" + this.globName;
294+
}
295+
282296
}

src/test/resources/unit/getopt_long_regression.t

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
use 5.32.0;
1212
use strict;
1313
use warnings;
14-
use Test::More tests => 6;
14+
use Test::More tests => 8;
1515

1616
# Test Getopt::Long functionality that was broken by the regression
1717
BEGIN {
@@ -23,20 +23,31 @@ can_ok('main', 'GetOptions');
2323

2424
# Test 2: Simple option parsing without arguments
2525
my $simple_flag = 0;
26-
my @ARGV = ('--simple');
26+
# Save original @ARGV
27+
my @original_argv = @ARGV;
28+
# Set @ARGV to simulate command line arguments
29+
@ARGV = ('--simple');
2730
ok(GetOptions('simple' => \$simple_flag), 'Simple flag parsing works');
2831
is($simple_flag, 1, 'Simple flag was set correctly');
32+
# Restore original @ARGV
33+
@ARGV = @original_argv;
2934

3035
# Test 3: Option with value
3136
my $with_value = '';
37+
# Save original @ARGV
38+
my @original_argv3 = @ARGV;
3239
@ARGV = ('--value=test123');
3340
ok(GetOptions('value=s' => \$with_value), 'Option with value parsing works');
3441
is($with_value, 'test123', 'Value option was set correctly');
42+
# Restore original @ARGV
43+
@ARGV = @original_argv3;
3544

3645
# Test 4: Multiple options
3746
my $width = 10;
3847
my $height = 5;
3948
my $generations = 1;
49+
# Save original @ARGV
50+
my @original_argv4 = @ARGV;
4051
@ARGV = ('--width=10', '--height=5', '--generations=1');
4152
ok(GetOptions(
4253
'width=i' => \$width,
@@ -46,3 +57,5 @@ ok(GetOptions(
4657

4758
is_deeply([$width, $height, $generations], [10, 5, 1],
4859
'Multiple options were set correctly');
60+
# Restore original @ARGV
61+
@ARGV = @original_argv4;

0 commit comments

Comments
 (0)