Skip to content

Commit c386ad4

Browse files
committed
Use SourceSection/Location instead of own SourceLocation
We introduce a new `SourceLocation` interface, which allows to bridge the gap between Langkit's and Truffle's types, and use that as a basis for diagnostics. We remove the `Locatable` interface, instead storing `Nodes` directly, using the `AbstractTruffleException` interface. We get rid of `DummyLocation`, instead using nodes & abstract accessors. We also unify the interface for `DiagnosticEmitter`. As a consequence, the code for emitting diagnostics is mostly shared at this stage. Unifying the emission of rule violations is the last missing step.
1 parent c366862 commit c386ad4

File tree

157 files changed

+876
-1185
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

157 files changed

+876
-1185
lines changed

lkql_checker/src/gnatcheck-compiler.adb

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -336,18 +336,23 @@ package body Gnatcheck.Compiler is
336336
Msg (File_Idx .. Idx - 1) &
337337
Msg (Idx + 7 .. Last - 2) &
338338
Annotate_Rule (All_Rules.Table (Id).all),
339-
Diagnosis_Kind =>
340-
(if Last - Idx > 21
341-
and then Msg (Idx + 7 .. Idx + 20) = "internal error"
342-
then Internal_Error else Rule_Violation),
339+
Diagnosis_Kind => Rule_Violation,
343340
SF => SF,
344341
Rule => Id);
345342
return;
346343
end;
347344
elsif Msg (Idx .. Idx + 6) = "error: " then
348345
Message_Kind := Error;
346+
347+
if Msg'Last - Idx > 21
348+
and then Msg (Idx + 7 .. Idx + 20) = "internal error"
349+
then
350+
Kind := Internal_Error;
351+
else
352+
Kind := Compiler_Error;
353+
end if;
354+
349355
Errors := True;
350-
Kind := Compiler_Error;
351356

