Skip to content

Commit 2ca4eef

Browse files
authored
Merge pull request #28 from DanexCodr/copilot/fix-bugs-in-coderive-codebase
Fix ParamSkip-discovered runtime output bugs (float rendering + text literal tokenization)
2 parents fddaadc + 7037603 commit 2ca4eef

5 files changed

Lines changed: 52 additions & 49 deletions

File tree

.gitignore

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,3 +10,7 @@ server/build/
1010
!docs/assets/Coderive.jar
1111
!gradle/wrapper/gradle-wrapper.jar
1212
!source_.jar
13+
14+
# Generated runtime artifacts
15+
src/main/cod/src/bin/
16+
src/main/cod/src/idx/

src/main/java/cod/lexer/StringLexer.java

Lines changed: 12 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -215,9 +215,17 @@ private Token readText() {
215215

216216
extractedStrings.add(fullText.toString());
217217

218-
// If no interpolations, return a simple text literal
219-
if (parts.size() == 1 && parts.get(0).type == TokenType.TEXT_LIT) {
220-
return Token.createTextLiteral(fullSource, startPos, length, startLine, startCol);
218+
// If no interpolation expressions, return a simple text literal token.
219+
// This also preserves escaped characters correctly and handles empty strings.
220+
boolean hasInterpolation = false;
221+
for (Token part : parts) {
222+
if (part.type == TokenType.INTERPOL) {
223+
hasInterpolation = true;
224+
break;
225+
}
226+
}
227+
if (!hasInterpolation) {
228+
return Token.createTextLiteral(fullText.toString(), startLine, startCol);
221229
}
222230

223231
return new Token(
@@ -522,4 +530,4 @@ public List<String> extractAllStrings() {
522530

523531
return new ArrayList<String>(extractedStrings);
524532
}
525-
}
533+
}

src/main/java/cod/lexer/Token.java

Lines changed: 9 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -73,26 +73,15 @@ public Token(
7373
public String getText() {
7474
if (cachedText == null && length > 0) {
7575
if (type == TokenType.TEXT_LIT && length >= 2) {
76-
// Find where the actual content starts (skip quotes and pipes)
77-
int contentStart = start;
78-
int contentEnd = start + length - 1;
79-
80-
// Skip leading quote characters
81-
while (contentStart <= contentEnd &&
82-
(source[contentStart] == '"' || source[contentStart] == '|')) {
83-
contentStart++;
84-
}
85-
86-
// Skip trailing quote characters
87-
while (contentEnd >= contentStart &&
88-
(source[contentEnd] == '"' || source[contentEnd] == '|')) {
89-
contentEnd--;
90-
}
91-
92-
if (contentStart <= contentEnd) {
93-
cachedText = new String(source, contentStart, contentEnd - contentStart + 1);
76+
int end = start + length - 1;
77+
if (length >= 4 &&
78+
source[start] == '|' && source[start + 1] == '"' &&
79+
source[end - 1] == '"' && source[end] == '|') {
80+
cachedText = new String(source, start + 2, length - 4);
81+
} else if (source[start] == '"' && source[end] == '"') {
82+
cachedText = new String(source, start + 1, length - 2);
9483
} else {
95-
cachedText = "";
84+
cachedText = new String(source, start, length);
9685
}
9786
} else {
9887
cachedText = new String(source, start, length);
@@ -290,4 +279,4 @@ public String toString() {
290279
public void reset() {
291280
cachedText = null;
292281
}
293-
}
282+
}

src/main/java/cod/math/AutoStackingNumber.java

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
import java.io.Serializable;
44
import java.util.Arrays;
5+
import java.math.BigDecimal;
56

67
/**
78
* Auto-stacking fixed-point number with 1-7 stacks of 64-bit words.
@@ -24,6 +25,7 @@ public class AutoStackingNumber implements Comparable<AutoStackingNumber>, Seria
2425
private static final int WORD_BITS = 64;
2526
private static final long WORD_MASK = 0xFFFFFFFFFFFFFFFFL;
2627
private static final long FRAC_MASK = (1L << 60) - 1; // 60 bits of ones for fractional parts
28+
private static final BigDecimal DECIMAL_COMPARISON_EPSILON = new BigDecimal("0.000000000000001");
2729

2830
// Zero and One constants for each stack level
2931
private static final AutoStackingNumber[][] CONSTANTS = new AutoStackingNumber[MAX_STACKS + 1][3];
@@ -753,6 +755,30 @@ public String toString() {
753755
}
754756
if (allZero) break;
755757
}
758+
759+
String exact = sb.toString();
760+
String pretty = Double.toString(doubleValue());
761+
if (pretty.indexOf('E') >= 0 || pretty.indexOf('e') >= 0) {
762+
pretty = BigDecimal.valueOf(doubleValue()).stripTrailingZeros().toPlainString();
763+
}
764+
765+
try {
766+
if (pretty.length() < exact.length()) {
767+
BigDecimal exactValue = new BigDecimal(exact);
768+
BigDecimal prettyValue = new BigDecimal(pretty);
769+
BigDecimal delta = exactValue.subtract(prettyValue).abs();
770+
BigDecimal relative = exactValue.abs().multiply(DECIMAL_COMPARISON_EPSILON);
771+
BigDecimal tolerance =
772+
relative.compareTo(DECIMAL_COMPARISON_EPSILON) > 0
773+
? relative
774+
: DECIMAL_COMPARISON_EPSILON;
775+
if (delta.compareTo(tolerance) <= 0) {
776+
return pretty;
777+
}
778+
}
779+
} catch (Exception ignored) {
780+
// Fallback to exact representation from internal stacks
781+
}
756782
}
757783

758784
return sb.toString();

src/main/java/cod/parser/ExpressionParser.java

Lines changed: 1 addition & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -141,11 +141,6 @@ public MethodCallNode parse() throws ParseError {
141141
methodName = qualifiedNameStr.substring(qualifiedNameStr.lastIndexOf('.') + 1);
142142
}
143143

144-
// DEBUG: Only for createMessage
145-
if (methodName.equals("createMessage")) {
146-
System.err.println("=== DEBUG: createMessage call detected ===");
147-
}
148-
149144
MethodCallNode call = ASTFactory.createMethodCall(methodName, qualifiedNameStr, nameStartToken);
150145

151146
if (!qualifiedNameStr.contains(".") && globalFunctionNames != null &&
@@ -159,21 +154,6 @@ public MethodCallNode parse() throws ParseError {
159154
if (isNamedArgument()) {
160155
parseNamedArgumentList(call.arguments, call.argNames);
161156
} else {
162-
// DEBUG: Parse the argument
163-
if (methodName.equals("createMessage")) {
164-
System.err.println(" Parsing argument for createMessage");
165-
Token argToken = now();
166-
System.err.println(" Argument token type: " + argToken.type);
167-
System.err.println(" Argument token raw slice: '" +
168-
new String(argToken.source, argToken.start, argToken.length) + "'");
169-
System.err.println(" Argument token getText(): '" + argToken.getText() + "'");
170-
System.err.println(" Argument token start=" + argToken.start + ", length=" + argToken.length);
171-
System.err.println(" First char: '" + argToken.source[argToken.start] +
172-
"' (" + (int)argToken.source[argToken.start] + ")");
173-
System.err.println(" Last char: '" + argToken.source[argToken.start + argToken.length - 1] +
174-
"' (" + (int)argToken.source[argToken.start + argToken.length - 1] + ")");
175-
}
176-
177157
call.arguments.add(parseExpr());
178158
call.argNames.add(null);
179159

@@ -185,10 +165,6 @@ public MethodCallNode parse() throws ParseError {
185165
}
186166
expect(RPAREN);
187167

188-
if (methodName.equals("createMessage")) {
189-
System.err.println("=== END createMessage debug ===");
190-
}
191-
192168
return call;
193169
}
194170
});
@@ -1527,4 +1503,4 @@ private boolean isComparisonOp(Token t) {
15271503
public GlobalRegistry getGlobalRegistry() {
15281504
return globalRegistry;
15291505
}
1530-
}
1506+
}

0 commit comments

Comments
 (0)