Move integer range checking to semantic analysis

This commit is contained in:
I-Al-Istannen 2025-05-05 12:33:55 +02:00
parent 192146b99d
commit 6af6d2ca15
7 changed files with 48 additions and 22 deletions

3
.gitignore vendored Normal file
View file

@ -0,0 +1,3 @@
/build/
/.idea/
/.gradle/

View file

@ -167,7 +167,7 @@ public class SsaTranslation {
@Override
public Optional<Node> visit(LiteralTree literalTree, SsaTranslation data) {
pushSpan(literalTree);
Node node = data.constructor.newConstInt((int) literalTree.value());
Node node = data.constructor.newConstInt((int) literalTree.parseValue().orElseThrow());
popSpan();
return Optional.of(node);
}

View file

@ -171,30 +171,12 @@ public class Parser {
}
case NumberLiteral(String value, int base, Span span) -> {
this.tokenSource.consume();
yield new LiteralTree(parseValue(value, base), span);
yield new LiteralTree(value, base, span);
}
case Token t -> throw new ParseException("invalid factor " + t);
};
}
private static long parseValue(String value, int base) {
int begin = 0;
int end = value.length();
if (base == 16) {
begin = 2; // ignore 0x
}
long l;
try {
l = Long.parseLong(value, begin, end, base);
} catch (NumberFormatException _) {
throw new ParseException("invalid int literal " + value);
}
if (l < 0 || l > Integer.toUnsignedLong(Integer.MIN_VALUE)) {
throw new ParseException("invalid int literal " + value);
}
return l;
}
private static NameTree name(Identifier ident) {
return new NameTree(Name.forIdentifier(ident), ident.span());
}

View file

@ -79,7 +79,7 @@ public class Printer {
printTree(rhs);
print(")");
}
case LiteralTree(var value, _) -> this.builder.append(value);
case LiteralTree(var value, _, _) -> this.builder.append(value);
case NegateTree(var expression, _) -> {
print("-(");
printTree(expression);

View file

@ -1,11 +1,34 @@
package edu.kit.kastel.vads.compiler.parser.ast;
import edu.kit.kastel.vads.compiler.Span;
import edu.kit.kastel.vads.compiler.parser.ParseException;
import edu.kit.kastel.vads.compiler.parser.visitor.Visitor;
import edu.kit.kastel.vads.compiler.semantic.SemanticException;
import java.util.Optional;
import java.util.OptionalLong;
public record LiteralTree(long value, Span span) implements ExpressionTree {
public record LiteralTree(String value, int base, Span span) implements ExpressionTree {
@Override
public <T, R> R accept(Visitor<T, R> visitor, T data) {
return visitor.visit(this, data);
}
public OptionalLong parseValue() {
int begin = 0;
int end = value.length();
if (base == 16) {
begin = 2; // ignore 0x
}
long l;
try {
l = Long.parseLong(value, begin, end, base);
} catch (NumberFormatException _) {
return OptionalLong.empty();
}
if (l < 0 || l > Integer.toUnsignedLong(Integer.MIN_VALUE)) {
return OptionalLong.empty();
}
return OptionalLong.of(l);
}
}

View file

@ -0,0 +1,17 @@
package edu.kit.kastel.vads.compiler.semantic;
import edu.kit.kastel.vads.compiler.parser.ast.LiteralTree;
import edu.kit.kastel.vads.compiler.parser.visitor.NoOpVisitor;
import edu.kit.kastel.vads.compiler.parser.visitor.Unit;
public class IntegerLiteralRangeAnalysis implements NoOpVisitor<Namespace<Void>> {
@Override
public Unit visit(LiteralTree literalTree, Namespace<Void> data) {
literalTree.parseValue()
.orElseThrow(
() -> new SemanticException("invalid integer literal " + literalTree.value())
);
return NoOpVisitor.super.visit(literalTree, data);
}
}

View file

@ -12,6 +12,7 @@ public class SemanticAnalysis {
}
public void analyze() {
this.program.accept(new RecursivePostorderVisitor<>(new IntegerLiteralRangeAnalysis()), new Namespace<>());
this.program.accept(new RecursivePostorderVisitor<>(new VariableStatusAnalysis()), new Namespace<>());
this.program.accept(new RecursivePostorderVisitor<>(new ReturnAnalysis()), new ReturnAnalysis.ReturnState());
}