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

View file

@ -171,30 +171,12 @@ public class Parser {
} }
case NumberLiteral(String value, int base, Span span) -> { case NumberLiteral(String value, int base, Span span) -> {
this.tokenSource.consume(); 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); 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) { private static NameTree name(Identifier ident) {
return new NameTree(Name.forIdentifier(ident), ident.span()); return new NameTree(Name.forIdentifier(ident), ident.span());
} }

View file

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

View file

@ -1,11 +1,34 @@
package edu.kit.kastel.vads.compiler.parser.ast; package edu.kit.kastel.vads.compiler.parser.ast;
import edu.kit.kastel.vads.compiler.Span; 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.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 @Override
public <T, R> R accept(Visitor<T, R> visitor, T data) { public <T, R> R accept(Visitor<T, R> visitor, T data) {
return visitor.visit(this, 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() { 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 VariableStatusAnalysis()), new Namespace<>());
this.program.accept(new RecursivePostorderVisitor<>(new ReturnAnalysis()), new ReturnAnalysis.ReturnState()); this.program.accept(new RecursivePostorderVisitor<>(new ReturnAnalysis()), new ReturnAnalysis.ReturnState());
} }