diff --git a/lkql_jit/.idea/codeStyles/Project.xml b/lkql_jit/.idea/codeStyles/Project.xml
index 5db2678ad..fe31047ed 100644
--- a/lkql_jit/.idea/codeStyles/Project.xml
+++ b/lkql_jit/.idea/codeStyles/Project.xml
@@ -5,6 +5,7 @@
+
diff --git a/lkql_jit/builtins_annotations/pom.xml b/lkql_jit/builtins_annotations/pom.xml
new file mode 100644
index 000000000..c4b088a3b
--- /dev/null
+++ b/lkql_jit/builtins_annotations/pom.xml
@@ -0,0 +1,55 @@
+
+
+ 4.0.0
+
+
+ lkql_jit
+ com.adacore
+ 0.1.0
+
+
+ builtins_annotations
+ 0.1.0
+
+
+
+ org.graalvm.truffle
+ truffle-api
+ ${graalvm.version}
+
+
+ org.graalvm.truffle
+ truffle-dsl-processor
+ ${graalvm.version}
+ provided
+
+
+
+
+
+
+
+ com.diffplug.spotless
+ spotless-maven-plugin
+ 2.40.0
+
+ true
+
+
+
+
+ maven-compiler-plugin
+
+
+ --add-exports
+ org.graalvm.truffle/com.oracle.truffle.api.dsl=ALL-UNNAMED
+ -proc:none
+
+
+
+
+
+
+
diff --git a/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInFunction.java b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInFunction.java
new file mode 100644
index 000000000..09b3702c0
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInFunction.java
@@ -0,0 +1,23 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Annotation to add a new built-in function to LKQL. Those annotations are automatically processed
+ * by the BuiltInProcessor Java processor.
+ */
+@Target(ElementType.TYPE)
+public @interface BuiltInFunction {
+
+ /** Name for this built-in function */
+ String name();
+
+ /** Documentation for this built-in function */
+ String doc();
+}
diff --git a/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInMethod.java b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInMethod.java
new file mode 100644
index 000000000..e08d1b329
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInMethod.java
@@ -0,0 +1,34 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.annotations;
+
+import java.lang.annotation.*;
+
+/**
+ * Annotation to add a new built-in method to LKQL. Those annotations are automatically processed by
+ * the BuiltInProcessor Java processor.
+ */
+@Target(ElementType.TYPE)
+public @interface BuiltInMethod {
+
+ /** Name for this built-in method. */
+ String name() default "";
+
+ /** Documentation for this built-in method. */
+ String doc() default "";
+
+ /**
+ * Types that this method should be added onto. Note that if the final computed set is empty,
+ * method will be added on all types.
+ */
+ String[] targetTypes() default {};
+
+ /**
+ * Whether method is a property. A property is a built-in method that doesn't need any
+ * arguments, and that doesn't take parens when you call it.
+ */
+ boolean isProperty() default false;
+}
diff --git a/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInProcessor.java b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInProcessor.java
new file mode 100644
index 000000000..ba13b0e43
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltInProcessor.java
@@ -0,0 +1,441 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.annotations;
+
+import java.io.IOException;
+import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.util.*;
+import java.util.stream.Collectors;
+import javax.annotation.processing.*;
+import javax.lang.model.SourceVersion;
+import javax.lang.model.element.*;
+import javax.lang.model.type.TypeMirror;
+import org.graalvm.collections.Pair;
+
+/**
+ * This built-in processor will process every BuiltIn annotation, and create built-in objects, as
+ * well as a global factory, that will be used to add built-ins to the LKQL language.
+ *
+ *
This makes it very simple to add built-ins to the language (see usages of
+ * BuiltInFunction/BuiltInMethod for examples), and works with native image since it doesn't use
+ * reflection.
+ *
+ *
The signature of the built-in function is infered from the parameters of the first
+ * specialization of the built-in.
+ */
+@SupportedAnnotationTypes({
+ "com.adacore.lkql_jit.annotations.BuiltInFunction",
+ "com.adacore.lkql_jit.annotations.BuiltInMethod"
+})
+@SupportedSourceVersion(SourceVersion.RELEASE_17)
+public class BuiltInProcessor extends AbstractProcessor {
+
+ /** Suffix for generated built-in classes. */
+ final String SUFFIX = "BuiltIns";
+
+ /**
+ * Set of already processed classes containing built-in declarations. Used as a guard in
+ * processBuiltInFactory
+ */
+ final Set processedFactories = new HashSet<>();
+
+ /**
+ * Set of generated built-in packages. Each element is a pair . Each
+ * package contains a namespace class which contains two static methods.
+ */
+ final HashSet> builtInPackages = new HashSet<>();
+
+ /** Whether built-ins have been processed already. Global guard. */
+ boolean processed = false;
+
+ @Override
+ public boolean process(Set extends TypeElement> annotations, RoundEnvironment roundEnv) {
+ if (processed) {
+ return true;
+ }
+
+ processed = true;
+
+ for (var annotation : annotations) {
+
+ // Grab all elements annotated with BuiltInFunction/Method
+ Set extends Element> annotatedElements =
+ roundEnv.getElementsAnnotatedWith(annotation);
+
+ for (var element : annotatedElements) {
+
+ // Grab the enclosing class, which is the factory class. Note that since a lot of
+ // those classes contain several built-ins, this means that we will call
+ // processBuiltInFactory several time per factory
+ var factoryBase = element.getEnclosingElement();
+ try {
+ processBuiltInFactory((TypeElement) factoryBase);
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ try (final var stream =
+ new PrintStream(
+ processingEnv
+ .getFiler()
+ .createSourceFile("com.adacore.lkql_jit.built_ins.AllBuiltIns")
+ .openOutputStream(),
+ true,
+ StandardCharsets.UTF_8)) {
+ // Package
+ stream.println("package com.adacore.lkql_jit.built_ins;");
+
+ // Imports
+ stream.println("import java.util.stream.Stream;");
+ stream.println("import java.util.stream.Collectors;");
+ stream.println("import java.util.Arrays;");
+ stream.println("import java.util.Map;");
+ stream.println("import java.util.List;");
+ stream.println("import java.util.HashMap;");
+ stream.println("import com.adacore.lkql_jit.utils.LKQLTypesHelper;");
+ stream.println("import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;");
+ stream.println("import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;");
+
+ for (var p : builtInPackages) {
+ stream.println("import " + p.getLeft() + "." + p.getRight() + ";");
+ }
+ stream.println("public class AllBuiltIns {");
+
+ stream.println(
+ " static private List allFunctionsCache = null;");
+ stream.println(
+ " static private Map>"
+ + " allMethodsCache = null;");
+
+ // allFunctions method
+ stream.println(" public static List allFunctions() {");
+ stream.println(" if (allFunctionsCache != null) {");
+ stream.println(" return allFunctionsCache;");
+ stream.println(" }");
+ stream.println(" allFunctionsCache = Stream.of(");
+ stream.println(
+ builtInPackages.stream()
+ .map(
+ p ->
+ " Arrays.stream("
+ + p.getRight()
+ + ".getFunctions())")
+ .collect(Collectors.joining(",\n"))
+ + ")");
+ stream.println(" .reduce(Stream::concat).orElseGet(Stream::empty)");
+ stream.println(" .collect(Collectors.toList());");
+ stream.println(" return allFunctionsCache;");
+ stream.println(" }");
+
+ // allMethods method
+ stream.println(
+ " public static Map>"
+ + " allMethods() {");
+ stream.println(" if (allMethodsCache != null) {");
+ stream.println(" return allMethodsCache;");
+ stream.println(" }");
+ stream.println(
+ " allMethodsCache = new HashMap>();");
+ for (var p : builtInPackages) {
+ stream.println(" for (var pair : " + p.getRight() + ".getMethods()) {");
+ stream.println(
+ " var keys = pair.getLeft().length == 0 ?"
+ + " LKQLTypesHelper.ALL_TYPES : pair.getLeft();");
+ stream.println(" for (var key : keys) {");
+ stream.println(
+ " var typeMap = allMethodsCache.computeIfAbsent(key, t ->"
+ + " new HashMap<>());");
+ stream.println(
+ " typeMap.put(pair.getRight().name, pair.getRight());");
+ stream.println(" }");
+ stream.println(" }");
+ }
+ stream.println(" return allMethodsCache;");
+ stream.println(" }");
+
+ stream.println("}");
+ } catch (IOException e) {
+ throw new RuntimeException(e);
+ }
+
+ return true;
+ }
+
+ private void log(String toLog) {
+ System.out.println(toLog);
+ }
+
+ private TypeMirror virtualFrameType() {
+ return processingEnv
+ .getElementUtils()
+ .getTypeElement("com.oracle.truffle.api.frame.VirtualFrame")
+ .asType();
+ }
+
+ /**
+ * Return the code string to build the built-in arguments for given built-in. The string
+ * contains two function parameters, the names and the default values, joined by a ", ".
+ */
+ private String builtInArguments(TypeElement builtIn, boolean omitSelfParam) {
+
+ var names = new ArrayList();
+ var defaultVals = new ArrayList();
+
+ for (var el : builtIn.getEnclosedElements()) {
+
+ if (!(el instanceof ExecutableElement method)) {
+ continue;
+ }
+
+ if ((method.getAnnotationMirrors().stream()
+ .noneMatch(
+ e ->
+ e.getAnnotationType()
+ .asElement()
+ .getSimpleName()
+ .toString()
+ .contains("Specialization")))) {
+ continue;
+ }
+
+ var params =
+ method.getParameters().stream()
+ .filter(
+ p -> {
+ return !processingEnv
+ .getTypeUtils()
+ .isSameType(p.asType(), virtualFrameType())
+ // If there is an annotation, it can only be the
+ // "DefaultVal" annotation. Skip other parameters
+ // with annotations.
+ && p.getAnnotationMirrors().stream()
+ .allMatch(
+ a ->
+ Objects.equals(
+ a.getAnnotationType()
+ .asElement()
+ .getSimpleName()
+ .toString(),
+ "DefaultVal"));
+ })
+ .skip(omitSelfParam ? 1 : 0)
+ .toList();
+
+ for (var p : params) {
+ var defaultValAnnot = p.getAnnotation(DefaultVal.class);
+ var defaultVal = (defaultValAnnot != null ? defaultValAnnot.value() : null);
+ var name = p.getSimpleName().toString();
+ var nameSB = new StringBuilder();
+
+ // Adapt parameter names from Java style (aParamName) to LKQL style (a_param_name)
+ name.chars()
+ .mapToObj(c -> Character.valueOf((char) c))
+ .forEach(
+ c -> {
+ if (Character.isUpperCase(c)) {
+ nameSB.append("_").append(Character.toLowerCase(c));
+ } else {
+ nameSB.append(c);
+ }
+ });
+
+ names.add("\"" + nameSB + "\"");
+ defaultVals.add(defaultVal != null ? "\"" + defaultVal + "\"" : "null");
+ }
+
+ return "new String[] {"
+ + String.join(", ", names)
+ + "}, new String[] {"
+ + String.join(", ", defaultVals)
+ + "}";
+ }
+
+ throw new RuntimeException("Couldn't compute profile for " + builtIn.toString());
+ }
+
+ /**
+ * Process one built-in factory class. This will emit one "BuiltIns.java" per
+ * factory. This file contains a class that always has the same structure:
+ */
+ private void processBuiltInFactory(TypeElement builtInFactoryClass) throws IOException {
+ // This function is called once per built-in contained by the factory, so potentially
+ // several times per built-in. For this reason we keep track of already processed factories
+ // and bail out if it has already been processed.
+ if (processedFactories.contains(builtInFactoryClass)) {
+ return;
+ }
+ processedFactories.add(builtInFactoryClass);
+
+ // Create output source file
+ final var output =
+ processingEnv
+ .getFiler()
+ .createSourceFile(
+ builtInFactoryClass.getQualifiedName() + SUFFIX,
+ builtInFactoryClass);
+
+ final var packageElement = (PackageElement) builtInFactoryClass.getEnclosingElement();
+ final var packageName = packageElement.getQualifiedName().toString();
+ final var className = builtInFactoryClass.getSimpleName() + SUFFIX;
+
+ // Collect built-in functions and methods contained in the factory.
+ var builtInFunctions =
+ builtInFactoryClass.getEnclosedElements().stream()
+ .filter(e -> e.getAnnotation(BuiltInFunction.class) != null)
+ .map(e -> (TypeElement) e)
+ .toList();
+
+ var builtInMethods =
+ builtInFactoryClass.getEnclosedElements().stream()
+ .filter(e -> e.getAnnotation(BuiltInMethod.class) != null)
+ .map(e -> (TypeElement) e)
+ .toList();
+
+ // Emit the output source file. The file will contain one package class with two static
+ // functions, one which returns the built-in functions, one which returns the built-in
+ // methods.
+ try (final var stream =
+ new PrintStream(output.openOutputStream(), true, StandardCharsets.UTF_8)) {
+ stream.println("package " + packageName + ";");
+ stream.println();
+
+ // Emit imports
+ stream.println("import java.util.List;");
+ stream.println("import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;");
+ stream.println("import com.adacore.lkql_jit.built_ins.BuiltInBody;");
+ stream.println("import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;");
+ stream.println("import org.graalvm.collections.Pair;");
+ stream.println("public class " + className + " { ");
+
+ // Built-in functions computation
+ stream.println(" public static BuiltInFunctionValue[] getFunctions() {");
+ stream.println(" return new BuiltInFunctionValue[] {");
+ stream.println(
+ builtInFunctions.stream()
+ .map(
+ builtInFn -> {
+ var fnAnnot =
+ builtInFn.getAnnotation(BuiltInFunction.class);
+
+ return " new BuiltInFunctionValue(\""
+ + fnAnnot.name()
+ + "\", \""
+ + fnAnnot.doc()
+ + "\", "
+ + builtInArguments(builtInFn, false)
+ + ", BuiltInBody.create("
+ + builtInFactoryClass.getSimpleName().toString()
+ + "Factory."
+ + builtInFn.getSimpleName().toString()
+ + "Factory.getInstance()"
+ + "))";
+ })
+ .collect(Collectors.joining(",\n")));
+ stream.println(" };");
+ stream.println(" }");
+
+ // Built-in methods computation
+ stream.println(
+ " public static List> getMethods() {");
+ stream.println(" return List.of(");
+ stream.println(
+ builtInMethods.stream()
+ .map(
+ builtInMethod -> {
+ var methodAnnotation =
+ builtInMethod.getAnnotation(BuiltInMethod.class);
+ var fnAnnotation =
+ builtInMethod.getAnnotation(BuiltInFunction.class);
+
+ var name = methodAnnotation.name();
+ var doc = methodAnnotation.doc();
+ var isProperty = methodAnnotation.isProperty();
+
+ if (fnAnnotation != null) {
+ if (name.equals("")) {
+ // If the method annotation has no name and there is
+ // a function annotation, take its name
+ name = fnAnnotation.name();
+ }
+
+ if (doc.equals("")) {
+ // If the method annotation has no doc and there is
+ // a function annotation, take its name
+ doc = fnAnnotation.doc();
+ }
+ }
+
+ var targetTypes = methodAnnotation.targetTypes();
+
+ // If there are no explicit targetTypes on the method
+ // annotation, try to get them from the
+ // @BuiltinMethodContainer annotation on the
+ // enclosing class.
+ if (targetTypes.length == 0) {
+ var containerAnnot =
+ builtInMethod
+ .getEnclosingElement()
+ .getAnnotation(
+ BuiltinMethodContainer.class);
+
+ if (containerAnnot != null) {
+ targetTypes = containerAnnot.targetTypes();
+ }
+ }
+
+ // If we still don't have explicit target types, then it
+ // means that the method is a method on all types.
+ if (targetTypes.length == 0) {
+ targetTypes = new String[] {};
+ }
+
+ var wrapper =
+ "BuiltInMethodFactory."
+ + (isProperty
+ ? "createAttribute"
+ : "createMethod")
+ + "(\""
+ + name
+ + "\", \""
+ + doc
+ + "\""
+ + (isProperty
+ ? ""
+ : ", "
+ + builtInArguments(
+ builtInMethod,
+ true))
+ + ", BuiltInBody.create("
+ + builtInFactoryClass
+ .getSimpleName()
+ .toString()
+ + "Factory."
+ + builtInMethod.getSimpleName().toString()
+ + "Factory.getInstance()"
+ + "))";
+
+ return " Pair.create(new String[] {"
+ + Arrays.stream(targetTypes)
+ .map(t -> "\"" + t + "\"")
+ .collect(Collectors.joining(", "))
+ + " },"
+ + wrapper
+ + ")";
+ })
+ .collect(Collectors.joining(",\n")));
+
+ stream.println(" );");
+ stream.println(" }");
+ stream.println("}");
+ }
+
+ builtInPackages.add(Pair.create(packageName, className));
+ }
+}
diff --git a/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltinMethodContainer.java b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltinMethodContainer.java
new file mode 100644
index 000000000..d7e5c3ed6
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/BuiltinMethodContainer.java
@@ -0,0 +1,19 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+/**
+ * Marks a class as a container for built-in method declarations. This allows declaring the target
+ * types for all contained methods only once.
+ */
+@Target(ElementType.TYPE)
+public @interface BuiltinMethodContainer {
+ /** Target types for all built-in methods contained by this BuiltInMethodContainer. */
+ String[] targetTypes();
+}
diff --git a/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/DefaultVal.java b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/DefaultVal.java
new file mode 100644
index 000000000..76e1ee44b
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/java/com/adacore/lkql_jit/annotations/DefaultVal.java
@@ -0,0 +1,14 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.annotations;
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Target;
+
+@Target(ElementType.PARAMETER)
+public @interface DefaultVal {
+ String value();
+}
diff --git a/lkql_jit/builtins_annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor b/lkql_jit/builtins_annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor
new file mode 100644
index 000000000..5df5a40db
--- /dev/null
+++ b/lkql_jit/builtins_annotations/src/main/resources/META-INF/services/javax.annotation.processing.Processor
@@ -0,0 +1 @@
+com.adacore.lkql_jit.annotations.BuiltInProcessor
diff --git a/lkql_jit/language/pom.xml b/lkql_jit/language/pom.xml
index ee17ded34..33d60767f 100644
--- a/lkql_jit/language/pom.xml
+++ b/lkql_jit/language/pom.xml
@@ -73,6 +73,27 @@
true
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+
+
+
+
+ com.adacore
+ builtins_annotations
+ 0.1.0
+
+
+ org.graalvm.truffle
+ truffle-dsl-processor
+ ${graalvm.version}
+
+
+
+
+
@@ -103,6 +124,12 @@
0.1.0
+
+ com.adacore
+ builtins_annotations
+ 0.1.0
+
+
com.adacoreliblkqllang
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java
index 0758a6a57..540dde7b8 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLContext.java
@@ -7,7 +7,6 @@
import com.adacore.libadalang.Libadalang;
import com.adacore.liblkqllang.Liblkqllang;
-import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;
import com.adacore.lkql_jit.checker.BaseChecker;
import com.adacore.lkql_jit.checker.NodeChecker;
import com.adacore.lkql_jit.checker.UnitChecker;
@@ -372,18 +371,6 @@ private void invalidateOptionCaches() {
this.emitter = null;
}
- // ----- Value related methods -----
-
- /**
- * Get the meta table for the given type.
- *
- * @param type The type to get the meta table for.
- * @return The meta table for the type.
- */
- public Map getMetaTable(String type) {
- return this.global.getMetaTable(type);
- }
-
// ----- IO methods -----
/**
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLLanguage.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLLanguage.java
index 297b176f0..de3794ec5 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLLanguage.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLLanguage.java
@@ -135,6 +135,7 @@ public static LKQLLanguage getLanguage(LKQLNode node) {
*/
@Override
protected LKQLContext createContext(Env env) {
+
// Create the global values
GlobalScope globalValues = new GlobalScope();
@@ -231,6 +232,13 @@ protected CallTarget parse(ParsingRequest request) {
return new TopLevelRootNode(request.getSource().isInternal(), result, this).getCallTarget();
}
+ /** Translate the given source from string. */
+ public LKQLNode translate(String source, String sourceName) {
+ Source src = Source.newBuilder(Constants.LKQL_ID, source, sourceName).build();
+ var root = lkqlAnalysisContext.getUnitFromBuffer(source, sourceName).getRoot();
+ return translate(root, src, false);
+ }
+
/**
* Translate the given source Langkit AST.
*
@@ -275,6 +283,7 @@ public LKQLNode translate(
// Do the translation pass and return the result
final TranslationPass translationPass = new TranslationPass(source, scriptFrames);
+
return lkqlLangkitRoot.accept(translationPass);
}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/AbstractBuiltInFunctionBody.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/AbstractBuiltInFunctionBody.java
deleted file mode 100644
index 4ac9737b8..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/AbstractBuiltInFunctionBody.java
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins;
-
-import com.adacore.lkql_jit.nodes.LKQLNode;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/** This node represents a base for all built-in functions body. */
-public abstract class AbstractBuiltInFunctionBody extends Expr {
-
- // ----- Attributes -----
-
- /** The node that called the expression. */
- protected FunCall callNode;
-
- // ----- Constructors -----
-
- /** Create a new expression for a built-in function. */
- protected AbstractBuiltInFunctionBody() {
- super(null);
- }
-
- // ----- Getters -----
-
- public FunCall getCallNode() {
- return callNode;
- }
-
- // ----- Setters -----
-
- public void setCallNode(FunCall callNode) {
- this.callNode = callNode;
- }
-
- // ----- Instance methods -----
-
- public LKQLNode argNode(int index) {
- return this.callNode.getArgList().getArgs()[index];
- }
-
- // ----- Class methods -----
-
- /** Create a new built-in function body from the given callback representing its execution. */
- public static AbstractBuiltInFunctionBody fromCallback(BuiltInCallback callback) {
- return new AbstractBuiltInFunctionBody() {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- return callback.apply(frame, this.callNode);
- }
- };
- }
-
- // ----- Override methods -----
-
- /**
- * @see com.adacore.lkql_jit.nodes.LKQLNode#toString(int)
- */
- @Override
- public String toString(int indentLevel) {
- return "BUILT_IN NODE";
- }
-
- // ----- Inner classes -----
-
- /** Function interface for lambda constructor to {@link BuiltInFunctionValue}. */
- public interface BuiltInCallback {
- public Object apply(VirtualFrame frame, FunCall call);
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInBody.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInBody.java
new file mode 100644
index 000000000..f434d3169
--- /dev/null
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInBody.java
@@ -0,0 +1,78 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.built_ins;
+
+import com.adacore.lkql_jit.nodes.LKQLNode;
+import com.adacore.lkql_jit.nodes.expressions.Expr;
+import com.adacore.lkql_jit.nodes.expressions.FunCall;
+import com.adacore.lkql_jit.nodes.expressions.value_read.ReadArgument;
+import com.oracle.truffle.api.dsl.*;
+
+/** This node represents a base for all built-in functions body. */
+@NodeChild(value = "argumentNodes", type = LKQLNode[].class)
+@GenerateNodeFactory
+public abstract class BuiltInBody extends Expr {
+ /** The node that called the expression. */
+ protected FunCall callNode;
+
+ // ----- Constructors -----
+
+ /** Create a new expression for a built-in function. */
+ protected BuiltInBody() {
+ super(null);
+ }
+
+ // ----- Getters -----
+
+ public FunCall getCallNode() {
+ return callNode;
+ }
+
+ // ----- Setters -----
+
+ public void setCallNode(FunCall callNode) {
+ this.callNode = callNode;
+ }
+
+ // ----- Instance methods -----
+
+ public LKQLNode argNode(int index) {
+ return this.callNode.getArgList().getArgs()[index];
+ }
+
+ // ----- Override methods -----
+
+ /**
+ * @see com.adacore.lkql_jit.nodes.LKQLNode#toString(int)
+ */
+ @Override
+ public String toString(int indentLevel) {
+ return "BUILT_IN NODE";
+ }
+
+ // ----- Inner classes -----
+
+ /** Create a BuiltInBody instance from a node factory. */
+ public static BuiltInBody create(NodeFactory extends BuiltInBody> factory) {
+
+ // The builtin node factory is a class that is automatically generated by the Truffle DSL.
+ // The signature returned by the factory reflects the signature of the @Specialization
+ // methods in the builtin classes.
+
+ int argumentCount = factory.getExecutionSignature().size();
+ LKQLNode[] argumentNodes = new LKQLNode[argumentCount];
+
+ // Builtin functions are like normal functions, i.e., the arguments are
+ // passed in as an LKQLNode[] array. A ReadArgument extracts a parameter
+ // from this array.
+
+ for (int i = 0; i < argumentCount; i++) {
+ argumentNodes[i] = new ReadArgument(null, i);
+ }
+ // Instantiate the builtin node. This node performs the actual functionality.
+ return factory.createNode((Object) argumentNodes);
+ }
+}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java
index b99e657e3..d81092c22 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java
@@ -5,55 +5,40 @@
package com.adacore.lkql_jit.built_ins;
+import com.adacore.lkql_jit.LKQLLanguage;
+import com.adacore.lkql_jit.nodes.TopLevelList;
import com.adacore.lkql_jit.nodes.expressions.Expr;
import com.adacore.lkql_jit.nodes.expressions.FunCall;
import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode;
import com.adacore.lkql_jit.runtime.Closure;
import com.adacore.lkql_jit.runtime.values.LKQLFunction;
+import com.oracle.truffle.api.CompilerDirectives;
/** This class represents the LKQL value of a built-in function. */
public class BuiltInFunctionValue extends LKQLFunction {
+ public String[] stringDefaultVals;
+
+ private boolean defaultValsEvald = false;
+
// ----- Constructor -----
- /**
- * Create a built-in function value.
- *
- * @param name The name of the built-in.
- * @param documentation The documentation of the built-in.
- * @param names The names of the built-in parameters.
- * @param defaultValues The default values of the parameters.
- * @param body The expression representing the built-in body.
- */
+ /** Create a built-in function value. */
public BuiltInFunctionValue(
String name,
String documentation,
String[] names,
- Expr[] defaultValues,
- AbstractBuiltInFunctionBody body) {
+ String[] defaultValues,
+ BuiltInBody body) {
super(
new FunctionRootNode(null, null, false, body),
Closure.EMPTY,
name,
documentation,
names,
- defaultValues);
- }
+ new Expr[names.length]);
- public BuiltInFunctionValue(
- String name,
- String documentation,
- String[] names,
- Expr[] defaultValues,
- AbstractBuiltInFunctionBody.BuiltInCallback fn) {
- super(
- new FunctionRootNode(
- null, null, false, AbstractBuiltInFunctionBody.fromCallback(fn)),
- Closure.EMPTY,
- name,
- documentation,
- names,
- defaultValues);
+ stringDefaultVals = defaultValues;
}
// ----- Instance methods -----
@@ -64,6 +49,29 @@ public BuiltInFunctionValue(
* @param callNode The node which called the built-in.
*/
public void setCallNode(FunCall callNode) {
- ((AbstractBuiltInFunctionBody) this.getBody()).setCallNode(callNode);
+ ((BuiltInBody) this.getBody()).setCallNode(callNode);
+ }
+
+ @Override
+ public Expr[] getParameterDefaultValues() {
+ if (stringDefaultVals != null && !defaultValsEvald) {
+ for (int i = 0; i < parameterDefaultValues.length; i++) {
+ if (stringDefaultVals[i] != null) {
+ parameterDefaultValues[i] = getDefaultValAt(i);
+ }
+ }
+ defaultValsEvald = true;
+ }
+ return parameterDefaultValues;
+ }
+
+ @CompilerDirectives.TruffleBoundary
+ private Expr getDefaultValAt(int i) {
+ var prg =
+ ((TopLevelList)
+ LKQLLanguage.getLanguage(rootNode.getBody())
+ .translate(stringDefaultVals[i], ""))
+ .program;
+ return (Expr) prg[0];
}
}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctions.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctions.java
new file mode 100644
index 000000000..b40138ca8
--- /dev/null
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctions.java
@@ -0,0 +1,445 @@
+//
+// Copyright (C) 2005-2024, AdaCore
+// SPDX-License-Identifier: GPL-3.0-or-later
+//
+
+package com.adacore.lkql_jit.built_ins;
+
+import com.adacore.lkql_jit.LKQLLanguage;
+import com.adacore.lkql_jit.LKQLTypeSystemGen;
+import com.adacore.lkql_jit.annotations.*;
+import com.adacore.lkql_jit.exception.LKQLRuntimeException;
+import com.adacore.lkql_jit.runtime.values.*;
+import com.adacore.lkql_jit.runtime.values.bases.BasicLKQLValue;
+import com.adacore.lkql_jit.runtime.values.interfaces.Indexable;
+import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
+import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue;
+import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
+import com.adacore.lkql_jit.utils.Constants;
+import com.adacore.lkql_jit.utils.Iterator;
+import com.adacore.lkql_jit.utils.LKQLTypesHelper;
+import com.adacore.lkql_jit.utils.TextWriter;
+import com.adacore.lkql_jit.utils.functions.ArrayUtils;
+import com.adacore.lkql_jit.utils.functions.FileUtils;
+import com.adacore.lkql_jit.utils.functions.StringUtils;
+import com.oracle.truffle.api.CompilerDirectives;
+import com.oracle.truffle.api.dsl.Cached;
+import com.oracle.truffle.api.dsl.Specialization;
+import com.oracle.truffle.api.interop.ArityException;
+import com.oracle.truffle.api.interop.InteropLibrary;
+import com.oracle.truffle.api.interop.UnsupportedMessageException;
+import com.oracle.truffle.api.interop.UnsupportedTypeException;
+import com.oracle.truffle.api.library.CachedLibrary;
+import java.io.StringWriter;
+import java.util.Arrays;
+import java.util.Comparator;
+import java.util.Map;
+
+/**
+ * Module where most of the LKQL built-in functions are declared. General purpose built-in functions
+ * are declared here.
+ */
+public class BuiltInFunctions {
+
+ @BuiltInFunction(
+ name = "unique",
+ doc = "Given a collection, create a list with all duplicates removed")
+ @BuiltInMethod(targetTypes = LKQLTypesHelper.LKQL_LIST, isProperty = true)
+ abstract static class UniqueExpr extends BuiltInBody {
+ @Specialization
+ protected LKQLList onIndexable(Indexable indexable) {
+ return new LKQLList(ArrayUtils.unique(indexable.getContent()).toArray(new Object[0]));
+ }
+ }
+
+ @BuiltInFunction(
+ name = "pattern",
+ doc = "Given a regex pattern string, create a pattern object")
+ abstract static class PatternExpr extends BuiltInBody {
+ @Specialization
+ protected LKQLPattern onValidArgs(String regex, @DefaultVal("true") boolean caseSensitive) {
+ return new LKQLPattern(getCallNode(), regex, caseSensitive);
+ }
+ }
+
+ /** Expression of the "print" function. */
+ @BuiltInFunction(name = "print", doc = "Built-in print function. Prints the argument")
+ @BuiltInMethod(isProperty = true)
+ abstract static class PrintExpr extends BuiltInBody {
+ @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT)
+ protected LKQLUnit onBoolean(
+ Object toPrint,
+ @DefaultVal("true") boolean newLine,
+ @CachedLibrary("toPrint") InteropLibrary printingLibrary) {
+ if (newLine) {
+ LKQLLanguage.getContext(null)
+ .println((String) printingLibrary.toDisplayString(toPrint));
+ } else {
+ LKQLLanguage.getContext(null)
+ .print((String) printingLibrary.toDisplayString(toPrint));
+ }
+ return LKQLUnit.INSTANCE;
+ }
+ }
+
+ @BuiltInFunction(name = "img", doc = "Return a string representation of an object")
+ @BuiltInMethod(isProperty = true)
+ abstract static class ImgExpr extends BuiltInBody {
+ @Specialization
+ protected String onString(String string) {
+ return StringUtils.toRepr(string);
+ }
+
+ @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT)
+ protected String onObject(Object obj, @CachedLibrary("obj") InteropLibrary objLibrary) {
+ return (String) objLibrary.toDisplayString(obj);
+ }
+ }
+
+ @BuiltInFunction(
+ name = "doc",
+ doc = "Given any object, return the documentation associated with it")
+ @BuiltInMethod(isProperty = true)
+ abstract static class DocExpr extends BuiltInBody {
+ @Specialization
+ protected String onLKQLValue(LKQLValue value) {
+ return value.lkqlDocumentation();
+ }
+
+ @Specialization
+ protected String onAny(Object obj) {
+ return "";
+ }
+ }
+
+ @BuiltInFunction(
+ name = "reduce",
+ doc =
+ "Given a collection, a reduction function, and an initial value reduce the"
+ + " result")
+ @BuiltInMethod(
+ targetTypes = {
+ LKQLTypesHelper.LKQL_SELECTOR_LIST,
+ LKQLTypesHelper.LKQL_LAZY_LIST,
+ LKQLTypesHelper.LKQL_LIST
+ })
+ abstract static class ReduceExpr extends BuiltInBody {
+ @Specialization(
+ limit = Constants.SPECIALIZED_LIB_LIMIT,
+ guards = "function.parameterNames.length == 2")
+ protected Object onValidArgs(
+ Iterable iterable,
+ LKQLFunction function,
+ Object initValue,
+ @CachedLibrary("function") InteropLibrary functionLibrary) {
+ Iterator iterator = iterable.iterator();
+ while (iterator.hasNext()) {
+ try {
+ initValue =
+ functionLibrary.execute(
+ function,
+ function.closure.getContent(),
+ initValue,
+ iterator.next());
+ } catch (ArityException
+ | UnsupportedTypeException
+ | UnsupportedMessageException e) {
+ // TODO: Implement runtime checks in the LKQLFunction class and base computing
+ // on them (#138)
+ throw LKQLRuntimeException.fromJavaException(e, argNode(1));
+ }
+ }
+ return initValue;
+ }
+ }
+
+ @BuiltInFunction(
+ name = "document_builtins",
+ doc = "Return a string in the RsT format containing documentation for all built-ins")
+ abstract static class DocumentBuiltinsExpr extends BuiltInBody {
+ @CompilerDirectives.TruffleBoundary
+ @Specialization
+ public static String exec() {
+ var sw = new StringWriter();
+ try (TextWriter writer = new TextWriter(sw)) {
+ writer.write("Standard library\n");
+ writer.write("----------------\n");
+ writer.write("\n");
+ writer.write("Builtin functions\n");
+ writer.write("^^^^^^^^^^^^^^^^^\n");
+ writer.write("\n");
+
+ for (var func : AllBuiltIns.allFunctions()) {
+ writer.write(".. function:: ");
+ writer.write(func.getName());
+ writer.write("(" + String.join(", ", func.parameterNames) + ")");
+ writer.write("\n\n");
+ writer.withIndent(
+ () -> {
+ writer.write(func.documentation);
+ });
+ writer.write("\n");
+ writer.write("\n");
+ }
+
+ writer.write("Builtin methods\n");
+ writer.write("^^^^^^^^^^^^^^^\n");
+ writer.write("\n");
+
+ var sortedBuiltinMethods =
+ new java.util.ArrayList<>(
+ AllBuiltIns.allMethods().entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .toList());
+
+ for (var entry : sortedBuiltinMethods) {
+
+ var methods =
+ entry.getValue().entrySet().stream()
+ .sorted(Map.Entry.comparingByKey())
+ .toList();
+
+ // Skip type if there are no methods to document
+ if (methods.size() == 0) {
+ continue;
+ }
+
+ var typeName = entry.getKey();
+ var header = "Methods for `" + typeName + "`";
+ writer.write(header + "\n");
+ writer.write("\"".repeat(header.length()) + "\n");
+
+ for (var method : methods) {
+ writer.write(".. method:: ");
+ writer.write(typeName + "." + method.getKey());
+ writer.write(
+ "("
+ + String.join(
+ ", ",
+ Arrays.stream(method.getValue().paramNames)
+ .toArray(String[]::new))
+ + ")");
+ writer.write("\n\n");
+ writer.withIndent(
+ () -> {
+ writer.write(method.getValue().documentation);
+ });
+ writer.write("\n");
+ writer.write("\n");
+ }
+ }
+
+ return sw.getBuffer().toString();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @BuiltInFunction(
+ name = "base_name",
+ doc = "Given a string that represents a file name, returns the basename")
+ @BuiltInMethod(
+ targetTypes = {LKQLTypesHelper.LKQL_STRING},
+ isProperty = true)
+ abstract static class BaseNameExpr extends BuiltInBody {
+ @Specialization
+ protected String executeOnString(String fileName) {
+ return FileUtils.baseName(fileName);
+ }
+ }
+
+ @BuiltInFunction(
+ name = "concat",
+ doc = "Given a list of lists or strings, return a concatenated list or string")
+ abstract static class ConcatExpr extends BuiltInBody {
+
+ protected static boolean isString(Object o) {
+ return LKQLTypeSystemGen.isString(o);
+ }
+
+ protected static boolean isList(Object o) {
+ return LKQLTypeSystemGen.isLKQLList(o);
+ }
+
+ @Specialization(guards = {"list.size() > 0", "isString(list.get(0))"})
+ protected String onListOfStrings(LKQLList list) {
+ // Create a string builder and add all strings in the list
+ String result = LKQLTypeSystemGen.asString(list.get(0));
+ for (int i = 1; i < list.size(); i++) {
+ final Object item = list.get(i);
+ if (!LKQLTypeSystemGen.isString(item)) {
+ this.invalidElemType(list, item);
+ }
+ result = StringUtils.concat(result, LKQLTypeSystemGen.asString(item));
+ }
+ return result;
+ }
+
+ @Specialization(guards = {"list.size() > 0", "isList(list.get(0))"})
+ protected LKQLList onListOfLists(LKQLList list) {
+ Object[] result = LKQLTypeSystemGen.asLKQLList(list.get(0)).getContent();
+ for (int i = 1; i < list.size(); i++) {
+ final Object item = list.get(i);
+ if (!LKQLTypeSystemGen.isLKQLList(item)) {
+ this.invalidElemType(list, item);
+ }
+ result = ArrayUtils.concat(result, LKQLTypeSystemGen.asLKQLList(item).getContent());
+ }
+ return new LKQLList(result);
+ }
+
+ @Specialization(guards = "notValidElem.size() > 0")
+ @CompilerDirectives.TruffleBoundary
+ protected LKQLList invalidElemType(
+ @SuppressWarnings("unused") LKQLList notValidElem,
+ @Cached("notValidElem.get(0)") Object elem) {
+ throw LKQLRuntimeException.wrongType(
+ LKQLTypesHelper.LKQL_LIST
+ + " of "
+ + LKQLTypesHelper.typeUnion(
+ LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.LKQL_STRING),
+ LKQLTypesHelper.fromJava(elem) + " element",
+ argNode(0));
+ }
+
+ @Specialization(guards = "emptyList.size() == 0")
+ protected LKQLList onEmptyList(@SuppressWarnings("unused") LKQLList emptyList) {
+ return new LKQLList(new Object[0]);
+ }
+ }
+
+ @BuiltInFunction(name = "map", doc = "Given a collection, a mapping function")
+ abstract static class MapExpr extends BuiltInBody {
+ @Specialization(
+ limit = Constants.SPECIALIZED_LIB_LIMIT,
+ guards = "function.parameterNames.length == 1")
+ protected LKQLList onValidArgs(
+ Iterable iterable,
+ LKQLFunction function,
+ @CachedLibrary("function") InteropLibrary functionLibrary) {
+ Object[] res = new Object[(int) iterable.size()];
+ int i = 0;
+ Iterator iterator = iterable.iterator();
+
+ while (iterator.hasNext()) {
+ try {
+ res[i] =
+ functionLibrary.execute(
+ function, function.closure.getContent(), iterator.next());
+ } catch (ArityException
+ | UnsupportedTypeException
+ | UnsupportedMessageException e) {
+ // TODO: Implement runtime checks in the LKQLFunction class and base computing
+ // on them (#138)
+ throw LKQLRuntimeException.fromJavaException(e, argNode(1));
+ }
+ i++;
+ }
+
+ return new LKQLList(res);
+ }
+ }
+
+ @BuiltInFunction(
+ name = "profile",
+ doc = "Given any object, if it is a callable, return its profile as text")
+ abstract static class ProfileExpr extends BuiltInBody {
+ @Specialization
+ protected String onLKQLValue(LKQLValue val) {
+ return val.lkqlProfile();
+ }
+
+ @Specialization
+ protected String onOthers(Object obj) {
+ return "";
+ }
+ }
+
+ @BuiltInFunction(
+ name = "document_namespace",
+ doc = "Return a string in the RsT format containing documentation for all built-ins")
+ abstract static class DocumentNamespaceExpr extends BuiltInBody {
+
+ private static void documentCallable(TextWriter writer, BasicLKQLValue callable) {
+ writer.write(".. function:: " + callable.lkqlProfile() + "\n\n");
+ writer.withIndent(
+ () -> {
+ writer.write(callable.lkqlDocumentation());
+ });
+ writer.write("\n\n");
+ }
+
+ @Specialization
+ @CompilerDirectives.TruffleBoundary
+ protected String impl(LKQLNamespace namespace, String name) {
+ var sw = new StringWriter();
+ try (TextWriter writer = new TextWriter(sw)) {
+
+ var header = name + "'s API doc";
+ writer.write(header + "\n");
+ writer.write("-".repeat(header.length()));
+ writer.write("\n\n");
+
+ writer.write("Functions\n");
+ writer.write("^^^^^^^^^\n");
+
+ var functions =
+ namespace.asMap().values().stream()
+ .filter(LKQLTypeSystemGen::isLKQLFunction)
+ .map(LKQLTypeSystemGen::asLKQLFunction)
+ .sorted(Comparator.comparing(LKQLFunction::getName));
+
+ for (var func : functions.toList()) {
+ documentCallable(writer, func);
+ }
+
+ writer.write("Selectors\n");
+ writer.write("^^^^^^^^^\n");
+
+ var selectors =
+ namespace.asMap().values().stream()
+ .filter(LKQLTypeSystemGen::isLKQLSelector)
+ .map(LKQLTypeSystemGen::asLKQLSelector)
+ .sorted(Comparator.comparing(LKQLSelector::lkqlProfile));
+
+ for (var sel : selectors.toList()) {
+ documentCallable(writer, sel);
+ }
+
+ return sw.getBuffer().toString();
+ } catch (Exception e) {
+ throw new RuntimeException(e);
+ }
+ }
+ }
+
+ @BuiltInFunction(name = "help", doc = "Print formatted help for the given object")
+ @BuiltInMethod(isProperty = true)
+ abstract static class HelpExpr extends BuiltInBody {
+ @Specialization
+ protected Object onLKQLValue(LKQLValue value) {
+ LKQLLanguage.getContext(callNode)
+ .println(
+ StringUtils.concat(
+ value.lkqlProfile(), "\n", value.lkqlDocumentation()));
+ return LKQLUnit.INSTANCE;
+ }
+ }
+
+ @BuiltInFunction(name = "units", doc = "Return a list of all units")
+ abstract static class UnitsExpr extends BuiltInBody {
+ @Specialization
+ protected LKQLList alwaysTrue() {
+ return new LKQLList(LKQLLanguage.getContext(callNode).getAllUnits());
+ }
+ }
+
+ @BuiltInFunction(name = "specified_units", doc = "Return a list of units specified by the user")
+ abstract static class SpecifiedUnitsExpr extends BuiltInBody {
+ @Specialization
+ protected LKQLList alwaysTrue() {
+ return new LKQLList(LKQLLanguage.getContext(callNode).getSpecifiedUnits());
+ }
+ }
+}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodFactory.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodFactory.java
index 7e88ccc06..497ebff5b 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodFactory.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodFactory.java
@@ -5,9 +5,7 @@
package com.adacore.lkql_jit.built_ins;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
import com.adacore.lkql_jit.utils.functions.ArrayUtils;
-import java.util.Map;
/**
* This class is a factory for a specific built-in method. This factory will build a new method
@@ -23,15 +21,15 @@ public final class BuiltInMethodFactory {
public final String[] paramNames;
- public final Expr[] paramDefaults;
+ public String[] defaultValues;
- public final AbstractBuiltInFunctionBody methodBody;
+ public final BuiltInBody methodBody;
/**
- * Whether the factory should produce "attribute" value. See the {@link BuiltInAttributeValue}
+ * Whether the factory should produce "attribute" value. See the {@link BuiltInPropertyValue}
* class for more information.
*/
- public final boolean isAttribute;
+ public final boolean isProperty;
// ----- Constructors -----
@@ -39,101 +37,56 @@ public final class BuiltInMethodFactory {
public BuiltInMethodFactory(
String name,
String documentation,
- String[] paramNames,
- Expr[] paramDefaults,
- AbstractBuiltInFunctionBody methodBody,
- boolean isAttribute) {
+ String[] names,
+ String[] defaultValues,
+ BuiltInBody methodBody,
+ boolean isProperty) {
this.name = name;
this.documentation = documentation;
- this.paramNames = paramNames;
- this.paramDefaults = paramDefaults;
+ this.paramNames = names;
+ this.defaultValues = defaultValues;
this.methodBody = methodBody;
- this.isAttribute = isAttribute;
+ this.isProperty = isProperty;
}
// ----- Instance methods -----
/** Instantiate the method with the given "thisValue" and return the LKQL value. */
public BuiltInMethodValue instantiate(Object thisValue) {
- return this.isAttribute
- ? new BuiltInAttributeValue(
+ return this.isProperty
+ ? new BuiltInPropertyValue(
this.name, this.documentation, this.methodBody, thisValue)
: new BuiltInMethodValue(
this.name,
this.documentation,
this.paramNames,
- this.paramDefaults,
+ this.defaultValues,
this.methodBody,
thisValue);
}
// ----- Class methods -----
- /**
- * Create a new methods factory wrapping an existing function value. The first function
- * parameter is considered as the "this" parameter.
- */
- public static BuiltInMethodFactory fromFunctionValue(
- BuiltInFunctionValue value, boolean isAttribute) {
- String[] paramNames = value.parameterNames.clone();
- Expr[] paramDefaults = value.parameterDefaultValues.clone();
- paramNames[0] = "this";
- paramDefaults[0] = null;
- return new BuiltInMethodFactory(
- value.name,
- value.documentation,
- paramNames,
- paramDefaults,
- (AbstractBuiltInFunctionBody) value.rootNode.getBody(),
- isAttribute);
- }
-
- /** Util function to create a map entry associating the method name with its value. */
- public static Map.Entry createMethod(
- String name,
- String doc,
- String[] paramNames,
- Expr[] paramDefaults,
- AbstractBuiltInFunctionBody.BuiltInCallback callback) {
- return createMethod(
- name,
- doc,
- paramNames,
- paramDefaults,
- AbstractBuiltInFunctionBody.fromCallback(callback));
- }
-
/**
* Util function to create a map entry associating the method name with its value.
*
- * @param paramNames Names of the method parameters. This array SHOULDN'T contain the "this"
- * parameter since it is automatically added by this method.
- * @param paramDefaults Default values for the method parameters. A null value will
- * automatically be added at the start of it to represents the "this" default value.
+ * @param parameters Specs for parameters. This array SHOULDN'T contain the "this" parameter
+ * since it is automatically added by this method.
*/
- public static Map.Entry createMethod(
- String name,
- String doc,
- String[] paramNames,
- Expr[] paramDefaults,
- AbstractBuiltInFunctionBody body) {
- return Map.entry(
+ public static BuiltInMethodFactory createMethod(
+ String name, String doc, String[] names, String[] defaultValues, BuiltInBody body) {
+ return new BuiltInMethodFactory(
name,
- new BuiltInMethodFactory(
- name,
- doc,
- ArrayUtils.concat(new String[] {"this"}, paramNames),
- ArrayUtils.concat(new Expr[] {null}, paramDefaults),
- body,
- false));
+ doc,
+ ArrayUtils.concat(new String[] {"this"}, names),
+ ArrayUtils.concat(new String[] {null}, defaultValues),
+ body,
+ false);
}
/** Create a map entry containing a method factory which will produce attribute values. */
- public static Map.Entry createAttribute(
- String name, String doc, AbstractBuiltInFunctionBody body) {
- return Map.entry(
- name,
- new BuiltInMethodFactory(
- name, doc, new String[] {"this"}, new Expr[] {null}, body, true));
+ public static BuiltInMethodFactory createAttribute(String name, String doc, BuiltInBody body) {
+ return new BuiltInMethodFactory(
+ name, doc, new String[] {"this"}, new String[] {null}, body, true);
}
}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodValue.java
index 856267452..d4a39981e 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodValue.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInMethodValue.java
@@ -5,8 +5,6 @@
package com.adacore.lkql_jit.built_ins;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-
/** This class represents the LKQL value of an instantiated built-in method. */
public class BuiltInMethodValue extends BuiltInFunctionValue {
@@ -25,8 +23,8 @@ public BuiltInMethodValue(
String name,
String documentation,
String[] names,
- Expr[] defaultValues,
- AbstractBuiltInFunctionBody body,
+ String[] defaultValues,
+ BuiltInBody body,
Object thisValue) {
super(name, documentation, names, defaultValues, body);
this.thisValue = thisValue;
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInAttributeValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInPropertyValue.java
similarity index 53%
rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInAttributeValue.java
rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInPropertyValue.java
index ae04410ad..0205e2d73 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInAttributeValue.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInPropertyValue.java
@@ -5,16 +5,14 @@
package com.adacore.lkql_jit.built_ins;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-
/**
* This class represents the LKQL value of an instantiated attribute. An attribute is a special
* method with not other arguments than "this" and is called implicitly by the dotted-name notation.
*/
-public class BuiltInAttributeValue extends BuiltInMethodValue {
+public class BuiltInPropertyValue extends BuiltInMethodValue {
/** Create a new built-in attribute value. */
- public BuiltInAttributeValue(
- String name, String documentation, AbstractBuiltInFunctionBody body, Object thisValue) {
- super(name, documentation, new String[] {"this"}, new Expr[] {null}, body, thisValue);
+ public BuiltInPropertyValue(
+ String name, String documentation, BuiltInBody body, Object thisValue) {
+ super(name, documentation, new String[] {"this"}, new String[] {null}, body, thisValue);
}
}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInsHolder.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInsHolder.java
deleted file mode 100644
index 3c7e4f7ef..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInsHolder.java
+++ /dev/null
@@ -1,99 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins;
-
-import com.adacore.lkql_jit.built_ins.functions.*;
-import com.adacore.lkql_jit.built_ins.methods.*;
-import com.adacore.lkql_jit.checker.built_ins.NodeCheckerFunction;
-import com.adacore.lkql_jit.checker.built_ins.UnitCheckerFunction;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-
-/**
- * This class is a data class helper containing all built-ins of LKQL.
- *
- * @author Hugo GUERRIER
- */
-public final class BuiltInsHolder {
- /** The built-in function list. */
- public final List builtInFunctions =
- List.of(
- PrintFunction.getValue(),
- ImgFunction.getValue(),
- BaseNameFunction.getValue(),
- ConcatFunction.getValue(),
- ReduceFunction.getValue(),
- MapFunction.getValue(),
- UniqueFunction.getValue(),
- DocFunction.getValue(),
- ProfileFunction.getValue(),
- DocumentBuiltins.getValue(),
- DocumentNamespace.getValue(),
- HelpFunction.getValue(),
- UnitsFunction.getValue(),
- SpecifiedUnitsFunction.getValue(),
- PatternFunction.getValue(),
- NodeCheckerFunction.getValue(),
- UnitCheckerFunction.getValue());
-
- /** The built-in method list. */
- public final Map> builtInMethods =
- Map.ofEntries(
- create(LKQLTypesHelper.LKQL_LIST, ListMethods.methods),
- create(LKQLTypesHelper.LKQL_STRING, StrMethods.methods),
- create(LKQLTypesHelper.ADA_NODE, NodeMethods.methods),
- create(LKQLTypesHelper.ANALYSIS_UNIT, AnalysisUnitMethods.methods),
- create(LKQLTypesHelper.TOKEN, TokenMethods.methods),
- create(LKQLTypesHelper.LKQL_LAZY_LIST, IterableMethods.methods),
- create(LKQLTypesHelper.LKQL_SELECTOR_LIST, IterableMethods.methods),
- create(LKQLTypesHelper.REWRITING_CONTEXT, RewritingContextMethods.methods),
- create(LKQLTypesHelper.REWRITING_NODE, RewritingNodeMethods.methods),
- create(LKQLTypesHelper.LKQL_UNIT, null),
- create(LKQLTypesHelper.LKQL_BOOLEAN, null),
- create(LKQLTypesHelper.LKQL_INTEGER, null),
- create(LKQLTypesHelper.LKQL_FUNCTION, null),
- create(LKQLTypesHelper.LKQL_PROPERTY_REF, null),
- create(LKQLTypesHelper.LKQL_SELECTOR, null),
- create(LKQLTypesHelper.LKQL_TUPLE, null),
- create(LKQLTypesHelper.LKQL_OBJECT, null),
- create(LKQLTypesHelper.LKQL_NAMESPACE, null));
-
- public final Map commonMethods =
- Map.of(
- ImgFunction.NAME,
- BuiltInMethodFactory.fromFunctionValue(ImgFunction.getValue(), true),
- PrintFunction.NAME,
- BuiltInMethodFactory.fromFunctionValue(PrintFunction.getValue(), false),
- DocFunction.NAME,
- BuiltInMethodFactory.fromFunctionValue(DocFunction.getValue(), true));
-
- public static Map combine(
- Map m1, Map m2) {
- var res = new HashMap();
- res.putAll(m1);
- res.putAll(m2);
- return res;
- }
-
- private static Map.Entry> create(
- String name, Map vals) {
- if (vals == null) {
- vals = new HashMap<>();
- }
- return Map.entry(name, vals);
- }
-
- private static BuiltInsHolder instance = null;
-
- public static BuiltInsHolder get() {
- if (instance == null) {
- instance = new BuiltInsHolder();
- }
- return instance;
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/SpecializedBuiltInBody.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/SpecializedBuiltInBody.java
deleted file mode 100644
index 02f5b0a19..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/SpecializedBuiltInBody.java
+++ /dev/null
@@ -1,50 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins;
-
-import com.adacore.lkql_jit.LKQLTypeSystem;
-import com.oracle.truffle.api.dsl.TypeSystemReference;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import com.oracle.truffle.api.nodes.Node;
-
-public abstract class SpecializedBuiltInBody<
- T extends SpecializedBuiltInBody.SpecializedBuiltInNode>
- extends AbstractBuiltInFunctionBody {
-
- // ----- Attributes -----
-
- /** This node represents the execution of the built-in function. */
- @Child protected T specializedNode;
-
- // ----- Constructors -----
-
- /** Create a new specialized body with its corresponding execution node. */
- public SpecializedBuiltInBody(T specializedNode) {
- this.specializedNode = specializedNode;
- this.specializedNode.body = this;
- }
-
- // ----- Instance methods -----
-
- /** Dispatch the function arguments to the specialized execution node. */
- protected abstract Object dispatch(Object[] args);
-
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- return this.dispatch(frame.getArguments());
- }
-
- // ----- Inner classes -----
-
- /** This class represents an execution node, payload of a built-in body. */
- @TypeSystemReference(LKQLTypeSystem.class)
- public abstract static class SpecializedBuiltInNode extends Node {
- // ----- Attributes -----
-
- /** The built-in body that owns this specialized node. */
- protected SpecializedBuiltInBody body;
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java
deleted file mode 100644
index 95c90a706..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java
+++ /dev/null
@@ -1,59 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.adacore.lkql_jit.utils.functions.FileUtils;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-
-/**
- * This class represents the "base_name" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class BaseNameFunction {
-
- public static final String NAME = "base_name";
-
- /** Get a brand new "base_name" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given a string that represents a file name, returns the basename",
- new String[] {"str"},
- new Expr[] {null},
- new SpecializedBuiltInBody<>(BaseNameFunctionFactory.BaseNameExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeBaseName(args[0]);
- }
- });
- }
-
- /** Expression of the "base_name" function. */
- abstract static class BaseNameExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract String executeBaseName(Object fileName);
-
- @Specialization
- protected String executeOnString(String fileName) {
- return FileUtils.baseName(fileName);
- }
-
- @Fallback
- protected String invalidType(Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_STRING,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java
deleted file mode 100644
index b494393ec..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java
+++ /dev/null
@@ -1,111 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.adacore.lkql_jit.utils.functions.ArrayUtils;
-import com.adacore.lkql_jit.utils.functions.StringUtils;
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.dsl.Cached;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-
-/**
- * This class represents the "concat" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class ConcatFunction {
-
- public static final String NAME = "concat";
-
- /** Get a brand new "concat" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given a list of lists or strings, return a concatenated list or string",
- new String[] {"lists"},
- new Expr[] {null},
- new SpecializedBuiltInBody<>(ConcatFunctionFactory.ConcatExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeConcat(args[0]);
- }
- });
- }
-
- /** Expression of the "concat" function. */
- abstract static class ConcatExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract Object executeConcat(Object list);
-
- protected static boolean isString(Object o) {
- return LKQLTypeSystemGen.isString(o);
- }
-
- protected static boolean isList(Object o) {
- return LKQLTypeSystemGen.isLKQLList(o);
- }
-
- @Specialization(guards = {"list.size() > 0", "isString(list.get(0))"})
- protected String onListOfStrings(LKQLList list) {
- // Create a string builder and add all strings in the list
- String result = LKQLTypeSystemGen.asString(list.get(0));
- for (int i = 1; i < list.size(); i++) {
- final Object item = list.get(i);
- if (!LKQLTypeSystemGen.isString(item)) {
- this.invalidElemType(list, item);
- }
- result = StringUtils.concat(result, LKQLTypeSystemGen.asString(item));
- }
- return result;
- }
-
- @Specialization(guards = {"list.size() > 0", "isList(list.get(0))"})
- protected LKQLList onListOfLists(LKQLList list) {
- Object[] result = LKQLTypeSystemGen.asLKQLList(list.get(0)).getContent();
- for (int i = 1; i < list.size(); i++) {
- final Object item = list.get(i);
- if (!LKQLTypeSystemGen.isLKQLList(item)) {
- this.invalidElemType(list, item);
- }
- result = ArrayUtils.concat(result, LKQLTypeSystemGen.asLKQLList(item).getContent());
- }
- return new LKQLList(result);
- }
-
- @Specialization(guards = "notValidElem.size() > 0")
- @CompilerDirectives.TruffleBoundary
- protected LKQLList invalidElemType(
- @SuppressWarnings("unused") LKQLList notValidElem,
- @Cached("notValidElem.get(0)") Object elem) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_LIST
- + " of "
- + LKQLTypesHelper.typeUnion(
- LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.LKQL_STRING),
- LKQLTypesHelper.fromJava(elem) + " element",
- body.argNode(0));
- }
-
- @Specialization(guards = "emptyList.size() == 0")
- protected LKQLList onEmptyList(@SuppressWarnings("unused") LKQLList emptyList) {
- return new LKQLList(new Object[0]);
- }
-
- @Fallback
- protected LKQLList invalidType(Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.fromJava(notValid), body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java
deleted file mode 100644
index 2f14bc5d4..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * This class represents the "doc" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class DocFunction {
-
- public static final String NAME = "doc";
-
- /** Get a brand new "doc" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given any object, return the documentation associated with it",
- new String[] {"obj"},
- new Expr[] {null},
- (VirtualFrame frame, FunCall call) -> {
- // Get the argument
- Object arg = frame.getArguments()[0];
-
- // If the argument is an LKQL value, read the documentation from ir
- if (LKQLTypeSystemGen.isLKQLValue(arg)) {
- return ((LKQLValue) arg).lkqlDocumentation();
- }
-
- // Return the default empty documentation
- return "";
- });
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentBuiltins.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentBuiltins.java
deleted file mode 100644
index 5d688d0af..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentBuiltins.java
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.BuiltInsHolder;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.utils.TextWriter;
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import java.io.StringWriter;
-import java.util.Map;
-
-public class DocumentBuiltins {
- public static final String NAME = "document_builtins";
-
- /** Get a brand new "document_builtins" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Return a string in the RsT format containing documentation for all built-ins",
- new String[] {},
- new Expr[] {},
- (VirtualFrame frame, FunCall call) ->
- documentBuiltinsImpl(frame.materialize(), call));
- }
-
- /** Function for the "document_builtins" execution. */
- @CompilerDirectives.TruffleBoundary
- public static String documentBuiltinsImpl(
- @SuppressWarnings("unused") MaterializedFrame frame,
- @SuppressWarnings("unused") FunCall call) {
- var sw = new StringWriter();
- try (TextWriter writer = new TextWriter(sw)) {
- writer.write("Standard library\n");
- writer.write("----------------\n");
- writer.write("\n");
- writer.write("Builtin functions\n");
- writer.write("^^^^^^^^^^^^^^^^^\n");
- writer.write("\n");
-
- for (var func : BuiltInsHolder.get().builtInFunctions) {
- writer.write(".. function:: ");
- writer.write(func.getName());
- writer.write("(" + String.join(", ", func.parameterNames) + ")");
- writer.write("\n\n");
- writer.withIndent(
- () -> {
- writer.write(func.documentation);
- });
- writer.write("\n");
- writer.write("\n");
- }
-
- writer.write("Builtin methods\n");
- writer.write("^^^^^^^^^^^^^^^\n");
- writer.write("\n");
-
- var sortedBuiltinMethods =
- new java.util.ArrayList<>(
- BuiltInsHolder.get().builtInMethods.entrySet().stream()
- .sorted(Map.Entry.comparingByKey())
- .toList());
-
- sortedBuiltinMethods.add(0, Map.entry("Any", BuiltInsHolder.get().commonMethods));
-
- for (var entry : sortedBuiltinMethods) {
-
- var methods =
- entry.getValue().entrySet().stream()
- .sorted(Map.Entry.comparingByKey())
- .toList();
-
- // Skip type if there are no methods to document
- if (methods.size() == 0) {
- continue;
- }
-
- var typeName = entry.getKey();
- var header = "Methods for `" + typeName + "`";
- writer.write(header + "\n");
- writer.write("\"".repeat(header.length()) + "\n");
-
- for (var method : methods) {
- writer.write(".. method:: ");
- writer.write(typeName + "." + method.getKey());
- writer.write("(" + String.join(", ", method.getValue().paramNames) + ")");
- writer.write("\n\n");
- writer.withIndent(
- () -> {
- writer.write(method.getValue().documentation);
- });
- writer.write("\n");
- writer.write("\n");
- }
- }
-
- return sw.getBuffer().toString();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentNamespace.java
deleted file mode 100644
index d5cec3aa7..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocumentNamespace.java
+++ /dev/null
@@ -1,109 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.LKQLFunction;
-import com.adacore.lkql_jit.runtime.values.LKQLNamespace;
-import com.adacore.lkql_jit.runtime.values.LKQLSelector;
-import com.adacore.lkql_jit.runtime.values.bases.BasicLKQLValue;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.adacore.lkql_jit.utils.TextWriter;
-import com.oracle.truffle.api.CompilerDirectives;
-import com.oracle.truffle.api.frame.MaterializedFrame;
-import com.oracle.truffle.api.frame.VirtualFrame;
-import java.io.StringWriter;
-import java.util.Comparator;
-
-public class DocumentNamespace {
- public static final String NAME = "document_namespace";
-
- /** Get a brand new "document_namespace" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Return a string in the RsT format containing documentation for all built-ins",
- new String[] {"namespace", "name"},
- new Expr[] {null, null},
- (VirtualFrame frame, FunCall call) -> impl(frame.materialize(), call));
- }
-
- /** Function for the "document_namespace" execution. */
- @CompilerDirectives.TruffleBoundary
- private static Object impl(MaterializedFrame frame, FunCall call) {
- Object nsObj = frame.getArguments()[0];
- Object nameObj = frame.getArguments()[1];
-
- if (!LKQLTypeSystemGen.isLKQLNamespace(nsObj)) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_NAMESPACE,
- LKQLTypesHelper.fromJava(nsObj),
- call.getArgList().getArgs()[0]);
- }
-
- if (!LKQLTypeSystemGen.isString(nameObj)) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_STRING,
- LKQLTypesHelper.fromJava(nameObj),
- call.getArgList().getArgs()[1]);
- }
-
- LKQLNamespace namespace = LKQLTypeSystemGen.asLKQLNamespace(nsObj);
- String name = LKQLTypeSystemGen.asString(nameObj);
-
- var sw = new StringWriter();
- try (TextWriter writer = new TextWriter(sw)) {
-
- var header = name + "'s API doc";
- writer.write(header + "\n");
- writer.write("-".repeat(header.length()));
- writer.write("\n\n");
-
- writer.write("Functions\n");
- writer.write("^^^^^^^^^\n");
-
- var functions =
- namespace.asMap().values().stream()
- .filter(LKQLTypeSystemGen::isLKQLFunction)
- .map(LKQLTypeSystemGen::asLKQLFunction)
- .sorted(Comparator.comparing(LKQLFunction::getName));
-
- for (var func : functions.toList()) {
- documentCallable(writer, func);
- }
-
- writer.write("Selectors\n");
- writer.write("^^^^^^^^^\n");
-
- var selectors =
- namespace.asMap().values().stream()
- .filter(LKQLTypeSystemGen::isLKQLSelector)
- .map(LKQLTypeSystemGen::asLKQLSelector)
- .sorted(Comparator.comparing(LKQLSelector::lkqlProfile));
-
- for (var sel : selectors.toList()) {
- documentCallable(writer, sel);
- }
-
- return sw.getBuffer().toString();
- } catch (Exception e) {
- throw new RuntimeException(e);
- }
- }
-
- private static void documentCallable(TextWriter writer, BasicLKQLValue callable) {
- writer.write(".. function:: " + callable.lkqlProfile() + "\n\n");
- writer.withIndent(
- () -> {
- writer.write(callable.lkqlDocumentation());
- });
- writer.write("\n\n");
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java
deleted file mode 100644
index 149704289..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java
+++ /dev/null
@@ -1,53 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLLanguage;
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.LKQLUnit;
-import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue;
-import com.adacore.lkql_jit.utils.functions.StringUtils;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * This class represents "help" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class HelpFunction {
-
- public static final String NAME = "help";
-
- /** Get a brand new "help" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given any object, return formatted help for it",
- new String[] {"obj"},
- new Expr[] {null},
- (VirtualFrame frame, FunCall call) -> {
- // Get the argument
- Object arg = frame.getArguments()[0];
-
- // If the argument is an LKQL value, read the documentation from ir
- if (LKQLTypeSystemGen.isLKQLValue(arg)) {
- LKQLValue value = LKQLTypeSystemGen.asLKQLValue(arg);
- LKQLLanguage.getContext(call)
- .println(
- StringUtils.concat(
- value.lkqlProfile(),
- "\n",
- value.lkqlDocumentation()));
- }
-
- // Return the default empty documentation
- return LKQLUnit.INSTANCE;
- });
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java
deleted file mode 100644
index 7b68ed2c6..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java
+++ /dev/null
@@ -1,56 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.utils.Constants;
-import com.adacore.lkql_jit.utils.functions.StringUtils;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.InteropLibrary;
-import com.oracle.truffle.api.library.CachedLibrary;
-
-/**
- * This class represents the "img" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class ImgFunction {
-
- public static final String NAME = "img";
-
- /** Get a brand new "img" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Return a string representation of an object",
- new String[] {"val"},
- new Expr[] {null},
- new SpecializedBuiltInBody<>(ImgFunctionFactory.ImgExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeImg(args[0]);
- }
- });
- }
-
- /** Expression of the "img" function. */
- abstract static class ImgExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract String executeImg(Object obj);
-
- @Specialization
- protected String onString(String string) {
- return StringUtils.toRepr(string);
- }
-
- @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT)
- protected String onObject(Object obj, @CachedLibrary("obj") InteropLibrary objLibrary) {
- return (String) objLibrary.toDisplayString(obj);
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java
deleted file mode 100644
index 79511cd86..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java
+++ /dev/null
@@ -1,108 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.runtime.values.LKQLFunction;
-import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
-import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.adacore.lkql_jit.utils.Constants;
-import com.adacore.lkql_jit.utils.Iterator;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.ArityException;
-import com.oracle.truffle.api.interop.InteropLibrary;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
-import com.oracle.truffle.api.interop.UnsupportedTypeException;
-import com.oracle.truffle.api.library.CachedLibrary;
-
-/**
- * This class represents the "map" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class MapFunction {
-
- public static final String NAME = "map";
-
- /** Get a brand new "map" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given an iterable object and a function, return the list resulting of the "
- + "function application on each element of the iterable object: "
- + "map(lst, f) -> [f(lst[1]), f(lst[2]), ...]",
- new String[] {"indexable", "fn"},
- new Expr[] {null, null},
- new SpecializedBuiltInBody<>(MapFunctionFactory.MaxExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeMap(args[0], args[1]);
- }
- });
- }
-
- /** Expression of the "map" function. */
- abstract static class MaxExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract LKQLList executeMap(Object iterable, Object function);
-
- @Specialization(
- limit = Constants.SPECIALIZED_LIB_LIMIT,
- guards = "function.parameterNames.length == 1")
- protected LKQLList onValidArgs(
- Iterable iterable,
- LKQLFunction function,
- @CachedLibrary("function") InteropLibrary functionLibrary) {
- Object[] res = new Object[(int) iterable.size()];
- int i = 0;
- Iterator iterator = iterable.iterator();
-
- while (iterator.hasNext()) {
- try {
- res[i] =
- functionLibrary.execute(
- function, function.closure.getContent(), iterator.next());
- } catch (ArityException
- | UnsupportedTypeException
- | UnsupportedMessageException e) {
- // TODO: Implement runtime checks in the LKQLFunction class and base computing
- // on them (#138)
- throw LKQLRuntimeException.fromJavaException(e, body.argNode(1));
- }
- i++;
- }
-
- return new LKQLList(res);
- }
-
- @Specialization
- protected LKQLList onInvalidFunction(Iterable iterable, LKQLFunction function) {
- throw LKQLRuntimeException.wrongArity(
- 1, function.parameterNames.length, body.argNode(1));
- }
-
- @Specialization
- protected LKQLList invalidType(Iterable iterable, Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_FUNCTION,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(1));
- }
-
- @Fallback
- protected LKQLList invalidType(Object notValid, Object function) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_ITERABLE,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java
deleted file mode 100644
index 4c6e84304..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java
+++ /dev/null
@@ -1,68 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.literals.BooleanLiteral;
-import com.adacore.lkql_jit.runtime.values.LKQLPattern;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-
-/**
- * This class represents the "pattern" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class PatternFunction {
-
- public static final String NAME = "pattern";
-
- /** Get a brand new "pattern" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given a regex pattern string, create a pattern object",
- new String[] {"regex", "case_sensitive"},
- new Expr[] {null, new BooleanLiteral(null, true)},
- new SpecializedBuiltInBody<>(PatternFunctionFactory.PatternExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executePattern(args[0], args[1]);
- }
- });
- }
-
- /** Expression of the "pattern" function. */
- abstract static class PatternExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract LKQLPattern executePattern(Object regex, Object caseSensitive);
-
- @Specialization
- protected LKQLPattern onValidArgs(String regex, boolean caseSensitive) {
- return new LKQLPattern(body.getCallNode(), regex, caseSensitive);
- }
-
- @Specialization
- protected LKQLPattern invalidType(String regex, Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_BOOLEAN,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(1));
- }
-
- @Fallback
- protected LKQLPattern invalidType(Object notValid, Object caseSensitive) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_STRING,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java
deleted file mode 100644
index 32ab1fd72..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java
+++ /dev/null
@@ -1,74 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLLanguage;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.literals.BooleanLiteral;
-import com.adacore.lkql_jit.runtime.values.LKQLUnit;
-import com.adacore.lkql_jit.utils.Constants;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.InteropLibrary;
-import com.oracle.truffle.api.library.CachedLibrary;
-
-/**
- * This class represents the "print" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class PrintFunction {
-
- public static final String NAME = "print";
-
- /** Get a brand new "print" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Built-in print function. Prints whatever is passed as an argument",
- new String[] {"val", "new_line"},
- new Expr[] {null, new BooleanLiteral(null, true)},
- new SpecializedBuiltInBody<>(PrintFunctionFactory.PrintExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executePrint(args[0], args[1]);
- }
- });
- }
-
- /** Expression of the "print" function. */
- abstract static class PrintExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract LKQLUnit executePrint(Object toPrint, Object newline);
-
- @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT)
- protected LKQLUnit onBoolean(
- Object toPrint,
- boolean newline,
- @CachedLibrary("toPrint") InteropLibrary printingLibrary) {
- if (newline) {
- LKQLLanguage.getContext(null)
- .println((String) printingLibrary.toDisplayString(toPrint));
- } else {
- LKQLLanguage.getContext(null)
- .print((String) printingLibrary.toDisplayString(toPrint));
- }
- return LKQLUnit.INSTANCE;
- }
-
- @Fallback
- protected LKQLUnit invalidType(Object toPrint, Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_BOOLEAN,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(1));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java
deleted file mode 100644
index b60d35da2..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java
+++ /dev/null
@@ -1,44 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * This class represents the "profile" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class ProfileFunction {
-
- public static final String NAME = "profile";
-
- /** Get a brand new "profile" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given any object, if it is a callable, return its profile as text",
- new String[] {"obj"},
- new Expr[] {null},
- (VirtualFrame frame, FunCall call) -> {
- // Get the argument
- Object arg = frame.getArguments()[0];
-
- // If the argument is an LKQL value, read the documentation from ir
- if (LKQLTypeSystemGen.isLKQLValue(arg)) {
- return ((LKQLValue) arg).lkqlProfile();
- }
-
- // Return the default empty documentation
- return "";
- });
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java
deleted file mode 100644
index fd6a1060f..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java
+++ /dev/null
@@ -1,105 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.runtime.values.LKQLFunction;
-import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
-import com.adacore.lkql_jit.utils.Constants;
-import com.adacore.lkql_jit.utils.Iterator;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-import com.oracle.truffle.api.interop.ArityException;
-import com.oracle.truffle.api.interop.InteropLibrary;
-import com.oracle.truffle.api.interop.UnsupportedMessageException;
-import com.oracle.truffle.api.interop.UnsupportedTypeException;
-import com.oracle.truffle.api.library.CachedLibrary;
-
-/**
- * This class represents the "reduce" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class ReduceFunction {
-
- public static final String NAME = "reduce";
-
- /** Get a brand new "reduce" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given a collection, a reduction function, and an initial value reduce the result",
- new String[] {"indexable", "fn", "init"},
- new Expr[] {null, null, null},
- new SpecializedBuiltInBody<>(ReduceFunctionFactory.ReduceExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeReduce(args[0], args[1], args[2]);
- }
- });
- }
-
- /** Expression of the "reduce" function. */
- abstract static class ReduceExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract Object executeReduce(Object iterable, Object function, Object initValue);
-
- @Specialization(
- limit = Constants.SPECIALIZED_LIB_LIMIT,
- guards = "function.parameterNames.length == 2")
- protected Object onValidArgs(
- Iterable iterable,
- LKQLFunction function,
- Object initValue,
- @CachedLibrary("function") InteropLibrary functionLibrary) {
- Iterator iterator = iterable.iterator();
- while (iterator.hasNext()) {
- try {
- initValue =
- functionLibrary.execute(
- function,
- function.closure.getContent(),
- initValue,
- iterator.next());
- } catch (ArityException
- | UnsupportedTypeException
- | UnsupportedMessageException e) {
- // TODO: Implement runtime checks in the LKQLFunction class and base computing
- // on them (#138)
- throw LKQLRuntimeException.fromJavaException(e, body.argNode(1));
- }
- }
- return initValue;
- }
-
- @Specialization
- protected Object onInvalidFunction(
- Iterable iterable, LKQLFunction function, Object initValue) {
- throw LKQLRuntimeException.wrongArity(
- 2, function.parameterNames.length, body.argNode(1));
- }
-
- @Specialization
- protected Object invalidType(Iterable iterable, Object notValid, Object initValue) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_FUNCTION,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(1));
- }
-
- @Fallback
- protected Object invalidType(Object notValid, Object function, Object initValue) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_ITERABLE,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java
deleted file mode 100644
index c7d43b974..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLLanguage;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * This class represents the "units" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class SpecifiedUnitsFunction {
-
- public static final String NAME = "specified_units";
-
- /** Get a brand new "specified_units" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Return an iterator on units specified by the user",
- new String[] {},
- new Expr[] {},
- (VirtualFrame frame, FunCall call) ->
- new LKQLList(LKQLLanguage.getContext(call).getSpecifiedUnits()));
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java
deleted file mode 100644
index 5d287fb5b..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java
+++ /dev/null
@@ -1,62 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.built_ins.SpecializedBuiltInBody;
-import com.adacore.lkql_jit.exception.LKQLRuntimeException;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.runtime.values.interfaces.Indexable;
-import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.adacore.lkql_jit.utils.LKQLTypesHelper;
-import com.adacore.lkql_jit.utils.functions.ArrayUtils;
-import com.oracle.truffle.api.dsl.Fallback;
-import com.oracle.truffle.api.dsl.Specialization;
-
-/**
- * This class represents the "unique" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class UniqueFunction {
-
- public static final String NAME = "unique";
-
- /** Get a brand new "unique" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Given collection, remove all identical elements in order to have only one instance"
- + " of each",
- new String[] {"indexable"},
- new Expr[] {null},
- new SpecializedBuiltInBody<>(UniqueFunctionFactory.UniqueExprNodeGen.create()) {
- @Override
- protected Object dispatch(Object[] args) {
- return specializedNode.executeUnique(args[0]);
- }
- });
- }
-
- /** Expression of the "unique" function. */
- abstract static class UniqueExpr extends SpecializedBuiltInBody.SpecializedBuiltInNode {
-
- public abstract LKQLList executeUnique(Object indexable);
-
- @Specialization
- protected LKQLList onIndexable(Indexable indexable) {
- return new LKQLList(ArrayUtils.unique(indexable.getContent()).toArray(new Object[0]));
- }
-
- @Fallback
- protected LKQLList invalidType(Object notValid) {
- throw LKQLRuntimeException.wrongType(
- LKQLTypesHelper.LKQL_ITERABLE,
- LKQLTypesHelper.fromJava(notValid),
- body.argNode(0));
- }
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java
deleted file mode 100644
index 53ed697bf..000000000
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java
+++ /dev/null
@@ -1,34 +0,0 @@
-//
-// Copyright (C) 2005-2024, AdaCore
-// SPDX-License-Identifier: GPL-3.0-or-later
-//
-
-package com.adacore.lkql_jit.built_ins.functions;
-
-import com.adacore.lkql_jit.LKQLLanguage;
-import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue;
-import com.adacore.lkql_jit.nodes.expressions.Expr;
-import com.adacore.lkql_jit.nodes.expressions.FunCall;
-import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.oracle.truffle.api.frame.VirtualFrame;
-
-/**
- * This class represents the "units" built-in function in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
-public final class UnitsFunction {
-
- public static final String NAME = "units";
-
- /** Get a brand new "units" function value. */
- public static BuiltInFunctionValue getValue() {
- return new BuiltInFunctionValue(
- NAME,
- "Return an iterator on all units",
- new String[] {},
- new Expr[] {},
- (VirtualFrame frame, FunCall call) ->
- new LKQLList(LKQLLanguage.getContext(call).getAllUnits()));
- }
-}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java
index 41d4743c8..74aa32913 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java
@@ -5,61 +5,44 @@
package com.adacore.lkql_jit.built_ins.methods;
-import static com.adacore.lkql_jit.built_ins.BuiltInMethodFactory.createAttribute;
-
import com.adacore.libadalang.Libadalang;
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.AbstractBuiltInFunctionBody;
-import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;
+import com.adacore.libadalang.Libadalang.AnalysisUnit;
+import com.adacore.lkql_jit.annotations.BuiltInMethod;
+import com.adacore.lkql_jit.annotations.BuiltinMethodContainer;
+import com.adacore.lkql_jit.built_ins.BuiltInBody;
import com.adacore.lkql_jit.runtime.values.LKQLNull;
import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
-import com.oracle.truffle.api.frame.VirtualFrame;
+import com.adacore.lkql_jit.utils.LKQLTypesHelper;
+import com.oracle.truffle.api.dsl.Specialization;
import java.util.ArrayList;
-import java.util.Map;
-/**
- * This class contains all built-in methods for the analysis unit type in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
+/** This class contains all built-in methods for the analysis unit type in the LKQL language. */
+@BuiltinMethodContainer(targetTypes = {LKQLTypesHelper.ANALYSIS_UNIT})
public final class AnalysisUnitMethods {
- public static final Map methods =
- Map.ofEntries(
- createAttribute("root", "Return the root for this unit", new RootExpr()),
- createAttribute("name", "Return the name of this unit", new NameExpr()),
- createAttribute("tokens", "Return the tokens of the unit", new TokensExpr()),
- createAttribute(
- "text", "Return the text of the analysis unit", new TextExpr()));
-
- // ----- Inner classes -----
-
- /** Expression of the "root" method. */
- public static final class RootExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- Libadalang.AdaNode res =
- LKQLTypeSystemGen.asAnalysisUnit(frame.getArguments()[0]).getRoot();
+ @BuiltInMethod(name = "root", doc = "Return the root for this unit", isProperty = true)
+ abstract static class RootExpr extends BuiltInBody {
+ @Specialization
+ public Object onUnit(AnalysisUnit self) {
+ Libadalang.AdaNode res = self.getRoot();
return res.isNone() ? LKQLNull.INSTANCE : res;
}
}
- /** Expression of the "name" method. */
- public static final class NameExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- return LKQLTypeSystemGen.asAnalysisUnit(frame.getArguments()[0]).getFileName();
+ @BuiltInMethod(name = "name", doc = "Return the name for this unit", isProperty = true)
+ abstract static class NameExpr extends BuiltInBody {
+ @Specialization
+ public String onUnit(AnalysisUnit self) {
+ return self.getFileName();
}
}
- /** Expression of the "tokens" method. */
- public static final class TokensExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- Libadalang.AnalysisUnit unit =
- LKQLTypeSystemGen.asAnalysisUnit(frame.getArguments()[0]);
- Libadalang.Token current = unit.getFirstToken();
- Libadalang.Token last = unit.getLastToken();
+ @BuiltInMethod(name = "tokens", doc = "Return the tokens for this unit", isProperty = true)
+ abstract static class TokensExpr extends BuiltInBody {
+ @Specialization
+ public LKQLList onUnit(AnalysisUnit self) {
+ Libadalang.Token current = self.getFirstToken();
+ Libadalang.Token last = self.getLastToken();
ArrayList resList = new ArrayList<>();
while (!current.isEquivalent(last) && !current.isNone()) {
resList.add(current);
@@ -69,11 +52,11 @@ public Object executeGeneric(VirtualFrame frame) {
}
}
- /** Expression of the "text" method. */
- public static final class TextExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- return LKQLTypeSystemGen.asAnalysisUnit(frame.getArguments()[0]).getText();
+ @BuiltInMethod(name = "text", doc = "Return the text for this unit", isProperty = true)
+ abstract static class TextExpr extends BuiltInBody {
+ @Specialization
+ public String onUnit(AnalysisUnit self) {
+ return self.getText();
}
}
}
diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java
index 213be1e58..777768749 100644
--- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java
+++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java
@@ -5,57 +5,37 @@
package com.adacore.lkql_jit.built_ins.methods;
-import static com.adacore.lkql_jit.built_ins.BuiltInMethodFactory.createAttribute;
-
-import com.adacore.lkql_jit.LKQLTypeSystemGen;
-import com.adacore.lkql_jit.built_ins.AbstractBuiltInFunctionBody;
-import com.adacore.lkql_jit.built_ins.BuiltInMethodFactory;
-import com.adacore.lkql_jit.built_ins.functions.MapFunction;
-import com.adacore.lkql_jit.built_ins.functions.ReduceFunction;
+import com.adacore.lkql_jit.annotations.BuiltInMethod;
+import com.adacore.lkql_jit.annotations.BuiltinMethodContainer;
+import com.adacore.lkql_jit.built_ins.BuiltInBody;
import com.adacore.lkql_jit.runtime.values.LKQLTuple;
import com.adacore.lkql_jit.runtime.values.interfaces.Iterable;
import com.adacore.lkql_jit.runtime.values.lists.LKQLList;
import com.adacore.lkql_jit.utils.Iterator;
-import com.oracle.truffle.api.frame.VirtualFrame;
+import com.adacore.lkql_jit.utils.LKQLTypesHelper;
+import com.oracle.truffle.api.dsl.Specialization;
import java.util.LinkedList;
import java.util.List;
-import java.util.Map;
-/**
- * This class contains all built-in methods for the iterable type in the LKQL language.
- *
- * @author Hugo GUERRIER
- */
+/** This class contains all built-in methods for the iterable type in the LKQL language. */
+@BuiltinMethodContainer(
+ targetTypes = {
+ LKQLTypesHelper.LKQL_LAZY_LIST,
+ LKQLTypesHelper.LKQL_SELECTOR_LIST,
+ LKQLTypesHelper.LKQL_LIST
+ })
public class IterableMethods {
- public static final Map methods =
- Map.ofEntries(
- Map.entry(
- ReduceFunction.NAME,
- BuiltInMethodFactory.fromFunctionValue(
- ReduceFunction.getValue(), false)),
- Map.entry(
- MapFunction.NAME,
- BuiltInMethodFactory.fromFunctionValue(MapFunction.getValue(), false)),
- createAttribute(
- "enumerate",
- "Return the content of the iterable object with each element associated"
- + " to its index in a tuple: [(, ), ...]",
- new EnumerateExpr()),
- createAttribute(
- "to_list", "Transform an iterator into a list", new ToListExpr()),
- createAttribute(
- "length", "Get the length of the iterable element", new LengthExpr()));
-
- // ----- Inner classes -----
-
- /** Expression for the "enumerate" method. */
- public static class EnumerateExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- // Get the iterable receiver
- final var receiver = LKQLTypeSystemGen.asIterable(frame.getArguments()[0]);
-
+ @BuiltInMethod(
+ name = "enumerate",
+ doc =
+ """
+ Return the content of the iterable object with each element associated \
+ to its index in a tuple: [(, ), ...]""",
+ isProperty = true)
+ abstract static class EnumerateExpr extends BuiltInBody {
+ @Specialization
+ public LKQLList execute(LKQLList receiver) {
// Create the result array and fill it
final var resContent = new Object[(int) receiver.size()];
long index = 1;
@@ -70,16 +50,13 @@ public Object executeGeneric(VirtualFrame frame) {
}
}
- /** Expression of the "to_list" method. */
- public static class ToListExpr extends AbstractBuiltInFunctionBody {
- @Override
- public Object executeGeneric(VirtualFrame frame) {
- // Get the iterable receiver
- Iterable receiver = LKQLTypeSystemGen.asIterable(frame.getArguments()[0]);
-
+ @BuiltInMethod(name = "to_list", doc = "Transform into a list", isProperty = true)
+ abstract static class ToListExpr extends BuiltInBody {
+ @Specialization
+ public LKQLList onIterable(Iterable self) {
// Create a new list from the iterable
List