352357
elsif Msg (Idx .. Idx + 8) = "warning: " then
353358
if Index (Msg (Idx .. Msg'Last), ": violation of restriction") /= 0

lkql_jit/cli/src/main/java/com/adacore/lkql_jit/drivers/LKQLLauncher.java

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -226,10 +226,9 @@ protected int executeScript(Context.Builder contextBuilder) {
226226
System.err.println("File not found : " + this.args.script);
227227
return 2;
228228
} catch (Exception e) {
229+
System.err.println(e.getMessage());
229230
if (this.args.verbose) {
230231
e.printStackTrace();
231-
} else {
232-
System.err.println(e.getMessage());
233232
}
234233
return 0;
235234
}

lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
import com.adacore.lkql_jit.utils.Constants;
1818
import com.adacore.lkql_jit.utils.functions.ArrayUtils;
1919
import com.adacore.lkql_jit.utils.functions.StringUtils;
20+
import com.adacore.lkql_jit.utils.source_location.LalLocationWrapper;
2021
import com.oracle.truffle.api.CompilerDirectives;
2122
import com.oracle.truffle.api.TruffleLanguage;
2223
import com.oracle.truffle.api.source.Source;
@@ -44,6 +45,8 @@ public final class LKQLContext {
4445
/** The global values of the LKQL execution. */
4546
private final GlobalScope global;
4647

48+
public final CheckerUtils.SourceLinesCache linesCache = new CheckerUtils.SourceLinesCache();
49+
4750
// ----- Ada project attributes -----
4851

4952
/** The analysis context for the ada files. */
@@ -55,10 +58,14 @@ public final class LKQLContext {
5558
/** Event handler for the project manager. */
5659
private final Libadalang.EventHandler eventHandler =
5760
Libadalang.EventHandler.create(
58-
(ctx, name, from, found, not_found_is_error) -> {
59-
if (!found && not_found_is_error) {
61+
(ctx, name, from, found, notFoundIsError) -> {
62+
if (!found && notFoundIsError) {
6063
boolean isFatal = !this.keepGoingOnMissingFile();
61-
this.getDiagnosticEmitter().emitMissingFile(from, name, isFatal, this);
64+
this.getDiagnosticEmitter()
65+
.emitFileNotFound(
66+
new LalLocationWrapper(from.getRoot(), this.linesCache),
67+
name,
68+
notFoundIsError);
6269
if (isFatal) {
6370
this.env.getContext().closeExited(null, 1);
6471
}
@@ -508,7 +515,7 @@ public void initSources() {
508515
this.specifiedSourceFiles.add(sourceFile.getAbsolutePath());
509516
} else {
510517
this.getDiagnosticEmitter()
511-
.emitMissingFile(null, file, !this.keepGoingOnMissingFile(), this);
518+
.emitFileNotFound(null, file, this.keepGoingOnMissingFile());
512519
}
513520
}
514521
}

lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLLanguage.java

Lines changed: 21 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77

88
import com.adacore.liblkqllang.Liblkqllang;
99
import com.adacore.lkql_jit.built_ins.values.LKQLNamespace;
10+
import com.adacore.lkql_jit.checker.utils.CheckerUtils;
1011
import com.adacore.lkql_jit.exception.LKQLRuntimeException;
1112
import com.adacore.lkql_jit.langkit_translator.passes.FramingPass;
1213
import com.adacore.lkql_jit.langkit_translator.passes.TranslationPass;
@@ -17,6 +18,7 @@
1718
import com.adacore.lkql_jit.runtime.GlobalScope;
1819
import com.adacore.lkql_jit.utils.Constants;
1920
import com.adacore.lkql_jit.utils.enums.DiagnosticOutputMode;
21+
import com.adacore.lkql_jit.utils.source_location.SourceSectionWrapper;
2022
import com.oracle.truffle.api.CallTarget;
2123
import com.oracle.truffle.api.Option;
2224
import com.oracle.truffle.api.TruffleLanguage;
@@ -323,9 +325,6 @@ protected OptionDescriptors getOptionDescriptors() {
323325
return new LKQLLanguageOptionDescriptors();
324326
}
325327

326-
/**
327-
* @see com.oracle.truffle.api.TruffleLanguage#parse(ParsingRequest)
328-
*/
329328
@Override
330329
protected CallTarget parse(ParsingRequest request) {
331330
final Liblkqllang.AnalysisUnit unit;
@@ -341,9 +340,22 @@ protected CallTarget parse(ParsingRequest request) {
341340
}
342341

343342
// Verify the parsing result
344-
final Liblkqllang.Diagnostic[] diagnostics = unit.getDiagnostics();
343+
final var diagnostics = unit.getDiagnostics();
345344
if (diagnostics.length > 0) {
346-
throw LKQLRuntimeException.parsingException(diagnostics, request.getSource());
345+
var ctx = LKQLLanguage.getContext(null);
346+
347+
// Iterate over diagnostics
348+
for (Liblkqllang.Diagnostic diagnostic : diagnostics) {
349+
ctx.getDiagnosticEmitter()
350+
.emitDiagnostic(
351+
CheckerUtils.MessageKind.ERROR,
352+
diagnostic.message.toString(),
353+
null,
354+
SourceSectionWrapper.create(
355+
diagnostic.sourceLocationRange, request.getSource()));
356+
}
357+
throw LKQLRuntimeException.fromMessage(
358+
"Syntax errors in " + unit.getFileName(false) + ": stopping interpreter");
347359
}
348360

349361
// Get the LKQL langkit AST
@@ -357,7 +369,10 @@ protected CallTarget parse(ParsingRequest request) {
357369
// Print the Truffle AST if the JIT is in debug mode
358370
if (getContext(result).isVerbose()) {
359371
System.out.println(
360-
"=== Truffle AST <" + result.getLocation().getFileName() + "> :\n" + result);
372+
"=== Truffle AST <"
373+
+ result.getSourceSection().getSource().getPath()
374+
+ "> :\n"
375+
+ result);
361376
}
362377

363378
// Return the call target

lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,10 @@ public String lkqlProfile() {
191191
for (int i = 0; i < parameterNames.length; i++) {
192192
var defVal = parameterDefaultValues[i];
193193
if (defVal != null) {
194-
expandedParams.add(parameterNames[i] + "=" + defVal.getLocation().getText());
194+
expandedParams.add(
195+
parameterNames[i]
196+
+ "="
197+
+ defVal.getSourceSection().getCharacters().toString());
195198
} else {
196199
expandedParams.add(parameterNames[i]);
197200
}

lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -12,13 +12,13 @@
1212
import com.adacore.lkql_jit.utils.LKQLTypesHelper;
1313
import com.adacore.lkql_jit.utils.functions.ObjectUtils;
1414
import com.adacore.lkql_jit.utils.functions.ReflectionUtils;
15-
import com.adacore.lkql_jit.utils.source_location.Locatable;
1615
import com.oracle.truffle.api.CompilerDirectives;
1716
import com.oracle.truffle.api.dsl.Fallback;
1817
import com.oracle.truffle.api.dsl.Specialization;
1918
import com.oracle.truffle.api.interop.*;
2019
import com.oracle.truffle.api.library.ExportLibrary;
2120
import com.oracle.truffle.api.library.ExportMessage;
21+
import com.oracle.truffle.api.nodes.Node;
2222
import com.oracle.truffle.api.utilities.TriState;
2323

2424
/** This class represents a Libadalang property access in LKQL. */
@@ -73,7 +73,7 @@ public boolean isField() {
7373
* @param caller The locatable which called the execution.
7474
* @param arguments The argument for the property call.
7575
*/
76-
public Object executeAsProperty(Locatable caller, ArgList argList, Object... arguments) {
76+
public Object executeAsProperty(Node caller, ArgList argList, Object... arguments) {
7777
try {
7878
return ReflectionUtils.callProperty(
7979
this.node, this.description, caller, argList, arguments);
@@ -88,7 +88,7 @@ public Object executeAsProperty(Locatable caller, ArgList argList, Object... arg
8888
*
8989
* @param caller The locatable which called the execution.
9090
*/
91-
public Object executeAsField(Locatable caller) {
91+
public Object executeAsField(Node caller) {
9292
try {
9393
return ReflectionUtils.callProperty(this.node, this.description, caller, null);
9494
} catch (com.adacore.lkql_jit.exception.utils.UnsupportedTypeException e) {

lkql_jit/language/src/main/java/com/adacore/lkql_jit/checker/built_ins/NodeCheckerFunction.java

Lines changed: 22 additions & 46 deletions
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,8 @@
2020
import com.adacore.lkql_jit.nodes.expressions.Expr;
2121
import com.adacore.lkql_jit.utils.LKQLTypesHelper;
2222
import com.adacore.lkql_jit.utils.functions.StringUtils;
23+
import com.adacore.lkql_jit.utils.source_location.LalLocationWrapper;
24+
import com.adacore.lkql_jit.utils.source_location.SourceSectionWrapper;
2325
import com.oracle.truffle.api.CompilerDirectives;
2426
import com.oracle.truffle.api.frame.VirtualFrame;
2527
import com.oracle.truffle.api.interop.ArityException;
@@ -86,9 +88,6 @@ public Object executeGeneric(VirtualFrame frame) {
8688
this.callNode.getArgList().getArgs()[0]);
8789
}
8890

89-
// Initialize the cache that will contain decoded source lines of all needed units
90-
CheckerUtils.SourceLinesCache linesCache = new CheckerUtils.SourceLinesCache();
91-
9291
// Traverse the tree
9392
// Create the list of node to explore with the generic instantiation info
9493
final LinkedList<VisitStep> visitList = new LinkedList<>();
@@ -130,21 +129,14 @@ public Object executeGeneric(VirtualFrame frame) {
130129
}
131130

132131
// Apply the "both" checkers
133-
this.executeCheckers(
134-
frame, currentStep, currentNode, allNodeCheckers, context, linesCache);
132+
this.executeCheckers(frame, currentStep, currentNode, allNodeCheckers, context);
135133

136134
// If we're in Ada code execute the Ada checkers else execute the SPARK checkers
137135
if (inSparkCode) {
138136
this.executeCheckers(
139-
frame,
140-
currentStep,
141-
currentNode,
142-
sparkNodeCheckers,
143-
context,
144-
linesCache);
137+
frame, currentStep, currentNode, sparkNodeCheckers, context);
145138
} else {
146-
this.executeCheckers(
147-
frame, currentStep, currentNode, adaNodeCheckers, context, linesCache);
139+
this.executeCheckers(frame, currentStep, currentNode, adaNodeCheckers, context);
148140
}
149141

150142
// Add the children to the visit list
@@ -181,46 +173,38 @@ public Object executeGeneric(VirtualFrame frame) {
181173
* @param currentNode The node to execute the checkers on.
182174
* @param checkers The checekrs to execute.
183175
* @param context The LKQL context.
184-
* @param linesCache The cache for Ada lines.
185176
*/
186177
private void executeCheckers(
187178
VirtualFrame frame,
188179
VisitStep currentStep,
189180
Libadalang.AdaNode currentNode,
190181
NodeChecker[] checkers,
191-
LKQLContext context,
192-
CheckerUtils.SourceLinesCache linesCache) {
182+
LKQLContext context) {
193183
// For each checker apply it on the current node if needed
194184
for (NodeChecker checker : checkers) {
195185
if (!currentStep.inGenericInstantiation()
196186
|| checker.isFollowGenericInstantiations()) {
197187
try {
198-
this.applyNodeRule(frame, checker, currentNode, context, linesCache);
188+
this.applyNodeRule(frame, checker, currentNode, context);
199189
} catch (LangkitException e) {
200-
// TODO: Remove those clunky hardcoded names when getting rid of Ada
201-
// implementation
202190
// Report LAL exception only in debug mode
203191
if (context.isCheckerDebug()) {
204192
context.getDiagnosticEmitter()
205-
.emitInternalError(
206-
checker.getName(),
207-
currentNode.getUnit(),
208-
currentNode.getSourceLocationRange().start,
209-
e.getLoc().toString(),
193+
.emitDiagnostic(
194+
CheckerUtils.MessageKind.ERROR,
210195
e.getMsg(),
211-
context);
196+
new LalLocationWrapper(currentNode, context.linesCache),
197+
new SourceSectionWrapper(e.getLoc()),
198+
checker.getName());
212199
}
213200
} catch (LKQLRuntimeException e) {
214-
// TODO: Remove those clunky hardcoded names when getting rid of Ada
215-
// implementation
216201
context.getDiagnosticEmitter()
217-
.emitInternalError(
218-
checker.getName(),
219-
currentNode.getUnit(),
220-
currentNode.getSourceLocationRange().start,
221-
e.getLocationString(),
222-
e.getRawMessage(),
223-
context);
202+
.emitDiagnostic(
203+
CheckerUtils.MessageKind.ERROR,
204+
e.getErrorMessage(),
205+
new LalLocationWrapper(currentNode, context.linesCache),
206+
e.getSourceLoc(),
207+
checker.getName());
224208
}
225209
}
226210
}
@@ -233,14 +217,12 @@ private void executeCheckers(
233217
* @param checker The checker to apply.
234218
* @param node The node to apply the checker on.
235219
* @param context The LKQL context.
236-
* @param linesCache The cache of all units' source text lines.
237220
*/
238221
private void applyNodeRule(
239222
VirtualFrame frame,
240223
NodeChecker checker,
241224
Libadalang.AdaNode node,
242-
LKQLContext context,
243-
CheckerUtils.SourceLinesCache linesCache) {
225+
LKQLContext context) {
244226
// Get the function for the checker
245227
LKQLFunction functionValue = checker.getFunction();
246228
String aliasName = checker.getAlias();
@@ -283,7 +265,7 @@ private void applyNodeRule(
283265
}
284266

285267
if (ruleResult) {
286-
reportViolation(context, checker, node, linesCache);
268+
reportViolation(context, checker, node);
287269
}
288270
}
289271

@@ -293,14 +275,10 @@ private void applyNodeRule(
293275
* @param context The context to output the message.
294276
* @param checker The checker corresponding to the violated rule.
295277
* @param node The node that violated the checker.
296-
* @param linesCache The cache of all units' source text lines.
297278
*/
298279
@CompilerDirectives.TruffleBoundary
299280
private static void reportViolation(
300-
LKQLContext context,
301-
NodeChecker checker,
302-
Libadalang.AdaNode node,
303-
CheckerUtils.SourceLinesCache linesCache) {
281+
LKQLContext context, NodeChecker checker, Libadalang.AdaNode node) {
304282
if (node instanceof Libadalang.BasicDecl basicDecl) {
305283
Libadalang.AdaNode definingName = basicDecl.pDefiningName();
306284
node = definingName.isNone() ? node : definingName;
@@ -309,10 +287,8 @@ private static void reportViolation(
309287
.emitRuleViolation(
310288
checker.getName(),
311289
checker.getMessage(),
312-
node.getSourceLocationRange(),
313-
node.getUnit(),
290+
new LalLocationWrapper(node, context.linesCache),
314291
node.pGenericInstantiations(),
315-
linesCache,
316292
context);
317293
}
318294

0 commit comments

Comments
 (0)