From a4ff0242e0cea3f996190103f4bfb60c9030c805 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 10 Oct 2023 09:54:09 +0200 Subject: [PATCH 01/23] Move the 'built_ins' package out of the 'runtime' pacakge Built-in packages commonly are outside of the runtime package in other Truffle language implementations (Graal Python, Graal Ruby...). --- .../main/java/com/adacore/lkql_jit/LKQLContext.java | 2 +- .../main/java/com/adacore/lkql_jit/LKQLLanguage.java | 2 +- .../{runtime => }/built_ins/BuiltInFactory.java | 8 ++++---- .../built_ins/BuiltInFunctionValue.java | 2 +- .../built_ins/BuiltInSelectorValue.java | 2 +- .../{runtime => }/built_ins/BuiltinFunctionBody.java | 2 +- .../built_ins/functions/BaseNameFunction.java | 4 ++-- .../built_ins/functions/ConcatFunction.java | 4 ++-- .../built_ins/functions/DocFunction.java | 4 ++-- .../built_ins/functions/HelpFunction.java | 4 ++-- .../built_ins/functions/ImgFunction.java | 4 ++-- .../built_ins/functions/MapFunction.java | 6 +++--- .../built_ins/functions/NodeCheckerFunction.java | 6 +++--- .../built_ins/functions/PatternFunction.java | 4 ++-- .../built_ins/functions/PrintFunction.java | 4 ++-- .../built_ins/functions/ProfileFunction.java | 4 ++-- .../built_ins/functions/ReduceFunction.java | 6 +++--- .../built_ins/functions/SpecifiedUnitsFunction.java | 4 ++-- .../built_ins/functions/UniqueFunction.java | 4 ++-- .../built_ins/functions/UnitCheckerFunction.java | 6 +++--- .../built_ins/functions/UnitsFunction.java | 4 ++-- .../built_ins/methods/AnalysisUnitMethods.java | 10 +++++----- .../{runtime => }/built_ins/methods/BoolMethods.java | 4 ++-- .../built_ins/methods/BuiltInMethods.java | 4 ++-- .../built_ins/methods/CommonMethods.java | 8 ++++---- .../built_ins/methods/FunctionMethods.java | 4 ++-- .../{runtime => }/built_ins/methods/IntMethods.java | 4 ++-- .../built_ins/methods/IterableMethods.java | 10 +++++----- .../built_ins/methods/LazyListMethods.java | 4 ++-- .../{runtime => }/built_ins/methods/ListMethods.java | 10 +++++----- .../built_ins/methods/NamespaceMethods.java | 4 ++-- .../{runtime => }/built_ins/methods/NodeMethods.java | 10 +++++----- .../built_ins/methods/ObjectMethods.java | 4 ++-- .../built_ins/methods/PropertyRefMethods.java | 4 ++-- .../built_ins/methods/SelectorListMethods.java | 4 ++-- .../built_ins/methods/SelectorMethods.java | 4 ++-- .../{runtime => }/built_ins/methods/StrMethods.java | 12 ++++++------ .../built_ins/methods/TokenMethods.java | 10 +++++----- .../built_ins/methods/TupleMethods.java | 4 ++-- .../{runtime => }/built_ins/methods/UnitMethods.java | 4 ++-- .../built_ins/selectors/BuiltInSelector.java | 2 +- .../built_ins/selectors/ChildrenSelector.java | 8 ++++---- .../built_ins/selectors/NextSiblingsSelector.java | 8 ++++---- .../built_ins/selectors/ParentSelector.java | 8 ++++---- .../built_ins/selectors/PrevSiblingsSelector.java | 8 ++++---- .../built_ins/selectors/ReadBuiltInThis.java | 2 +- .../built_ins/selectors/SuperTypesSelector.java | 8 ++++---- .../langkit_translator/passes/FramingPass.java | 2 +- .../adacore/lkql_jit/nodes/expressions/FunCall.java | 2 +- .../lkql_jit/nodes/expressions/dot/DotAccess.java | 2 +- .../nodes/expressions/dot/SafeDotAccess.java | 2 +- .../com/adacore/lkql_jit/runtime/GlobalScope.java | 2 +- 52 files changed, 129 insertions(+), 129 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/BuiltInFactory.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/BuiltInFunctionValue.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/BuiltInSelectorValue.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/BuiltinFunctionBody.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/BaseNameFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/ConcatFunction.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/DocFunction.java (95%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/HelpFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/ImgFunction.java (95%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/MapFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/NodeCheckerFunction.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/PatternFunction.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/PrintFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/ProfileFunction.java (95%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/ReduceFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/SpecifiedUnitsFunction.java (95%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/UniqueFunction.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/UnitCheckerFunction.java (98%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/functions/UnitsFunction.java (95%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/AnalysisUnitMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/BoolMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/BuiltInMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/CommonMethods.java (91%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/FunctionMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/IntMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/IterableMethods.java (92%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/LazyListMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/ListMethods.java (93%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/NamespaceMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/NodeMethods.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/ObjectMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/PropertyRefMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/SelectorListMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/SelectorMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/StrMethods.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/TokenMethods.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/TupleMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/methods/UnitMethods.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/BuiltInSelector.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/ChildrenSelector.java (93%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/NextSiblingsSelector.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/ParentSelector.java (93%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/PrevSiblingsSelector.java (94%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/ReadBuiltInThis.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => }/built_ins/selectors/SuperTypesSelector.java (94%) 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 5f1545756..1d815597b 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 @@ -23,10 +23,10 @@ package com.adacore.lkql_jit; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.declarations.FunctionDeclaration; import com.adacore.lkql_jit.runtime.GlobalScope; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLConfigFileResult; 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 261325bae..f7153a815 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 @@ -23,13 +23,13 @@ package com.adacore.lkql_jit; import com.adacore.liblkqllang.Liblkqllang; +import com.adacore.lkql_jit.built_ins.BuiltInFactory; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.langkit_translator.LangkitTranslator; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.TopLevelList; import com.adacore.lkql_jit.nodes.root_nodes.TopLevelRootNode; import com.adacore.lkql_jit.runtime.GlobalScope; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFactory; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.enums.DiagnosticOutputMode; import com.oracle.truffle.api.CallTarget; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFactory.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFactory.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFactory.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFactory.java index 89b4d21e0..57402c4f3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFactory.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFactory.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins; +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.built_ins.selectors.*; import com.adacore.lkql_jit.langkit_translator.passes.framing_utils.ScriptFramesBuilder; import com.adacore.lkql_jit.runtime.GlobalScope; -import com.adacore.lkql_jit.runtime.built_ins.functions.*; -import com.adacore.lkql_jit.runtime.built_ins.methods.*; -import com.adacore.lkql_jit.runtime.built_ins.selectors.*; import java.util.ArrayList; import java.util.List; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFunctionValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFunctionValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java index 05e0b619e..c176e4fec 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInFunctionValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInFunctionValue.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins; +package com.adacore.lkql_jit.built_ins; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInSelectorValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInSelectorValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java index 6f061b12e..bdb7c0ee6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltInSelectorValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins; +package com.adacore.lkql_jit.built_ins; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltinFunctionBody.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltinFunctionBody.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltinFunctionBody.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltinFunctionBody.java index c21213a5e..b67e7a205 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/BuiltinFunctionBody.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltinFunctionBody.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins; +package com.adacore.lkql_jit.built_ins; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/BaseNameFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/BaseNameFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java index def2708c8..c4f4e073d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/BaseNameFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/BaseNameFunction.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.FileUtils; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ConcatFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ConcatFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java index babb8a275..e5c4429b7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ConcatFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ConcatFunction.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/DocFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java similarity index 95% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/DocFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java index b571764aa..6e5519c7a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/DocFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/DocFunction.java @@ -20,12 +20,12 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/HelpFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/HelpFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java index bd2776b9b..b55c93716 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/HelpFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/HelpFunction.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.functions.StringUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ImgFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java similarity index 95% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ImgFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java index a9875738a..19eaf0fb5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ImgFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ImgFunction.java @@ -20,11 +20,11 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +package com.adacore.lkql_jit.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/MapFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/MapFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java index a2dc588ab..ce57d91b3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/MapFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/MapFunction.java @@ -20,15 +20,15 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.BuiltinFunctionBody; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/NodeCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/NodeCheckerFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java index 392dfb42b..88d052a22 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/NodeCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java @@ -20,19 +20,19 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +package com.adacore.lkql_jit.built_ins.functions; import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLContext; 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.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.runtime.values.UnitValue; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PatternFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PatternFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java index 626cb2c00..34bf50b73 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PatternFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PatternFunction.java @@ -20,14 +20,14 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.nodes.expressions.literals.BooleanLiteral; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PrintFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PrintFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java index 19d68ddc8..e3bc80bb3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/PrintFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/PrintFunction.java @@ -20,15 +20,15 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; import com.adacore.lkql_jit.nodes.expressions.literals.BooleanLiteral; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ProfileFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java similarity index 95% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ProfileFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java index c5f1f0b3c..eb937de44 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ProfileFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ProfileFunction.java @@ -20,12 +20,12 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ReduceFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ReduceFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java index 0b4ab8daf..204d03273 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/ReduceFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/ReduceFunction.java @@ -20,15 +20,15 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.BuiltinFunctionBody; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/SpecifiedUnitsFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java similarity index 95% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/SpecifiedUnitsFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java index ee7ef671f..884c895d0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/SpecifiedUnitsFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/SpecifiedUnitsFunction.java @@ -20,12 +20,12 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ListValue; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UniqueFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UniqueFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java index bea037836..897d23134 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UniqueFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UniqueFunction.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; import com.adacore.lkql_jit.utils.LKQLTypesHelper; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java similarity index 98% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitCheckerFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index c87169bca..c45e1f613 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -20,19 +20,19 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +package com.adacore.lkql_jit.built_ins.functions; import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLContext; 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.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.runtime.values.UnitValue; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitsFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java similarity index 95% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitsFunction.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java index 29fc24848..295063d59 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/functions/UnitsFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitsFunction.java @@ -20,12 +20,12 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.functions; +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.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ListValue; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/AnalysisUnitMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/AnalysisUnitMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java index 373c3dfc7..9f6ecd01a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/AnalysisUnitMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/AnalysisUnitMethods.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -65,7 +65,7 @@ public static AnalysisUnitMethods getInstance() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { @@ -108,7 +108,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BoolMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BoolMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BoolMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BoolMethods.java index e73a069b1..1f5309e01 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BoolMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BoolMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static BoolMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BuiltInMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BuiltInMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BuiltInMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BuiltInMethods.java index c54a7be26..e24cb8c6e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/BuiltInMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/BuiltInMethods.java @@ -20,9 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import java.util.Map; /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/CommonMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/CommonMethods.java similarity index 91% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/CommonMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/CommonMethods.java index 1f24d48dc..2197b10d8 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/CommonMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/CommonMethods.java @@ -20,10 +20,10 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.functions.*; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.functions.*; import java.util.HashMap; import java.util.Map; @@ -59,7 +59,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getMethods() + * @see BuiltInMethods#getMethods() */ @Override public Map getMethods() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/FunctionMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/FunctionMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/FunctionMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/FunctionMethods.java index b3e66f6c3..a11d1bfaf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/FunctionMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/FunctionMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static FunctionMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IntMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IntMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IntMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IntMethods.java index b2a52938a..c88c02b63 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IntMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IntMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static IntMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IterableMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java similarity index 92% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IterableMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java index 848022efd..a8c86e81a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/IterableMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/IterableMethods.java @@ -20,13 +20,13 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.functions.ReduceFunction; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; -import com.adacore.lkql_jit.runtime.built_ins.functions.ReduceFunction; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; @@ -42,7 +42,7 @@ public abstract class IterableMethods extends CommonMethods { /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/LazyListMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/LazyListMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/LazyListMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/LazyListMethods.java index 51dfbc5e2..d85e36814 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/LazyListMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/LazyListMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static LazyListMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ListMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java similarity index 93% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ListMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java index 9cf5a0691..14f4b9d48 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ListMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java @@ -20,14 +20,14 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.functions.UniqueFunction; 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.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.functions.UniqueFunction; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; @@ -65,7 +65,7 @@ public static ListMethods getInstance() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { @@ -123,7 +123,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NamespaceMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NamespaceMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NamespaceMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NamespaceMethods.java index 3746c28d3..a6ac3ff6a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NamespaceMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NamespaceMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static NamespaceMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NodeMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NodeMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java index a0f4dad26..6c7c6905a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/NodeMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java @@ -20,15 +20,15 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.libadalang.Libadalang; 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.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.UnitValue; @@ -72,7 +72,7 @@ public static NodeMethods getInstance() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { @@ -162,7 +162,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ObjectMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ObjectMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ObjectMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ObjectMethods.java index 5da96b388..0f4b7d388 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/ObjectMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ObjectMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static ObjectMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/PropertyRefMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/PropertyRefMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/PropertyRefMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/PropertyRefMethods.java index 7178ea1a5..69147a473 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/PropertyRefMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/PropertyRefMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static PropertyRefMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorListMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorListMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorListMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorListMethods.java index 4176d0396..e060fcb36 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorListMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorListMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static SelectorListMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorMethods.java index 44be81ac6..18fdce872 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/SelectorMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/SelectorMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static SelectorMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/StrMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/StrMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java index 3544ebc11..1171ff4f9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/StrMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java @@ -20,14 +20,14 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.functions.BaseNameFunction; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; -import com.adacore.lkql_jit.runtime.built_ins.functions.BaseNameFunction; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -68,7 +68,7 @@ public static StrMethods getInstance() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { @@ -181,7 +181,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TokenMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TokenMethods.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TokenMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TokenMethods.java index cf3c119cf..9cd8ffb2c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TokenMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TokenMethods.java @@ -20,15 +20,15 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; 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.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -67,7 +67,7 @@ public static TokenMethods getInstance() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.CommonMethods#initMethods() + * @see CommonMethods#initMethods() */ @Override protected void initMethods() { @@ -165,7 +165,7 @@ protected void initMethods() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TupleMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TupleMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TupleMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TupleMethods.java index e24171c1a..ac83893f6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/TupleMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/TupleMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static TupleMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/UnitMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/UnitMethods.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/UnitMethods.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/UnitMethods.java index 16a066998..7028202ef 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/methods/UnitMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/UnitMethods.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.methods; +package com.adacore.lkql_jit.built_ins.methods; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -58,7 +58,7 @@ public static UnitMethods getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.methods.BuiltInMethods#getType() + * @see BuiltInMethods#getType() */ @Override public String getType() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/BuiltInSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/BuiltInSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java index 5b22d9ba6..71062e805 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/BuiltInSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.runtime.values.SelectorValue; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ChildrenSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java similarity index 93% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ChildrenSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java index 19e72b5da..d666e6634 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ChildrenSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java @@ -20,8 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; +import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; @@ -31,7 +32,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; /** @@ -74,7 +74,7 @@ public static ChildrenSelector getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getName() + * @see BuiltInSelector#getName() */ @Override public String getName() { @@ -82,7 +82,7 @@ public String getName() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getValue() + * @see BuiltInSelector#getValue() */ @Override public SelectorValue getValue() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/NextSiblingsSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/NextSiblingsSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java index b6e08aa56..1b868e05c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/NextSiblingsSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java @@ -20,8 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; +import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -34,7 +35,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; /** @@ -77,7 +77,7 @@ public static NextSiblingsSelector getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getName() + * @see BuiltInSelector#getName() */ @Override public String getName() { @@ -85,7 +85,7 @@ public String getName() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getValue() + * @see BuiltInSelector#getValue() */ @Override public SelectorValue getValue() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ParentSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java similarity index 93% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ParentSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java index a5b837bee..728d7be43 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ParentSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java @@ -20,8 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; +import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; @@ -30,7 +31,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; /** @@ -73,7 +73,7 @@ public static ParentSelector getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getName() + * @see BuiltInSelector#getName() */ @Override public String getName() { @@ -81,7 +81,7 @@ public String getName() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getValue() + * @see BuiltInSelector#getValue() */ @Override public SelectorValue getValue() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/PrevSiblingsSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/PrevSiblingsSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java index 3f6911f88..61207f5f4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/PrevSiblingsSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java @@ -20,8 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; +import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -34,7 +35,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; /** @@ -77,7 +77,7 @@ public static PrevSiblingsSelector getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getName() + * @see BuiltInSelector#getName() */ @Override public String getName() { @@ -85,7 +85,7 @@ public String getName() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getValue() + * @see BuiltInSelector#getValue() */ @Override public SelectorValue getValue() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ReadBuiltInThis.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ReadBuiltInThis.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ReadBuiltInThis.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ReadBuiltInThis.java index 2b2e48b37..562e2385a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/ReadBuiltInThis.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ReadBuiltInThis.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/SuperTypesSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java similarity index 94% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/SuperTypesSelector.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java index 6db62c0a5..d57dc791b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/built_ins/selectors/SuperTypesSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java @@ -20,8 +20,9 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.built_ins.selectors; +package com.adacore.lkql_jit.built_ins.selectors; +import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInSelectorValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; /** @@ -78,7 +78,7 @@ public static SuperTypesSelector getInstance() { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getName() + * @see BuiltInSelector#getName() */ @Override public String getName() { @@ -86,7 +86,7 @@ public String getName() { } /** - * @see com.adacore.lkql_jit.runtime.built_ins.selectors.BuiltInSelector#getValue() + * @see BuiltInSelector#getValue() */ @Override public SelectorValue getValue() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/langkit_translator/passes/FramingPass.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/langkit_translator/passes/FramingPass.java index 1355a9349..384a3ed8c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/langkit_translator/passes/FramingPass.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/langkit_translator/passes/FramingPass.java @@ -23,10 +23,10 @@ package com.adacore.lkql_jit.langkit_translator.passes; import com.adacore.liblkqllang.Liblkqllang; +import com.adacore.lkql_jit.built_ins.BuiltInFactory; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.TranslatorException; import com.adacore.lkql_jit.langkit_translator.passes.framing_utils.ScriptFramesBuilder; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFactory; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index 4acf021c1..da867dfaf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -23,12 +23,12 @@ package com.adacore.lkql_jit.nodes.expressions; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; import com.adacore.lkql_jit.utils.LKQLTypesHelper; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index 26eeb02d4..7d8833e27 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -25,12 +25,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.NamespaceValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.ObjectValue; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java index ff3f44e6f..da728af64 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java @@ -25,12 +25,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java index 53d948ec3..47174c1e0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java @@ -22,7 +22,7 @@ package com.adacore.lkql_jit.runtime; -import com.adacore.lkql_jit.runtime.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.oracle.truffle.api.CompilerDirectives; import java.util.HashMap; From ee73549e8ca59afc9d4613a6173b34e55883910c Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Thu, 23 Nov 2023 12:30:53 +0100 Subject: [PATCH 02/23] Add a test driver to run arbitrary Java applications --- testsuite/drivers/java_driver.py | 61 ++++++++++++++++++++++++++++++++ testsuite/testsuite.py | 3 +- 2 files changed, 63 insertions(+), 1 deletion(-) create mode 100644 testsuite/drivers/java_driver.py diff --git a/testsuite/drivers/java_driver.py b/testsuite/drivers/java_driver.py new file mode 100644 index 000000000..cca783bb1 --- /dev/null +++ b/testsuite/drivers/java_driver.py @@ -0,0 +1,61 @@ +import os + +from drivers.base_driver import BaseDriver +from e3.testsuite.driver.classic import TestAbortWithFailure + + +class JavaDriver(BaseDriver): + """ + This driver runs the provided Java application in the GraalVM with a direct + access to the LKQL JIT Truffle language. This driver is mainly used to + test the LKQL Truffle interoperability features. + + The Java application to run must be placed into a file named `Main.java` + in the test directory. + """ + + def run(self) -> None: + # Get and check the test Java main file + main_java_file = self.working_dir("Main.java") + if not os.path.isfile(main_java_file): + raise TestAbortWithFailure("Missing 'Main.java' file") + + # Get the needed environment variable + graal_home = os.environ["GRAAL_HOME"] + lkql_jit_home = os.environ.get( + "LKQL_JIT_HOME", os.path.join(graal_home, "languages", "lkql") + ) + + # Get the GraalVM Java executable + java = ( + os.path.join(graal_home, "bin", "java.exe") + if os.name == "nt" + else os.path.join(graal_home, "bin", "java") + ) + + # Create the class path + class_path = os.pathsep.join( + [ + os.path.join(graal_home, "lib", "truffle", "truffle-api.jar"), + os.path.join(lkql_jit_home, "lkql_jit.jar"), + ] + ) + + # Create the value for java.library.path property + java_library_path = ( + os.environ.get("PATH", "") + if os.name == "nt" + else os.environ.get("LD_LIBRARY_PATH", "") + ) + + # Run Java with the main file + self.check_run( + [ + java, + "-cp", + class_path, + f"-Djava.library.path={java_library_path}", + f"-Dtruffle.class.path.append={os.path.join(lkql_jit_home, 'lkql_jit.jar')}", + main_java_file, + ] + ) diff --git a/testsuite/testsuite.py b/testsuite/testsuite.py index cc7fdb8c9..403d2bd3a 100755 --- a/testsuite/testsuite.py +++ b/testsuite/testsuite.py @@ -14,7 +14,7 @@ from e3.testsuite.testcase_finder import ProbingError, YAMLTestFinder, TestFinderResult from drivers import ( - checker_driver, gnatcheck_driver, interpreter_driver, parser_driver + checker_driver, gnatcheck_driver, interpreter_driver, parser_driver, java_driver ) class PerfTestFinder(YAMLTestFinder): @@ -80,6 +80,7 @@ class LKQLTestsuite(Testsuite): tests_subdir = "tests" test_driver_map = {'parser': parser_driver.ParserDriver, 'interpreter': interpreter_driver.InterpreterDriver, + 'java': java_driver.JavaDriver, 'checker': checker_driver.CheckerDriver, 'gnatcheck': gnatcheck_driver.GnatcheckDriver} From 649b9bb82cf29b484c86ab1f522b1b43d77fdcf0 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 10 Oct 2023 14:34:19 +0200 Subject: [PATCH 03/23] Rework the representation of the namespace values Add lib dispatching and specialization limits in Constants --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 3 +- .../built_ins/values/LKQLNamespace.java | 282 ++++++++++++++++++ .../adacore/lkql_jit/nodes/TopLevelList.java | 4 +- .../lkql_jit/nodes/declarations/Import.java | 10 +- .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../nodes/expressions/dot/DotAccess.java | 13 +- .../nodes/expressions/operators/BinEq.java | 14 +- .../nodes/expressions/operators/BinNeq.java | 14 +- .../runtime/values/NamespaceValue.java | 115 ------- .../com/adacore/lkql_jit/utils/Constants.java | 14 + .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- .../utils/functions/ParsingUtils.java | 25 +- testsuite/tests/interop/namespace/Main.java | 30 ++ testsuite/tests/interop/namespace/test.out | 7 + testsuite/tests/interop/namespace/test.yaml | 1 + 15 files changed, 390 insertions(+), 149 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NamespaceValue.java create mode 100644 testsuite/tests/interop/namespace/Main.java create mode 100644 testsuite/tests/interop/namespace/test.out create mode 100644 testsuite/tests/interop/namespace/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 1f6b4b325..007c99851 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.*; @@ -59,7 +60,7 @@ Libadalang.AnalysisUnit.class, boolean.class, ObjectValue.class, - NamespaceValue.class, + LKQLNamespace.class, Nullish.class, LKQLValue.class, }) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java new file mode 100644 index 000000000..28e72820e --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -0,0 +1,282 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.runtime.Cell; +import com.adacore.lkql_jit.runtime.values.ListValue; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.utils.Constants; +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.TruffleLanguage; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.FrameDescriptor; +import com.oracle.truffle.api.frame.MaterializedFrame; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.object.DynamicObjectLibrary; +import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.api.utilities.TriState; +import java.util.Arrays; +import java.util.HashMap; +import java.util.Map; +import java.util.Objects; + +/** This class represents the namespaces in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLNamespace extends DynamicObject implements LKQLValue { + + // ----- Attributes ----- + + /** The dynamic object library to perform uncached operations on the LKQL namespace. */ + private static final DynamicObjectLibrary objectLibrary = DynamicObjectLibrary.getUncached(); + + // ----- Constructors ----- + + /** Create a new LKQL namespace with its shape. */ + public LKQLNamespace(Shape shape) { + super(shape); + } + + // ----- Class methods ----- + + /** Create a namespace from the given Truffle frame and its store values. */ + @CompilerDirectives.TruffleBoundary + public static LKQLNamespace createUncached(MaterializedFrame frame) { + // Prepare the map for the symbols + final Map symbols = new HashMap<>(); + + // Get the frame descriptor and iterate on the frame slots to get the symbols + final FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); + for (int i = 0; i < frameDescriptor.getNumberOfSlots(); i++) { + final String name = (String) frameDescriptor.getSlotName(i); + if (name != null) { + symbols.put(name, ((Cell) frame.getObject(i)).getRef()); + } + } + + // Return the new namespace + LKQLNamespace res = new LKQLNamespace(Shape.newBuilder().build()); + for (String key : symbols.keySet()) { + objectLibrary.put(res, key, symbols.get(key)); + } + return res; + } + + // ----- Instance methods ----- + + /** + * Get the value in the LKQL namespace at the given key with the uncached strategy. This method + * uses an uncached library so this is not design for performance critical usages. + */ + public Object getUncached(final Object key) { + return objectLibrary.getOrDefault(this, key, null); + } + + /** + * Get the key array from the namespace value. This method uses an uncached library so this is + * not designed for performance critical usages. + */ + public Object[] keysUncached() { + return objectLibrary.getKeyArray(this); + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL namespaces. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL namespaces. */ + @Specialization + protected static TriState onLKQLNamespace( + final LKQLNamespace left, final LKQLNamespace right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLNamespace receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL namespace. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLNamespace receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + Object toDisplayString( + @SuppressWarnings("unused") final boolean allowSideEffects, + @CachedLibrary("this") DynamicObjectLibrary thisLibrary, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { + // Prepare the result string builder and get the keys of the object + StringBuilder resultBuilder = new StringBuilder("Namespace("); + Object[] keys = thisLibrary.getKeyArray(this); + + // Iterate over keys and add the values + for (int i = 0; i < keys.length; i++) { + // Get key/value + Object key = keys[i]; + Object value = thisLibrary.getOrDefault(this, key, null); + + // Create the string of the value + String valueString; + if (value instanceof String) { + valueString = StringUtils.toRepr((String) interopLibrary.toDisplayString(value)); + } else { + valueString = (String) interopLibrary.toDisplayString(value); + } + + // Add the strings to the result + resultBuilder.append(key).append(": ").append(valueString); + if (i < keys.length - 1) resultBuilder.append(", "); + } + + // Return the string result + resultBuilder.append(")"); + return resultBuilder.toString(); + } + + /** Tell the interop library that this value has members. */ + @ExportMessage + boolean hasMembers() { + return true; + } + + /** + * Get if the given member is in the receiver namespace. All members are readable but not + * modifiable. + */ + @ExportMessage + boolean isMemberReadable( + final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return objectLibrary.containsKey(this, member); + } + + /** Get the existing members for the receiver namespace. */ + @ExportMessage + Object getMembers( + @SuppressWarnings("unused") final boolean includeInternal, + @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return new ListValue(objectLibrary.getKeyArray(this)); + } + + /** Get the value of the wanted member in the receiver namespace. */ + @ExportMessage + Object readMember( + final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) + throws UnknownIdentifierException { + final Object result = objectLibrary.getOrDefault(this, member, null); + if (result == null) throw UnknownIdentifierException.create(member); + return result; + } + + // ----- LKQL value methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(LKQLValue o) { + if (this == o) return true; + if (!(o instanceof LKQLNamespace other)) return false; + + // Create the libraries to access object fields + DynamicObjectLibrary thisLib = DynamicObjectLibrary.getFactory().getUncached(this); + DynamicObjectLibrary otherLib = DynamicObjectLibrary.getFactory().getUncached(other); + + // Get the keys + Object[] thisKeys = thisLib.getKeyArray(this); + Object[] otherKeys = otherLib.getKeyArray(other); + + // Check the key array length + if (thisKeys.length != otherKeys.length) return false; + + // Iterate over the keys and verify their values + for (Object key : thisKeys) { + // Ensure that the other contains the key + if (!otherLib.containsKey(other, key)) return false; + + // Compare the values + Object thisObject = thisLib.getOrDefault(this, key, null); + Object otherObject = otherLib.getOrDefault(other, key, null); + if ((thisObject instanceof LKQLValue thisValue) + && (otherObject instanceof LKQLValue otherValue)) { + if (!thisValue.internalEquals(otherValue)) return false; + } else { + if (!Objects.equals(thisObject, otherObject)) return false; + } + } + return true; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary interopLibrary = InteropLibrary.getUncached(this); + return (String) interopLibrary.toDisplayString(this); + } + + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof LKQLNamespace other)) return false; + return this.internalEquals(other); + } + + @Override + public int hashCode() { + Object[] keys = this.keysUncached(); + Object[] values = new Object[keys.length]; + for (int i = 0; i < keys.length; i++) { + values[i] = this.getUncached(keys[i]); + } + return Arrays.hashCode(ArrayUtils.concat(keys, values)); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/TopLevelList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/TopLevelList.java index 65ad492b8..9e5ef1440 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/TopLevelList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/TopLevelList.java @@ -24,8 +24,8 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.nodes.declarations.Import; -import com.adacore.lkql_jit.runtime.values.NamespaceValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.CompilerDirectives; @@ -103,7 +103,7 @@ public Object executeGeneric(VirtualFrame frame) { final LKQLContext context = LKQLLanguage.getContext(this); // Return the namespace corresponding to the program execution - return context.getEnv().asGuestValue(NamespaceValue.create(frame.materialize())); + return LKQLNamespace.createUncached(frame.materialize()); } // ----- Class methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java index deb0deec3..3991e5819 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java @@ -24,9 +24,9 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.NamespaceValue; import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.FrameUtils; @@ -50,7 +50,7 @@ public final class Import extends LKQLNode { // ----- Attributes ----- /** A cache to avoid importing same module multiple times. */ - private static final Map importCache = new HashMap<>(); + private static final Map importCache = new HashMap<>(); /** Name of the module to import. */ private final String name; @@ -89,7 +89,7 @@ public Import(SourceLocation location, String name, int slot) { public Object executeGeneric(VirtualFrame frame) { // Execute the module file try { - NamespaceValue module = this.importModule(this.moduleFile); + LKQLNamespace module = this.importModule(this.moduleFile); // TODO: Create a new ImportInternal node to avoid this runtime check if (this.slot != -1) { FrameUtils.writeLocal(frame, this.slot, module); @@ -110,7 +110,7 @@ public Object executeGeneric(VirtualFrame frame) { * @throws IOException If Truffle cannot create a source from the file. */ @CompilerDirectives.TruffleBoundary - private NamespaceValue importModule(File moduleFile) throws IOException { + private LKQLNamespace importModule(File moduleFile) throws IOException { // If the file is already in the cache if (importCache.containsKey(moduleFile)) { return importCache.get(moduleFile); @@ -131,7 +131,7 @@ private NamespaceValue importModule(File moduleFile) throws IOException { // Get the current context and parse the file with the internal strategy CallTarget target = context.getEnv().parseInternal(source); - NamespaceValue res = (NamespaceValue) context.getEnv().asHostObject(target.call()); + LKQLNamespace res = (LKQLNamespace) target.call(); importCache.put(moduleFile, res); return res; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 9b8df8e5c..5e5a52467 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; @@ -240,8 +241,8 @@ public ObjectValue executeObject(VirtualFrame frame) throws UnexpectedResultExce * @return The result of the node execution as a namespace value. * @throws UnexpectedResultException If the node cannot be evaluated as a namespace. */ - public NamespaceValue executeNamespace(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectNamespaceValue(executeGeneric(frame)); + public LKQLNamespace executeNamespace(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLNamespace(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index 7d8833e27..f9e0bc94c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -26,15 +26,16 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NamespaceValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.runtime.values.PropertyRefValue; +import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.CompilerDirectives; @@ -42,6 +43,8 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.object.DynamicObjectLibrary; import java.util.Map; /** @@ -110,8 +113,10 @@ protected Object onObject(ObjectValue receiver) { * @param receiver The namespace. * @return The member of the namespace. */ - @Specialization - protected Object onNamespace(NamespaceValue receiver) { + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected Object onNamespace( + final LKQLNamespace receiver, + @CachedLibrary("receiver") DynamicObjectLibrary receiverLibrary) { // Try to get the built in Object builtIn = this.tryBuildIn(receiver); if (builtIn != null) { @@ -119,7 +124,7 @@ protected Object onNamespace(NamespaceValue receiver) { } // Get the namespace member - Object res = receiver.get(this.member.getName()); + Object res = receiverLibrary.getOrDefault(receiver, this.member.getName(), null); if (res != null) { return res; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 57aae53c6..6a5ce84cf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -23,12 +23,16 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.runtime.values.*; +import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; 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; import java.math.BigInteger; /** @@ -254,9 +258,13 @@ protected boolean eqObjects(ObjectValue left, ObjectValue right) { * @param right The right namespace value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqNamespaces(NamespaceValue left, NamespaceValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqNamespaces( + final LKQLNamespace left, + final LKQLNamespace right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 7f3c24fbe..e51f9131e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -23,12 +23,16 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.runtime.values.*; +import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; 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; import java.math.BigInteger; /** @@ -268,9 +272,13 @@ protected boolean neqObjects(ObjectValue left, ObjectValue right) { * @param right The right namespace value * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqNamespaces(NamespaceValue left, NamespaceValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqNamespaces( + final LKQLNamespace left, + final LKQLNamespace right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NamespaceValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NamespaceValue.java deleted file mode 100644 index af998710e..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NamespaceValue.java +++ /dev/null @@ -1,115 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.runtime.Cell; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.frame.FrameDescriptor; -import com.oracle.truffle.api.frame.MaterializedFrame; -import java.util.HashMap; -import java.util.Map; - -/** - * This class represents the namespace values in the LKQL language. - * - * @author Hugo GUERRIER - */ -public final class NamespaceValue implements LKQLValue { - - // ----- Attributes ----- - - /** Map which contains the symbols in the namespace. */ - private final Map symbols; - - // ----- Constructors ----- - - /** - * Create a new namespace with its name and bindings. - * - * @param symbols The symbols in the namespace. - */ - public NamespaceValue(final Map symbols) { - this.symbols = symbols; - } - - /** - * Create a namespace from the given frame. - * - * @param frame The frame to create the namespace from. - * @return The newly created namespace. - */ - @CompilerDirectives.TruffleBoundary - public static NamespaceValue create(final MaterializedFrame frame) { - // Prepare the map for the symbols - final Map symbols = new HashMap<>(); - - // Get the frame descriptor to iterate on the frame slots - final FrameDescriptor frameDescriptor = frame.getFrameDescriptor(); - for (int i = 0; i < frameDescriptor.getNumberOfSlots(); i++) { - final String name = (String) frameDescriptor.getSlotName(i); - if (name != null) { - symbols.put(name, ((Cell) frame.getObject(i)).getRef()); - } - } - - // Return the new namespace - return new NamespaceValue(symbols); - } - - // ----- Getters ----- - - /** - * Get a value from the namespace with its name. - * - * @param symbol The name of the value to get. - * @return The value if it exists, null else. - */ - @CompilerDirectives.TruffleBoundary - public Object get(final String symbol) { - return this.symbols.getOrDefault(symbol, null); - } - - // ----- Value methods ----- - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof NamespaceValue other)) return false; - return this.symbols.equals(other.symbols); - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - // Return the string - return "Namespace "; - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java index e1d41519b..844e40872 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java @@ -29,6 +29,20 @@ */ public class Constants { + // ----- JIT configuration ---- + + /** + * Number of internally dispatched specialized Truffle library. For more information see + * https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/library/CachedLibrary.html#limit-- + */ + public static final String DISPATCHED_LIB_LIMIT = "4"; + + /** + * Number of specialization instantiations. For more information see + * https://www.graalvm.org/truffle/javadoc/com/oracle/truffle/api/dsl/Specialization.html#limit-- + */ + public static final String SPECIALIZED_LIB_LIMIT = "3"; + // ----- LKQL values ----- /** Identifier of LKQL in the GraalVM system. */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 8f33535db..fb1627004 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -162,7 +162,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_BOOLEAN; } else if (LKQLTypeSystemGen.isObjectValue(obj)) { return LKQL_OBJECT; - } else if (LKQLTypeSystemGen.isNamespaceValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLNamespace(obj)) { return LKQL_NAMESPACE; } else { return defaultValue; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java index 87d7a9fb0..53c3abedd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java @@ -25,14 +25,15 @@ import com.adacore.liblkqllang.Liblkqllang; import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.langkit_translator.LangkitTranslator; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.NamespaceValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLConfigFileResult; import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.object.DynamicObjectLibrary; import com.oracle.truffle.api.source.Source; import java.io.IOException; import java.util.ArrayList; @@ -139,13 +140,13 @@ public static LKQLConfigFileResult parseLKQLConfigFile( final CallTarget callTarget = context.getEnv().parseInternal(source); // Get the namespace of the LKQL config file to extract rule configuration - final NamespaceValue namespace = - (NamespaceValue) context.getEnv().asHostObject(callTarget.call()); + final LKQLNamespace namespace = (LKQLNamespace) callTarget.call(); + final DynamicObjectLibrary objectLibrary = + DynamicObjectLibrary.getFactory().create(namespace); // Get the rules - final Object allRulesSource = namespace.get("rules"); - if (LKQLTypeSystemGen.isObjectValue(allRulesSource)) { - final ObjectValue allRulesObject = LKQLTypeSystemGen.asObjectValue(allRulesSource); + final Object allRulesSource = objectLibrary.getOrDefault(namespace, "rules", null); + if (allRulesSource instanceof ObjectValue allRulesObject) { processRulesObject(allRulesObject, allRules, aliases, args); } else { throw LKQLRuntimeException.fromMessage( @@ -153,17 +154,15 @@ public static LKQLConfigFileResult parseLKQLConfigFile( } // Get the Ada rules (not mandatory) - final Object adaRulesSource = namespace.get("ada_rules"); - if (LKQLTypeSystemGen.isObjectValue(adaRulesSource)) { - final ObjectValue adaRulesObject = LKQLTypeSystemGen.asObjectValue(adaRulesSource); + final Object adaRulesSource = objectLibrary.getOrDefault(namespace, "ada_rules", null); + if (adaRulesSource instanceof ObjectValue adaRulesObject) { processRulesObject(adaRulesObject, adaRules, aliases, args); } // Get the SPARK rules (not mandatory) - final Object sparkRulesSource = namespace.get("spark_rules"); - if (LKQLTypeSystemGen.isObjectValue(sparkRulesSource)) { - final ObjectValue sparkRulesObject = - LKQLTypeSystemGen.asObjectValue(sparkRulesSource); + final Object sparkRulesSource = + objectLibrary.getOrDefault(namespace, "spark_rules", null); + if (sparkRulesSource instanceof ObjectValue sparkRulesObject) { processRulesObject(sparkRulesObject, sparkRules, aliases, args); } diff --git a/testsuite/tests/interop/namespace/Main.java b/testsuite/tests/interop/namespace/Main.java new file mode 100644 index 000000000..7b456147d --- /dev/null +++ b/testsuite/tests/interop/namespace/Main.java @@ -0,0 +1,30 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val x = 42 + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + System.out.println("=== Namespace interop messages:"); + print("toString()", namespace.toString()); + print("hasMembers()", namespace.hasMembers()); + print("hasMember('x')", namespace.hasMember("x")); + print("hasMember('y')", namespace.hasMember("y")); + print("getMember('x')", namespace.getMember("x")); + print("getMember('y')", namespace.getMember("y")); + // TODO (LATER IN MR): Call "getMemberKeys" when list values are interop + } +} diff --git a/testsuite/tests/interop/namespace/test.out b/testsuite/tests/interop/namespace/test.out new file mode 100644 index 000000000..7624beb75 --- /dev/null +++ b/testsuite/tests/interop/namespace/test.out @@ -0,0 +1,7 @@ +=== Namespace interop messages: + toString(): Namespace(x: 42) + hasMembers(): true + hasMember('x'): true + hasMember('y'): false + getMember('x'): 42 + getMember('y'): null diff --git a/testsuite/tests/interop/namespace/test.yaml b/testsuite/tests/interop/namespace/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/namespace/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 2ba89ffe4ac3b80b296938743e47ff78d36f7943 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 22 Aug 2023 11:39:54 +0200 Subject: [PATCH 04/23] Rework the representation of the tuple values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 3 +- .../lkql_jit/built_ins/values/LKQLTuple.java | 215 ++++++++++++++++++ .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../lkql_jit/nodes/expressions/Indexing.java | 32 +++ .../expressions/literals/TupleLiteral.java | 8 +- .../nodes/expressions/operators/BinEq.java | 11 +- .../nodes/expressions/operators/BinNeq.java | 11 +- .../lkql_jit/runtime/values/TupleValue.java | 121 ---------- .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- testsuite/tests/interop/tuple/Main.java | 30 +++ testsuite/tests/interop/tuple/test.out | 7 + testsuite/tests/interop/tuple/test.yaml | 1 + 12 files changed, 312 insertions(+), 134 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/TupleValue.java create mode 100644 testsuite/tests/interop/tuple/Main.java create mode 100644 testsuite/tests/interop/tuple/test.out create mode 100644 testsuite/tests/interop/tuple/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 007c99851..1cf560b67 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.*; @@ -48,7 +49,7 @@ FunctionValue.class, PropertyRefValue.class, SelectorValue.class, - TupleValue.class, + LKQLTuple.class, ListValue.class, LazyListValue.class, SelectorListValue.class, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java new file mode 100644 index 000000000..b9e347f10 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -0,0 +1,215 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.exception.utils.InvalidIndexException; +import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.utils.Constants; +import com.adacore.lkql_jit.utils.functions.StringUtils; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +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.interop.InvalidArrayIndexException; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; +import java.util.Arrays; +import java.util.Objects; + +/** This class represents a tuple in LKQL. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLTuple implements TruffleObject, Indexable { + + // ----- Attributes ----- + + /** The content of the tuple. */ + private final Object[] content; + + // ----- Constructors ----- + + /** Create a new tuple with its content. */ + public LKQLTuple(final Object[] content) { + this.content = content; + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + public boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + public Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two tuples. */ + @ExportMessage + public static class IsIdenticalOrUndefined { + /** Compare two LKQL tuples. */ + @Specialization + public static TriState onTuple(final LKQLTuple left, final LKQLTuple right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + public static TriState onOther( + @SuppressWarnings("unused") final LKQLTuple receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL tuple. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(final LKQLTuple receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public Object toDisplayString( + @SuppressWarnings("unused") final boolean allowSideEffect, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { + // Prepare the result + StringBuilder resultBuilder = new StringBuilder("("); + + // Iterate over the list values + for (int i = 0; i < this.content.length; i++) { + Object elem = this.content[i]; + + // Get the element string + String elemString; + if (elem instanceof String) { + elemString = StringUtils.toRepr((String) interopLibrary.toDisplayString(elem)); + } else { + elemString = (String) interopLibrary.toDisplayString(elem); + } + + // Add the element string to the result + resultBuilder.append(elemString); + if (i < this.content.length - 1) resultBuilder.append(", "); + } + + // Return the result + resultBuilder.append(")"); + return resultBuilder.toString(); + } + + /** Tell the interop library that the value is array like. */ + @ExportMessage + public boolean hasArrayElements() { + return true; + } + + /** Get the array size for the interop library. */ + @ExportMessage + public long getArraySize() { + return this.content.length; + } + + /** Tell the interop library if the wanted index is readable. */ + @ExportMessage + public boolean isArrayElementReadable(final long index) { + return index < this.content.length && index >= 0; + } + + /** Get the array element of the given index. */ + @ExportMessage + public Object readArrayElement(final long index) throws InvalidArrayIndexException { + try { + return this.content[(int) index]; + } catch (IndexOutOfBoundsException e) { + throw InvalidArrayIndexException.create(index, e); + } + } + + // ----- Indexable methods ----- + + @Override + public Object get(int index) throws InvalidIndexException { + try { + return this.content[index]; + } catch (IndexOutOfBoundsException e) { + throw new InvalidIndexException(); + } + } + + @Override + public Object[] getContent() { + return this.content; + } + + // ----- LKQL value methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(final LKQLValue o) { + if (o == this) return true; + if (!(o instanceof LKQLTuple other)) return false; + if (other.content.length != this.content.length) return false; + for (int i = 0; i < this.content.length; i++) { + Object mineObject = this.content[i]; + Object hisObject = other.content[i]; + if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { + if (!mine.internalEquals(his)) return false; + } else { + if (!Objects.equals(mineObject, hisObject)) return false; + } + } + return true; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary tupleLib = InteropLibrary.getUncached(this); + return (String) tupleLib.toDisplayString(this); + } + + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof LKQLTuple other)) return false; + return this.internalEquals(other); + } + + @Override + public int hashCode() { + return Arrays.hashCode(this.content); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 5e5a52467..e8038d93e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; @@ -163,8 +164,8 @@ public SelectorValue executeSelector(VirtualFrame frame) throws UnexpectedResult * @return The result of the node execution as a tuple value. * @throws UnexpectedResultException If the node cannot be evaluated as a tuple. */ - public TupleValue executeTuple(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectTupleValue(executeGeneric(frame)); + public LKQLTuple executeTuple(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLTuple(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java index 6e6668781..c1a109cb2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java @@ -24,16 +24,22 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; +import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.InvalidArrayIndexException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; /** * This node represents the indexing operation in the LKQL language. @@ -64,6 +70,32 @@ protected Indexing(SourceLocation location, boolean isSafe) { // ----- Execution methods ----- + /** + * Execute the indexing operation on a truffle tuple. + * + * @param tuple The tuple to index + * @param index The index of the element to get. + * @return The element at the given index in the tuple, unit if the index is invalid and the + * indexing is safe else raise a runtime error. + */ + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected Object indexTuple( + final LKQLTuple tuple, + final long index, + @CachedLibrary("tuple") InteropLibrary tupleLibrary) { + try { + return tupleLibrary.readArrayElement(tuple, index - 1); + } catch (InvalidArrayIndexException e) { + if (this.isSafe) { + return UnitValue.getInstance(); + } else { + throw LKQLRuntimeException.invalidIndex((int) index, this); + } + } catch (UnsupportedMessageException e) { + throw LKQLRuntimeException.fromJavaException(e, this); + } + } + /** * Get a value in the collection with a long index. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/TupleLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/TupleLiteral.java index 2574ba953..fcc2fd7b4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/TupleLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/TupleLiteral.java @@ -22,10 +22,11 @@ package com.adacore.lkql_jit.nodes.expressions.literals; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.TupleValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; /** * This node represents a tuple literal declaration in the LKQL language. @@ -68,7 +69,8 @@ public Object executeGeneric(VirtualFrame frame) { * com.adacore.lkql_jit.nodes.expressions.Expr#executeTuple(com.oracle.truffle.api.frame.VirtualFrame) */ @Override - public TupleValue executeTuple(VirtualFrame frame) { + @ExplodeLoop + public LKQLTuple executeTuple(VirtualFrame frame) { // Evaluate the tuple values Object[] values = new Object[this.exprs.length]; for (int i = 0; i < this.exprs.length; i++) { @@ -76,7 +78,7 @@ public TupleValue executeTuple(VirtualFrame frame) { } // Return the tuple value - return new TupleValue(values); + return new LKQLTuple(values); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 6a5ce84cf..cc3e1e154 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -162,9 +163,13 @@ protected boolean eqSelectors(SelectorValue left, SelectorValue right) { * @param right The right tuple value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqTuples(TupleValue left, TupleValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqTuples( + final LKQLTuple left, + final LKQLTuple right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index e51f9131e..988e4f75d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -163,9 +164,13 @@ protected boolean neqSelectors(SelectorValue left, SelectorValue right) { * @param right The right tuple value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqTuples(TupleValue left, TupleValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqTuples( + final LKQLTuple left, + final LKQLTuple right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/TupleValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/TupleValue.java deleted file mode 100644 index 5e71537b7..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/TupleValue.java +++ /dev/null @@ -1,121 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.utils.functions.StringUtils; -import com.oracle.truffle.api.CompilerDirectives; -import java.util.Objects; - -/** - * This class represents the tuple values in the LKQL language. - * - * @author Hugo GUERRIER - */ -public final class TupleValue implements Indexable { - - // ----- Attributes ----- - - /** The values contained in the tuple. */ - private final Object[] content; - - // ----- Constructors ----- - - /** - * Create a new tuple value. - * - * @param content The content of the tuple. - */ - public TupleValue(Object[] content) { - this.content = content; - } - - // ----- Value methods ----- - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#get(int) - */ - @Override - public Object get(int index) throws InvalidIndexException { - if (index < 0 || index >= this.content.length) { - throw new InvalidIndexException(); - } - return this.content[index]; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#getContent() - */ - @Override - public Object[] getContent() { - return this.content; - } - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof TupleValue other)) return false; - if (other.content.length != this.content.length) return false; - for (int i = 0; i < this.content.length; i++) { - Object mineObject = this.content[i]; - Object hisObject = other.content[i]; - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - // Create the tuple string in a builder - StringBuilder builder = new StringBuilder(); - builder.append('('); - for (int i = 0; i < this.content.length; i++) { - if (this.content[i] == null) { - builder.append("null"); - } else if (this.content[i] instanceof String s) { - builder.append(StringUtils.toRepr(s)); - } else { - builder.append(this.content[i].toString()); - } - if (i < this.content.length - 1) builder.append(", "); - } - builder.append(')'); - - // Return the tuple string representation - return builder.toString(); - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index fb1627004..10c83e2cb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -144,7 +144,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_PROPERTY_REF; } else if (LKQLTypeSystemGen.isSelectorValue(obj)) { return LKQL_SELECTOR; - } else if (LKQLTypeSystemGen.isTupleValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLTuple(obj)) { return LKQL_TUPLE; } else if (LKQLTypeSystemGen.isListValue(obj)) { return LKQL_LIST; diff --git a/testsuite/tests/interop/tuple/Main.java b/testsuite/tests/interop/tuple/Main.java new file mode 100644 index 000000000..e31b645fc --- /dev/null +++ b/testsuite/tests/interop/tuple/Main.java @@ -0,0 +1,30 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val tuple = (1, "Coucou", (1, 2)) + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value tuple = namespace.getMember("tuple"); + System.out.println("=== Tuple interop messages:"); + print("toString()", tuple.toString()); + print("hasArrayElements()", tuple.hasArrayElements()); + print("getArraySize()", tuple.getArraySize()); + print("getArrayElement(0)", tuple.getArrayElement(0)); + print("getArrayElement(1)", tuple.getArrayElement(1)); + print("getArrayElement(2)", tuple.getArrayElement(2)); + } +} diff --git a/testsuite/tests/interop/tuple/test.out b/testsuite/tests/interop/tuple/test.out new file mode 100644 index 000000000..4d1a03998 --- /dev/null +++ b/testsuite/tests/interop/tuple/test.out @@ -0,0 +1,7 @@ +=== Tuple interop messages: + toString(): (1, "Coucou", (1, 2)) + hasArrayElements(): true + getArraySize(): 3 + getArrayElement(0): 1 + getArrayElement(1): Coucou + getArrayElement(2): (1, 2) diff --git a/testsuite/tests/interop/tuple/test.yaml b/testsuite/tests/interop/tuple/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/tuple/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 6af5ee3b16136c7277bbe0bd6b244153ab8083fc Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 22 Aug 2023 15:10:28 +0200 Subject: [PATCH 05/23] Rework the representation of the unit values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 19 +-- .../built_ins/functions/HelpFunction.java | 4 +- .../functions/NodeCheckerFunction.java | 4 +- .../built_ins/functions/PrintFunction.java | 4 +- .../functions/UnitCheckerFunction.java | 4 +- .../built_ins/methods/NodeMethods.java | 4 +- .../lkql_jit/built_ins/values/LKQLUnit.java | 135 ++++++++++++++++++ .../declarations/FunctionDeclaration.java | 4 +- .../lkql_jit/nodes/declarations/Import.java | 4 +- .../nodes/declarations/ValueDeclaration.java | 4 +- .../selector/SelectorDeclaration.java | 4 +- .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../lkql_jit/nodes/expressions/FunCall.java | 5 +- .../lkql_jit/nodes/expressions/Indexing.java | 6 +- .../expressions/literals/UnitLiteral.java | 8 +- .../nodes/expressions/match/Match.java | 4 +- .../nodes/expressions/operators/BinEq.java | 5 +- .../nodes/expressions/operators/BinNeq.java | 5 +- .../nodes/root_nodes/SelectorRootNode.java | 4 +- .../lkql_jit/runtime/values/UnitValue.java | 83 ----------- testsuite/tests/interop/unit/Main.java | 28 ++++ testsuite/tests/interop/unit/test.out | 5 + testsuite/tests/interop/unit/test.yaml | 1 + 23 files changed, 220 insertions(+), 129 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/UnitValue.java create mode 100644 testsuite/tests/interop/unit/Main.java create mode 100644 testsuite/tests/interop/unit/test.out create mode 100644 testsuite/tests/interop/unit/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 1cf560b67..60f15bce0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.*; @@ -41,7 +42,7 @@ * @author Hugo GUERRIER */ @TypeSystem({ - UnitValue.class, + LKQLUnit.class, long.class, BigInteger.class, String.class, @@ -75,9 +76,9 @@ public abstract class LKQLTypeSystem { * @param value The value to test. * @return True if the value is unit, false else. */ - @TypeCheck(UnitValue.class) - public static boolean isUnit(Object value) { - return value == UnitValue.getInstance(); + @TypeCheck(LKQLUnit.class) + public static boolean isUnit(final Object value) { + return value == LKQLUnit.INSTANCE; } /** @@ -86,9 +87,9 @@ public static boolean isUnit(Object value) { * @param value The value to cast. * @return The unit value. */ - @TypeCast(UnitValue.class) - public static UnitValue asUnit(Object value) { - return UnitValue.getInstance(); + @TypeCast(LKQLUnit.class) + public static LKQLUnit asUnit(@SuppressWarnings("unused") final Object value) { + return LKQLUnit.INSTANCE; } // ----- Nullish values ----- @@ -100,8 +101,8 @@ public static UnitValue asUnit(Object value) { * @return True if the value si nullish, false else. */ @TypeCheck(Nullish.class) - public static boolean isNullish(Object value) { - return value == UnitValue.getInstance() || value == NodeNull.getInstance(); + public static boolean isNullish(final Object value) { + return value == LKQLUnit.INSTANCE || value == NodeNull.getInstance(); } // ----- Boolean value methods ----- 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 index b55c93716..10ade6a9e 100644 --- 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 @@ -25,9 +25,9 @@ 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.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.frame.VirtualFrame; @@ -68,7 +68,7 @@ public static BuiltInFunctionValue getValue() { } // Return the default empty documentation - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; }); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java index 88d052a22..e9eab95e6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -187,7 +187,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the unit instance - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } /** 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 index e3bc80bb3..91a7a3477 100644 --- 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 @@ -25,11 +25,11 @@ 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.built_ins.values.LKQLUnit; 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.nodes.expressions.literals.BooleanLiteral; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.oracle.truffle.api.frame.VirtualFrame; @@ -77,7 +77,7 @@ public static BuiltInFunctionValue getValue() { } // Return the unit value - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; }); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index c45e1f613..cb049cb5e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -132,7 +132,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the unit value - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java index 6c7c6905a..a386455b2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java @@ -27,11 +27,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.ReflectionUtils; @@ -215,7 +215,7 @@ public static final class DumpExpr extends BuiltinFunctionBody { public Object executeGeneric(VirtualFrame frame) { LKQLLanguage.getContext(this) .print(LKQLTypeSystemGen.asAdaNode(frame.getArguments()[0]).dumpAST()); - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java new file mode 100644 index 000000000..d58e1c7d4 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java @@ -0,0 +1,135 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; +import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; + +/** This class represents the unit value in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLUnit implements TruffleObject, LKQLValue, Truthy, Nullish { + + // ----- Attributes ----- + + /** The only instance of the unit value. */ + public static final LKQLUnit INSTANCE = new LKQLUnit(); + + /** The identity hash of the only instance of the LKQL unit. */ + private static final int IDENTITY_HASH = System.identityHashCode(INSTANCE); + + // ----- Constructors ----- + + /** The private constructor. */ + private LKQLUnit() {} + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Tell the interop API if the receiver is identical to the other. */ + @ExportMessage + static TriState isIdenticalOrUndefined( + @SuppressWarnings("unused") final LKQLUnit receiver, final Object other) { + return TriState.valueOf(receiver == other); + } + + /** + * Return the identity hash code for the given receiver (always the same because unit value is + * singleton). + */ + @ExportMessage + static int identityHashCode(@SuppressWarnings("unused") final LKQLUnit receiver) { + return IDENTITY_HASH; + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffect) { + return "()"; + } + + /** Tell the interop API that the value is nullish. */ + @ExportMessage + boolean isNull() { + return true; + } + + /** Tell the interop API that the value is a boolean like value. */ + @ExportMessage + boolean isBoolean() { + return true; + } + + /** Get the boolean like value from unit, which is always false. */ + @ExportMessage + boolean asBoolean() { + return false; + } + + // ----- LKQL value methods ----- + + @Override + public boolean internalEquals(LKQLValue o) { + return o == this; + } + + @Override + public boolean isTruthy() { + return false; + } + + // ----- Override methods ----- + + @Override + public boolean equals(Object o) { + return o == this; + } + + @Override + public int hashCode() { + return super.hashCode(); + } + + @Override + public String toString() { + return "()"; + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java index b3548ff2a..d4ab628b9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java @@ -23,10 +23,10 @@ package com.adacore.lkql_jit.nodes.declarations; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.FunExpr; import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.ObjectValue; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.FrameUtils; @@ -120,7 +120,7 @@ public Object executeGeneric(VirtualFrame frame) { FrameUtils.writeLocal(frame, this.slot, functionValue); // Return the unit value - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } // ----- Instance methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java index 3991e5819..be7d96a2b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/Import.java @@ -25,9 +25,9 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.FrameUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -99,7 +99,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the unit value - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/ValueDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/ValueDeclaration.java index 1d766ba63..e353c1877 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/ValueDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/ValueDeclaration.java @@ -22,8 +22,8 @@ package com.adacore.lkql_jit.nodes.declarations; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.functions.FrameUtils; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -71,7 +71,7 @@ public ValueDeclaration(final SourceLocation location, final int slot, final Exp @Override public Object executeGeneric(VirtualFrame frame) { FrameUtils.writeLocal(frame, this.slot, this.value.executeGeneric(frame)); - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java index 014555125..7944ab0b5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java @@ -23,12 +23,12 @@ package com.adacore.lkql_jit.nodes.declarations.selector; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.declarations.Annotation; import com.adacore.lkql_jit.nodes.declarations.Declaration; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; import com.adacore.lkql_jit.runtime.values.SelectorValue; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.ClosureDescriptor; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.FrameUtils; @@ -120,7 +120,7 @@ public Object executeGeneric(VirtualFrame frame) { Closure.create(frame.materialize(), this.closureDescriptor), this.name, this.documentation)); - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index e8038d93e..bbba32e73 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -26,6 +26,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; @@ -64,8 +65,8 @@ protected Expr(SourceLocation location) { * @return The result of the node execution as unit. * @throws UnexpectedResultException If the node cannot be evaluated as a unit value. */ - public UnitValue executeUnit(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectUnitValue(executeGeneric(frame)); + public LKQLUnit executeUnit(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLUnit(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index da867dfaf..33447d0de 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -235,8 +236,8 @@ protected SelectorListValue onSelector(VirtualFrame frame, SelectorValue selecto * @return The unit value. */ @Specialization(guards = "isSafe") - protected Object onNullish(@SuppressWarnings("unused") Nullish value) { - return UnitValue.getInstance(); + protected Object onNullish(@SuppressWarnings("unused") final Nullish value) { + return LKQLUnit.INSTANCE; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java index c1a109cb2..067dd801c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java @@ -25,10 +25,10 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -87,7 +87,7 @@ protected Object indexTuple( return tupleLibrary.readArrayElement(tuple, index - 1); } catch (InvalidArrayIndexException e) { if (this.isSafe) { - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } else { throw LKQLRuntimeException.invalidIndex((int) index, this); } @@ -109,7 +109,7 @@ protected Object indexIndexable(Indexable collection, long index) { return collection.get((int) index - 1); } catch (InvalidIndexException e) { if (this.isSafe) { - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } else { throw LKQLRuntimeException.invalidIndex((int) index, this); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/UnitLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/UnitLiteral.java index cfae8d04c..d62b2b3dc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/UnitLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/UnitLiteral.java @@ -22,8 +22,8 @@ package com.adacore.lkql_jit.nodes.expressions.literals; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -53,7 +53,7 @@ public UnitLiteral(SourceLocation location) { */ @Override public Object executeGeneric(VirtualFrame frame) { - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } /** @@ -61,8 +61,8 @@ public Object executeGeneric(VirtualFrame frame) { * com.adacore.lkql_jit.nodes.expressions.Expr#executeUnit(com.oracle.truffle.api.frame.VirtualFrame) */ @Override - public UnitValue executeUnit(VirtualFrame frame) { - return UnitValue.getInstance(); + public LKQLUnit executeUnit(VirtualFrame frame) { + return LKQLUnit.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/match/Match.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/match/Match.java index c6a50b2a0..2d47cd40b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/match/Match.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/match/Match.java @@ -22,8 +22,8 @@ package com.adacore.lkql_jit.nodes.expressions.match; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; @@ -82,7 +82,7 @@ public Object executeGeneric(VirtualFrame frame) { // If no arm matched, return the unit value // Probably want to raise an exception in the future - return UnitValue.getInstance(); + return LKQLUnit.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index cc3e1e154..79ff4d480 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -68,8 +69,8 @@ protected BinEq( */ @Specialization protected boolean eqUnit( - @SuppressWarnings("unused") UnitValue left, - @SuppressWarnings("unused") UnitValue right) { + @SuppressWarnings("unused") final LKQLUnit left, + @SuppressWarnings("unused") final LKQLUnit right) { return true; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 988e4f75d..797d8a50e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -68,8 +69,8 @@ protected BinNeq( */ @Specialization protected boolean neqUnit( - @SuppressWarnings("unused") UnitValue left, - @SuppressWarnings("unused") UnitValue right) { + @SuppressWarnings("unused") final LKQLUnit left, + @SuppressWarnings("unused") final LKQLUnit right) { return false; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java index 474077c89..da653d8a1 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java @@ -22,10 +22,10 @@ package com.adacore.lkql_jit.nodes.root_nodes; +import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.UnitValue; import com.adacore.lkql_jit.utils.functions.FrameUtils; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -117,7 +117,7 @@ public Object execute(VirtualFrame frame) { if (res != null) break; } if (res == null) { - res = new SelectorCallResult(SelectorExpr.Mode.DEFAULT, UnitValue.getInstance()); + res = new SelectorCallResult(SelectorExpr.Mode.DEFAULT, LKQLUnit.INSTANCE); } // Do the memoization cache addition diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/UnitValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/UnitValue.java deleted file mode 100644 index 091188c04..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/UnitValue.java +++ /dev/null @@ -1,83 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; -import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; - -/** - * This class represents the unit value in the LKQL language. - * - * @author Hugo GUERRIER - */ -public final class UnitValue implements Nullish, Truthy { - - // ----- Attributes ----- - - /** The unique instance of the unit value in the language. */ - private static UnitValue instance = null; - - // ----- Constructors ----- - - /** Create a new unit value, private for the singleton. */ - private UnitValue() {} - - /** - * Get the unique instance of the unit value. - * - * @return The unit value. - */ - public static UnitValue getInstance() { - if (instance == null) { - instance = new UnitValue(); - } - return instance; - } - - // ----- Value methods ----- - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Truthy#isTruthy() - */ - @Override - public boolean isTruthy() { - return false; - } - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - public boolean internalEquals(LKQLValue o) { - return o == this; - } - - // ----- Override methods ----- - - @Override - public String toString() { - return "()"; - } -} diff --git a/testsuite/tests/interop/unit/Main.java b/testsuite/tests/interop/unit/Main.java new file mode 100644 index 000000000..5e7437f55 --- /dev/null +++ b/testsuite/tests/interop/unit/Main.java @@ -0,0 +1,28 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val unit = () + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value unit = namespace.getMember("unit"); + System.out.println("=== Unit interop messages:"); + print("toString()", unit.toString()); + print("isNull()", unit.isNull()); + print("isBoolean()", unit.isBoolean()); + print("asBoolean()", unit.asBoolean()); + } +} diff --git a/testsuite/tests/interop/unit/test.out b/testsuite/tests/interop/unit/test.out new file mode 100644 index 000000000..d427d6725 --- /dev/null +++ b/testsuite/tests/interop/unit/test.out @@ -0,0 +1,5 @@ +=== Unit interop messages: + toString(): () + isNull(): true + isBoolean(): true + asBoolean(): false diff --git a/testsuite/tests/interop/unit/test.yaml b/testsuite/tests/interop/unit/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/unit/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 753025fafd08f539207ddb64038c9fa58a50ffe6 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Wed, 23 Aug 2023 11:31:52 +0200 Subject: [PATCH 06/23] Change the checkers representation from ObjectValue to pure Java classes --- .../com/adacore/lkql_jit/LKQLContext.java | 66 +++---- .../functions/NodeCheckerFunction.java | 48 ++--- .../functions/UnitCheckerFunction.java | 31 +-- .../declarations/FunctionDeclaration.java | 52 +++-- .../adacore/lkql_jit/runtime/GlobalScope.java | 8 +- .../com/adacore/lkql_jit/utils/Constants.java | 4 - .../lkql_jit/utils/checkers/BaseChecker.java | 177 ++++++++++++++++++ .../lkql_jit/utils/checkers/NodeChecker.java | 79 ++++++++ .../lkql_jit/utils/checkers/UnitChecker.java | 79 ++++++++ 9 files changed, 451 insertions(+), 93 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java 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 1d815597b..b1dff7afa 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 @@ -25,11 +25,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.nodes.declarations.FunctionDeclaration; import com.adacore.lkql_jit.runtime.GlobalScope; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLConfigFileResult; +import com.adacore.lkql_jit.utils.checkers.BaseChecker; +import com.adacore.lkql_jit.utils.checkers.NodeChecker; +import com.adacore.lkql_jit.utils.checkers.UnitChecker; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.ParsingUtils; @@ -116,16 +117,16 @@ public final class LKQLContext { private Map> allRulesArgs = null; /** The filtered node checkers cache. */ - private ObjectValue[] filteredAllNodeCheckers = null; + private NodeChecker[] filteredAllNodeCheckers = null; /** The filtered node checkers for Ada code only. */ - private ObjectValue[] filteredAdaNodeCheckers = null; + private NodeChecker[] filteredAdaNodeCheckers = null; /** The filtered node checkers for SPARK code only. */ - private ObjectValue[] filteredSparkNodeCheckers = null; + private NodeChecker[] filteredSparkNodeCheckers = null; /** The filtered unit checkers cache. */ - private ObjectValue[] filteredUnitCheckers = null; + private UnitChecker[] filteredUnitCheckers = null; /** Whether there is at least one rule that needs to follow generic instantiations. */ private boolean needsToFollowInstantiations = false; @@ -789,7 +790,7 @@ public Object getRuleArg(String ruleName, String argName) { * @return The node checkers array filtered according to options. */ @CompilerDirectives.TruffleBoundary - public ObjectValue[] getAllNodeCheckers() { + public NodeChecker[] getAllNodeCheckers() { if (this.filteredAllNodeCheckers == null) { this.initCheckerCaches(); } @@ -801,7 +802,7 @@ public ObjectValue[] getAllNodeCheckers() { * * @return The node checkers array for Ada code only. */ - public ObjectValue[] getAdaNodeCheckers() { + public NodeChecker[] getAdaNodeCheckers() { if (this.filteredAdaNodeCheckers == null) { this.initCheckerCaches(); } @@ -813,7 +814,7 @@ public ObjectValue[] getAdaNodeCheckers() { * * @return The node checkers array for SPARK code only. */ - public ObjectValue[] getSparkNodeCheckers() { + public NodeChecker[] getSparkNodeCheckers() { if (this.filteredSparkNodeCheckers == null) { this.initCheckerCaches(); } @@ -826,7 +827,7 @@ public ObjectValue[] getSparkNodeCheckers() { * @return The list for unit checkers filtered according to options. */ @CompilerDirectives.TruffleBoundary - public ObjectValue[] getUnitCheckersFiltered() { + public UnitChecker[] getUnitCheckersFiltered() { if (this.filteredUnitCheckers == null) { this.initCheckerCaches(); } @@ -837,11 +838,11 @@ public ObjectValue[] getUnitCheckersFiltered() { @CompilerDirectives.TruffleBoundary private void initCheckerCaches() { // Prepare the working variables - final List allNodeCheckers = new ArrayList<>(); - final List adaNodeCheckers = new ArrayList<>(); - final List sparkNodeCheckers = new ArrayList<>(); - final List unitCheckers = new ArrayList<>(); - final Map allCheckers = this.global.getCheckers(); + final List allNodeCheckers = new ArrayList<>(); + final List adaNodeCheckers = new ArrayList<>(); + final List sparkNodeCheckers = new ArrayList<>(); + final List unitCheckers = new ArrayList<>(); + final Map allCheckers = this.global.getCheckers(); // Get the command line required rules final List allRules = this.getAllRules(); @@ -849,44 +850,45 @@ private void initCheckerCaches() { final List sparkRules = this.getSparkRules(); // Lambda to dispatch checkers in the correct lists - final BiConsumer> dispatchChecker = + final BiConsumer> dispatchChecker = (checker, nodeCheckers) -> { - if (checker.get("mode") == FunctionDeclaration.CheckerMode.NODE) { - nodeCheckers.add(checker); - if ((boolean) checker.get("follow_generic_instantiations")) { + if (checker instanceof NodeChecker nodeChecker) { + nodeCheckers.add(nodeChecker); + if (nodeChecker.isFollowGenericInstantiations()) { needsToFollowInstantiations = true; } } else { - unitCheckers.add(checker); + UnitChecker unitChecker = (UnitChecker) checker; + unitCheckers.add(unitChecker); } }; // Lambda to get the checker object value from the rule name - final Function getAssociatedChecker = + final Function getAssociatedChecker = (ruleName) -> { // Get the checker from the given rule name - ObjectValue res = null; + BaseChecker checker; final String aliasResolved = this.getRuleFromAlias(ruleName); if (aliasResolved != null) { - res = new ObjectValue(allCheckers.get(aliasResolved)); - res.set("alias", ruleName); + checker = allCheckers.get(aliasResolved).copy(); + checker.setAlias(ruleName); } else { - res = allCheckers.get(ruleName); + checker = allCheckers.get(ruleName); } // Verify that the checker is not null - if (res == null) { + if (checker == null) { throw LKQLRuntimeException.fromMessage( "Could not find any rule named " + ruleName); } // Return the result - return res; + return checker; }; // If there is no wanted rule, run them all (if the appropriate option is set) if (allRules.size() == 0 && this.env.getOptions().get(LKQLLanguage.fallbackToAllRules)) { - for (ObjectValue checker : allCheckers.values()) { + for (BaseChecker checker : allCheckers.values()) { dispatchChecker.accept(checker, allNodeCheckers); } } @@ -905,10 +907,10 @@ private void initCheckerCaches() { } // Set the checker caches - this.filteredAllNodeCheckers = allNodeCheckers.toArray(new ObjectValue[0]); - this.filteredAdaNodeCheckers = adaNodeCheckers.toArray(new ObjectValue[0]); - this.filteredSparkNodeCheckers = sparkNodeCheckers.toArray(new ObjectValue[0]); - this.filteredUnitCheckers = unitCheckers.toArray(new ObjectValue[0]); + this.filteredAllNodeCheckers = allNodeCheckers.toArray(new NodeChecker[0]); + this.filteredAdaNodeCheckers = adaNodeCheckers.toArray(new NodeChecker[0]); + this.filteredSparkNodeCheckers = sparkNodeCheckers.toArray(new NodeChecker[0]); + this.filteredUnitCheckers = unitCheckers.toArray(new UnitChecker[0]); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java index e9eab95e6..ba6d302c4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java @@ -35,8 +35,8 @@ import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.FunctionValue; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; +import com.adacore.lkql_jit.utils.checkers.NodeChecker; import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; @@ -88,9 +88,9 @@ public Object executeGeneric(VirtualFrame frame) { // Get the arguments final LKQLContext context = LKQLLanguage.getContext(this); final Libadalang.AdaNode root; - final ObjectValue[] allNodeCheckers = context.getAllNodeCheckers(); - final ObjectValue[] adaNodeCheckers = context.getAdaNodeCheckers(); - final ObjectValue[] sparkNodeCheckers = context.getSparkNodeCheckers(); + final NodeChecker[] allNodeCheckers = context.getAllNodeCheckers(); + final NodeChecker[] adaNodeCheckers = context.getAdaNodeCheckers(); + final NodeChecker[] sparkNodeCheckers = context.getSparkNodeCheckers(); final boolean mustFollowInstantiations = context.mustFollowInstantiations(); final boolean hasSparkCheckers = sparkNodeCheckers.length > 0; @@ -204,13 +204,13 @@ private void executeCheckers( VirtualFrame frame, VisitStep currentStep, Libadalang.AdaNode currentNode, - ObjectValue[] checkers, + NodeChecker[] checkers, LKQLContext context, CheckerUtils.SourceLinesCache linesCache) { - // For each checker apply it on the current node of needed - for (ObjectValue checker : checkers) { + // For each checker apply it on the current node if needed + for (NodeChecker checker : checkers) { if (!currentStep.inGenericInstantiation() - || (boolean) checker.get("follow_generic_instantiations")) { + || checker.isFollowGenericInstantiations()) { try { this.applyNodeRule(frame, checker, currentNode, context, linesCache); } catch (LangkitException e) { @@ -220,7 +220,7 @@ private void executeCheckers( if (context.isCheckerDebug()) { context.getDiagnosticEmitter() .emitInternalError( - (String) checker.get("name"), + checker.getName(), currentNode.getUnit(), currentNode.getSourceLocationRange().start, e.getLoc().toString(), @@ -234,7 +234,7 @@ private void executeCheckers( // implementation context.getDiagnosticEmitter() .emitInternalError( - (String) checker.get("name"), + checker.getName(), currentNode.getUnit(), currentNode.getSourceLocationRange().start, e.getLocationString(), @@ -247,24 +247,24 @@ private void executeCheckers( } /** - * Apply the rule on the given node. + * Apply the checker on the given node. * * @param frame The frame to execute the default arg value. - * @param rule The rule to apply. - * @param node The node to apply the rule on. + * @param checker The checker to apply. + * @param node The node to apply the checker on. * @param context The LKQL context. * @param linesCache The cache of all units' source text lines. */ private void applyNodeRule( VirtualFrame frame, - ObjectValue rule, + NodeChecker checker, Libadalang.AdaNode node, LKQLContext context, CheckerUtils.SourceLinesCache linesCache) { // Get the function for the checker - FunctionValue functionValue = (FunctionValue) rule.get("function"); - String aliasName = (String) rule.get("alias"); - String lowerRuleName = StringUtils.toLowerCase((String) rule.get("name")); + FunctionValue functionValue = checker.getFunction(); + String aliasName = checker.getAlias(); + String lowerRuleName = StringUtils.toLowerCase(checker.getName()); // Prepare the arguments Object[] arguments = new Object[functionValue.getParamNames().length + 1]; @@ -286,7 +286,7 @@ private void applyNodeRule( // Place the closure in the arguments arguments[0] = functionValue.getClosure().getContent(); - // Call the rule + // Call the checker final boolean ruleResult; try { ruleResult = @@ -300,7 +300,7 @@ private void applyNodeRule( } if (ruleResult) { - reportViolation(context, rule, node, linesCache); + reportViolation(context, checker, node, linesCache); } } @@ -308,14 +308,14 @@ private void applyNodeRule( * Report a rule violation with the node that violate it. * * @param context The context to output the message. - * @param rule The violated rule. - * @param node The node that violated the rule. + * @param checker The checker corresponding to the violated rule. + * @param node The node that violated the checker. * @param linesCache The cache of all units' source text lines. */ @CompilerDirectives.TruffleBoundary private static void reportViolation( LKQLContext context, - ObjectValue rule, + NodeChecker checker, Libadalang.AdaNode node, CheckerUtils.SourceLinesCache linesCache) { if (node instanceof Libadalang.BasicDecl basicDecl) { @@ -324,8 +324,8 @@ private static void reportViolation( } context.getDiagnosticEmitter() .emitRuleViolation( - (String) rule.get("name"), - (String) rule.get("message"), + checker.getName(), + checker.getMessage(), node.getSourceLocationRange(), node.getUnit(), node.pGenericInstantiations(), diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index cb049cb5e..efa53610d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -39,6 +39,7 @@ import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; +import com.adacore.lkql_jit.utils.checkers.UnitChecker; import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.frame.VirtualFrame; @@ -83,7 +84,7 @@ public Object executeGeneric(VirtualFrame frame) { // Get the arguments LKQLContext context = LKQLLanguage.getContext(this); Libadalang.AnalysisUnit unit; - ObjectValue[] checkers = context.getUnitCheckersFiltered(); + UnitChecker[] checkers = context.getUnitCheckersFiltered(); try { unit = LKQLTypeSystemGen.expectAnalysisUnit(frame.getArguments()[0]); @@ -98,9 +99,9 @@ public Object executeGeneric(VirtualFrame frame) { CheckerUtils.SourceLinesCache linesCache = new CheckerUtils.SourceLinesCache(); // Iterate over all checker - for (ObjectValue rule : checkers) { + for (UnitChecker checker : checkers) { try { - this.applyUnitRule(frame, rule, unit, context, linesCache); + this.applyUnitRule(frame, checker, unit, context, linesCache); } catch (LangkitException e) { // TODO: Remove those clunky hardcoded names when getting rid of Ada // implementation @@ -108,7 +109,7 @@ public Object executeGeneric(VirtualFrame frame) { if (context.isCheckerDebug()) { context.getDiagnosticEmitter() .emitInternalError( - (String) rule.get("name"), + checker.getName(), unit, Libadalang.SourceLocation.create(1, (short) 1), e.getLoc().toString(), @@ -121,7 +122,7 @@ public Object executeGeneric(VirtualFrame frame) { // implementation context.getDiagnosticEmitter() .emitInternalError( - (String) rule.get("name"), + checker.getName(), unit, Libadalang.SourceLocation.create(1, (short) 1), e.getLocationString(), @@ -136,26 +137,26 @@ public Object executeGeneric(VirtualFrame frame) { } /** - * Apply the rule on the given unit. + * Apply the checker on the given unit. * - * @param frame The frame for the rule execution. - * @param rule The rule to execute. - * @param unit The unit to execute the rule on. + * @param frame The frame for the checker execution. + * @param checker The checker to execute. + * @param unit The unit to execute the checker on. * @param context The context for the execution. * @param linesCache The cache of all units' source text lines. */ private void applyUnitRule( VirtualFrame frame, - ObjectValue rule, + UnitChecker checker, Libadalang.AnalysisUnit unit, LKQLContext context, CheckerUtils.SourceLinesCache linesCache) { // Get the function for the checker - final FunctionValue functionValue = (FunctionValue) rule.get("function"); + final FunctionValue functionValue = checker.getFunction(); - // Retrieve the rule name - final String aliasName = (String) rule.get("alias"); - final String lowerRuleName = StringUtils.toLowerCase((String) rule.get("name")); + // Retrieve the checker name + final String aliasName = checker.getAlias(); + final String lowerRuleName = StringUtils.toLowerCase(checker.getName()); // Prepare the arguments Object[] arguments = new Object[functionValue.getParamNames().length + 1]; @@ -177,7 +178,7 @@ private void applyUnitRule( // Put the closure in the arguments arguments[0] = functionValue.getClosure().getContent(); - // Get the message list from the rule function + // Get the message list from the checker function final Iterable messageList; try { messageList = diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java index d4ab628b9..09c564540 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java @@ -26,9 +26,10 @@ import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.FunExpr; import com.adacore.lkql_jit.runtime.values.FunctionValue; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.Constants; -import com.adacore.lkql_jit.utils.functions.ArrayUtils; +import com.adacore.lkql_jit.utils.checkers.BaseChecker; +import com.adacore.lkql_jit.utils.checkers.NodeChecker; +import com.adacore.lkql_jit.utils.checkers.UnitChecker; import com.adacore.lkql_jit.utils.functions.FrameUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -144,24 +145,47 @@ private void exportChecker(VirtualFrame frame, FunctionValue functionValue) { if (checkerArguments[1] == null) checkerArguments[1] = this.name; // Verify the remediation mode - if (ArrayUtils.indexOf(Constants.CHECKER_VALID_REMEDIATION, checkerArguments[5]) == -1) { - checkerArguments[5] = Constants.CHECKER_PARAMETER_DEFAULT_VALUES[5]; - } + final BaseChecker.Remediation remediation = + switch ((String) checkerArguments[5]) { + case "EASY" -> BaseChecker.Remediation.EASY; + case "MAJOR" -> BaseChecker.Remediation.MAJOR; + default -> BaseChecker.Remediation.MEDIUM; + }; // Create the object value representing the checker - final ObjectValue checkerObject = - new ObjectValue( - ArrayUtils.concat( - Constants.CHECKER_PARAMETER_NAMES, - new String[] {"function", "name", "mode"}), - ArrayUtils.concat( - checkerArguments, - new Object[] {functionValue, this.name, this.checkerMode})); + final BaseChecker checker = + this.checkerMode == CheckerMode.NODE + ? new NodeChecker( + this.name, + functionValue, + (String) checkerArguments[0], + (String) checkerArguments[1], + (boolean) checkerArguments[2], + (String) checkerArguments[3], + (String) checkerArguments[4], + remediation, + (long) checkerArguments[6], + (boolean) checkerArguments[7], + (String) checkerArguments[8], + (String) checkerArguments[9]) + : new UnitChecker( + this.name, + functionValue, + (String) checkerArguments[0], + (String) checkerArguments[1], + (boolean) checkerArguments[2], + (String) checkerArguments[3], + (String) checkerArguments[4], + remediation, + (long) checkerArguments[6], + (boolean) checkerArguments[7], + (String) checkerArguments[8], + (String) checkerArguments[9]); // Put the object in the context LKQLLanguage.getContext(this) .getGlobal() - .addChecker(StringUtils.toLowerCase(functionValue.getName()), checkerObject); + .addChecker(StringUtils.toLowerCase(functionValue.getName()), checker); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java index 47174c1e0..008721bb6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/GlobalScope.java @@ -23,7 +23,7 @@ package com.adacore.lkql_jit.runtime; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.runtime.values.ObjectValue; +import com.adacore.lkql_jit.utils.checkers.BaseChecker; import com.oracle.truffle.api.CompilerDirectives; import java.util.HashMap; import java.util.Map; @@ -39,7 +39,7 @@ public final class GlobalScope { // ----- Attributes ----- /** The defined LKQL rules. */ - private final Map checkers; + private final Map checkers; /** The array containing the built-in functions and selectors. */ private final Object[] builtIns; @@ -67,7 +67,7 @@ public GlobalScope(int buildInNb) { * * @return The LKQL checkers. */ - public Map getCheckers() { + public Map getCheckers() { return this.checkers; } @@ -78,7 +78,7 @@ public Map getCheckers() { * @param checker The object representing the checker. */ @CompilerDirectives.TruffleBoundary - public void addChecker(String name, ObjectValue checker) { + public void addChecker(String name, BaseChecker checker) { this.checkers.put(name, checker); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java index 844e40872..768a366fe 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/Constants.java @@ -116,8 +116,4 @@ public class Constants { /** The default values for annotation parameters. */ public static final Object[] CHECKER_PARAMETER_DEFAULT_VALUES = new Object[] {null, null, false, "Misc", "Misc", "MEDIUM", 0L, false, "", "amd64"}; - - /** The valid value for the remediation parameters. */ - public static final String[] CHECKER_VALID_REMEDIATION = - new String[] {"EASY", "MEDIUM", "MAJOR"}; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java new file mode 100644 index 000000000..c245b053a --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java @@ -0,0 +1,177 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.utils.checkers; + +import com.adacore.lkql_jit.runtime.values.FunctionValue; + +/** + * This class represents a checker in the LKQL language. A checker is an annotated function which is + * going to be used to perform the node and unit checking. + */ +public abstract class BaseChecker { + + // ----- Attributes ----- + + /** Name of the checker (This is the rule name). */ + protected final String name; + + /** Alias of the checker (User can define alias to rules). */ + protected String alias; + + /** Function to execute as checker. */ + protected final FunctionValue function; + + /** Message to display when the rule violated. */ + protected final String message; + + /** Help to display when rule violated. */ + protected final String help; + + /** Whether the generic instantiations in the checker. */ + protected final boolean followGenericInstantiations; + + /** Category of the checker. */ + protected final String category; + + /** Sub-category of the checker. */ + protected final String subcategory; + + /** Remediation level of the checker. */ + protected final Remediation remediation; + + /** Execution cost of the checker. */ + protected final long executionCost; + + /** If the checker has a parametric exemption. */ + protected final boolean parametricExemption; + + /** Version impacted by the checker. */ + protected final String impact; + + /** Target of the checker. */ + protected final String target; + + // ----- Constructors ----- + + /** Create a base checker with all its value. */ + public BaseChecker( + final String name, + final FunctionValue function, + final String message, + final String help, + final boolean followGenericInstantiations, + final String category, + final String subcategory, + final Remediation remediation, + final long executionCost, + final boolean parametricExemption, + final String impact, + final String target) { + this.name = name; + this.function = function; + this.message = message; + this.help = help; + this.followGenericInstantiations = followGenericInstantiations; + this.category = category; + this.subcategory = subcategory; + this.remediation = remediation; + this.executionCost = executionCost; + this.parametricExemption = parametricExemption; + this.impact = impact; + this.target = target; + } + + // ----- Getters ----- + + public String getName() { + return name; + } + + public String getAlias() { + return alias; + } + + public FunctionValue getFunction() { + return function; + } + + public String getMessage() { + return message; + } + + public String getHelp() { + return help; + } + + public boolean isFollowGenericInstantiations() { + return followGenericInstantiations; + } + + public String getCategory() { + return category; + } + + public String getSubcategory() { + return subcategory; + } + + public Remediation getRemediation() { + return remediation; + } + + public long getExecutionCost() { + return executionCost; + } + + public boolean isParametricExemption() { + return parametricExemption; + } + + public String getImpact() { + return impact; + } + + public String getTarget() { + return target; + } + + // ----- Setters ----- + + public void setAlias(String alias) { + this.alias = alias; + } + + // ----- Instance methods ----- + + /** Create a deep copy of the current checker and return it. */ + public abstract BaseChecker copy(); + + // ----- Inner classes ----- + + /** This enum represents the valid remediation levels */ + public enum Remediation { + EASY, + MEDIUM, + MAJOR + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java new file mode 100644 index 000000000..fc631f7e0 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.utils.checkers; + +import com.adacore.lkql_jit.runtime.values.FunctionValue; + +/** This class represents a node checker in the LKQL system. */ +public final class NodeChecker extends BaseChecker { + + // ----- Constructors ----- + + /** Create a new node checker. */ + public NodeChecker( + final String name, + final FunctionValue function, + final String message, + final String help, + final boolean followGenericInstantiations, + final String category, + final String subcategory, + final Remediation remediation, + final long executionCost, + final boolean parametricExemption, + final String impact, + final String target) { + super( + name, + function, + message, + help, + followGenericInstantiations, + category, + subcategory, + remediation, + executionCost, + parametricExemption, + impact, + target); + } + + // ----- Instance methods ----- + + @Override + public BaseChecker copy() { + return new NodeChecker( + this.name, + this.function, + this.message, + this.help, + this.followGenericInstantiations, + this.category, + this.subcategory, + this.remediation, + this.executionCost, + this.parametricExemption, + this.impact, + this.target); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java new file mode 100644 index 000000000..1bea57a95 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java @@ -0,0 +1,79 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.utils.checkers; + +import com.adacore.lkql_jit.runtime.values.FunctionValue; + +/** This class represents a unit checker in the LKQL system. */ +public final class UnitChecker extends BaseChecker { + + // ----- Constructors ----- + + /** Create a new unit checker. */ + public UnitChecker( + final String name, + final FunctionValue function, + final String message, + final String help, + final boolean followGenericInstantiations, + final String category, + final String subcategory, + final Remediation remediation, + final long executionCost, + final boolean parametricExemption, + final String impact, + final String target) { + super( + name, + function, + message, + help, + followGenericInstantiations, + category, + subcategory, + remediation, + executionCost, + parametricExemption, + impact, + target); + } + + // ----- Instance methods ----- + + @Override + public BaseChecker copy() { + return new UnitChecker( + this.name, + this.function, + this.message, + this.help, + this.followGenericInstantiations, + this.category, + this.subcategory, + this.remediation, + this.executionCost, + this.parametricExemption, + this.impact, + this.target); + } +} From 9f5de7b3d21b4aa07fb0cc10660d50640a6a9771 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Wed, 23 Aug 2023 16:02:55 +0200 Subject: [PATCH 07/23] Rework the representation of the object values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 3 +- .../functions/UnitCheckerFunction.java | 24 +- .../lkql_jit/built_ins/values/LKQLObject.java | 270 ++++++++++++++++++ .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../nodes/expressions/dot/DotAccess.java | 12 +- .../expressions/literals/ObjectLiteral.java | 32 ++- .../nodes/expressions/operators/BinEq.java | 11 +- .../nodes/expressions/operators/BinNeq.java | 11 +- .../lkql_jit/runtime/values/ObjectValue.java | 148 ---------- .../lkql_jit/utils/LKQLTypesHelper.java | 10 +- .../utils/functions/ParsingUtils.java | 29 +- testsuite/tests/interop/object/Main.java | 33 +++ testsuite/tests/interop/object/test.out | 9 + testsuite/tests/interop/object/test.yaml | 1 + 14 files changed, 396 insertions(+), 202 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ObjectValue.java create mode 100644 testsuite/tests/interop/object/Main.java create mode 100644 testsuite/tests/interop/object/test.out create mode 100644 testsuite/tests/interop/object/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 60f15bce0..9dbaf8711 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; @@ -61,8 +62,8 @@ Libadalang.Token.class, Libadalang.AnalysisUnit.class, boolean.class, - ObjectValue.class, LKQLNamespace.class, + LKQLObject.class, Nullish.class, LKQLValue.class, }) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index efa53610d..1c213f65e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.FunctionValue; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -179,9 +179,9 @@ private void applyUnitRule( arguments[0] = functionValue.getClosure().getContent(); // Get the message list from the checker function - final Iterable messageList; + final Iterable violationList; try { - messageList = + violationList = LKQLTypeSystemGen.expectIterable( this.dispatcher.executeDispatch(functionValue, arguments)); } catch (UnexpectedResultException e) { @@ -192,14 +192,14 @@ private void applyUnitRule( } // Display all the violation message - Iterator messageIterator = messageList.iterator(); - while (messageIterator.hasNext()) { - ObjectValue message = (ObjectValue) messageIterator.next(); + Iterator violationIterator = violationList.iterator(); + while (violationIterator.hasNext()) { + LKQLObject violation = (LKQLObject) violationIterator.next(); - // Get the message text - String messageText; + // Get the violation text + String message; try { - messageText = LKQLTypeSystemGen.expectString(message.get("message")); + message = LKQLTypeSystemGen.expectString(violation.getUncached("message")); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_STRING, @@ -207,8 +207,8 @@ private void applyUnitRule( functionValue.getBody()); } - // Get the message location - Object loc = message.get("loc"); + // Get the violation location + Object loc = violation.getUncached("loc"); final Libadalang.AnalysisUnit locUnit; final Libadalang.SourceLocationRange slocRange; final Libadalang.AdaNodeArray genericInstantiations; @@ -233,7 +233,7 @@ private void applyUnitRule( context.getDiagnosticEmitter() .emitRuleViolation( lowerRuleName, - messageText, + message, slocRange, locUnit, genericInstantiations, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java new file mode 100644 index 000000000..67e9ae997 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -0,0 +1,270 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.runtime.values.ListValue; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.utils.Constants; +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.TruffleLanguage; +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.interop.TruffleObject; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.object.DynamicObjectLibrary; +import com.oracle.truffle.api.object.Shape; +import com.oracle.truffle.api.utilities.TriState; +import java.util.Arrays; +import java.util.Objects; + +/** This class represents an object value in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public final class LKQLObject extends DynamicObject implements TruffleObject, LKQLValue { + + // ----- Class attributes ----- + + /** An uncached dynamic object library. */ + private static final DynamicObjectLibrary objectLibrary = DynamicObjectLibrary.getUncached(); + + // ----- Constructors ----- + + /** Create a new LKQL object with its dynamic shape. */ + public LKQLObject(final Shape shape) { + super(shape); + } + + // ----- Class methods ----- + + /** + * Create an LQKL object value from its keys and values. This method doesn't use a cached + * library so this is not designed for performance critical usages. + */ + public static LKQLObject createUncached(final Object[] keys, final Object[] values) { + final LKQLObject res = new LKQLObject(Shape.newBuilder().build()); + for (int i = 0; i < keys.length; i++) { + objectLibrary.put(res, keys[i], values[i]); + } + return res; + } + + // ----- Instance methods ------ + + /** + * Get the value in the LKQL object at the given key with the uncached strategy. If the key + * doesn't exist then a null value is returned. This method uses an uncached library so this is + * not design for performance critical usages. + */ + public Object getUncached(final Object key) { + return objectLibrary.getOrDefault(this, key, null); + } + + /** + * Get the key array from the object value. This method uses an uncached library so this is no + * designed for performance critical usages. + */ + public Object[] keysUncached() { + return objectLibrary.getKeyArray(this); + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL objects. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL objects. */ + @Specialization + protected static TriState onLKQLObject(final LKQLObject left, final LKQLObject right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLObject receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL object. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLObject receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string of the object. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + Object toDisplayString( + @SuppressWarnings("unused") final boolean allowSideEffects, + @CachedLibrary("this") DynamicObjectLibrary thisLibrary, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { + // Prepare the result string builder and get the keys of the object + StringBuilder resultBuilder = new StringBuilder("{"); + Object[] keys = thisLibrary.getKeyArray(this); + + // Iterate over keys and add the values + for (int i = 0; i < keys.length; i++) { + // Get key/value + Object key = keys[i]; + Object value = thisLibrary.getOrDefault(this, key, null); + + // Create the string of the value + String valueString; + if (value instanceof String) { + valueString = StringUtils.toRepr((String) interopLibrary.toDisplayString(value)); + } else { + valueString = (String) interopLibrary.toDisplayString(value); + } + + // Add the strings to the result + resultBuilder.append('"').append(key).append('"'); + resultBuilder.append(": ").append(valueString); + if (i < keys.length - 1) resultBuilder.append(", "); + } + + // Return the string result + resultBuilder.append("}"); + return resultBuilder.toString(); + } + + /** Tell the interop library that the value has members. */ + @ExportMessage + boolean hasMembers() { + return true; + } + + /** + * Get if the given member is in the receiver object. All members are readable but not + * modifiable. + */ + @ExportMessage + boolean isMemberReadable( + final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return objectLibrary.containsKey(this, member); + } + + /** Get the existing members for the receiver object. */ + @ExportMessage + Object getMembers( + @SuppressWarnings("unused") final boolean includeInternal, + @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return new ListValue(objectLibrary.getKeyArray(this)); + } + + /** Get the value of the wanted member in the receiver object. */ + @ExportMessage + Object readMember( + final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) + throws UnknownIdentifierException { + Object result = objectLibrary.getOrDefault(this, member, null); + if (result == null) throw UnknownIdentifierException.create(member); + return result; + } + + // ----- LKQL value methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(final LKQLValue o) { + if (this == o) return true; + if (!(o instanceof LKQLObject other)) return false; + + // Create the libraries to access object fields + DynamicObjectLibrary thisLib = DynamicObjectLibrary.getFactory().getUncached(this); + DynamicObjectLibrary otherLib = DynamicObjectLibrary.getFactory().getUncached(other); + + // Get the keys + Object[] thisKeys = thisLib.getKeyArray(this); + Object[] otherKeys = otherLib.getKeyArray(other); + + // Check the key array length + if (thisKeys.length != otherKeys.length) return false; + + // Iterate over the keys and verify their values + for (Object key : thisKeys) { + // Ensure that the other contains the key + if (!otherLib.containsKey(other, key)) return false; + + // Compare the values + Object thisObject = thisLib.getOrDefault(this, key, null); + Object otherObject = otherLib.getOrDefault(other, key, null); + if ((thisObject instanceof LKQLValue thisValue) + && (otherObject instanceof LKQLValue otherValue)) { + if (!thisValue.internalEquals(otherValue)) return false; + } else { + if (!Objects.equals(thisObject, otherObject)) return false; + } + } + + // Return the success + return true; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary objectLib = InteropLibrary.getUncached(this); + return (String) objectLib.toDisplayString(this); + } + + @Override + public boolean equals(final Object o) { + if (o == this) return true; + if (!(o instanceof LKQLObject other)) return false; + return this.internalEquals(other); + } + + @Override + public int hashCode() { + Object[] keys = this.keysUncached(); + Object[] values = new Object[keys.length]; + for (int i = 0; i < keys.length; i++) { + values[i] = this.getUncached(keys[i]); + } + return Arrays.hashCode(ArrayUtils.concat(keys, values)); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index bbba32e73..79b7e8dec 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.LKQLNode; @@ -232,8 +233,8 @@ public Iterable executeIterable(VirtualFrame frame) throws UnexpectedResultExcep * @return The result of the node execution as an object value. * @throws UnexpectedResultException If the node cannot be evaluated as an object. */ - public ObjectValue executeObject(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectObjectValue(executeGeneric(frame)); + public LKQLObject executeObject(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLObject(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index f9e0bc94c..16b16eadb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -27,13 +27,13 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -84,13 +84,15 @@ protected DotAccess(SourceLocation location, Identifier member) { // ----- Execution methods ----- /** - * Execute the dot access on an object value. + * Access to a member of an object value. * * @param receiver The receiver object value. * @return The member of the object. */ - @Specialization - protected Object onObject(ObjectValue receiver) { + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected Object onObject( + final LKQLObject receiver, + @CachedLibrary("receiver") DynamicObjectLibrary receiverLibrary) { // Try to get the built in Object builtIn = this.tryBuildIn(receiver); if (builtIn != null) { @@ -98,7 +100,7 @@ protected Object onObject(ObjectValue receiver) { } // Get the object member - Object res = receiver.get(this.member.getName()); + final Object res = receiverLibrary.getOrDefault(receiver, this.member.getName(), null); if (res != null) { return res; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ObjectLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ObjectLiteral.java index 39acd3fef..7f9916540 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ObjectLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ObjectLiteral.java @@ -22,11 +22,13 @@ package com.adacore.lkql_jit.nodes.expressions.literals; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.ExplodeLoop; +import com.oracle.truffle.api.object.DynamicObjectLibrary; +import com.oracle.truffle.api.object.Shape; /** * This node represents the literal node for an LKQL object. @@ -40,10 +42,18 @@ public final class ObjectLiteral extends Expr { /** Object ordered keys. */ private final String[] keys; + /** The shape of the dynamic object. */ + private final Shape shape; + // ----- Children ----- /** Object ordered values. */ - @Children private Expr[] values; + @Children private final Expr[] values; + + /** Object library to insert values in the result. */ + @Child + @SuppressWarnings("FieldMayBeFinal") + private DynamicObjectLibrary objectLibrary; // ----- Constructors ----- @@ -55,10 +65,12 @@ public final class ObjectLiteral extends Expr { * @param keys Ordered keys of the object. * @param values Ordered values of the object. */ - public ObjectLiteral(SourceLocation location, String[] keys, Expr[] values) { + public ObjectLiteral(final SourceLocation location, final String[] keys, final Expr[] values) { super(location); this.keys = keys; + this.shape = Shape.newBuilder().build(); this.values = values; + this.objectLibrary = DynamicObjectLibrary.getUncached(); } // ----- Execution methods ----- @@ -78,15 +90,15 @@ public Object executeGeneric(VirtualFrame frame) { */ @Override @ExplodeLoop - public ObjectValue executeObject(VirtualFrame frame) { - // Execute the values of the object - final Object[] values = new Object[this.keys.length]; + public LKQLObject executeObject(final VirtualFrame frame) { + // Create the result object + LKQLObject res = new LKQLObject(this.shape); for (int i = 0; i < this.keys.length; i++) { - values[i] = this.values[i].executeGeneric(frame); + this.objectLibrary.put(res, this.keys[i], this.values[i].executeGeneric(frame)); } - // Return the object value - return new ObjectValue(this.keys, values); + // Return the new LKQL object + return res; } // ----- Override methods ----- @@ -95,7 +107,7 @@ public ObjectValue executeObject(VirtualFrame frame) { * @see com.adacore.lkql_jit.nodes.LKQLNode#toString(int) */ @Override - public String toString(int indentLevel) { + public String toString(final int indentLevel) { return this.nodeRepresentation(indentLevel); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 79ff4d480..8098ef228 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; @@ -252,9 +253,13 @@ protected boolean eqBooleans(boolean left, boolean right) { * @param right The right object value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqObjects(ObjectValue left, ObjectValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqObjects( + final LKQLObject left, + final LKQLObject right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 797d8a50e..34d04b625 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.runtime.values.*; @@ -266,9 +267,13 @@ protected boolean neqBooleans(boolean left, boolean right) { * @param right The right object value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqObjects(ObjectValue left, ObjectValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqObjects( + final LKQLObject left, + final LKQLObject right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ObjectValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ObjectValue.java deleted file mode 100644 index b817bd2f2..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ObjectValue.java +++ /dev/null @@ -1,148 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.utils.functions.StringUtils; -import com.oracle.truffle.api.CompilerDirectives; -import java.util.HashMap; -import java.util.Iterator; -import java.util.Map; -import java.util.Objects; - -/** - * This class represents the object values in the LKQL language. - * - * @author Hugo GUERRIER - */ -public final class ObjectValue implements LKQLValue { - - // ----- Attributes ----- - - /** The content of the object. */ - private final Map content; - - // ----- Constructors ----- - - /** - * Create an object value. - * - * @param keys The keys of the object. - * @param values The values of the object. - */ - @CompilerDirectives.TruffleBoundary - public ObjectValue(String[] keys, Object[] values) { - this.content = new HashMap<>(keys.length); - for (int i = 0; i < keys.length; i++) { - this.content.put(keys[i], values[i]); - } - } - - /** - * Create a deep copy of the given object value. - * - * @param other The other object. - */ - @CompilerDirectives.TruffleBoundary - public ObjectValue(ObjectValue other) { - this.content = new HashMap<>(other.content); - } - - // ----- Getters ----- - - public Map getContent() { - return this.content; - } - - @CompilerDirectives.TruffleBoundary - public Object get(String key) { - return this.content.getOrDefault(key, null); - } - - @CompilerDirectives.TruffleBoundary - public void set(String key, Object value) { - this.content.put(key, value); - } - - @CompilerDirectives.TruffleBoundary - public boolean contains(String key) { - return this.content.containsKey(key); - } - - // ----- Value methods ----- - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (this == o) return true; - if (!(o instanceof ObjectValue other)) return false; - if (this.content.size() != other.content.size()) return false; - for (String key : this.content.keySet()) { - Object mineObject = this.content.getOrDefault(key, null); - Object hisObject = other.content.getOrDefault(key, null); - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - // Create the object string builder - StringBuilder res = new StringBuilder(); - res.append("{"); - Iterator keyIterator = this.content.keySet().stream().sorted().iterator(); - while (keyIterator.hasNext()) { - String key = keyIterator.next(); - Object value = this.content.get(key); - String valueString; - if (value == null) { - valueString = "null"; - } else if (value instanceof String s) { - valueString = StringUtils.toRepr(s); - } else { - valueString = value.toString(); - } - - res.append('"').append(key).append('"'); - res.append(": ").append(valueString); - if (keyIterator.hasNext()) { - res.append(", "); - } - } - res.append("}"); - - // Return the result - return res.toString(); - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 10c83e2cb..c697128d2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -24,10 +24,10 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.oracle.truffle.api.CompilerDirectives; import java.math.BigInteger; @@ -160,7 +160,7 @@ public static String fromJava(Object obj, String defaultValue) { return ANALYSIS_UNIT; } else if (LKQLTypeSystemGen.isBoolean(obj)) { return LKQL_BOOLEAN; - } else if (LKQLTypeSystemGen.isObjectValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLObject(obj)) { return LKQL_OBJECT; } else if (LKQLTypeSystemGen.isLKQLNamespace(obj)) { return LKQL_NAMESPACE; @@ -286,7 +286,7 @@ else if (javaValue instanceof Libadalang.Aspect aspect) { ? NodeNull.getInstance() : Libadalang.AdaNode.fromEntity(aspect.value) }; - return new ObjectValue(keys, values); + return LKQLObject.createUncached(keys, values); } // If the source is a reference result structure @@ -298,7 +298,7 @@ else if (javaValue instanceof Libadalang.RefResult refResultStruct) { ? NodeNull.getInstance() : Libadalang.AdaNode.fromEntity(refResultStruct.ref) }; - return new ObjectValue(keys, values); + return LKQLObject.createUncached(keys, values); } // If the source is a parameter-actual structure @@ -308,7 +308,7 @@ else if (javaValue instanceof Libadalang.ParamActual paramActual) { Libadalang.AdaNode.fromEntity(paramActual.actual), Libadalang.AdaNode.fromEntity(paramActual.param) }; - return new ObjectValue(keys, values); + return LKQLObject.createUncached(keys, values); } // Else, throw an exception for the unsupported type diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java index 53c3abedd..3e9ca3347 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ParsingUtils.java @@ -26,10 +26,10 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.langkit_translator.LangkitTranslator; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.ObjectValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLConfigFileResult; import com.oracle.truffle.api.CallTarget; @@ -146,7 +146,7 @@ public static LKQLConfigFileResult parseLKQLConfigFile( // Get the rules final Object allRulesSource = objectLibrary.getOrDefault(namespace, "rules", null); - if (allRulesSource instanceof ObjectValue allRulesObject) { + if (allRulesSource instanceof LKQLObject allRulesObject) { processRulesObject(allRulesObject, allRules, aliases, args); } else { throw LKQLRuntimeException.fromMessage( @@ -155,14 +155,14 @@ public static LKQLConfigFileResult parseLKQLConfigFile( // Get the Ada rules (not mandatory) final Object adaRulesSource = objectLibrary.getOrDefault(namespace, "ada_rules", null); - if (adaRulesSource instanceof ObjectValue adaRulesObject) { + if (adaRulesSource instanceof LKQLObject adaRulesObject) { processRulesObject(adaRulesObject, adaRules, aliases, args); } // Get the SPARK rules (not mandatory) final Object sparkRulesSource = objectLibrary.getOrDefault(namespace, "spark_rules", null); - if (sparkRulesSource instanceof ObjectValue sparkRulesObject) { + if (sparkRulesSource instanceof LKQLObject sparkRulesObject) { processRulesObject(sparkRulesObject, sparkRules, aliases, args); } @@ -182,14 +182,15 @@ public static LKQLConfigFileResult parseLKQLConfigFile( * @param args The map containing all parsed arguments. */ private static void processRulesObject( - final ObjectValue rulesObject, + final LKQLObject rulesObject, final List rules, final Map aliases, final Map> args) { // For each rule in the rules object explore its arguments - for (String ruleName : rulesObject.getContent().keySet()) { + for (Object ruleNameObject : rulesObject.keysUncached()) { // Get the rule arguments and check that it's an indexable value - final Object ruleArgs = rulesObject.get(ruleName); + final String ruleName = (String) ruleNameObject; + final Object ruleArgs = rulesObject.getUncached(ruleName); if (!LKQLTypeSystemGen.isIndexable(ruleArgs)) { throw LKQLRuntimeException.fromMessage("Rule arguments must be an indexable value"); } @@ -200,13 +201,13 @@ private static void processRulesObject( rules.add(ruleName); } else { for (Object ruleArg : ruleArgsContent) { - if (!LKQLTypeSystemGen.isObjectValue(ruleArg)) { + if (!LKQLTypeSystemGen.isLKQLObject(ruleArg)) { throw LKQLRuntimeException.fromMessage( "Rule argument must be an object value"); } processArgObject( ruleName, - LKQLTypeSystemGen.asObjectValue(ruleArg), + LKQLTypeSystemGen.asLKQLObject(ruleArg), rules, aliases, args); @@ -226,13 +227,13 @@ private static void processRulesObject( */ private static void processArgObject( final String ruleName, - final ObjectValue argObject, + final LKQLObject argObject, final List rules, final Map aliases, final Map> args) { // If the arg has an alias get the name of it and add it in the alias list final String realName; - final Object aliasName = argObject.get(Constants.ALIAS_NAME_SYMBOL); + final Object aliasName = argObject.getUncached(Constants.ALIAS_NAME_SYMBOL); if (aliasName != null) { if (!LKQLTypeSystemGen.isString(aliasName)) { throw LKQLRuntimeException.fromMessage("Rule alias name must be a string"); @@ -247,14 +248,16 @@ private static void processArgObject( rules.add(realName); // Get all other arguments - for (String argName : argObject.getContent().keySet()) { + for (Object argNameObject : argObject.keysUncached()) { + final String argName = (String) argNameObject; + // If the argument name is "alias_symbol" continue the exploration if (argName.equals(Constants.ALIAS_NAME_SYMBOL)) { continue; } // Put the argument in the map - Object argValue = argObject.get(argName); + Object argValue = argObject.getUncached(argName); Map ruleArgs = args.getOrDefault(realName, new HashMap<>()); ruleArgs.put(argName, argValue); args.put(realName, ruleArgs); diff --git a/testsuite/tests/interop/object/Main.java b/testsuite/tests/interop/object/Main.java new file mode 100644 index 000000000..2097e56a5 --- /dev/null +++ b/testsuite/tests/interop/object/Main.java @@ -0,0 +1,33 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val object = {x: 42, y: "Hello"} + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value object = namespace.getMember("object"); + System.out.println("=== Object interop messages:"); + print("toString()", object.toString()); + print("hasMembers()", object.hasMembers()); + print("hasMember('x')", object.hasMember("x")); + print("hasMember('y')", object.hasMember("y")); + print("hasMember('z')", object.hasMember("z")); + print("getMember('x')", object.getMember("x")); + print("getMember('y')", object.getMember("y")); + print("getMember('z')", object.getMember("z")); + // TODO (LATER IN MR): Call "getMemberKeys" when list values are interop + } +} diff --git a/testsuite/tests/interop/object/test.out b/testsuite/tests/interop/object/test.out new file mode 100644 index 000000000..5fa247427 --- /dev/null +++ b/testsuite/tests/interop/object/test.out @@ -0,0 +1,9 @@ +=== Object interop messages: + toString(): {"x": 42, "y": "Hello"} + hasMembers(): true + hasMember('x'): true + hasMember('y'): true + hasMember('z'): false + getMember('x'): 42 + getMember('y'): Hello + getMember('z'): null diff --git a/testsuite/tests/interop/object/test.yaml b/testsuite/tests/interop/object/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/object/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From ac4e0dbe77852ef08c9c701779fe8b5ec892721f Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Wed, 23 Aug 2023 17:05:21 +0200 Subject: [PATCH 08/23] minor: Modify the misc token tests because object keys aren't ordered anymore --- testsuite/tests/miscellaneous/tokens/script.lkql | 2 +- testsuite/tests/miscellaneous/tokens/test.out | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/testsuite/tests/miscellaneous/tokens/script.lkql b/testsuite/tests/miscellaneous/tokens/script.lkql index 1770401e2..91a3840dd 100644 --- a/testsuite/tests/miscellaneous/tokens/script.lkql +++ b/testsuite/tests/miscellaneous/tokens/script.lkql @@ -1,3 +1,3 @@ -print([(a, {line: a.start_line, column: a.start_column}) for a in (select first AdaNode).tokens]) +print([(a, a.start_line, a.start_column) for a in (select first AdaNode).tokens]) print((select first AdaNode).token_start().unit) print((select first AdaNode).unit.tokens) diff --git a/testsuite/tests/miscellaneous/tokens/test.out b/testsuite/tests/miscellaneous/tokens/test.out index 485b558b4..e7f419d5c 100644 --- a/testsuite/tests/miscellaneous/tokens/test.out +++ b/testsuite/tests/miscellaneous/tokens/test.out @@ -1,3 +1,3 @@ -[(, {"column": 1, "line": 1}), (, {"column": 5, "line": 1}), (, {"column": 6, "line": 1}), (, {"column": 9, "line": 1}), (, {"column": 10, "line": 1}), (, {"column": 17, "line": 1}), (, {"column": 18, "line": 1}), (, {"column": 19, "line": 1}), (, {"column": 22, "line": 1}), (, {"column": 23, "line": 1}), (, {"column": 26, "line": 1}), (, {"column": 27, "line": 1}), (, {"column": 34, "line": 1}), (, {"column": 35, "line": 1}), (, {"column": 1, "line": 3}), (, {"column": 10, "line": 3}), (, {"column": 11, "line": 3}), (, {"column": 15, "line": 3}), (, {"column": 16, "line": 3}), (, {"column": 18, "line": 3}), (, {"column": 4, "line": 4}), (, {"column": 11, "line": 4}), (, {"column": 20, "line": 4}), (, {"column": 21, "line": 4}), (, {"column": 22, "line": 4}), (, {"column": 28, "line": 4}), (, {"column": 29, "line": 4}), (, {"column": 31, "line": 4}), (, {"column": 32, "line": 4}), (, {"column": 47, "line": 4}), (, {"column": 48, "line": 4}), (, {"column": 4, "line": 5}), (, {"column": 19, "line": 5}), (, {"column": 20, "line": 5}), (, {"column": 21, "line": 5}), (, {"column": 22, "line": 5}), (, {"column": 30, "line": 5}), (, {"column": 31, "line": 5}), (, {"column": 37, "line": 5}), (, {"column": 38, "line": 5}), (, {"column": 40, "line": 5}), (, {"column": 41, "line": 5}), (, {"column": 65, "line": 5}), (, {"column": 66, "line": 5}), (, {"column": 1, "line": 6}), (, {"column": 6, "line": 6}), (, {"column": 4, "line": 7}), (, {"column": 12, "line": 7}), (, {"column": 13, "line": 7}), (, {"column": 14, "line": 7}), (, {"column": 21, "line": 7}), (, {"column": 22, "line": 7}), (, {"column": 23, "line": 7}), (, {"column": 1, "line": 8}), (, {"column": 4, "line": 8}), (, {"column": 5, "line": 8}), (, {"column": 9, "line": 8})] +[(, 1, 1), (, 1, 5), (, 1, 6), (, 1, 9), (, 1, 10), (, 1, 17), (, 1, 18), (, 1, 19), (, 1, 22), (, 1, 23), (, 1, 26), (, 1, 27), (, 1, 34), (, 1, 35), (, 3, 1), (, 3, 10), (, 3, 11), (, 3, 15), (, 3, 16), (, 3, 18), (, 4, 4), (, 4, 11), (, 4, 20), (, 4, 21), (, 4, 22), (, 4, 28), (, 4, 29), (, 4, 31), (, 4, 32), (, 4, 47), (, 4, 48), (, 5, 4), (, 5, 19), (, 5, 20), (, 5, 21), (, 5, 22), (, 5, 30), (, 5, 31), (, 5, 37), (, 5, 38), (, 5, 40), (, 5, 41), (, 5, 65), (, 5, 66), (, 6, 1), (, 6, 6), (, 7, 4), (, 7, 12), (, 7, 13), (, 7, 14), (, 7, 21), (, 7, 22), (, 7, 23), (, 8, 1), (, 8, 4), (, 8, 5), (, 8, 9)] [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] From ab61082dce832b984ce10b7f923691e4d852aed8 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Thu, 24 Aug 2023 12:07:08 +0200 Subject: [PATCH 09/23] Rework the representaiton of the list values Add a new "LKQLIterator" value to represents iterators. --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 3 +- .../built_ins/functions/ConcatFunction.java | 19 +- .../built_ins/functions/MapFunction.java | 4 +- .../functions/SpecifiedUnitsFunction.java | 4 +- .../built_ins/functions/UniqueFunction.java | 4 +- .../built_ins/functions/UnitsFunction.java | 7 +- .../methods/AnalysisUnitMethods.java | 4 +- .../built_ins/methods/IterableMethods.java | 4 +- .../built_ins/methods/ListMethods.java | 9 +- .../built_ins/methods/NodeMethods.java | 6 +- .../built_ins/methods/StrMethods.java | 4 +- .../built_ins/values/LKQLNamespace.java | 4 +- .../lkql_jit/built_ins/values/LKQLObject.java | 4 +- .../values/iterators/LKQLIterator.java | 76 +++++ .../values/iterators/LKQLListIterator.java | 62 +++++ .../built_ins/values/lists/LKQLArrayList.java | 76 +++++ .../built_ins/values/lists/LKQLList.java | 259 ++++++++++++++++++ .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../lkql_jit/nodes/expressions/Query.java | 9 +- .../expressions/literals/ListLiteral.java | 11 +- .../expressions/operators/BinConcat.java | 29 +- .../nodes/expressions/operators/BinEq.java | 11 +- .../nodes/expressions/operators/BinNeq.java | 11 +- .../lkql_jit/nodes/patterns/SelectorCall.java | 17 +- .../chained_patterns/ChainedPatternLink.java | 6 +- .../lkql_jit/runtime/values/ListValue.java | 209 -------------- .../lkql_jit/utils/LKQLTypesHelper.java | 6 +- .../utils/functions/ReflectionUtils.java | 6 +- testsuite/tests/interop/iterator/Main.java | 27 ++ testsuite/tests/interop/iterator/test.out | 9 + testsuite/tests/interop/iterator/test.yaml | 1 + testsuite/tests/interop/list/Main.java | 37 +++ testsuite/tests/interop/list/test.out | 12 + testsuite/tests/interop/list/test.yaml | 1 + testsuite/tests/interop/namespace/Main.java | 2 +- testsuite/tests/interop/namespace/test.out | 1 + testsuite/tests/interop/object/Main.java | 2 +- testsuite/tests/interop/object/test.out | 1 + 38 files changed, 675 insertions(+), 287 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLIterator.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ListValue.java create mode 100644 testsuite/tests/interop/iterator/Main.java create mode 100644 testsuite/tests/interop/iterator/test.out create mode 100644 testsuite/tests/interop/iterator/test.yaml create mode 100644 testsuite/tests/interop/list/Main.java create mode 100644 testsuite/tests/interop/list/test.out create mode 100644 testsuite/tests/interop/list/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 9dbaf8711..62c3d7a33 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -27,6 +27,7 @@ import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.*; @@ -52,7 +53,7 @@ PropertyRefValue.class, SelectorValue.class, LKQLTuple.class, - ListValue.class, + LKQLList.class, LazyListValue.class, SelectorListValue.class, LazyCollection.class, 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 index e5c4429b7..c26d35f1c 100644 --- 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 @@ -24,10 +24,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; 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.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -59,7 +60,7 @@ public static BuiltInFunctionValue getValue() { Object lists = frame.getArguments()[0]; // Check the type of the argument - if (!LKQLTypeSystemGen.isListValue(lists)) { + if (!LKQLTypeSystemGen.isLKQLList(lists)) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.fromJava(lists), @@ -67,7 +68,7 @@ public static BuiltInFunctionValue getValue() { } // Cast the argument to list - ListValue listValue = (ListValue) lists; + LKQLList listValue = LKQLTypeSystemGen.asLKQLList(lists); // If the list is not empty if (listValue.size() > 0) { @@ -95,12 +96,12 @@ public static BuiltInFunctionValue getValue() { } // If the first item is a list look for lists in the list - if (LKQLTypeSystemGen.isListValue(firstItem)) { + if (LKQLTypeSystemGen.isLKQLList(firstItem)) { // Create a result array and add all list of the argument - Object[] result = LKQLTypeSystemGen.asListValue(firstItem).getContent(); + Object[] result = LKQLTypeSystemGen.asLKQLList(firstItem).getContent(); for (int i = 1; i < listValue.size(); i++) { final Object item = listValue.get(i); - if (!LKQLTypeSystemGen.isListValue(item)) { + if (!LKQLTypeSystemGen.isLKQLList(item)) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.fromJava(item), @@ -109,9 +110,9 @@ public static BuiltInFunctionValue getValue() { result = ArrayUtils.concat( result, - LKQLTypeSystemGen.asListValue(item).getContent()); + LKQLTypeSystemGen.asLKQLList(item).getContent()); } - return new ListValue(result); + return new LKQLArrayList(result); } // Else there is an error @@ -124,7 +125,7 @@ public static BuiltInFunctionValue getValue() { // If the list is empty just return an empty list else { - return new ListValue(new Object[0]); + return new LKQLArrayList(new Object[0]); } }); } 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 index ce57d91b3..e3d836588 100644 --- 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 @@ -25,12 +25,12 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.FunctionValue; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -118,7 +118,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the result - return new ListValue(res); + return new LKQLArrayList(res); } } } 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 index 884c895d0..2565a08ed 100644 --- 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 @@ -24,9 +24,9 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.oracle.truffle.api.frame.VirtualFrame; /** @@ -48,7 +48,7 @@ public static BuiltInFunctionValue getValue() { new String[] {}, new Expr[] {}, (VirtualFrame frame, FunCall call) -> { - return new ListValue(LKQLLanguage.getContext(call).getSpecifiedUnits()); + return new LKQLArrayList(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 index 897d23134..675da84dd 100644 --- 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 @@ -24,10 +24,10 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; 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.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; @@ -70,7 +70,7 @@ public static BuiltInFunctionValue getValue() { Indexable indexable = LKQLTypeSystemGen.asIndexable(indexableObject); // Return the result list - return new ListValue( + return new LKQLArrayList( ArrayUtils.unique(indexable.getContent()).toArray(new Object[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 index 295063d59..771ee1aca 100644 --- 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 @@ -24,9 +24,9 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.oracle.truffle.api.frame.VirtualFrame; /** @@ -47,8 +47,7 @@ public static BuiltInFunctionValue getValue() { "Return an iterator on all units", new String[] {}, new Expr[] {}, - (VirtualFrame frame, FunCall call) -> { - return new ListValue(LKQLLanguage.getContext(call).getAllUnits()); - }); + (VirtualFrame frame, FunCall call) -> + new LKQLArrayList(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 9f6ecd01a..88bb8b74c 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 @@ -26,8 +26,8 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; @@ -148,7 +148,7 @@ public Object executeGeneric(VirtualFrame frame) { resList.add(current); current = current.next(); } - return new ListValue(resList.toArray(new Libadalang.Token[0])); + return new LKQLArrayList(resList.toArray(new Libadalang.Token[0])); } } 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 a8c86e81a..7210662d2 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 @@ -26,8 +26,8 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.ReduceFunction; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.oracle.truffle.api.frame.VirtualFrame; @@ -84,7 +84,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the new list value - return new ListValue(resList.toArray(new Object[0])); + return new LKQLArrayList(resList.toArray(new Object[0])); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java index 14f4b9d48..516680dbb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java @@ -25,10 +25,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.functions.UniqueFunction; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; 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.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; import java.util.Arrays; @@ -81,7 +82,7 @@ protected void initMethods() { (VirtualFrame frame, FunCall call) -> { var args = frame.getArguments(); - if (!LKQLTypeSystemGen.isListValue(args[0])) { + if (!LKQLTypeSystemGen.isLKQLList(args[0])) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.fromJava(args[0]), @@ -102,7 +103,7 @@ protected void initMethods() { call.getArgList().getArgs()[2]); } - ListValue list = LKQLTypeSystemGen.asListValue(args[0]); + LKQLList list = LKQLTypeSystemGen.asLKQLList(args[0]); long lowBound = LKQLTypeSystemGen.asLong(args[1]); long highBound = LKQLTypeSystemGen.asLong(args[2]); @@ -112,7 +113,7 @@ protected void initMethods() { throw LKQLRuntimeException.invalidIndex((int) highBound, call); } - return new ListValue( + return new LKQLArrayList( Arrays.copyOfRange( list.getContent(), (int) lowBound - 1, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java index a386455b2..56073bffb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java @@ -28,9 +28,9 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; @@ -187,7 +187,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the list value - return new ListValue(res); + return new LKQLArrayList(res); } } @@ -269,7 +269,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the result - return new ListValue(resList.toArray(new Libadalang.Token[0])); + return new LKQLArrayList(resList.toArray(new Libadalang.Token[0])); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java index 1171ff4f9..208c3f0db 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java @@ -26,9 +26,9 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.BaseNameFunction; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -340,7 +340,7 @@ public Object executeGeneric(VirtualFrame frame) { LKQLTypeSystemGen.asString(separatorObject)); // Return the list value of the split string - return new ListValue(separated); + return new LKQLArrayList(separated); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index 28e72820e..4058cf595 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -23,8 +23,8 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.runtime.Cell; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; @@ -205,7 +205,7 @@ boolean isMemberReadable( Object getMembers( @SuppressWarnings("unused") final boolean includeInternal, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new ListValue(objectLibrary.getKeyArray(this)); + return new LKQLArrayList(objectLibrary.getKeyArray(this)); } /** Get the value of the wanted member in the receiver namespace. */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index 67e9ae997..4080f7fbb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -23,7 +23,7 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.runtime.values.ListValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; @@ -191,7 +191,7 @@ boolean isMemberReadable( Object getMembers( @SuppressWarnings("unused") final boolean includeInternal, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new ListValue(objectLibrary.getKeyArray(this)); + return new LKQLArrayList(objectLibrary.getKeyArray(this)); } /** Get the value of the wanted member in the receiver object. */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLIterator.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLIterator.java new file mode 100644 index 000000000..0a6541a3d --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLIterator.java @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.iterators; + +import com.adacore.lkql_jit.utils.Iterator; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.StopIterationException; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; + +/** This class represents an iterator value in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public abstract class LKQLIterator implements TruffleObject, Iterator { + + // ----- Constructors ----- + + /** The protected constructor. */ + protected LKQLIterator() {} + + // ----- Iterator required methods ----- + + /** Get whether the iterator has a next element. */ + public abstract boolean hasNext(); + + /** Get the next element and move the cursor forward. */ + public abstract Object next(); + + // ----- Value methods ----- + + /** Tell the interop library that the value is an iterator. */ + @ExportMessage + public boolean isIterator() { + return true; + } + + /** Get if the iterator has a next element. */ + @ExportMessage + public boolean hasIteratorNextElement() { + return this.hasNext(); + } + + /** + * Get the next element of the iterator. + * + * @throws StopIterationException If there is no next element. + */ + @ExportMessage + public Object getIteratorNextElement() throws StopIterationException { + try { + return this.next(); + } catch (IndexOutOfBoundsException e) { + throw StopIterationException.create(e); + } + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java new file mode 100644 index 000000000..bcb8e1bdf --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java @@ -0,0 +1,62 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.iterators; + +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; + +/** This class represents an iterator on a list in the LKQL language. */ +public final class LKQLListIterator extends LKQLIterator { + + // ----- Instance attributes ----- + + /** The list to iterate on. */ + private final LKQLList list; + + /** The cursor to the next element to return. */ + private int cursor; + + // ----- Constructors ----- + + /** Create a new list iterator with the iterated list. */ + public LKQLListIterator(final LKQLList list) { + this.list = list; + this.cursor = 0; + } + + // ----- Iterator required methods ----- + + @Override + public boolean hasNext() { + return this.cursor < this.list.size(); + } + + @Override + public Object next() { + return this.list.get(this.cursor++); + } + + @Override + public void reset() { + this.cursor = 0; + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java new file mode 100644 index 000000000..b5e4e3af0 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java @@ -0,0 +1,76 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.lists; + +import com.adacore.lkql_jit.exception.utils.InvalidIndexException; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; + +/** This class represents an array list in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public final class LKQLArrayList extends LKQLList { + + // ----- Attributes ----- + + /** The content of the array list. */ + private final Object[] content; + + // ----- Constructors ----- + + /** Create a new array list with its content. */ + public LKQLArrayList(final Object[] content) { + this.content = content; + } + + // ----- List required methods ----- + + @Override + public long size() { + return this.content.length; + } + + @Override + public Object get(int i) throws InvalidIndexException { + try { + return this.content[i]; + } catch (IndexOutOfBoundsException e) { + throw new InvalidIndexException(); + } + } + + @Override + public Object[] asArray() { + return this.content; + } + + // ----- Value methods ----- + + /** Return the identity hash code for the given LKQL array list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLArrayList receiver) { + return System.identityHashCode(receiver); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java new file mode 100644 index 000000000..093c38124 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java @@ -0,0 +1,259 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.lists; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.iterators.LKQLListIterator; +import com.adacore.lkql_jit.exception.utils.InvalidIndexException; +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.interfaces.Truthy; +import com.adacore.lkql_jit.utils.Constants; +import com.adacore.lkql_jit.utils.functions.StringUtils; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +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.interop.TruffleObject; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; +import java.util.Objects; + +/** This abstract class represents all list like values in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public abstract class LKQLList implements TruffleObject, Iterable, Indexable, Truthy { + + // ----- Constructors ----- + + /** The protected constructor. */ + protected LKQLList() {} + + // ----- List required methods ----- + + /** Get the size of the list. */ + public abstract long size(); + + /** + * Get the list element at the given index. + * + * @throws InvalidIndexException If the given index is invalid. + */ + public abstract Object get(int i) throws InvalidIndexException; + + /** Get the list as a pure Java array. */ + public abstract Object[] asArray(); + + /** Get a new iterator on the list. */ + public LKQLListIterator iterator() { + return new LKQLListIterator(this); + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + public boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + public Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two lists. */ + @ExportMessage + public static class IsIdenticalOrUndefined { + /** Compare two LKQL lists. */ + @Specialization + public static TriState onList(final LKQLList left, final LKQLList right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + public static TriState onOther( + @SuppressWarnings("unused") final LKQLList receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLList receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public Object toDisplayString( + @SuppressWarnings("unused") final boolean allowSideEffect, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { + // Prepare the result + StringBuilder resultBuilder = new StringBuilder("["); + + // Iterate over the list values + for (int i = 0; i < this.size(); i++) { + Object elem = this.get(i); + + // Get the element string + String elemString; + if (elem instanceof String) { + elemString = StringUtils.toRepr((String) interopLibrary.toDisplayString(elem)); + } else { + elemString = (String) interopLibrary.toDisplayString(elem); + } + + // Add the element string to the result + resultBuilder.append(elemString); + if (i < this.size() - 1) resultBuilder.append(", "); + } + + // Return the result + resultBuilder.append("]"); + return resultBuilder.toString(); + } + + /** Tell the interop API that the list can be cast to a boolean. */ + @ExportMessage + public boolean isBoolean() { + return true; + } + + /** Get the boolean representation of the list. */ + @ExportMessage + public boolean asBoolean() { + return this.isTruthy(); + } + + /** Tell the interop library that the value is array like. */ + @ExportMessage + public boolean hasArrayElements() { + return true; + } + + /** Get the array size for the interop library. */ + @ExportMessage + public long getArraySize() { + return this.size(); + } + + /** Tell the interop library if the wanted index is readable. */ + @ExportMessage + public boolean isArrayElementReadable(long index) { + try { + this.get((int) index); + return true; + } catch (InvalidIndexException e) { + return false; + } + } + + /** Get the array element of the given index. */ + @ExportMessage + public Object readArrayElement(long index) { + return this.get((int) index); + } + + /** Tell the interop library that the list has an iterator object. */ + @ExportMessage + public boolean hasIterator() { + return true; + } + + /** Get the iterator for the list. */ + @ExportMessage + public Object getIterator() { + return this.iterator(); + } + + // ---- LKQL value methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(final LKQLValue o) { + if (o == this) return true; + if (!(o instanceof LKQLList other)) return false; + if (this.size() != other.size()) return false; + for (int i = 0; i < this.size(); i++) { + Object mineObject = this.get(i); + Object hisObject = other.get(i); + if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { + if (!mine.internalEquals(his)) return false; + } else { + if (!Objects.equals(mineObject, hisObject)) return false; + } + } + return true; + } + + @Override + public boolean isTruthy() { + try { + this.get(0); + return true; + } catch (InvalidIndexException e) { + return false; + } + } + + @Override + public Object[] getContent() { + return this.asArray(); + } + + @Override + @CompilerDirectives.TruffleBoundary + public boolean contains(Object elem) { + final LKQLListIterator iterator = this.iterator(); + while (iterator.hasNext()) { + Object val = iterator.next(); + if (elem.equals(val)) return true; + } + return false; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary listLibrary = InteropLibrary.getUncached(this); + return (String) listLibrary.toDisplayString(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof LKQLList other)) return false; + return this.internalEquals(other); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 79b7e8dec..765ed9ed3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; @@ -177,8 +178,8 @@ public LKQLTuple executeTuple(VirtualFrame frame) throws UnexpectedResultExcepti * @return The result of the node execution as a list value. * @throws UnexpectedResultException If the node cannot be evaluated as a list. */ - public ListValue executeList(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectListValue(executeGeneric(frame)); + public LKQLList executeList(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLList(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index ee70ebeb3..6ade29a55 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -25,11 +25,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; import com.adacore.lkql_jit.nodes.patterns.chained_patterns.ChainedNodePattern; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; @@ -137,9 +138,9 @@ public Object executeGeneric(VirtualFrame frame) { } // Else, if the "from" is a list of node - else if (LKQLTypeSystemGen.isListValue(fromObject)) { + else if (LKQLTypeSystemGen.isLKQLList(fromObject)) { // Verify the content of the list - ListValue fromList = LKQLTypeSystemGen.asListValue(fromObject); + LKQLList fromList = LKQLTypeSystemGen.asLKQLList(fromObject); fromNodes = new Libadalang.AdaNode[(int) fromList.size()]; for (int i = 0; i < fromList.size(); i++) { try { @@ -174,7 +175,7 @@ else if (LKQLTypeSystemGen.isListValue(fromObject)) { } // Return the result list value - return new ListValue(resNodes.toArray(new Libadalang.AdaNode[0])); + return new LKQLArrayList(resNodes.toArray(new Libadalang.AdaNode[0])); } // If the query mode is first diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java index ae60c1b98..7e35dbdff 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java @@ -22,10 +22,12 @@ package com.adacore.lkql_jit.nodes.expressions.literals; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.nodes.ExplodeLoop; /** * This node represents a list literal node in the LKQL language. @@ -47,7 +49,7 @@ public final class ListLiteral extends Expr { * @param location The location of the node in the source. * @param exprs The expressions inside the list. */ - public ListLiteral(SourceLocation location, Expr[] exprs) { + public ListLiteral(final SourceLocation location, final Expr[] exprs) { super(location); this.exprs = exprs; } @@ -68,7 +70,8 @@ public Object executeGeneric(VirtualFrame frame) { * com.adacore.lkql_jit.nodes.expressions.Expr#executeList(com.oracle.truffle.api.frame.VirtualFrame) */ @Override - public ListValue executeList(VirtualFrame frame) { + @ExplodeLoop + public LKQLList executeList(VirtualFrame frame) { // Evaluate the list content Object[] values = new Object[this.exprs.length]; for (int i = 0; i < this.exprs.length; i++) { @@ -76,7 +79,7 @@ public ListValue executeList(VirtualFrame frame) { } // Return the list value - return new ListValue(values); + return new LKQLArrayList(values); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java index 34fefb48e..90e9db916 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java @@ -23,15 +23,20 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.runtime.values.ListValue; +import com.adacore.lkql_jit.utils.Constants; 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.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; 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.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; +import java.util.Arrays; /** * This node represents the concatenation operation in the LKQL language. @@ -75,9 +80,21 @@ protected String concatStrings(String left, String right) { * @param right The right list value. * @return The result of the list concatenation. */ - @Specialization - protected ListValue concatLists(ListValue left, ListValue right) { - return new ListValue(ArrayUtils.concat(left.getContent(), right.getContent())); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected LKQLList concatLists( + final LKQLList left, + final LKQLList right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + try { + final int leftSize = (int) leftLibrary.getArraySize(left); + final int rightSize = (int) rightLibrary.getArraySize(right); + final Object[] resContent = Arrays.copyOf(left.asArray(), leftSize + rightSize); + System.arraycopy(right.asArray(), 0, resContent, leftSize, rightSize); + return new LKQLArrayList(resContent); + } catch (UnsupportedMessageException e) { + throw LKQLRuntimeException.fromJavaException(e, this); + } } /** @@ -88,7 +105,7 @@ protected ListValue concatLists(ListValue left, ListValue right) { */ @Fallback protected void nonConcatenable(Object left, Object right) { - if (LKQLTypeSystemGen.isString(left) || LKQLTypeSystemGen.isListValue(left)) { + if (LKQLTypeSystemGen.isString(left) || LKQLTypeSystemGen.isLKQLList(left)) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.fromJava(left), LKQLTypesHelper.fromJava(right), this); } else { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 8098ef228..114c8ebc7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -27,6 +27,7 @@ import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -181,9 +182,13 @@ protected boolean eqTuples( * @param right The right list value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqLists(ListValue left, ListValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqLists( + final LKQLList left, + final LKQLList right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 34d04b625..858cc6555 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -27,6 +27,7 @@ import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -182,9 +183,13 @@ protected boolean neqTuples( * @param right The right list value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqLists(ListValue left, ListValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqLists( + final LKQLList left, + final LKQLList right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java index dbd0d3bce..563579831 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java @@ -24,6 +24,8 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.arguments.Arg; @@ -31,7 +33,6 @@ import com.adacore.lkql_jit.nodes.arguments.NamedArg; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.SelectorListValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.utils.Constants; @@ -146,20 +147,20 @@ public boolean executeVerification( * @param pattern The pattern to perform the filtering logic. * @return The list of the validating nodes. */ - public ListValue executeFiltering( + public LKQLList executeFiltering( VirtualFrame frame, Libadalang.AdaNode node, BasePattern pattern) { // Get the selector list SelectorListValue selectorListValue = this.getSelectorList(frame, node); // Prepare the result - ListValue res; + LKQLList res; // If the quantifier is all, verify it before returning anything if (this.quantifier == Quantifier.ALL) { if (this.isAll(frame, selectorListValue, pattern)) { res = this.getFilteredList(frame, selectorListValue, pattern); } else { - res = new ListValue(new Libadalang.AdaNode[0]); + res = new LKQLArrayList(new Libadalang.AdaNode[0]); } } @@ -300,7 +301,7 @@ private boolean isAny( * @param pattern The pattern for the filtering. * @return The list value */ - private ListValue getFilteredList( + private LKQLList getFilteredList( VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { // Prepare the result List resList = new ArrayList<>(); @@ -315,7 +316,7 @@ private ListValue getFilteredList( } // Return the result - return new ListValue(resList.toArray(new Libadalang.AdaNode[0])); + return new LKQLArrayList(resList.toArray(new Libadalang.AdaNode[0])); } /** @@ -327,7 +328,7 @@ private ListValue getFilteredList( */ private void doBinding( VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { - ListValue listValue = this.getFilteredList(frame, selectorListValue, pattern); + LKQLList listValue = this.getFilteredList(frame, selectorListValue, pattern); this.doBinding(frame, listValue); } @@ -337,7 +338,7 @@ private void doBinding( * @param frame The frame to execute in. * @param listValue The list bind. */ - private void doBinding(VirtualFrame frame, ListValue listValue) { + private void doBinding(VirtualFrame frame, LKQLList listValue) { FrameUtils.writeLocal(frame, this.bindingSlot, listValue); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/ChainedPatternLink.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/ChainedPatternLink.java index 994a25b03..6068b614b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/ChainedPatternLink.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/ChainedPatternLink.java @@ -24,10 +24,10 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.patterns.BasePattern; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -103,8 +103,8 @@ protected Libadalang.AdaNode[] doPatternFiltering(VirtualFrame frame, Object res } // If the result object is a list of node - else if (LKQLTypeSystemGen.isListValue(resultObject)) { - ListValue listValue = LKQLTypeSystemGen.asListValue(resultObject); + else if (LKQLTypeSystemGen.isLKQLList(resultObject)) { + LKQLList listValue = LKQLTypeSystemGen.asLKQLList(resultObject); for (int i = 0; i < listValue.size(); i++) { try { Libadalang.AdaNode toVerify = LKQLTypeSystemGen.expectAdaNode(listValue.get(i)); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ListValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ListValue.java deleted file mode 100644 index 547e82282..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/ListValue.java +++ /dev/null @@ -1,209 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -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.interfaces.Truthy; -import com.adacore.lkql_jit.utils.Iterator; -import com.adacore.lkql_jit.utils.functions.ArrayUtils; -import com.adacore.lkql_jit.utils.functions.StringUtils; -import com.oracle.truffle.api.CompilerDirectives; -import java.util.Objects; - -/** - * This class represents a list in the LKQL language. - * - * @author Hugo GUERRIER - */ -public final class ListValue implements Iterable, Indexable, Truthy { - - // ----- Attributes ----- - - /** The content of the list. */ - private final Object[] content; - - // ----- Constructors ----- - - /** - * Create a new list value. - * - * @param content The list content. - */ - public ListValue(Object[] content) { - this.content = content; - } - - // ----- Value methods ----- - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#get(int) - */ - @Override - public Object get(int index) throws InvalidIndexException { - if (index < 0 || index >= this.content.length) { - throw new InvalidIndexException(); - } - return this.content[index]; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#getContent() - */ - @Override - public Object[] getContent() { - return content; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#size() - */ - @Override - public long size() { - return this.content.length; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#contains(Object) - */ - @Override - public boolean contains(Object elem) { - return ArrayUtils.indexOf(this.content, elem) > -1; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Truthy#isTruthy() - */ - @Override - public boolean isTruthy() { - return this.content.length > 0; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#iterator() - */ - @Override - public Iterator iterator() { - return new ListValueIterator(this); - } - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof ListValue other)) return false; - if (other.content.length != this.content.length) return false; - for (int i = 0; i < this.content.length; i++) { - Object mineObject = this.content[i]; - Object hisObject = other.content[i]; - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - // Create the list string in a builder - StringBuilder builder = new StringBuilder(); - builder.append('['); - for (int i = 0; i < this.content.length; i++) { - if (this.content[i] == null) { - builder.append("null"); - } else if (this.content[i] instanceof String s) { - builder.append(StringUtils.toRepr(s)); - } else { - builder.append(this.content[i].toString()); - } - if (i < this.content.length - 1) builder.append(", "); - } - builder.append(']'); - - // Return the tuple string representation - return builder.toString(); - } - - // ----- Inner classes ----- - - /** This class represents an iterator for a list value. */ - public static final class ListValueIterator implements Iterator { - - // ----- Attributes ----- - - /** The list to iterate on. */ - private final ListValue list; - - /** The pointer to the next value to return. */ - private int pointer; - - // ----- Constructors ----- - - /** - * Create a new iterator on the list value. - * - * @param list The list to iterate on. - */ - public ListValueIterator(ListValue list) { - this.list = list; - this.pointer = 0; - } - - // ----- Iteration methods ----- - - /** - * @see com.adacore.lkql_jit.utils.Iterator#hasNext() - */ - @Override - public boolean hasNext() { - return this.pointer < this.list.size(); - } - - /** - * @see com.adacore.lkql_jit.utils.Iterator#next() - */ - @Override - public Object next() { - return this.list.get(this.pointer++); - } - - /** - * @see com.adacore.lkql_jit.utils.Iterator#reset() - */ - @Override - public void reset() { - this.pointer = 0; - } - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index c697128d2..978fb6052 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -25,8 +25,8 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLObject; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.oracle.truffle.api.CompilerDirectives; import java.math.BigInteger; @@ -146,7 +146,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_SELECTOR; } else if (LKQLTypeSystemGen.isLKQLTuple(obj)) { return LKQL_TUPLE; - } else if (LKQLTypeSystemGen.isListValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLList(obj)) { return LKQL_LIST; } else if (LKQLTypeSystemGen.isLazyListValue(obj)) { return LKQL_LAZY_LIST; @@ -265,7 +265,7 @@ else if (javaValue instanceof Libadalang.ArrayBase array) { res[i] = toLKQLValue(obj); i++; } - return new ListValue(res); + return new LKQLArrayList(res); } // If the source is an enum diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ReflectionUtils.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ReflectionUtils.java index 447bdc9d9..c3233b0cb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ReflectionUtils.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ReflectionUtils.java @@ -24,12 +24,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.ListValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.Locatable; import com.oracle.truffle.api.CompilerDirectives; @@ -78,9 +78,9 @@ public static Object refineArgument(Object source, Class type, Arg argument) // If the required type is a unit array else if (type.equals(Libadalang.AnalysisUnitArray.class)) { - ListValue resList; + LKQLList resList; try { - resList = LKQLTypeSystemGen.expectListValue(res); + resList = LKQLTypeSystemGen.expectLKQLList(res); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_LIST, diff --git a/testsuite/tests/interop/iterator/Main.java b/testsuite/tests/interop/iterator/Main.java new file mode 100644 index 000000000..01755bd08 --- /dev/null +++ b/testsuite/tests/interop/iterator/Main.java @@ -0,0 +1,27 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql").build(); + Value executable = context.parse("lkql", "val list = [1, \"Hello\", [1, 2]]"); + + Value namespace = executable.execute(false); + Value list = namespace.getMember("list"); + Value iterator = list.getIterator(); + System.out.println("=== List interop messages:"); + print("toString() (list)", list.toString()); + print("hasIterator()", list.hasIterator()); + print("isIterator()", iterator.isIterator()); + print("hasIteratorNextElement()", iterator.hasIteratorNextElement()); + System.out.println(" iterator elements:"); + while (iterator.hasIteratorNextElement()) { + Value elem = iterator.getIteratorNextElement(); + System.out.println(" - " + elem.toString()); + } + } +} diff --git a/testsuite/tests/interop/iterator/test.out b/testsuite/tests/interop/iterator/test.out new file mode 100644 index 000000000..5ddaf883b --- /dev/null +++ b/testsuite/tests/interop/iterator/test.out @@ -0,0 +1,9 @@ +=== List interop messages: + toString() (list): [1, "Hello", [1, 2]] + hasIterator(): true + isIterator(): true + hasIteratorNextElement(): true + iterator elements: + - 1 + - Hello + - [1, 2] diff --git a/testsuite/tests/interop/iterator/test.yaml b/testsuite/tests/interop/iterator/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/iterator/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file diff --git a/testsuite/tests/interop/list/Main.java b/testsuite/tests/interop/list/Main.java new file mode 100644 index 000000000..5098ce0a9 --- /dev/null +++ b/testsuite/tests/interop/list/Main.java @@ -0,0 +1,37 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val list = [1, "Hello", [1, 2]] + val empty_list = [] + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value list = namespace.getMember("list"); + Value emptyList = namespace.getMember("empty_list"); + System.out.println("=== List interop messages:"); + print("toString()", list.toString()); + print("hasArrayElements()", list.hasArrayElements()); + print("getArraySize()", list.getArraySize()); + print("isBoolean()", list.isBoolean()); + print("isBoolean() (empty list)", emptyList.isBoolean()); + print("asBoolean()", list.asBoolean()); + print("asBoolean() (empty list)", emptyList.asBoolean()); + print("getArrayElement(0)", list.getArrayElement(0)); + print("getArrayElement(1)", list.getArrayElement(1)); + print("getArrayElement(2)", list.getArrayElement(2)); + print("hasIterator()", list.hasIterator()); + } +} diff --git a/testsuite/tests/interop/list/test.out b/testsuite/tests/interop/list/test.out new file mode 100644 index 000000000..6354abef8 --- /dev/null +++ b/testsuite/tests/interop/list/test.out @@ -0,0 +1,12 @@ +=== List interop messages: + toString(): [1, "Hello", [1, 2]] + hasArrayElements(): true + getArraySize(): 3 + isBoolean(): true + isBoolean() (empty list): true + asBoolean(): true + asBoolean() (empty list): false + getArrayElement(0): 1 + getArrayElement(1): Hello + getArrayElement(2): [1, 2] + hasIterator(): true diff --git a/testsuite/tests/interop/list/test.yaml b/testsuite/tests/interop/list/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/list/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file diff --git a/testsuite/tests/interop/namespace/Main.java b/testsuite/tests/interop/namespace/Main.java index 7b456147d..4c7bffc62 100644 --- a/testsuite/tests/interop/namespace/Main.java +++ b/testsuite/tests/interop/namespace/Main.java @@ -25,6 +25,6 @@ public static void main(String[] args) { print("hasMember('y')", namespace.hasMember("y")); print("getMember('x')", namespace.getMember("x")); print("getMember('y')", namespace.getMember("y")); - // TODO (LATER IN MR): Call "getMemberKeys" when list values are interop + print("getMemberKeys()", namespace.getMemberKeys()); } } diff --git a/testsuite/tests/interop/namespace/test.out b/testsuite/tests/interop/namespace/test.out index 7624beb75..0977e9e83 100644 --- a/testsuite/tests/interop/namespace/test.out +++ b/testsuite/tests/interop/namespace/test.out @@ -5,3 +5,4 @@ hasMember('y'): false getMember('x'): 42 getMember('y'): null + getMemberKeys(): [x] diff --git a/testsuite/tests/interop/object/Main.java b/testsuite/tests/interop/object/Main.java index 2097e56a5..bc84053fd 100644 --- a/testsuite/tests/interop/object/Main.java +++ b/testsuite/tests/interop/object/Main.java @@ -28,6 +28,6 @@ public static void main(String[] args) { print("getMember('x')", object.getMember("x")); print("getMember('y')", object.getMember("y")); print("getMember('z')", object.getMember("z")); - // TODO (LATER IN MR): Call "getMemberKeys" when list values are interop + print("getMemberKeys()", object.getMemberKeys()); } } diff --git a/testsuite/tests/interop/object/test.out b/testsuite/tests/interop/object/test.out index 5fa247427..15038176b 100644 --- a/testsuite/tests/interop/object/test.out +++ b/testsuite/tests/interop/object/test.out @@ -7,3 +7,4 @@ getMember('x'): 42 getMember('y'): Hello getMember('z'): null + getMemberKeys(): [x, y] From a89ad7a03495ea9b214087609bd461c3540c45a8 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Thu, 5 Oct 2023 15:24:07 +0200 Subject: [PATCH 10/23] Rework the representation of the list comprehension values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 1 - .../built_ins/values/lists/LKQLLazyList.java | 91 +++++++++++++++++++ .../values/lists/LKQLListComprehension.java} | 86 ++++++++++-------- .../lkql_jit/nodes/expressions/Expr.java | 11 --- .../list_comprehension/ListComprehension.java | 16 ++-- .../nodes/expressions/operators/BinEq.java | 12 --- .../nodes/expressions/operators/BinNeq.java | 12 --- .../lkql_jit/utils/LKQLTypesHelper.java | 2 - testsuite/tests/interop/list_comp/Main.java | 37 ++++++++ testsuite/tests/interop/list_comp/test.out | 12 +++ testsuite/tests/interop/list_comp/test.yaml | 1 + 11 files changed, 195 insertions(+), 86 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/LazyListValue.java => built_ins/values/lists/LKQLListComprehension.java} (50%) create mode 100644 testsuite/tests/interop/list_comp/Main.java create mode 100644 testsuite/tests/interop/list_comp/test.out create mode 100644 testsuite/tests/interop/list_comp/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 62c3d7a33..8a721f2c7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -54,7 +54,6 @@ SelectorValue.class, LKQLTuple.class, LKQLList.class, - LazyListValue.class, SelectorListValue.class, LazyCollection.class, Indexable.class, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java new file mode 100644 index 000000000..b68770dd6 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java @@ -0,0 +1,91 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.lists; + +import com.adacore.lkql_jit.exception.utils.InvalidIndexException; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import java.util.ArrayList; +import java.util.List; + +/** This class represents the base of all LKQL lazy lists. */ +@ExportLibrary(InteropLibrary.class) +public abstract class LKQLLazyList extends LKQLList { + + // ----- Attributes ----- + + /** The cache of the lazy list. */ + protected final List cache; + + // ----- Constructors ----- + + protected LKQLLazyList() { + this.cache = new ArrayList<>(); + } + + // ----- Lazy list required methods ----- + + /** + * Initialize the lazy list cache to the given index. If n < 0 then initialize all the lazy list + * values. + */ + public abstract void initCache(int n); + + // ----- List required methods ----- + + @Override + public long size() { + this.initCache(-1); + return this.cache.size(); + } + + @Override + public Object get(int i) throws InvalidIndexException { + if (i >= 0) { + this.initCache(i); + try { + return this.cache.get(i); + } catch (IndexOutOfBoundsException e) { + throw new InvalidIndexException(); + } + } + throw new InvalidIndexException(); + } + + @Override + public Object[] asArray() { + this.initCache(-1); + return this.cache.toArray(new Object[0]); + } + + // ----- Value methods ----- + + /** Return the identity hash code for the given LKQL lazy list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLLazyList receiver) { + return System.identityHashCode(receiver); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/LazyListValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java similarity index 50% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/LazyListValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java index b72cb95a9..da0589b47 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/LazyListValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java @@ -20,77 +20,83 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values.lists; import com.adacore.lkql_jit.nodes.dispatchers.ListComprehensionDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.ListComprehensionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.root_nodes.ListComprehensionRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.LazyCollection; -import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; -/** - * This class represents a lazy list in the LKQL language, this is the result of a list - * comprehension. - * - * @author Hugo GUERRIER - */ -public final class LazyListValue extends LazyCollection { +/** This class represents a list comprehension value in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public final class LKQLListComprehension extends LKQLLazyList { // ----- Attributes ----- - /** The root node for the list comprehension. */ + /** Root node of the list comprehension. */ private final ListComprehensionRootNode rootNode; - /** The closure for the execution. */ - private final Closure closure; - - /** The dispatcher for the list comprehension root node. */ + /** Dispatcher for the list comprehension root node. */ private final ListComprehensionDispatcher dispatcher; - /** The list of arguments for the root node. */ - private final Object[][] argsList; + /** List of arguments to pass to the list comprehension root node. */ + private final Object[][] argumentsList; + + /** Pre-allocated argument array which already contains the list comprehension closure. */ + private final Object[] arguments; - /** The pointer to the next lazy value to evaluate. */ - private int lazyPointer; + /** Pointer to the current arguments to pass to the root node. */ + private int pointer; // ----- Constructors ----- /** - * Create a new lazy list value. + * Create a new LKQL list comprehension value with everything needed for its execution. * - * @param rootNode The root node for the execution. - * @param closure The closure for the root node execution. - * @param argsList The argument list. + * @param rootNode The root node which contains the list comprehension logics. + * @param closure The closure for the execution. + * @param argumentsList The sequence of arguments to pass to the list comprehension root node. */ @CompilerDirectives.TruffleBoundary - public LazyListValue(ListComprehensionRootNode rootNode, Closure closure, Object[][] argsList) { - super(argsList.length); + public LKQLListComprehension( + final ListComprehensionRootNode rootNode, + final Closure closure, + final Object[][] argumentsList) { this.rootNode = rootNode; - this.closure = closure; this.dispatcher = ListComprehensionDispatcherNodeGen.create(); - this.argsList = argsList; + this.argumentsList = argumentsList; + this.arguments = + this.argumentsList.length > 0 + ? new Object[this.argumentsList[0].length + 1] + : new Object[1]; + this.arguments[0] = closure.getContent(); + this.pointer = 0; } - // ----- Class methods ----- + // ----- Lazy list required methods ----- - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.LazyCollection#initCache(int) - */ @Override - protected void initCache(int index) { - while (this.lazyPointer < this.argsList.length - && (this.cache.size() - 1 < index || index == -1)) { - Object value = - this.dispatcher.executeDispatch( - this.rootNode, - ArrayUtils.concat( - new Object[] {this.closure.getContent()}, - this.argsList[this.lazyPointer++])); + public void initCache(int n) { + while (this.pointer < this.argumentsList.length && (this.cache.size() - 1 < n || n < 0)) { + final Object[] currentArguments = this.argumentsList[this.pointer++]; + System.arraycopy(currentArguments, 0, this.arguments, 1, currentArguments.length); + Object value = this.dispatcher.executeDispatch(this.rootNode, this.arguments); if (value != null) { this.cache.add(value); } } } + + // ----- Value methods ----- + + /** Return the identity hash code for the given LKQL list comprehension. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLListComprehension receiver) { + return System.identityHashCode(receiver); + } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 765ed9ed3..e4d84b75a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -182,17 +182,6 @@ public LKQLList executeList(VirtualFrame frame) throws UnexpectedResultException return LKQLTypeSystemGen.expectLKQLList(executeGeneric(frame)); } - /** - * Execute the expression as a lazy list value. - * - * @param frame The frame for execution. - * @return The result of the node execution as a lazy list value. - * @throws UnexpectedResultException If the node cannot be evaluated as a lazy list. - */ - public LazyListValue executeLazyList(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectLazyListValue(executeGeneric(frame)); - } - /** * Execute the expression as an indexable value. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java index 3e1b7f692..1e50925a5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java @@ -23,10 +23,11 @@ package com.adacore.lkql_jit.nodes.expressions.list_comprehension; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLListComprehension; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.root_nodes.ListComprehensionRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.LazyListValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.ClosureDescriptor; import com.adacore.lkql_jit.utils.Iterator; @@ -112,27 +113,26 @@ public ListComprehension( */ @Override public Object executeGeneric(VirtualFrame frame) { - return this.executeLazyList(frame); + return this.executeList(frame); } /** - * @see - * com.adacore.lkql_jit.nodes.expressions.Expr#executeLazyList(com.oracle.truffle.api.frame.VirtualFrame) + * @see Expr#executeList(VirtualFrame) */ @Override - public LazyListValue executeLazyList(VirtualFrame frame) { + public LKQLList executeList(VirtualFrame frame) { // Get the iterables for the list comprehension Iterable[] iterables = this.generators.executeCollections(frame); // Get the result size and prepare the result int resultSize = 1; for (Iterable iterable : iterables) { - resultSize *= iterable.size(); + resultSize *= (int) iterable.size(); } // Verify that the result size is strictly positive if (resultSize < 1) { - return new LazyListValue( + return new LKQLListComprehension( this.rootNode, Closure.create(frame.materialize(), this.closureDescriptor), new Object[0][]); @@ -156,7 +156,7 @@ public LazyListValue executeLazyList(VirtualFrame frame) { } while (this.increaseIndexes(iterators, valueBuffer)); // Return the result of the list comprehension as a lazy list - return new LazyListValue( + return new LKQLListComprehension( this.rootNode, Closure.create(frame.materialize(), this.closureDescriptor), argsList); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 114c8ebc7..079a61f4b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -191,18 +191,6 @@ protected boolean eqLists( return leftLibrary.isIdentical(left, right, rightLibrary); } - /** - * Do the equality verification on lazy lists. - * - * @param left The left lazy list value. - * @param right The right lazy list value. - * @return The result of the equality verification. - */ - @Specialization - protected boolean eqLazyLists(LazyListValue left, LazyListValue right) { - return left.internalEquals(right); - } - /** * Do the equality verification on selector lists. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 858cc6555..99e4cc11b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -192,18 +192,6 @@ protected boolean neqLists( return !leftLibrary.isIdentical(left, right, rightLibrary); } - /** - * Do the non-equality verification on lazy lists. - * - * @param left The left lazy list value. - * @param right The right lazy list value. - * @return The result of the non-equality verification. - */ - @Specialization - protected boolean neqLazyLists(LazyListValue left, LazyListValue right) { - return !left.internalEquals(right); - } - /** * Do the non-equality verification on selector lists. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 978fb6052..494061d91 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -148,8 +148,6 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_TUPLE; } else if (LKQLTypeSystemGen.isLKQLList(obj)) { return LKQL_LIST; - } else if (LKQLTypeSystemGen.isLazyListValue(obj)) { - return LKQL_LAZY_LIST; } else if (LKQLTypeSystemGen.isSelectorListValue(obj)) { return LKQL_SELECTOR_LIST; } else if (LKQLTypeSystemGen.isAdaNode(obj)) { diff --git a/testsuite/tests/interop/list_comp/Main.java b/testsuite/tests/interop/list_comp/Main.java new file mode 100644 index 000000000..f7178bde9 --- /dev/null +++ b/testsuite/tests/interop/list_comp/Main.java @@ -0,0 +1,37 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val lazy_list = [x for x in [1, \"Coucou\", [4, 5]]] + val empty_list = [x for x in [5] if x != 5] + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value lazyList = namespace.getMember("lazy_list"); + Value emptyList = namespace.getMember("empty_list"); + System.out.println("=== Lazy list interop messages:"); + print("toString()", lazyList.toString()); + print("hasArrayElements()", lazyList.hasArrayElements()); + print("getArraySize()", lazyList.getArraySize()); + print("isBoolean()", lazyList.isBoolean()); + print("isBoolean() (empty lazy list)", emptyList.isBoolean()); + print("asBoolean()", lazyList.asBoolean()); + print("asBoolean() (empty lazy list)", emptyList.asBoolean()); + print("getArrayElement(0)", lazyList.getArrayElement(0)); + print("getArrayElement(1)", lazyList.getArrayElement(1)); + print("getArrayElement(2)", lazyList.getArrayElement(2)); + print("hasIterator()", lazyList.hasIterator()); + } +} diff --git a/testsuite/tests/interop/list_comp/test.out b/testsuite/tests/interop/list_comp/test.out new file mode 100644 index 000000000..9743dc3bf --- /dev/null +++ b/testsuite/tests/interop/list_comp/test.out @@ -0,0 +1,12 @@ +=== Lazy list interop messages: + toString(): [1, "Coucou", [4, 5]] + hasArrayElements(): true + getArraySize(): 3 + isBoolean(): true + isBoolean() (empty lazy list): true + asBoolean(): true + asBoolean() (empty lazy list): false + getArrayElement(0): 1 + getArrayElement(1): Coucou + getArrayElement(2): [4, 5] + hasIterator(): true diff --git a/testsuite/tests/interop/list_comp/test.yaml b/testsuite/tests/interop/list_comp/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/list_comp/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From a1839a7a8a75b5d8ba514bc7b1eef893aa9ebb02 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 10 Oct 2023 11:10:00 +0200 Subject: [PATCH 11/23] Rework the representation of the selector list values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 2 - .../values/lists/LKQLSelectorList.java} | 96 ++++++++----------- .../lkql_jit/nodes/expressions/Expr.java | 12 --- .../lkql_jit/nodes/expressions/FunCall.java | 3 +- .../nodes/expressions/operators/BinEq.java | 12 --- .../nodes/expressions/operators/BinNeq.java | 12 --- .../lkql_jit/nodes/patterns/SelectorCall.java | 16 ++-- .../runtime/values/SelectorValue.java | 7 +- .../lkql_jit/utils/LKQLTypesHelper.java | 2 - .../tests/interop/selector_list/Main.java | 31 ++++++ .../tests/interop/selector_list/test.out | 7 ++ .../tests/interop/selector_list/test.yaml | 1 + 12 files changed, 92 insertions(+), 109 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/SelectorListValue.java => built_ins/values/lists/LKQLSelectorList.java} (77%) create mode 100644 testsuite/tests/interop/selector_list/Main.java create mode 100644 testsuite/tests/interop/selector_list/test.out create mode 100644 testsuite/tests/interop/selector_list/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 8a721f2c7..734605791 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -54,8 +54,6 @@ SelectorValue.class, LKQLTuple.class, LKQLList.class, - SelectorListValue.class, - LazyCollection.class, Indexable.class, Iterable.class, Libadalang.AdaNode.class, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorListValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java similarity index 77% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorListValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java index 3c1d48825..d52611bb6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorListValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values.lists; import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; @@ -28,18 +28,18 @@ import com.adacore.lkql_jit.nodes.dispatchers.SelectorDispatcherNodeGen; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.LazyCollection; +import com.adacore.lkql_jit.runtime.values.DepthNode; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; import java.util.HashSet; import java.util.LinkedList; import java.util.List; -/** - * This class represents a list returned by a selector call, this is a lazy list. - * - * @author Hugo GUERRIER - */ -public final class SelectorListValue extends LazyCollection { +/** This class represents the list returned by a selector call in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLSelectorList extends LKQLLazyList { // ----- Attributes ----- @@ -52,8 +52,8 @@ public final class SelectorListValue extends LazyCollection { /** The dispatcher for the selector root node. */ private final SelectorDispatcher dispatcher; - /** The cache in a set to perform recursion guard. */ - private final HashSet hashCache; + /** The cache of already explored nodes. */ + private final HashSet alreadyVisited; /** The list of the node to recurs on. */ private final List recursList; @@ -80,34 +80,29 @@ public final class SelectorListValue extends LazyCollection { * @param depth The precise required depth of the returned nodes. */ @CompilerDirectives.TruffleBoundary - public SelectorListValue( + public LKQLSelectorList( final SelectorRootNode rootNode, final Closure closure, final Libadalang.AdaNode adaNode, final int maxDepth, final int minDepth, final int depth) { - super(0); this.rootNode = rootNode; this.closure = closure; this.dispatcher = SelectorDispatcherNodeGen.create(); - this.hashCache = new HashSet<>(); + this.alreadyVisited = new HashSet<>(); this.recursList = new LinkedList<>(); - this.recursList.add(new DepthNode(0, adaNode)); this.maxDepth = maxDepth; this.minDepth = minDepth; this.depth = depth; + this.recursList.add(new DepthNode(0, adaNode)); } - // ----- Class methods ----- + // ----- Lazy list required methods ----- - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.LazyCollection#initCache(int) - */ @Override - @CompilerDirectives.TruffleBoundary - protected void initCache(int index) { - while (!this.recursList.isEmpty() && (this.cache.size() - 1 < index || index == -1)) { + public void initCache(int n) { + while (!(this.recursList.size() == 0) && (this.cache.size() - 1 < n || n == -1)) { // Get the first recurse item and execute the selector on it DepthNode nextNode = this.recursList.remove(0); SelectorRootNode.SelectorCallResult result = @@ -125,15 +120,12 @@ protected void initCache(int index) { } } - /** - * Add the object to the result cache of the selector list. - * - * @param toAdd The object to add. - */ + /** Add the object to the result cache of the selector list. */ + @CompilerDirectives.TruffleBoundary private void addResult(Object toAdd) { // If the object is just a node if (toAdd instanceof DepthNode node) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); } } @@ -141,22 +133,19 @@ private void addResult(Object toAdd) { // If the object is an array of node else if (toAdd instanceof DepthNode[] nodes) { for (DepthNode node : nodes) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); } } } } - /** - * Add the object to the recursing list of the selector list. - * - * @param toAdd The object to add. - */ + /** Add the object to the recursing list of the selector list. */ + @CompilerDirectives.TruffleBoundary private void addRecurs(Object toAdd) { // If the object is just a node if (toAdd instanceof DepthNode node) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.recursList.add(node); } } @@ -164,22 +153,19 @@ private void addRecurs(Object toAdd) { // If the object is an array of node else if (toAdd instanceof DepthNode[] nodes) { for (DepthNode node : nodes) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.recursList.add(node); } } } } - /** - * Add the object to the result and the recursing list. - * - * @param toAdd The object to add. - */ + /** Add the object to the result and the recursing list. */ + @CompilerDirectives.TruffleBoundary private void addRecursAndResult(Object toAdd) { // If the object is just a node if (toAdd instanceof DepthNode node) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); this.recursList.add(node); } @@ -188,7 +174,7 @@ private void addRecursAndResult(Object toAdd) { // If the object is an array of node else if (toAdd instanceof DepthNode[] nodes) { for (DepthNode node : nodes) { - if (this.isRecursionGuarded(node)) { + if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); this.recursList.add(node); } @@ -196,18 +182,15 @@ else if (toAdd instanceof DepthNode[] nodes) { } } - /** - * Add a node in the result and hashed cache with all verifications. - * - * @param node The node to add in the cache. - */ + /** Add a node in the result and hashed cache with all verifications. */ + @CompilerDirectives.TruffleBoundary private void addNodeResult(DepthNode node) { // If there is no defined depth if (this.depth < 0) { if ((this.maxDepth < 0 || node.getDepth() <= this.maxDepth) && (this.minDepth < 0 || node.getDepth() >= this.minDepth)) { this.cache.add(node); - this.hashCache.add(node); + this.alreadyVisited.add(node); } } @@ -215,18 +198,17 @@ private void addNodeResult(DepthNode node) { else { if (node.getDepth() == this.depth) { this.cache.add(node); - this.hashCache.add(node); + this.alreadyVisited.add(node); } } } - /** - * Get if a node is recursion guarded. - * - * @param node The node to verify. - * @return True if this node is recursion guarded, false else. - */ - private boolean isRecursionGuarded(DepthNode node) { - return !this.hashCache.contains(node); + // ----- Value methods ----- + + /** Return the identity hash code for the given LKQL selector list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLSelectorList receiver) { + return System.identityHashCode(receiver); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index e4d84b75a..a24520e51 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -193,18 +193,6 @@ public Indexable executeIndexable(VirtualFrame frame) throws UnexpectedResultExc return LKQLTypeSystemGen.expectIndexable(executeGeneric(frame)); } - /** - * Execute the expression as a selector list value. - * - * @param frame The frame for execution. - * @return The result of the node execution as a selector list value. - * @throws UnexpectedResultException If the node cannot be evaluated as a selector list. - */ - public SelectorListValue executeSelectorList(VirtualFrame frame) - throws UnexpectedResultException { - return LKQLTypeSystemGen.expectSelectorListValue(executeGeneric(frame)); - } - /** * Execute the expression as an iterable value. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index 33447d0de..0683b226a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -207,7 +208,7 @@ protected Object onProperty(VirtualFrame frame, PropertyRefValue propertyRefValu * @return The result of the selector value execution. */ @Specialization - protected SelectorListValue onSelector(VirtualFrame frame, SelectorValue selectorValue) { + protected LKQLSelectorList onSelector(VirtualFrame frame, SelectorValue selectorValue) { // Get the argument list and get the node from it Arg[] argList = this.argList.getArgs(); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 079a61f4b..e4cd22105 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -191,18 +191,6 @@ protected boolean eqLists( return leftLibrary.isIdentical(left, right, rightLibrary); } - /** - * Do the equality verification on selector lists. - * - * @param left The left selector list value. - * @param right The right selector list value. - * @return The result of the equality verification. - */ - @Specialization - protected boolean eqSelectorLists(SelectorListValue left, SelectorListValue right) { - return left.internalEquals(right); - } - /** * Do the equality verification on nodes. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 99e4cc11b..9e733cbcc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -192,18 +192,6 @@ protected boolean neqLists( return !leftLibrary.isIdentical(left, right, rightLibrary); } - /** - * Do the non-equality verification on selector lists. - * - * @param left The left selector list value. - * @param right The right selector list value. - * @return The result of the non-equality verification. - */ - @Specialization - protected boolean neqSelectorLists(SelectorListValue left, SelectorListValue right) { - return !left.internalEquals(right); - } - /** * Do the non-equality verification on nodes. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java index 563579831..1d16bae0b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java @@ -26,6 +26,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.arguments.Arg; @@ -33,7 +34,6 @@ import com.adacore.lkql_jit.nodes.arguments.NamedArg; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.SelectorListValue; import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.Iterator; @@ -119,7 +119,7 @@ public Object executeGeneric(VirtualFrame frame) { public boolean executeVerification( VirtualFrame frame, Libadalang.AdaNode node, BasePattern pattern) { // Get the selector list - SelectorListValue selectorListValue = this.getSelectorList(frame, node); + LKQLSelectorList selectorListValue = this.getSelectorList(frame, node); // Get the result of the validation boolean isValid; @@ -150,7 +150,7 @@ public boolean executeVerification( public LKQLList executeFiltering( VirtualFrame frame, Libadalang.AdaNode node, BasePattern pattern) { // Get the selector list - SelectorListValue selectorListValue = this.getSelectorList(frame, node); + LKQLSelectorList selectorListValue = this.getSelectorList(frame, node); // Prepare the result LKQLList res; @@ -187,7 +187,7 @@ public LKQLList executeFiltering( * @param node The root node of the selector list. * @return The selector list for the selector call. */ - private SelectorListValue getSelectorList(VirtualFrame frame, Libadalang.AdaNode node) { + private LKQLSelectorList getSelectorList(VirtualFrame frame, Libadalang.AdaNode node) { // Get the selector and verify its type Object selectorObject = this.selectorExpr.executeGeneric(frame); if (!LKQLTypeSystemGen.isSelectorValue(selectorObject)) { @@ -260,7 +260,7 @@ private SelectorListValue getSelectorList(VirtualFrame frame, Libadalang.AdaNode * @return True of all nodes of the traversal verify the pattern, false else. */ private boolean isAll( - VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { + VirtualFrame frame, LKQLSelectorList selectorListValue, BasePattern pattern) { // Iterate on nodes Iterator iterator = selectorListValue.iterator(); while (iterator.hasNext()) { @@ -281,7 +281,7 @@ private boolean isAll( * @return True if there is any node that verify the pattern, false else. */ private boolean isAny( - VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { + VirtualFrame frame, LKQLSelectorList selectorListValue, BasePattern pattern) { // Iterate on nodes Iterator iterator = selectorListValue.iterator(); while (iterator.hasNext()) { @@ -302,7 +302,7 @@ private boolean isAny( * @return The list value */ private LKQLList getFilteredList( - VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { + VirtualFrame frame, LKQLSelectorList selectorListValue, BasePattern pattern) { // Prepare the result List resList = new ArrayList<>(); @@ -327,7 +327,7 @@ private LKQLList getFilteredList( * @param pattern The pattern to filter the list. */ private void doBinding( - VirtualFrame frame, SelectorListValue selectorListValue, BasePattern pattern) { + VirtualFrame frame, LKQLSelectorList selectorListValue, BasePattern pattern) { LKQLList listValue = this.getFilteredList(frame, selectorListValue, pattern); this.doBinding(frame, listValue); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java index b5de7c4a8..10101fe63 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.runtime.values; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; @@ -76,7 +77,7 @@ public SelectorValue( * @param node The node to execute the selector on. * @return The selector list value. */ - public SelectorListValue execute(Libadalang.AdaNode node) { + public LKQLSelectorList execute(Libadalang.AdaNode node) { return this.execute(node, -1, -1, -1); } @@ -89,9 +90,9 @@ public SelectorListValue execute(Libadalang.AdaNode node) { * @param depth The precise depth to get. * @return The selector list value. */ - public SelectorListValue execute( + public LKQLSelectorList execute( Libadalang.AdaNode node, int maxDepth, int minDepth, int depth) { - return new SelectorListValue(this.rootNode, this.closure, node, maxDepth, minDepth, depth); + return new LKQLSelectorList(this.rootNode, this.closure, node, maxDepth, minDepth, depth); } // ----- Value methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 494061d91..1590fda91 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -148,8 +148,6 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_TUPLE; } else if (LKQLTypeSystemGen.isLKQLList(obj)) { return LKQL_LIST; - } else if (LKQLTypeSystemGen.isSelectorListValue(obj)) { - return LKQL_SELECTOR_LIST; } else if (LKQLTypeSystemGen.isAdaNode(obj)) { return ADA_NODE; } else if (LKQLTypeSystemGen.isToken(obj)) { diff --git a/testsuite/tests/interop/selector_list/Main.java b/testsuite/tests/interop/selector_list/Main.java new file mode 100644 index 000000000..c9cd8dfdc --- /dev/null +++ b/testsuite/tests/interop/selector_list/Main.java @@ -0,0 +1,31 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val nodes = children(units()[1].root) + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value nodes = namespace.getMember("nodes"); + System.out.println("=== Selector list interop messages:"); + print("toString()", nodes.toString()); + print("hasArrayElements()", nodes.hasArrayElements()); + print("getArraySize()", nodes.getArraySize()); + print("isBoolean()", nodes.isBoolean()); + print("asBoolean()", nodes.asBoolean()); + // TODO (LATER IN MR): Get first elements of the list when depth node are interop + print("hasIterator()", nodes.hasIterator()); + } +} diff --git a/testsuite/tests/interop/selector_list/test.out b/testsuite/tests/interop/selector_list/test.out new file mode 100644 index 000000000..7ef865e45 --- /dev/null +++ b/testsuite/tests/interop/selector_list/test.out @@ -0,0 +1,7 @@ +=== Selector list interop messages: + toString(): [, , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , , ] + hasArrayElements(): true + getArraySize(): 57 + isBoolean(): true + asBoolean(): true + hasIterator(): true diff --git a/testsuite/tests/interop/selector_list/test.yaml b/testsuite/tests/interop/selector_list/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/selector_list/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 269577dc1f25d6d9050326e5eade0170f5e1c25d Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 10 Oct 2023 11:19:37 +0200 Subject: [PATCH 12/23] minor: Remove 'LazyCollection' abstract class because it is not used anymore --- .../values/interfaces/LazyCollection.java | 248 ------------------ 1 file changed, 248 deletions(-) delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LazyCollection.java diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LazyCollection.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LazyCollection.java deleted file mode 100644 index 7e4edd6d2..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LazyCollection.java +++ /dev/null @@ -1,248 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values.interfaces; - -import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.utils.Iterator; -import com.adacore.lkql_jit.utils.functions.StringUtils; -import com.oracle.truffle.api.CompilerDirectives; -import java.util.ArrayList; -import java.util.List; -import java.util.Objects; - -/** - * This abstract class represents the base of all lazy collection in the LKQL JIT. - * - * @author Hugo GUERRIER - */ -public abstract class LazyCollection implements Indexable, Iterable, Truthy { - - // ----- Attributes ----- - - /** The cache of the lazy collection. */ - protected final List cache; - - // ----- Constructors ----- - - /** - * Create a new lazy collection base. - * - * @param initialCacheSize The initial cache size. - */ - protected LazyCollection(int initialCacheSize) { - this.cache = new ArrayList<>(initialCacheSize); - } - - // ----- Class methods ----- - - /** - * Initialize the cache to the given index. If the index is -1 this method should compute all - * the cache elements. - * - * @param index The index to index the cache to. - */ - protected abstract void initCache(int index); - - // ----- Value methods ----- - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#get(int) - */ - @Override - public Object get(int index) throws InvalidIndexException { - if (index >= 0) { - // Initialize the cache to the given index - this.initCache(index); - - // Try to get the cache element - if (index < this.cache.size()) return this.cache.get(index); - } - - // If the index is not a valid one, throw an exception - throw new InvalidIndexException(); - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Indexable#getContent() - */ - @Override - public Object[] getContent() { - this.initCache(-1); - return this.cache.toArray(new Object[0]); - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#size() - */ - @Override - public long size() { - this.initCache(-1); - return this.cache.size(); - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#contains(Object) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean contains(Object elem) { - // Cast the element as an LKQL value - LKQLValue lkqlElem = null; - if (elem instanceof LKQLValue) lkqlElem = (LKQLValue) elem; - - // Iterate over all list elements to compare them - Iterator iterator = this.iterator(); - while (iterator.hasNext()) { - Object next = iterator.next(); - if ((next instanceof LKQLValue lkqlNext) && lkqlElem != null) { - if (lkqlElem.internalEquals(lkqlNext)) return true; - } else { - if (Objects.equals(elem, next)) return true; - } - } - return false; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#iterator() - */ - @Override - public Iterator iterator() { - return new LazyCollectionIterator(this); - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Truthy#isTruthy() - */ - @Override - public boolean isTruthy() { - this.initCache(0); - return this.cache.size() > 0; - } - - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LazyCollection other)) return false; - if (this.size() != other.size()) return false; - for (int i = 0; i < this.size(); i++) { - Object mineObject = this.get(i); - Object hisObject = other.get(i); - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - // Create the string in a builder - StringBuilder builder = new StringBuilder(); - builder.append('['); - Iterator iterator = this.iterator(); - while (iterator.hasNext()) { - Object value = iterator.next(); - if (value == null) { - builder.append("null"); - } else if (value instanceof String s) { - builder.append(StringUtils.toRepr(s)); - } else { - builder.append(value); - } - if (iterator.hasNext()) { - builder.append(", "); - } - } - builder.append(']'); - - // Return the tuple string representation - return builder.toString(); - } - - // ----- Inner classes ----- - - /** This class represents an iterator for a lazy collection. */ - public static class LazyCollectionIterator implements Iterator { - - // ----- Attributes ----- - - /** The lazy collection to iterate on. */ - private final LazyCollection lazyCollection; - - /** The pointer for the iterator. */ - private int pointer; - - // ----- Constructors ----- - - /** - * Create the lazy collection iterator with the collection to iterate on. - * - * @param lazyCollection The lazy collection. - */ - public LazyCollectionIterator(LazyCollection lazyCollection) { - this.lazyCollection = lazyCollection; - this.pointer = 0; - } - - // ----- Iteration methods ----- - - /** - * @see com.adacore.lkql_jit.utils.Iterator#hasNext() - */ - @Override - public boolean hasNext() { - try { - this.lazyCollection.get(this.pointer); - return true; - } catch (InvalidIndexException e) { - return false; - } - } - - /** - * @see com.adacore.lkql_jit.utils.Iterator#next() - */ - @Override - public Object next() { - return this.lazyCollection.get(this.pointer++); - } - - /** - * @see com.adacore.lkql_jit.utils.Iterator#reset() - */ - @Override - public void reset() { - this.pointer = 0; - } - } -} From dfc4ca3ac93547b0701987ca966b97317584b639 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 10 Oct 2023 16:52:17 +0200 Subject: [PATCH 13/23] Rework the representation of the function values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 7 +- .../built_ins/BuiltInFunctionValue.java | 4 +- .../built_ins/functions/MapFunction.java | 39 +-- .../functions/NodeCheckerFunction.java | 29 +- .../built_ins/functions/ReduceFunction.java | 38 +-- .../functions/UnitCheckerFunction.java | 29 +- .../built_ins/values/LKQLFunction.java | 247 ++++++++++++++++++ .../declarations/FunctionDeclaration.java | 8 +- .../nodes/dispatchers/FunctionDispatcher.java | 80 ------ .../lkql_jit/nodes/expressions/Expr.java | 9 +- .../lkql_jit/nodes/expressions/FunCall.java | 72 +++-- .../lkql_jit/nodes/expressions/FunExpr.java | 6 +- .../nodes/expressions/dot/DotAccess.java | 27 +- .../nodes/expressions/dot/SafeDotAccess.java | 27 +- .../nodes/expressions/operators/BinEq.java | 15 +- .../nodes/expressions/operators/BinNeq.java | 15 +- .../runtime/values/FunctionValue.java | 148 ----------- .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- .../lkql_jit/utils/checkers/BaseChecker.java | 8 +- .../lkql_jit/utils/checkers/NodeChecker.java | 4 +- .../lkql_jit/utils/checkers/UnitChecker.java | 4 +- testsuite/tests/interop/function/Main.java | 29 ++ testsuite/tests/interop/function/test.out | 4 + testsuite/tests/interop/function/test.yaml | 1 + 24 files changed, 470 insertions(+), 382 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/FunctionDispatcher.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/FunctionValue.java create mode 100644 testsuite/tests/interop/function/Main.java create mode 100644 testsuite/tests/interop/function/test.out create mode 100644 testsuite/tests/interop/function/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 734605791..e24559cc3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -23,10 +23,7 @@ package com.adacore.lkql_jit; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; -import com.adacore.lkql_jit.built_ins.values.LKQLObject; -import com.adacore.lkql_jit.built_ins.values.LKQLTuple; -import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; @@ -49,7 +46,7 @@ BigInteger.class, String.class, Pattern.class, - FunctionValue.class, + LKQLFunction.class, PropertyRefValue.class, SelectorValue.class, LKQLTuple.class, 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 c176e4fec..a21097f78 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 @@ -22,11 +22,11 @@ package com.adacore.lkql_jit.built_ins; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; 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.FunctionValue; import com.oracle.truffle.api.frame.VirtualFrame; /** @@ -34,7 +34,7 @@ * * @author Hugo GUERRIER */ -public final class BuiltInFunctionValue extends FunctionValue { +public final class BuiltInFunctionValue extends LKQLFunction { // ----- Attributes ----- 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 index e3d836588..d05d30578 100644 --- 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 @@ -25,16 +25,18 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; +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.nodes.UnexpectedResultException; /** @@ -65,16 +67,14 @@ public static BuiltInFunctionValue getValue() { /** Expression of the "map" function. */ public static final class MapExpr extends BuiltinFunctionBody { - /** The dispatcher for the mapping function. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - private FunctionDispatcher dispatcher = FunctionDispatcherNodeGen.create(); + /** An uncached interop library for the checker functions execution. */ + private InteropLibrary interopLibrary = InteropLibrary.getUncached(); @Override public Object executeGeneric(VirtualFrame frame) { // Get the arguments Iterable iterable; - FunctionValue mapFunction; + LKQLFunction mapFunction; try { iterable = LKQLTypeSystemGen.expectIterable(frame.getArguments()[0]); @@ -86,7 +86,7 @@ public Object executeGeneric(VirtualFrame frame) { } try { - mapFunction = LKQLTypeSystemGen.expectFunctionValue(frame.getArguments()[1]); + mapFunction = LKQLTypeSystemGen.expectLKQLFunction(frame.getArguments()[1]); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_FUNCTION, @@ -95,7 +95,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Verify the function arrity - if (mapFunction.getParamNames().length != 1) { + if (mapFunction.getParameterNames().length != 1) { throw LKQLRuntimeException.fromMessage( "Function passed to map should have arity of one", this.callNode.getArgList().getArgs()[1]); @@ -108,12 +108,19 @@ public Object executeGeneric(VirtualFrame frame) { int i = 0; Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { - res[i] = - this.dispatcher.executeDispatch( - mapFunction, - new Object[] { - mapFunction.getClosure().getContent(), iterator.next() - }); + try { + res[i] = + this.interopLibrary.execute( + mapFunction, + mapFunction.getClosure().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, this.callNode); + } i++; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java index ba6d302c4..328c1f4f7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/NodeCheckerFunction.java @@ -28,19 +28,21 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.checkers.NodeChecker; import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.frame.VirtualFrame; +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.nodes.UnexpectedResultException; import java.util.LinkedList; @@ -75,10 +77,8 @@ public static BuiltInFunctionValue getValue() { */ private static final class NodeCheckerExpr extends BuiltinFunctionBody { - /** The dispatcher for the rule functions. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - private FunctionDispatcher dispatcher = FunctionDispatcherNodeGen.create(); + /** An uncached interop library for the checker functions execution. */ + private InteropLibrary interopLibrary = InteropLibrary.getUncached(); /** * @see BuiltinFunctionBody#executeGeneric(com.oracle.truffle.api.frame.VirtualFrame) @@ -262,15 +262,15 @@ private void applyNodeRule( LKQLContext context, CheckerUtils.SourceLinesCache linesCache) { // Get the function for the checker - FunctionValue functionValue = checker.getFunction(); + LKQLFunction functionValue = checker.getFunction(); String aliasName = checker.getAlias(); String lowerRuleName = StringUtils.toLowerCase(checker.getName()); // Prepare the arguments - Object[] arguments = new Object[functionValue.getParamNames().length + 1]; + Object[] arguments = new Object[functionValue.getParameterNames().length + 1]; arguments[1] = node; - for (int i = 1; i < functionValue.getDefaultValues().length; i++) { - String paramName = functionValue.getParamNames()[i]; + for (int i = 1; i < functionValue.getParameterDefaultValues().length; i++) { + String paramName = functionValue.getParameterNames()[i]; Object userDefinedArg = context.getRuleArg( (aliasName == null @@ -279,7 +279,7 @@ private void applyNodeRule( StringUtils.toLowerCase(paramName)); arguments[i + 1] = userDefinedArg == null - ? functionValue.getDefaultValues()[i].executeGeneric(frame) + ? functionValue.getParameterDefaultValues()[i].executeGeneric(frame) : userDefinedArg; } @@ -291,12 +291,15 @@ private void applyNodeRule( try { ruleResult = LKQLTypeSystemGen.expectBoolean( - this.dispatcher.executeDispatch(functionValue, arguments)); + interopLibrary.execute(functionValue, arguments)); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_BOOLEAN, LKQLTypesHelper.fromJava(e.getResult()), functionValue.getBody()); + } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) { + // TODO: Move function runtime verification to the LKQLFunction class (#138) + throw LKQLRuntimeException.fromJavaException(e, this.callNode); } if (ruleResult) { 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 index 204d03273..a70f94024 100644 --- 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 @@ -25,15 +25,17 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; +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.nodes.UnexpectedResultException; /** @@ -64,16 +66,14 @@ public static BuiltInFunctionValue getValue() { /** Expression for the "reduce" function. */ public static final class ReduceExpr extends BuiltinFunctionBody { - /** The dispatcher for the reduce function. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - private FunctionDispatcher dispatcher = FunctionDispatcherNodeGen.create(); + /** An uncached interop library for the checker functions execution. */ + private InteropLibrary interopLibrary = InteropLibrary.getUncached(); @Override public Object executeGeneric(VirtualFrame frame) { // Get the arguments Iterable iterable; - FunctionValue reduceFunction; + LKQLFunction reduceFunction; Object initValue = frame.getArguments()[2]; try { @@ -86,7 +86,7 @@ public Object executeGeneric(VirtualFrame frame) { } try { - reduceFunction = LKQLTypeSystemGen.expectFunctionValue(frame.getArguments()[1]); + reduceFunction = LKQLTypeSystemGen.expectLKQLFunction(frame.getArguments()[1]); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_FUNCTION, @@ -95,7 +95,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Verify the function arity - if (reduceFunction.getParamNames().length != 2) { + if (reduceFunction.getParameterNames().length != 2) { throw LKQLRuntimeException.fromMessage( "Function passed to reduce should have arity of two", this.callNode.getArgList().getArgs()[1]); @@ -104,14 +104,20 @@ public Object executeGeneric(VirtualFrame frame) { // Execute the reducing Iterator iterator = iterable.iterator(); while (iterator.hasNext()) { - initValue = - this.dispatcher.executeDispatch( - reduceFunction, - new Object[] { + try { + initValue = + this.interopLibrary.execute( + reduceFunction, reduceFunction.getClosure().getContent(), initValue, - iterator.next() - }); + 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, this.callNode); + } } // Return the result diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index 1c213f65e..5ccc00779 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -28,14 +28,12 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -43,6 +41,10 @@ import com.adacore.lkql_jit.utils.functions.CheckerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.frame.VirtualFrame; +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.nodes.UnexpectedResultException; /** @@ -71,10 +73,8 @@ public static BuiltInFunctionValue getValue() { /** This class is the expression of the "unit_checker" function. */ private static final class UnitCheckerExpr extends BuiltinFunctionBody { - /** The dispatcher for the rule functions. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - private FunctionDispatcher dispatcher = FunctionDispatcherNodeGen.create(); + /** An uncached interop library for the checker functions execution. */ + private InteropLibrary interopLibrary = InteropLibrary.getUncached(); /** * @see BuiltinFunctionBody#executeGeneric(com.oracle.truffle.api.frame.VirtualFrame) @@ -152,17 +152,17 @@ private void applyUnitRule( LKQLContext context, CheckerUtils.SourceLinesCache linesCache) { // Get the function for the checker - final FunctionValue functionValue = checker.getFunction(); + final LKQLFunction functionValue = checker.getFunction(); // Retrieve the checker name final String aliasName = checker.getAlias(); final String lowerRuleName = StringUtils.toLowerCase(checker.getName()); // Prepare the arguments - Object[] arguments = new Object[functionValue.getParamNames().length + 1]; + Object[] arguments = new Object[functionValue.getParameterNames().length + 1]; arguments[1] = unit; - for (int i = 1; i < functionValue.getDefaultValues().length; i++) { - String paramName = functionValue.getParamNames()[i]; + for (int i = 1; i < functionValue.getParameterDefaultValues().length; i++) { + String paramName = functionValue.getParameterNames()[i]; Object userDefinedArg = context.getRuleArg( (aliasName == null @@ -171,7 +171,7 @@ private void applyUnitRule( paramName); arguments[i + 1] = userDefinedArg == null - ? functionValue.getDefaultValues()[i].executeGeneric(frame) + ? functionValue.getParameterDefaultValues()[i].executeGeneric(frame) : userDefinedArg; } @@ -183,12 +183,15 @@ private void applyUnitRule( try { violationList = LKQLTypeSystemGen.expectIterable( - this.dispatcher.executeDispatch(functionValue, arguments)); + this.interopLibrary.execute(functionValue, arguments)); } catch (UnexpectedResultException e) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_LIST, LKQLTypesHelper.fromJava(e.getResult()), functionValue.getBody()); + } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) { + // TODO: Move function runtime verification to the LKQLFunction class (#138) + throw LKQLRuntimeException.fromJavaException(e, this.callNode); } // Display all the violation message diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java new file mode 100644 index 000000000..bd63e097f --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java @@ -0,0 +1,247 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.nodes.expressions.Expr; +import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode; +import com.adacore.lkql_jit.runtime.Closure; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.oracle.truffle.api.CallTarget; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.Cached; +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.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.nodes.DirectCallNode; +import com.oracle.truffle.api.nodes.IndirectCallNode; +import com.oracle.truffle.api.utilities.TriState; + +/** This class represents the function values in LKQL. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLFunction implements TruffleObject, LKQLValue { + + // ----- Attributes ----- + + /** The root node representing the function body. */ + private final FunctionRootNode rootNode; + + /** The closure for the function exercution. */ + private final Closure closure; + + /** The name of the function. */ + @CompilerDirectives.CompilationFinal private String name; + + /** The documentation of the function. */ + private final String documentation; + + /** Names of the function parameters. */ + private final String[] parameterNames; + + /** + * Default values of the function parameters (if a function parameter doesn't have any, the + * value is 'null'). + */ + private final Expr[] parameterDefaultValues; + + // ----- Constructors ----- + + /** + * Create a new function value. + * + * @param rootNode The function root node. + * @param closure The closure of the function. + * @param name The name of the function. + * @param documentation The documentation of the function. + * @param parameterNames The names of the parameters. + * @param parameterDefaultValues The default values of the parameters. + */ + public LKQLFunction( + final FunctionRootNode rootNode, + final Closure closure, + final String name, + final String documentation, + final String[] parameterNames, + final Expr[] parameterDefaultValues) { + this.rootNode = rootNode; + this.closure = closure; + this.name = name; + this.documentation = documentation; + this.parameterNames = parameterNames; + this.parameterDefaultValues = parameterDefaultValues; + } + + // ----- Getters ------ + + public FunctionRootNode getRootNode() { + return rootNode; + } + + public Closure getClosure() { + return closure; + } + + public String getName() { + return name; + } + + public String[] getParameterNames() { + return parameterNames; + } + + public Expr[] getParameterDefaultValues() { + return parameterDefaultValues; + } + + // ----- Setters ----- + + public void setName(String name) { + CompilerDirectives.transferToInterpreterAndInvalidate(); + this.name = name; + } + + // ----- Instance methods ----- + + /** Shortcut function to get the function associated call target. */ + public CallTarget getCallTarget() { + return this.rootNode.getCallTarget(); + } + + /** Shortcut function to get the LKQL node representing the body of the function. */ + public Expr getBody() { + return this.rootNode.getBody(); + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL functions. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL functions. */ + @Specialization + protected static TriState onFunction(final LKQLFunction left, final LKQLFunction right) { + if (left.rootNode == right.rootNode) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLFunction receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL function. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLFunction receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + return "function<" + this.name + ">"; + } + + /** Tell the interop library that the value is executable. */ + @ExportMessage + boolean isExecutable() { + return true; + } + + /** Inner class for the function execution. */ + @ExportMessage + static class Execute { + /** Execute the function with the cached strategy. */ + @Specialization(guards = "callTarget == directCallNode.getCallTarget()") + protected static Object doCached( + final LKQLFunction function, + final Object[] arguments, + @Cached("function.getCallTarget()") CallTarget callTarget, + @Cached("create(callTarget)") DirectCallNode directCallNode) { + return directCallNode.call(arguments); + } + + /** Execute the function with the uncached strategy. */ + @Specialization(replaces = "doCached") + protected static Object doUncached( + final LKQLFunction function, + final Object[] arguments, + @Cached() IndirectCallNode indirectCallNode) { + return indirectCallNode.call(function.getCallTarget(), arguments); + } + } + + /** Tell the interop library that this value has an executable name. */ + @ExportMessage + boolean hasExecutableName() { + return true; + } + + /** Return the function name to the interop library. */ + @ExportMessage + Object getExecutableName() { + return this.name; + } + + // ----- LKQL values methods ----- + + @Override + public boolean internalEquals(LKQLValue o) { + if (this == o) return true; + if (!(o instanceof LKQLFunction other)) return false; + return this.rootNode == other.rootNode; + } + + @Override + public String getDocumentation() { + return this.documentation; + } + + // ----- Override methods ----- + + @Override + public String toString() { + return "function<" + this.name + ">"; + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java index 09c564540..480d0e438 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/FunctionDeclaration.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.nodes.declarations; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.expressions.FunExpr; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.checkers.BaseChecker; import com.adacore.lkql_jit.utils.checkers.NodeChecker; @@ -108,9 +108,9 @@ public FunctionDeclaration( @Override public Object executeGeneric(VirtualFrame frame) { // Execute the function expression to get the functional value - final FunctionValue functionValue = this.functionExpression.executeFunction(frame); + final LKQLFunction functionValue = this.functionExpression.executeFunction(frame); functionValue.setName(this.name); - functionValue.setMemoized(this.isMemoized); + functionValue.getRootNode().setMemoized(this.isMemoized); // If the function is a checker, place it in the context if (this.checkerMode != CheckerMode.OFF) { @@ -127,7 +127,7 @@ public Object executeGeneric(VirtualFrame frame) { // ----- Instance methods ----- /** Export the checker object in the LKQL context. */ - private void exportChecker(VirtualFrame frame, FunctionValue functionValue) { + private void exportChecker(VirtualFrame frame, LKQLFunction functionValue) { // Execute the annotation arguments final Object[] checkerArguments = this.annotation diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/FunctionDispatcher.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/FunctionDispatcher.java deleted file mode 100644 index 1fdf2f56b..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/FunctionDispatcher.java +++ /dev/null @@ -1,80 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.nodes.dispatchers; - -import com.adacore.lkql_jit.runtime.values.FunctionValue; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.DirectCallNode; -import com.oracle.truffle.api.nodes.IndirectCallNode; -import com.oracle.truffle.api.nodes.Node; - -/** - * This node is a dispatcher for the function execution in the LKQL JIT. - * - * @author Hugo GUERRIER - */ -public abstract class FunctionDispatcher extends Node { - - // ----- Execution methods ----- - - /** Method to enter the dispatch of the node. */ - public abstract Object executeDispatch(FunctionValue function, Object[] arguments); - - /** - * Execute the function via a cached direct node. - * - * @param function The function value to execute. - * @param arguments The calling arguments. - * @param directCallNode The direct call node. - * @return The result of the function execution. - */ - @Specialization(guards = "function.getCallTarget() == directCallNode.getCallTarget()") - protected static Object dispatchDirect( - @SuppressWarnings("unused") FunctionValue function, - Object[] arguments, - @Cached("create(function.getCallTarget())") DirectCallNode directCallNode) { - return directCallNode.call(arguments); - } - - /** - * Execute the function with an indirect call. - * - * @param function The function value to execute. - * @param arguments The function call arguments. - * @param indirectCallNode The indirect call node. - * @return The result of the function execution. - */ - @Specialization(replaces = "dispatchDirect") - protected static Object dispatchIndirect( - FunctionValue function, Object[] arguments, @Cached IndirectCallNode indirectCallNode) { - return indirectCallNode.call(function.getCallTarget(), arguments); - } - - // ----- Override methods ----- - - @Override - public String toString() { - return "FunctionDispatcher"; - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index a24520e51..53109a6ba 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -24,10 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; -import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; -import com.adacore.lkql_jit.built_ins.values.LKQLObject; -import com.adacore.lkql_jit.built_ins.values.LKQLTuple; -import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.*; @@ -133,8 +130,8 @@ public String executeString(VirtualFrame frame) throws UnexpectedResultException * @return The result of the node execution as a function value. * @throws UnexpectedResultException If the node cannot be evaluated as a function. */ - public FunctionValue executeFunction(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectFunctionValue(executeGeneric(frame)); + public LKQLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLFunction(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index 0683b226a..549af1ab5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -24,15 +24,15 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; +import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; @@ -41,6 +41,11 @@ import com.oracle.truffle.api.dsl.NodeChild; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.VirtualFrame; +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 com.oracle.truffle.api.nodes.UnexpectedResultException; /** @@ -66,11 +71,6 @@ public abstract class FunCall extends Expr { @SuppressWarnings("FieldMayBeFinal") private ArgList argList; - /** The function dispatch node to optimize execution. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - private FunctionDispatcher dispatcher; - // ----- Constructors ----- /** @@ -90,7 +90,6 @@ protected FunCall( this.isSafe = isSafe; this.calleeLocation = calleeLocation; this.argList = argList; - this.dispatcher = FunctionDispatcherNodeGen.create(); } // ----- Getters ----- @@ -105,30 +104,31 @@ public ArgList getArgList() { * Execute the function call on a built-in function. * * @param frame The frame to execute the built-in in. - * @param builtInFunctionValue The built-in function. + * @param builtIn The built-in function. * @return The result of the built-in call. */ - @Specialization - protected Object onBuiltIn(VirtualFrame frame, BuiltInFunctionValue builtInFunctionValue) { + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected Object onBuiltIn( + VirtualFrame frame, + BuiltInFunctionValue builtIn, + @CachedLibrary("builtIn") InteropLibrary builtInLibrary) { // Set the call node in the built-in function - builtInFunctionValue.setCallNode(this); + builtIn.setCallNode(this); // Get the real argument names and default values - String[] actualParam = builtInFunctionValue.getParamNames(); - Expr[] defaultValues = builtInFunctionValue.getDefaultValues(); + String[] actualParam = builtIn.getParameterNames(); + Expr[] defaultValues = builtIn.getParameterDefaultValues(); // Execute the argument list // TODO: Do not materialize the frame here, for now we need to do it because of a Truffle // compilation error Object[] realArgs = this.argList.executeArgList( - frame.materialize(), - actualParam, - builtInFunctionValue.getThisValue() == null ? 0 : 1); + frame.materialize(), actualParam, builtIn.getThisValue() == null ? 0 : 1); // Add the "this" value to the arguments - if (builtInFunctionValue.getThisValue() != null) { - realArgs[0] = builtInFunctionValue.getThisValue(); + if (builtIn.getThisValue() != null) { + realArgs[0] = builtIn.getThisValue(); } // Verify that there is all arguments @@ -144,26 +144,35 @@ protected Object onBuiltIn(VirtualFrame frame, BuiltInFunctionValue builtInFunct // We don't place the closure in the arguments because built-ins don't have any. // Just execute the function. - return this.dispatcher.executeDispatch(builtInFunctionValue, realArgs); + try { + return builtInLibrary.execute(builtIn, realArgs); + } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) { + // TODO: Implement runtime checks in the LKQLFunction class and base computing on them + // (#138) + throw LKQLRuntimeException.fromJavaException(e, this.calleeLocation); + } } /** * Execute the function call on a function value. * * @param frame The frame to execution the function in. - * @param functionValue The function value to execute. + * @param function The function value to execute. * @return The result of the function call. */ - @Specialization - protected Object onFunction(VirtualFrame frame, FunctionValue functionValue) { + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected Object onFunction( + final VirtualFrame frame, + final LKQLFunction function, + @CachedLibrary("function") InteropLibrary functionLibrary) { // Get the real argument names and default values - String[] actualParam = functionValue.getParamNames(); - Expr[] defaultValues = functionValue.getDefaultValues(); + String[] names = function.getParameterNames(); + Expr[] defaultValues = function.getParameterDefaultValues(); // Prepare the argument array and the working var // TODO: Do not materialize the frame here, for now we need to do it because of a Truffle // compilation error - Object[] realArgs = this.argList.executeArgList(frame.materialize(), actualParam); + Object[] realArgs = this.argList.executeArgList(frame.materialize(), names); // Verify if there is no missing argument and evaluate the default values for (int i = 0; i < realArgs.length; i++) { @@ -177,11 +186,16 @@ protected Object onFunction(VirtualFrame frame, FunctionValue functionValue) { } // Place the closure in the arguments - realArgs = - ArrayUtils.concat(new Object[] {functionValue.getClosure().getContent()}, realArgs); + realArgs = ArrayUtils.concat(new Object[] {function.getClosure().getContent()}, realArgs); // Return the result of the function call - return this.dispatcher.executeDispatch(functionValue, realArgs); + try { + return functionLibrary.execute(function, realArgs); + } catch (ArityException | UnsupportedTypeException | UnsupportedMessageException e) { + // TODO: Implement runtime checks in the LKQLFunction class and base computing on them + // (#138) + throw LKQLRuntimeException.fromJavaException(e, this.calleeLocation); + } } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunExpr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunExpr.java index 514ec2582..73f2891f4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunExpr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunExpr.java @@ -23,10 +23,10 @@ package com.adacore.lkql_jit.nodes.expressions; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.nodes.declarations.ParameterDeclaration; import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.FunctionValue; import com.adacore.lkql_jit.utils.ClosureDescriptor; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -114,8 +114,8 @@ public Object executeGeneric(VirtualFrame frame) { * com.adacore.lkql_jit.nodes.expressions.Expr#executeFunction(com.oracle.truffle.api.frame.VirtualFrame) */ @Override - public FunctionValue executeFunction(VirtualFrame frame) { - return new FunctionValue( + public LKQLFunction executeFunction(VirtualFrame frame) { + return new LKQLFunction( this.functionRootNode, Closure.create(frame.materialize(), this.closureDescriptor), Constants.FUNCTION_DEFAULT_NAME, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index 16b16eadb..263664ada 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -30,8 +30,6 @@ import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.PropertyRefValue; @@ -43,6 +41,10 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; 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 com.oracle.truffle.api.object.DynamicObjectLibrary; import java.util.Map; @@ -60,13 +62,6 @@ public abstract class DotAccess extends Expr { /** The member to access. */ protected final Identifier member; - // ----- Children ----- - - /** The dispatcher for the built-in calls. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - protected FunctionDispatcher dispatcher; - // ----- Constructors ----- /** @@ -78,7 +73,6 @@ public abstract class DotAccess extends Expr { protected DotAccess(SourceLocation location, Identifier member) { super(location); this.member = member; - this.dispatcher = FunctionDispatcherNodeGen.create(); } // ----- Execution methods ----- @@ -226,8 +220,17 @@ protected Object tryBuildIn(Object receiver) { // Get the built in BuiltInFunctionValue builtIn = this.getBuiltIn(receiver); if (builtIn != null) { - if (builtIn.getParamNames().length <= 1) { - return this.dispatcher.executeDispatch(builtIn, new Object[] {receiver}); + InteropLibrary builtInLibrary = InteropLibrary.getUncached(builtIn); + if (builtIn.getParameterNames().length <= 1) { + try { + return builtInLibrary.execute(builtIn, receiver); + } catch (ArityException + | UnsupportedTypeException + | UnsupportedMessageException e) { + // TODO: Implement runtime checks in the LKQLFunction class and base computing + // on them (#138) + throw LKQLRuntimeException.fromJavaException(e, this.member); + } } else { builtIn.setThisValue(receiver); return builtIn; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java index da728af64..99605db22 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java @@ -28,8 +28,6 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcher; -import com.adacore.lkql_jit.nodes.dispatchers.FunctionDispatcherNodeGen; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.PropertyRefValue; @@ -40,6 +38,10 @@ import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.NodeChild; 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 java.util.Map; /** @@ -55,13 +57,6 @@ public abstract class SafeDotAccess extends Expr { /** The member to access. */ protected final Identifier member; - // ----- Children ----- - - /** The dispatcher for the built-in calls. */ - @Child - @SuppressWarnings("FieldMayBeFinal") - protected FunctionDispatcher dispatcher; - // ----- Constructors ----- /** @@ -73,7 +68,6 @@ public abstract class SafeDotAccess extends Expr { protected SafeDotAccess(SourceLocation location, Identifier member) { super(location); this.member = member; - this.dispatcher = FunctionDispatcherNodeGen.create(); } // ----- Execution methods ----- @@ -161,8 +155,17 @@ protected Object tryBuildIn(Object receiver) { // Get the built in BuiltInFunctionValue builtIn = this.getBuiltIn(receiver); if (builtIn != null) { - if (builtIn.getParamNames().length <= 1) { - return this.dispatcher.executeDispatch(builtIn, new Object[] {receiver}); + InteropLibrary builtInLibrary = InteropLibrary.getUncached(builtIn); + if (builtIn.getParameterNames().length <= 1) { + try { + return builtInLibrary.execute(builtIn, receiver); + } catch (ArityException + | UnsupportedTypeException + | UnsupportedMessageException e) { + // TODO: Implement runtime checks in the LKQLFunction class and base computing + // on them (#138) + throw LKQLRuntimeException.fromJavaException(e, this.member); + } } else { builtIn.setThisValue(receiver); return builtIn; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index e4cd22105..ef184249e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -23,10 +23,7 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; -import com.adacore.lkql_jit.built_ins.values.LKQLObject; -import com.adacore.lkql_jit.built_ins.values.LKQLTuple; -import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; @@ -131,9 +128,13 @@ protected boolean eqPatterns(Pattern left, Pattern right) { * @param right The right function value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqFunctions(FunctionValue left, FunctionValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqFunctions( + final LKQLFunction left, + final LKQLFunction right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 9e733cbcc..89c789134 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -23,10 +23,7 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; -import com.adacore.lkql_jit.built_ins.values.LKQLObject; -import com.adacore.lkql_jit.built_ins.values.LKQLTuple; -import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; @@ -131,9 +128,13 @@ protected boolean neqPatterns(Pattern left, Pattern right) { * @param right The right function value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqFunctions(FunctionValue left, FunctionValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqFunctions( + final LKQLFunction left, + final LKQLFunction right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/FunctionValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/FunctionValue.java deleted file mode 100644 index 9caf20e31..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/FunctionValue.java +++ /dev/null @@ -1,148 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode; -import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.oracle.truffle.api.CallTarget; -import com.oracle.truffle.api.CompilerDirectives; - -/** - * This class represents a functional value in the LKQL language. - * - * @author Hugo GUERRIER - */ -public class FunctionValue implements LKQLValue { - - // ----- Attributes ----- - - /** The function root node. */ - private final FunctionRootNode rootNode; - - /** The closure of the function. */ - private final Closure closure; - - /** The name of the function. */ - private String name; - - /** The string representing the function documentation. */ - private final String documentation; - - /** The name of the parameters. */ - private final String[] paramNames; - - /** The default values of the parameters. */ - private final Expr[] defaultValues; - - // ----- Constructors ----- - - /** - * Create a new function value. - * - * @param rootNode The function root node. - * @param closure The closure of the function. - * @param name The name of the function. - * @param documentation The documentation of the function. - * @param paramNames The names of the parameters. - * @param values The default values of the parameters. - */ - public FunctionValue( - FunctionRootNode rootNode, - Closure closure, - String name, - String documentation, - String[] paramNames, - Expr[] values) { - this.rootNode = rootNode; - this.closure = closure; - this.name = name; - this.documentation = documentation; - this.paramNames = paramNames; - this.defaultValues = values; - } - - // ----- Getters ----- - - public Closure getClosure() { - return this.closure; - } - - public String getName() { - return this.name; - } - - @Override - public String getDocumentation() { - return this.documentation; - } - - public String[] getParamNames() { - return this.paramNames; - } - - public Expr[] getDefaultValues() { - return this.defaultValues; - } - - public Expr getBody() { - return this.rootNode.getBody(); - } - - public CallTarget getCallTarget() { - return this.rootNode.getRealCallTarget(); - } - - // ----- Setters ----- - - public void setName(String name) { - this.name = name; - } - - public void setMemoized(boolean isMemoized) { - this.rootNode.setMemoized(isMemoized); - } - - // ----- Value methods ----- - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof FunctionValue other)) return false; - return this.rootNode.equals(other.rootNode); - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - return "function<" + this.name + ">"; - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 1590fda91..cf797e4a0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -138,7 +138,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_STRING; } else if (LKQLTypeSystemGen.isPattern(obj)) { return LKQL_PATTERN; - } else if (LKQLTypeSystemGen.isFunctionValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLFunction(obj)) { return LKQL_FUNCTION; } else if (LKQLTypeSystemGen.isPropertyRefValue(obj)) { return LKQL_PROPERTY_REF; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java index c245b053a..828a0b9cd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/BaseChecker.java @@ -22,7 +22,7 @@ package com.adacore.lkql_jit.utils.checkers; -import com.adacore.lkql_jit.runtime.values.FunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; /** * This class represents a checker in the LKQL language. A checker is an annotated function which is @@ -39,7 +39,7 @@ public abstract class BaseChecker { protected String alias; /** Function to execute as checker. */ - protected final FunctionValue function; + protected final LKQLFunction function; /** Message to display when the rule violated. */ protected final String message; @@ -76,7 +76,7 @@ public abstract class BaseChecker { /** Create a base checker with all its value. */ public BaseChecker( final String name, - final FunctionValue function, + final LKQLFunction function, final String message, final String help, final boolean followGenericInstantiations, @@ -111,7 +111,7 @@ public String getAlias() { return alias; } - public FunctionValue getFunction() { + public LKQLFunction getFunction() { return function; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java index fc631f7e0..8935c2d40 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/NodeChecker.java @@ -22,7 +22,7 @@ package com.adacore.lkql_jit.utils.checkers; -import com.adacore.lkql_jit.runtime.values.FunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; /** This class represents a node checker in the LKQL system. */ public final class NodeChecker extends BaseChecker { @@ -32,7 +32,7 @@ public final class NodeChecker extends BaseChecker { /** Create a new node checker. */ public NodeChecker( final String name, - final FunctionValue function, + final LKQLFunction function, final String message, final String help, final boolean followGenericInstantiations, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java index 1bea57a95..b4830976a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/checkers/UnitChecker.java @@ -22,7 +22,7 @@ package com.adacore.lkql_jit.utils.checkers; -import com.adacore.lkql_jit.runtime.values.FunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLFunction; /** This class represents a unit checker in the LKQL system. */ public final class UnitChecker extends BaseChecker { @@ -32,7 +32,7 @@ public final class UnitChecker extends BaseChecker { /** Create a new unit checker. */ public UnitChecker( final String name, - final FunctionValue function, + final LKQLFunction function, final String message, final String help, final boolean followGenericInstantiations, diff --git a/testsuite/tests/interop/function/Main.java b/testsuite/tests/interop/function/Main.java new file mode 100644 index 000000000..0fcbf6c3b --- /dev/null +++ b/testsuite/tests/interop/function/Main.java @@ -0,0 +1,29 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + fun my_function(x) = x * 2 + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value function = namespace.getMember("my_function"); + System.out.println("=== Function interop messages:"); + print("toString()", function.toString()); + print("canExecute()", function.canExecute()); + // TODO (issue #143): Remove the "null" argument when function will + // handle closure itself + print("execute(5)", function.execute(null, 5l)); + } +} diff --git a/testsuite/tests/interop/function/test.out b/testsuite/tests/interop/function/test.out new file mode 100644 index 000000000..29abd486e --- /dev/null +++ b/testsuite/tests/interop/function/test.out @@ -0,0 +1,4 @@ +=== Function interop messages: + toString(): function + canExecute(): true + execute(5): 10 diff --git a/testsuite/tests/interop/function/test.yaml b/testsuite/tests/interop/function/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/function/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 6216a081da79ddb3ea86e288ea146f1dd2bac820 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Thu, 12 Oct 2023 14:34:36 +0200 Subject: [PATCH 14/23] Rework the representation of the selector values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 2 +- .../built_ins/BuiltInSelectorValue.java | 4 +- .../built_ins/selectors/BuiltInSelector.java | 4 +- .../built_ins/selectors/ChildrenSelector.java | 4 +- .../selectors/NextSiblingsSelector.java | 4 +- .../built_ins/selectors/ParentSelector.java | 4 +- .../selectors/PrevSiblingsSelector.java | 4 +- .../selectors/SuperTypesSelector.java | 4 +- .../values/LKQLSelector.java} | 136 ++++++++++++------ .../selector/SelectorDeclaration.java | 4 +- .../lkql_jit/nodes/expressions/Expr.java | 4 +- .../lkql_jit/nodes/expressions/FunCall.java | 5 +- .../lkql_jit/nodes/expressions/Query.java | 8 +- .../nodes/expressions/operators/BinEq.java | 10 +- .../nodes/expressions/operators/BinNeq.java | 10 +- .../lkql_jit/nodes/patterns/SelectorCall.java | 8 +- .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- testsuite/tests/interop/selector/Main.java | 32 +++++ testsuite/tests/interop/selector/test.out | 3 + testsuite/tests/interop/selector/test.yaml | 1 + 20 files changed, 177 insertions(+), 76 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/SelectorValue.java => built_ins/values/LKQLSelector.java} (50%) create mode 100644 testsuite/tests/interop/selector/Main.java create mode 100644 testsuite/tests/interop/selector/test.out create mode 100644 testsuite/tests/interop/selector/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index e24559cc3..bea1bb26f 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -47,8 +47,8 @@ String.class, Pattern.class, LKQLFunction.class, + LKQLSelector.class, PropertyRefValue.class, - SelectorValue.class, LKQLTuple.class, LKQLList.class, Indexable.class, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java index bdb7c0ee6..0b41a3a0f 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/BuiltInSelectorValue.java @@ -22,17 +22,17 @@ package com.adacore.lkql_jit.built_ins; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the base of the built-in selector values. * * @author Hugo GUERRIER */ -public class BuiltInSelectorValue extends SelectorValue { +public class BuiltInSelectorValue extends LKQLSelector { // ----- Constructors ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java index 71062e805..e8dae19d4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/BuiltInSelector.java @@ -22,7 +22,7 @@ package com.adacore.lkql_jit.built_ins.selectors; -import com.adacore.lkql_jit.runtime.values.SelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; /** * This interface defines the LKQL built-in selector factories. @@ -43,5 +43,5 @@ public interface BuiltInSelector { * * @return The selector value. */ - SelectorValue getValue(); + LKQLSelector getValue(); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java index d666e6634..43c75e28d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ChildrenSelector.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; @@ -32,7 +33,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the "children" built-in selector. @@ -85,7 +85,7 @@ public String getName() { * @see BuiltInSelector#getValue() */ @Override - public SelectorValue getValue() { + public LKQLSelector getValue() { return new BuiltInSelectorValue( NAME, "Yields all the descendants of the given node in the tree\n", this.arms); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java index 1b868e05c..a41a4f244 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/NextSiblingsSelector.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the "next_siblings" built-in selector. @@ -88,7 +88,7 @@ public String getName() { * @see BuiltInSelector#getValue() */ @Override - public SelectorValue getValue() { + public LKQLSelector getValue() { return new BuiltInSelectorValue( NAME, "Yields the siblings following the given node in the tree\n", this.arms); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java index 728d7be43..20eae773b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/ParentSelector.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; @@ -31,7 +32,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the "parent" built-in selector. @@ -84,7 +84,7 @@ public String getName() { * @see BuiltInSelector#getValue() */ @Override - public SelectorValue getValue() { + public LKQLSelector getValue() { return new BuiltInSelectorValue( NAME, "Yields the parents (ancestors) of the given node in the tree\n", this.arms); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java index 61207f5f4..5c81fb770 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/PrevSiblingsSelector.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -35,7 +36,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the "previous_siblings" built-in selector. @@ -88,7 +88,7 @@ public String getName() { * @see BuiltInSelector#getValue() */ @Override - public SelectorValue getValue() { + public LKQLSelector getValue() { return new BuiltInSelectorValue( NAME, "Yields the siblings preceding the given node in the tree\n", this.arms); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java index d57dc791b..930d4993a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/selectors/SuperTypesSelector.java @@ -23,6 +23,7 @@ package com.adacore.lkql_jit.built_ins.selectors; import com.adacore.lkql_jit.built_ins.BuiltInSelectorValue; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; @@ -36,7 +37,6 @@ import com.adacore.lkql_jit.nodes.expressions.literals.UnitLiteral; import com.adacore.lkql_jit.nodes.patterns.UniversalPattern; import com.adacore.lkql_jit.nodes.patterns.node_patterns.NodeKindPattern; -import com.adacore.lkql_jit.runtime.values.SelectorValue; /** * This class represents the "super_types" built-in selector. @@ -89,7 +89,7 @@ public String getName() { * @see BuiltInSelector#getValue() */ @Override - public SelectorValue getValue() { + public LKQLSelector getValue() { return new BuiltInSelectorValue( NAME, "Given a TypeDecl node, yields all the super types of the type\n", this.arms); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java similarity index 50% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java index 10101fe63..8737a6a4a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/SelectorValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java @@ -20,34 +20,39 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.CompilerDirectives; - -/** - * This class represents the selector values in the LQKL language. - * - * @author Hugo GUERRIER - */ -public class SelectorValue implements LKQLValue { +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.*; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; + +/** This class represents the selector values in LKQL. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLSelector implements TruffleObject, LKQLValue { // ----- Attributes ----- - /** The root node of the selector. */ + /** The root node containing the selector semantics. */ private final SelectorRootNode rootNode; - /** The closure of the selector. */ + /** Closure for the selector execution. */ private final Closure closure; /** The name of the selector. */ private final String name; - /** The documentation of the selector value. */ + /** The documentation of the selector. */ private final String documentation; // ----- Constructors ----- @@ -55,30 +60,27 @@ public class SelectorValue implements LKQLValue { /** * Create a new selector value. * - * @param selectorRootNode The root node of the selector. + * @param rootNode The root node of the selector. * @param closure The closure of the selector. * @param name The name of the selector. * @param documentation The documentation of the selector. */ - @CompilerDirectives.TruffleBoundary - public SelectorValue( - SelectorRootNode selectorRootNode, Closure closure, String name, String documentation) { - this.rootNode = selectorRootNode; + public LKQLSelector( + final SelectorRootNode rootNode, + final Closure closure, + final String name, + final String documentation) { + this.rootNode = rootNode; this.closure = closure; this.name = name; this.documentation = documentation; } - // ----- Instance methods ----- + // ----- Instance functions ----- - /** - * Execute the selector value on an ada node. - * - * @param node The node to execute the selector on. - * @return The selector list value. - */ - public LKQLSelectorList execute(Libadalang.AdaNode node) { - return this.execute(node, -1, -1, -1); + /** Execute the selector value on an ada node. */ + public LKQLSelectorList getList(Libadalang.AdaNode node) { + return this.getList(node, -1, -1, -1); } /** @@ -88,38 +90,92 @@ public LKQLSelectorList execute(Libadalang.AdaNode node) { * @param maxDepth The maximum depth of the selector list. * @param minDepth The minimal depth of the selector list. * @param depth The precise depth to get. - * @return The selector list value. */ - public LKQLSelectorList execute( + public LKQLSelectorList getList( Libadalang.AdaNode node, int maxDepth, int minDepth, int depth) { return new LKQLSelectorList(this.rootNode, this.closure, node, maxDepth, minDepth, depth); } // ----- Value methods ----- - /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#getDocumentation() - */ - @Override - public String getDocumentation() { - return this.documentation; + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; } - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL selectors. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL selectors. */ + @Specialization + protected static TriState onSelector(final LKQLSelector left, final LKQLSelector right) { + if (left.rootNode == right.rootNode) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLSelector receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL selector. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLSelector receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + return "selector<" + this.name + ">"; + } + + /** Tell the interop library that the value is not executable. */ + @ExportMessage + boolean isExecutable() { + // TODO (issue #143): Make the LKQLSelector executable as LKQLFunctions + return false; + } + + /** Placeholder function for the Truffle DSL. */ + @ExportMessage + Object execute(Object[] arguments) + throws UnsupportedTypeException, ArityException, UnsupportedMessageException { + // TODO (issue #143): implement this method to execute the selector as a simple function + // returning a selector list + return null; + } + + // ----- LKQL value methods ----- + @Override public boolean internalEquals(LKQLValue o) { if (o == this) return true; - if (!(o instanceof SelectorValue other)) return false; - return this.name.equals(other.name); + if (!(o instanceof LKQLSelector other)) return false; + return this.rootNode == other.rootNode; + } + + @Override + public String getDocumentation() { + return this.documentation; } // ----- Override methods ----- @Override - @CompilerDirectives.TruffleBoundary public String toString() { return "selector<" + this.name + ">"; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java index 7944ab0b5..4cf48d0ae 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorDeclaration.java @@ -23,12 +23,12 @@ package com.adacore.lkql_jit.nodes.declarations.selector; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.declarations.Annotation; import com.adacore.lkql_jit.nodes.declarations.Declaration; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.utils.ClosureDescriptor; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.FrameUtils; @@ -115,7 +115,7 @@ public Object executeGeneric(VirtualFrame frame) { FrameUtils.writeLocal( frame, this.slot, - new SelectorValue( + new LKQLSelector( this.selectorRootNode, Closure.create(frame.materialize(), this.closureDescriptor), this.name, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 53109a6ba..5e1f5b841 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -153,8 +153,8 @@ public PropertyRefValue executePropertyRef(VirtualFrame frame) * @return The result of the node execution as a selector value. * @throws UnexpectedResultException If the node cannot be evaluated as a selector. */ - public SelectorValue executeSelector(VirtualFrame frame) throws UnexpectedResultException { - return LKQLTypeSystemGen.expectSelectorValue(executeGeneric(frame)); + public LKQLSelector executeSelector(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLSelector(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index 549af1ab5..f2e183f2c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLFunction; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; @@ -222,7 +223,7 @@ protected Object onProperty(VirtualFrame frame, PropertyRefValue propertyRefValu * @return The result of the selector value execution. */ @Specialization - protected LKQLSelectorList onSelector(VirtualFrame frame, SelectorValue selectorValue) { + protected LKQLSelectorList onSelector(VirtualFrame frame, LKQLSelector selectorValue) { // Get the argument list and get the node from it Arg[] argList = this.argList.getArgs(); @@ -241,7 +242,7 @@ protected LKQLSelectorList onSelector(VirtualFrame frame, SelectorValue selector } // Return the selector list value - return selectorValue.execute(node); + return selectorValue.getList(node); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index 6ade29a55..90c1184dd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; @@ -32,7 +33,6 @@ import com.adacore.lkql_jit.nodes.patterns.chained_patterns.ChainedNodePattern; import com.adacore.lkql_jit.runtime.values.DepthNode; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Iterator; @@ -112,7 +112,7 @@ public Query( @Override public Object executeGeneric(VirtualFrame frame) { // Prepare the working variable - SelectorValue through = null; + LKQLSelector through = null; Libadalang.AdaNode[] fromNodes; // Get the through expression @@ -276,11 +276,11 @@ private Libadalang.AdaNode exploreFirst(VirtualFrame frame, Iterator nodeIterato * exploration * @return The iterator for the node exploration */ - private Iterable createNodeIterable(Libadalang.AdaNode root, SelectorValue through) { + private Iterable createNodeIterable(Libadalang.AdaNode root, LKQLSelector through) { if (through == null) { return new ChildIterable(root, this.followGenerics); } else { - return through.execute(root); + return through.getList(root); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index ef184249e..11c662ea5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -155,9 +155,13 @@ protected boolean eqPropertyRefs(PropertyRefValue left, PropertyRefValue right) * @param right The right selector value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqSelectors(SelectorValue left, SelectorValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqSelectors( + final LKQLSelector left, + final LKQLSelector right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index 89c789134..b6957089d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -156,9 +156,13 @@ protected boolean neqPropertyRefs(PropertyRefValue left, PropertyRefValue right) * @param right The right selector value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqSelectors(SelectorValue left, SelectorValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqSelectors( + final LKQLSelector left, + final LKQLSelector right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java index 1d16bae0b..cb106e857 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; @@ -34,7 +35,6 @@ import com.adacore.lkql_jit.nodes.arguments.NamedArg; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.SelectorValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -190,7 +190,7 @@ public LKQLList executeFiltering( private LKQLSelectorList getSelectorList(VirtualFrame frame, Libadalang.AdaNode node) { // Get the selector and verify its type Object selectorObject = this.selectorExpr.executeGeneric(frame); - if (!LKQLTypeSystemGen.isSelectorValue(selectorObject)) { + if (!LKQLTypeSystemGen.isLKQLSelector(selectorObject)) { throw LKQLRuntimeException.wrongType( LKQLTypesHelper.LKQL_SELECTOR, LKQLTypesHelper.fromJava(selectorObject), @@ -247,8 +247,8 @@ private LKQLSelectorList getSelectorList(VirtualFrame frame, Libadalang.AdaNode } // Cast the selector value and return the selector list - SelectorValue selectorValue = LKQLTypeSystemGen.asSelectorValue(selectorObject); - return selectorValue.execute(node, maxDepth, minDepth, depth); + LKQLSelector selectorValue = LKQLTypeSystemGen.asLKQLSelector(selectorObject); + return selectorValue.getList(node, maxDepth, minDepth, depth); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index cf797e4a0..294e5a1bf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -142,7 +142,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_FUNCTION; } else if (LKQLTypeSystemGen.isPropertyRefValue(obj)) { return LKQL_PROPERTY_REF; - } else if (LKQLTypeSystemGen.isSelectorValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLSelector(obj)) { return LKQL_SELECTOR; } else if (LKQLTypeSystemGen.isLKQLTuple(obj)) { return LKQL_TUPLE; diff --git a/testsuite/tests/interop/selector/Main.java b/testsuite/tests/interop/selector/Main.java new file mode 100644 index 000000000..fc76e4257 --- /dev/null +++ b/testsuite/tests/interop/selector/Main.java @@ -0,0 +1,32 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val node = units()[1].root + + selector my_selector + | AdaNode => rec *this.children + | * => () + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value selector = namespace.getMember("my_selector"); + System.out.println("=== Selector interop messages:"); + print("toString()", selector.toString()); + print("canExecute()", selector.canExecute()); + // TODO (issue #143): Call the selector when it will implements + // the interop API + } +} diff --git a/testsuite/tests/interop/selector/test.out b/testsuite/tests/interop/selector/test.out new file mode 100644 index 000000000..e35655d1a --- /dev/null +++ b/testsuite/tests/interop/selector/test.out @@ -0,0 +1,3 @@ +=== Selector interop messages: + toString(): selector + canExecute(): false diff --git a/testsuite/tests/interop/selector/test.yaml b/testsuite/tests/interop/selector/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/selector/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From b0883620b63db3331d985c35b5ea7d66a4b9134d Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Thu, 12 Oct 2023 17:16:21 +0200 Subject: [PATCH 15/23] Rework the representation of the property reference values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 2 +- .../built_ins/values/LKQLProperty.java | 196 ++++++++++++++++++ .../lkql_jit/nodes/expressions/Expr.java | 5 +- .../lkql_jit/nodes/expressions/FunCall.java | 8 +- .../nodes/expressions/dot/DotAccess.java | 22 +- .../nodes/expressions/dot/SafeDotAccess.java | 20 +- .../nodes/expressions/operators/BinEq.java | 9 +- .../nodes/expressions/operators/BinNeq.java | 10 +- .../patterns/chained_patterns/FieldLink.java | 17 +- .../chained_patterns/PropertyLink.java | 17 +- .../node_patterns/NodePatternField.java | 17 +- .../node_patterns/NodePatternProperty.java | 17 +- .../runtime/values/PropertyRefValue.java | 159 -------------- .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- testsuite/tests/interop/property/Main.java | 28 +++ testsuite/tests/interop/property/test.out | 3 + testsuite/tests/interop/property/test.yaml | 1 + 17 files changed, 303 insertions(+), 230 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java delete mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/PropertyRefValue.java create mode 100644 testsuite/tests/interop/property/Main.java create mode 100644 testsuite/tests/interop/property/test.out create mode 100644 testsuite/tests/interop/property/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index bea1bb26f..979e1a354 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -48,7 +48,7 @@ Pattern.class, LKQLFunction.class, LKQLSelector.class, - PropertyRefValue.class, + LKQLProperty.class, LKQLTuple.class, LKQLList.class, Indexable.class, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java new file mode 100644 index 000000000..265b57a8e --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values; + +import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.exception.LKQLRuntimeException; +import com.adacore.lkql_jit.nodes.arguments.ArgList; +import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.utils.LKQLTypesHelper; +import com.adacore.lkql_jit.utils.functions.ReflectionUtils; +import com.adacore.lkql_jit.utils.source_location.Locatable; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.interop.*; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; + +/** This class represents a Libadalang property access in LKQL. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLProperty implements TruffleObject, LKQLValue { + + // ----- Attributes ----- + + /** The name of the Libadalang property. */ + private final String name; + + /** Description of the Libadalang property with its Java method and parameters. */ + private final Libadalang.LibadalangField description; + + /** The node associated to the property. */ + private final Libadalang.AdaNode node; + + // ----- Constructors ----- + + /** Create a new LKQL property from its name and associated node. */ + public LKQLProperty(final String name, final Libadalang.AdaNode node) { + this.name = name; + this.description = node.getFieldDescription(name); + this.node = node; + } + + /** Creation function used by the Truffle DSL to cached properties */ + public static LKQLProperty create(final String name, final Libadalang.AdaNode node) { + return new LKQLProperty(name, node); + } + + // ----- Getters ----- + + public Libadalang.AdaNode getNode() { + return node; + } + + public Libadalang.LibadalangField getDescription() { + return description; + } + + // ----- Instance methods ----- + + /** Get whether the property reference point to a node field. */ + public boolean isField() { + return this.name.startsWith("f"); + } + + /** + * Execute the property with the given arguments. + * + * @param caller The locatable which called the execution. + * @param arguments The argument for the property call. + */ + public Object executeAsProperty(Locatable caller, ArgList argList, Object... arguments) { + try { + return ReflectionUtils.callProperty( + this.node, this.description, caller, argList, arguments); + } catch (com.adacore.lkql_jit.exception.utils.UnsupportedTypeException e) { + throw LKQLRuntimeException.unsupportedType( + LKQLTypesHelper.category(e.getType()), caller); + } + } + + /** + * Execute the property as a field access without arguments. + * + * @param caller The locatable which called the execution. + */ + public Object executeAsField(Locatable caller) { + try { + return ReflectionUtils.callProperty(this.node, this.description, caller, null); + } catch (com.adacore.lkql_jit.exception.utils.UnsupportedTypeException e) { + throw LKQLRuntimeException.unsupportedType( + LKQLTypesHelper.category(e.getType()), caller); + } + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL properties. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL properties. */ + @Specialization + protected static TriState onProperty(final LKQLProperty left, final LKQLProperty right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLProperty receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL property. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLProperty receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + return "property<" + this.name + ">"; + } + + /** Tell the interop library that the value is not executable. */ + @ExportMessage + boolean isExecutable() { + // TODO (issue #143): Make the LKQLSelector executable as LKQLFunctions + return false; + } + + /** Placeholder function for the Truffle DSL. */ + @ExportMessage + Object execute(Object[] arguments) + throws UnsupportedTypeException, ArityException, UnsupportedMessageException { + // TODO (issue #143): implement this method to execute the property as a simple function + return null; + } + + // ----- LKQL values methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(LKQLValue o) { + if (this == o) return true; + if (!(o instanceof LKQLProperty other)) return false; + return this.description.equals(other.description); + } + + // ----- Override methods ----- + + @Override + public String toString() { + return "property<" + this.name + ">"; + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 5e1f5b841..34079e384 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -141,9 +141,8 @@ public LKQLFunction executeFunction(VirtualFrame frame) throws UnexpectedResultE * @return The result of the node execution as a property reference value. * @throws UnexpectedResultException If the node cannot be evaluated as a property reference. */ - public PropertyRefValue executePropertyRef(VirtualFrame frame) - throws UnexpectedResultException { - return LKQLTypeSystemGen.expectPropertyRefValue(executeGeneric(frame)); + public LKQLProperty executeProperty(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLProperty(executeGeneric(frame)); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index f2e183f2c..b2e92d386 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -25,13 +25,13 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLFunction; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -203,16 +203,16 @@ protected Object onFunction( * Execute the function call on a property reference value. * * @param frame The frame to execute the property reference in. - * @param propertyRefValue The property reference value to execute. + * @param property The property reference value to execute. * @return The result of the property call. */ @Specialization - protected Object onProperty(VirtualFrame frame, PropertyRefValue propertyRefValue) { + protected Object onProperty(VirtualFrame frame, LKQLProperty property) { // Execute the arguments as a simple array Object[] arguments = this.argList.executeArgList(frame); // Call the property and return its result - return propertyRefValue.execute(this, this.argList, arguments); + return property.executeAsProperty(this, this.argList, arguments); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index 263664ada..8ebfbf7bc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -28,11 +28,11 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; import com.adacore.lkql_jit.built_ins.values.LKQLObject; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -133,7 +133,7 @@ protected Object onNamespace( * Execute the dot access on a node with the cached strategy. * * @param receiver The node receiver. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @param isField The cached value if the property is a field. * @return The result of the property reference. */ @@ -141,22 +141,22 @@ protected Object onNamespace( guards = { "!receiver.isNone()", "getBuiltIn(receiver) == null", - "receiver == propertyRef.getNode()", - "propertyRef.getFieldDescription() != null" + "receiver == property.getNode()", + "property.getDescription() != null" }, limit = "1") protected Object onNodeCached( Libadalang.AdaNode receiver, - @Cached("create(receiver, member.getName())") PropertyRefValue propertyRef, - @Cached("propertyRef.isField()") boolean isField) { + @Cached("create(member.getName(), receiver)") LKQLProperty property, + @Cached("property.isField()") boolean isField) { // If the method is a field if (isField) { - return propertyRef.executeAsField(this); + return property.executeAsField(this); } // If the method is a property else { - return propertyRef; + return property; } } @@ -180,13 +180,13 @@ protected Object onNodeUncached(Libadalang.AdaNode receiver) { } // Create the property reference - PropertyRefValue propertyRef = PropertyRefValue.create(receiver, this.member.getName()); - if (propertyRef.getFieldDescription() == null) { + LKQLProperty property = new LKQLProperty(this.member.getName(), receiver); + if (property.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this.member); } // Return the result - return this.onNodeCached(receiver, propertyRef, propertyRef.isField()); + return this.onNodeCached(receiver, property, property.isField()); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java index 99605db22..2e626312c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java @@ -26,11 +26,11 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.runtime.values.NodeNull; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.CompilerDirectives; @@ -76,7 +76,7 @@ protected SafeDotAccess(SourceLocation location, Identifier member) { * Execute the safe dot access on a node with the cached strategy. * * @param receiver The node receiver. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @param isField The cached value if the property is a field. * @return The property reference or the field value. */ @@ -84,22 +84,22 @@ protected SafeDotAccess(SourceLocation location, Identifier member) { guards = { "!receiver.isNone()", "getBuiltIn(receiver) == null", - "receiver == propertyRef.getNode()", - "propertyRef.getFieldDescription() != null" + "receiver == property.getNode()", + "property.getDescription() != null" }, limit = "1") protected Object onNodeCached( Libadalang.AdaNode receiver, - @Cached("create(receiver, member.getName())") PropertyRefValue propertyRef, - @Cached("propertyRef.isField()") boolean isField) { + @Cached("create(member.getName(), receiver)") LKQLProperty property, + @Cached("property.isField()") boolean isField) { // If the method is a field if (isField) { - return propertyRef.executeAsField(this); + return property.executeAsField(this); } // If the method is a property else { - return propertyRef; + return property; } } @@ -123,8 +123,8 @@ protected Object onNodeUncached(Libadalang.AdaNode receiver) { } // Create the property reference - PropertyRefValue propertyRef = PropertyRefValue.create(receiver, this.member.getName()); - if (propertyRef.getFieldDescription() == null) { + LKQLProperty propertyRef = new LKQLProperty(this.member.getName(), receiver); + if (propertyRef.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this.member); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 11c662ea5..0eb25727e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -144,8 +144,13 @@ protected boolean eqFunctions( * @param right The right property reference value. * @return The result of the equality verification. */ - protected boolean eqPropertyRefs(PropertyRefValue left, PropertyRefValue right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqPropertyRefs( + final LKQLProperty left, + final LKQLProperty right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index b6957089d..d62a670b4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -144,9 +144,13 @@ protected boolean neqFunctions( * @param right The right property reference value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqPropertyRefs(PropertyRefValue left, PropertyRefValue right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqPropertyRefs( + final LKQLProperty left, + final LKQLProperty right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/FieldLink.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/FieldLink.java index e758d9893..81b8d5ed4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/FieldLink.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/FieldLink.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.nodes.patterns.chained_patterns; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -64,17 +64,16 @@ protected FieldLink(SourceLocation location, BasePattern pattern, String fieldNa * * @param frame The frame to execute the link in. * @param node The node get the field from. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @return The result of the link. */ - @Specialization( - guards = {"node == propertyRef.getNode()", "propertyRef.getFieldDescription() != null"}) + @Specialization(guards = {"node == property.getNode()", "property.getDescription() != null"}) protected Libadalang.AdaNode[] fieldCached( VirtualFrame frame, @SuppressWarnings("unused") Libadalang.AdaNode node, - @Cached("create(node, fieldName)") PropertyRefValue propertyRef) { + @Cached("create(fieldName, node)") LKQLProperty property) { // Get the value of the field - Object value = propertyRef.executeAsField(this); + Object value = property.executeAsField(this); // Do the pattern filtering return this.doPatternFiltering(frame, value); @@ -90,15 +89,15 @@ protected Libadalang.AdaNode[] fieldCached( @Specialization(replaces = "fieldCached") protected Libadalang.AdaNode[] fieldUnached(VirtualFrame frame, Libadalang.AdaNode node) { // Get the field method - PropertyRefValue propertyRef = new PropertyRefValue(node, this.fieldName); + LKQLProperty property = new LKQLProperty(this.fieldName, node); // Verify if the field method is null - if (propertyRef.getFieldDescription() == null) { + if (property.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this); } // Execute the field detail - return this.fieldCached(frame, node, propertyRef); + return this.fieldCached(frame, node, property); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/PropertyLink.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/PropertyLink.java index 9435c402a..34be6a0cb 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/PropertyLink.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/chained_patterns/PropertyLink.java @@ -23,10 +23,10 @@ package com.adacore.lkql_jit.nodes.patterns.chained_patterns; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.ArgList; import com.adacore.lkql_jit.nodes.patterns.BasePattern; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -75,15 +75,14 @@ public PropertyLink( * * @param frame The frame to execute the link in. * @param node The node get the property from. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @return The result of the link. */ - @Specialization( - guards = {"node == propertyRef.getNode()", "propertyRef.getFieldDescription() != null"}) + @Specialization(guards = {"node == property.getNode()", "property.getDescription() != null"}) protected Libadalang.AdaNode[] propertyCached( VirtualFrame frame, @SuppressWarnings("unused") Libadalang.AdaNode node, - @Cached("create(node, propertyName)") PropertyRefValue propertyRef) { + @Cached("create(propertyName, node)") LKQLProperty property) { // Evaluate the arguments Object[] arguments = new Object[this.argList.getArgs().length]; for (int i = 0; i < arguments.length; i++) { @@ -91,7 +90,7 @@ protected Libadalang.AdaNode[] propertyCached( } // Get the property result - Object value = propertyRef.execute(this, this.argList, arguments); + Object value = property.executeAsProperty(this, this.argList, arguments); // Do the filtering return this.doPatternFiltering(frame, value); @@ -107,15 +106,15 @@ protected Libadalang.AdaNode[] propertyCached( @Specialization(replaces = "propertyCached") protected Libadalang.AdaNode[] propertyUncached(VirtualFrame frame, Libadalang.AdaNode node) { // Get the property methods - PropertyRefValue propertyRef = new PropertyRefValue(node, this.propertyName); + LKQLProperty property = new LKQLProperty(this.propertyName, node); // Test if the property is valid - if (propertyRef.getFieldDescription() == null) { + if (property.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this); } // Return the result - return this.propertyCached(frame, node, propertyRef); + return this.propertyCached(frame, node, property); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternField.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternField.java index 8357a940c..0e81f6daa 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternField.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternField.java @@ -23,8 +23,8 @@ package com.adacore.lkql_jit.nodes.patterns.node_patterns; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -71,17 +71,16 @@ protected NodePatternField(SourceLocation location, String fieldName, DetailValu * * @param frame The frame to execute in. * @param node The node get the field from. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @return True if the detail is valid, false else. */ - @Specialization( - guards = {"node == propertyRef.getNode()", "propertyRef.getFieldDescription() != null"}) + @Specialization(guards = {"node == property.getNode()", "property.getDescription() != null"}) protected boolean fieldCached( VirtualFrame frame, @SuppressWarnings("unused") Libadalang.AdaNode node, - @Cached("create(node, fieldName)") PropertyRefValue propertyRef) { + @Cached("create(fieldName, node)") LKQLProperty property) { // Get the value of the field - Object value = propertyRef.executeAsField(this); + Object value = property.executeAsField(this); // Verify if the detail value match return this.expected.executeDetailValue(frame, value); @@ -97,15 +96,15 @@ protected boolean fieldCached( @Specialization(replaces = "fieldCached") protected boolean fieldUncached(VirtualFrame frame, Libadalang.AdaNode node) { // Get the field property reference - PropertyRefValue propertyRef = new PropertyRefValue(node, this.fieldName); + LKQLProperty property = new LKQLProperty(this.fieldName, node); // Verify if the field method is null - if (propertyRef.getFieldDescription() == null) { + if (property.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this); } // Execute the field detail - return this.fieldCached(frame, node, propertyRef); + return this.fieldCached(frame, node, property); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternProperty.java index 9dd07de0b..d62cf3fbc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternProperty.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodePatternProperty.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.nodes.patterns.node_patterns; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.PropertyRefValue; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; @@ -80,15 +80,14 @@ public NodePatternProperty( * * @param frame The frame to execute in. * @param node The node get the property from. - * @param propertyRef The cached property reference. + * @param property The cached property reference. * @return True if the detail is valid, false else. */ - @Specialization( - guards = {"node == propertyRef.getNode()", "propertyRef.getFieldDescription() != null"}) + @Specialization(guards = {"node == property.getNode()", "property.getDescription() != null"}) protected boolean propertyCached( VirtualFrame frame, @SuppressWarnings("unused") Libadalang.AdaNode node, - @Cached("create(node, propertyName)") PropertyRefValue propertyRef) { + @Cached("create(propertyName, node)") LKQLProperty property) { // Evaluate the arguments Object[] arguments = new Object[this.argList.getArgs().length]; for (int i = 0; i < arguments.length; i++) { @@ -96,7 +95,7 @@ protected boolean propertyCached( } // Get the property result - Object value = propertyRef.execute(this, this.argList, arguments); + Object value = property.executeAsProperty(this, this.argList, arguments); // Verify the pattern return this.expected.executeDetailValue(frame, value); @@ -112,15 +111,15 @@ protected boolean propertyCached( @Specialization(replaces = "propertyCached") protected boolean propertyUncached(VirtualFrame frame, Libadalang.AdaNode node) { // Get the property methods - PropertyRefValue propertyRef = new PropertyRefValue(node, this.propertyName); + LKQLProperty property = new LKQLProperty(this.propertyName, node); // Test if the property is null - if (propertyRef.getFieldDescription() == null) { + if (property.getDescription() == null) { throw LKQLRuntimeException.noSuchField(this); } // Return the result - return this.propertyCached(frame, node, propertyRef); + return this.propertyCached(frame, node, property); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/PropertyRefValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/PropertyRefValue.java deleted file mode 100644 index 08f690401..000000000 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/PropertyRefValue.java +++ /dev/null @@ -1,159 +0,0 @@ -/*---------------------------------------------------------------------------- --- L K Q L J I T -- --- -- --- Copyright (C) 2022-2023, AdaCore -- --- -- --- This library is free software; you can redistribute it and/or modify it -- --- under terms of the GNU General Public License as published by the Free -- --- Software Foundation; either version 3, or (at your option) any later -- --- version. This library is distributed in the hope that it will be useful, -- --- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- --- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- --- -- --- As a special exception under Section 7 of GPL version 3, you are granted -- --- additional permissions described in the GCC Runtime Library Exception, -- --- version 3.1, as published by the Free Software Foundation. -- --- -- --- You should have received a copy of the GNU General Public License and -- --- a copy of the GCC Runtime Library Exception along with this program; -- --- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- --- -- -----------------------------------------------------------------------------*/ - -package com.adacore.lkql_jit.runtime.values; - -import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; -import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.utils.LKQLTypesHelper; -import com.adacore.lkql_jit.utils.functions.ReflectionUtils; -import com.adacore.lkql_jit.utils.functions.StringUtils; -import com.adacore.lkql_jit.utils.source_location.Locatable; -import com.oracle.truffle.api.CompilerDirectives; - -/** - * This class represents a reference to an ada node property stored in a value. - * - * @author Hugo GUERRIER - */ -public final class PropertyRefValue implements LKQLValue { - - // ----- Attributes ----- - - /** The node to execute the property on. */ - private final Libadalang.AdaNode node; - - /** The property name. */ - private final String propertyName; - - /** The field Java description. */ - public final Libadalang.LibadalangField fieldDescription; - - // ----- Constructors ----- - - /** - * Create a new property reference value. - * - * @param node The node to create the property from. - * @param propertyName The name of the property to get. - */ - public PropertyRefValue(Libadalang.AdaNode node, String propertyName) { - this.node = node; - this.propertyName = propertyName; - this.fieldDescription = node.getFieldDescription(propertyName); - } - - /** - * Creator for the property reference value for the Truffle DSL. - * - * @param node The node to create the property on. - * @param propertyName The name of the property to get. - * @return The property reference. - */ - public static PropertyRefValue create(Libadalang.AdaNode node, String propertyName) { - return new PropertyRefValue(node, propertyName); - } - - // ----- Getters ----- - - public Libadalang.AdaNode getNode() { - return this.node; - } - - public String getPropertyName() { - return this.propertyName; - } - - public Libadalang.LibadalangField getFieldDescription() { - return this.fieldDescription; - } - - // ----- Class methods ----- - - /** - * Get if the property reference point to a node field. - * - * @return True of the property is a field, false else. - */ - public boolean isField() { - return this.propertyName.startsWith("f"); - } - - /** - * Execute the property with the given arguments. - * - * @param caller The locatable which called the execution. - * @param arguments The argument for the property call. - * @return The result of the property execution. - */ - public Object execute(Locatable caller, ArgList argList, Object... arguments) { - try { - return ReflectionUtils.callProperty( - this.node, this.fieldDescription, caller, argList, arguments); - } catch (UnsupportedTypeException e) { - throw LKQLRuntimeException.unsupportedType( - LKQLTypesHelper.category(e.getType()), caller); - } - } - - /** - * Execute the property as a field access without arguments. - * - * @param caller The locatable which called the execution. - * @return The result of the field call. - */ - public Object executeAsField(Locatable caller) { - try { - return ReflectionUtils.callProperty(this.node, this.fieldDescription, caller, null); - } catch (UnsupportedTypeException e) { - throw LKQLRuntimeException.unsupportedType( - LKQLTypesHelper.category(e.getType()), caller); - } - } - - // ----- Value methods ----- - - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ - @Override - public boolean internalEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof PropertyRefValue other)) return false; - return this.fieldDescription == other.fieldDescription; - } - - // ----- Override methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public String toString() { - return ""; - } -} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 294e5a1bf..1bb50164a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -140,7 +140,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_PATTERN; } else if (LKQLTypeSystemGen.isLKQLFunction(obj)) { return LKQL_FUNCTION; - } else if (LKQLTypeSystemGen.isPropertyRefValue(obj)) { + } else if (LKQLTypeSystemGen.isLKQLProperty(obj)) { return LKQL_PROPERTY_REF; } else if (LKQLTypeSystemGen.isLKQLSelector(obj)) { return LKQL_SELECTOR; diff --git a/testsuite/tests/interop/property/Main.java b/testsuite/tests/interop/property/Main.java new file mode 100644 index 000000000..a7ad0e482 --- /dev/null +++ b/testsuite/tests/interop/property/Main.java @@ -0,0 +1,28 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val property = units()[1].root.p_enclosing_compilation_unit + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value property = namespace.getMember("property"); + System.out.println("=== Property interop messages:"); + print("toString()", property.toString()); + print("canExecute()", property.canExecute()); + // TODO (issue #143): Call the proerty when it will implements + // the interop API + } +} diff --git a/testsuite/tests/interop/property/test.out b/testsuite/tests/interop/property/test.out new file mode 100644 index 000000000..0a1a159ed --- /dev/null +++ b/testsuite/tests/interop/property/test.out @@ -0,0 +1,3 @@ +=== Property interop messages: + toString(): property + canExecute(): false diff --git a/testsuite/tests/interop/property/test.yaml b/testsuite/tests/interop/property/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/property/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 5077a86b0c0505fb78ea64df3c793aa922dff682 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Fri, 13 Oct 2023 10:33:30 +0200 Subject: [PATCH 16/23] Rework the representation of the null values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 4 +- .../methods/AnalysisUnitMethods.java | 4 +- .../built_ins/methods/NodeMethods.java | 6 +- .../values/LKQLNull.java} | 118 ++++++++++++------ .../lkql_jit/nodes/expressions/Indexing.java | 6 +- .../lkql_jit/nodes/expressions/Query.java | 6 +- .../nodes/expressions/dot/DotAccess.java | 4 +- .../nodes/expressions/dot/SafeDotAccess.java | 6 +- .../expressions/literals/NullLiteral.java | 6 +- .../lkql_jit/nodes/patterns/NullPattern.java | 4 +- .../lkql_jit/nodes/patterns/RegexPattern.java | 4 +- .../node_patterns/NodeKindPattern.java | 4 +- .../lkql_jit/utils/LKQLTypesHelper.java | 10 +- testsuite/tests/interop/null/Main.java | 28 +++++ testsuite/tests/interop/null/test.out | 5 + testsuite/tests/interop/null/test.yaml | 1 + 16 files changed, 144 insertions(+), 72 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/NodeNull.java => built_ins/values/LKQLNull.java} (54%) create mode 100644 testsuite/tests/interop/null/Main.java create mode 100644 testsuite/tests/interop/null/test.out create mode 100644 testsuite/tests/interop/null/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 979e1a354..d05ae4793 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -98,7 +98,7 @@ public static LKQLUnit asUnit(@SuppressWarnings("unused") final Object value) { */ @TypeCheck(Nullish.class) public static boolean isNullish(final Object value) { - return value == LKQLUnit.INSTANCE || value == NodeNull.getInstance(); + return value == LKQLUnit.INSTANCE || value == LKQLNull.INSTANCE; } // ----- Boolean value methods ----- @@ -177,6 +177,6 @@ else if (nodeObject instanceof DepthNode depthNode) { } // Return the default value - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } } 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 88bb8b74c..1cbfb3a92 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 @@ -26,9 +26,9 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; import java.util.ArrayList; @@ -123,7 +123,7 @@ public static final class RootExpr extends BuiltinFunctionBody { public Object executeGeneric(VirtualFrame frame) { Libadalang.AdaNode res = LKQLTypeSystemGen.asAnalysisUnit(frame.getArguments()[0]).getRoot(); - return res.isNone() ? NodeNull.getInstance() : res; + return res.isNone() ? LKQLNull.INSTANCE : res; } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java index 56073bffb..200ba7e47 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java @@ -27,11 +27,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.ReflectionUtils; @@ -183,7 +183,7 @@ public Object executeGeneric(VirtualFrame frame) { Libadalang.AdaNode[] res = new Libadalang.AdaNode[childrenCount]; for (int i = 0; i < childrenCount; i++) { Libadalang.AdaNode child = node.getChild(i); - res[i] = (child.isNone() ? NodeNull.getInstance() : child); + res[i] = (child.isNone() ? LKQLNull.INSTANCE : child); } // Return the list value @@ -197,7 +197,7 @@ public static final class ParentExpr extends BuiltinFunctionBody { public Object executeGeneric(VirtualFrame frame) { Libadalang.AdaNode parent = LKQLTypeSystemGen.asAdaNode(frame.getArguments()[0]).parent(); - return parent.isNone() ? NodeNull.getInstance() : parent; + return parent.isNone() ? LKQLNull.INSTANCE : parent; } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NodeNull.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java similarity index 54% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NodeNull.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java index fe8432de3..2fc800a8b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/NodeNull.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java @@ -20,30 +20,36 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; -/** - * This value represent the null value in the LKQL language, it extends the ada node class because - * null is a special shape of node. - * - * @author Hugo GUERRIER - */ -public final class NodeNull extends Libadalang.AdaNode implements Nullish, Truthy { +/** This class represents the null value in LKQL. */ +@ExportLibrary(InteropLibrary.class) +public class LKQLNull extends Libadalang.AdaNode implements TruffleObject, Nullish, Truthy { // ----- Attributes ----- - /** The unique instance of the null value in the LKQL language. */ - private static NodeNull instance = null; + /** The sole instance of the LKQL null value. */ + public static final LKQLNull INSTANCE = new LKQLNull(); + + /** The identity hash of the only instance of the LKQL null. */ + private static final int IDENTITY_HASH = System.identityHashCode(INSTANCE); // ----- Constructors ----- - /** Create a new null value, private for the singleton. */ - private NodeNull() { + /** Private constructor for the null value. */ + private LKQLNull() { super( Libadalang.Entity.create( Libadalang.PointerWrapper.nullPointer(), @@ -56,56 +62,88 @@ private NodeNull() { false))); } - /** - * Get the only instance of null value. - * - * @return The instance of null value. - */ - public static NodeNull getInstance() { - if (instance == null) { - instance = new NodeNull(); - } - return instance; + // ----- Node methods ----- + + @Override + public boolean isNone() { + return true; } // ----- Value methods ----- + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Tell the interop API if the given other value is null. */ + @ExportMessage + static TriState isIdenticalOrUndefined( + @SuppressWarnings("unused") final LKQLNull receiver, final Object other) { + return TriState.valueOf(receiver == other); + } + /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Truthy#isTruthy() + * Return the identity hash code for the given receiver (always the same because null value is + * singleton). */ - @Override - public boolean isTruthy() { + @ExportMessage + static int identityHashCode(@SuppressWarnings("unused") final LKQLNull receiver) { + return IDENTITY_HASH; + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffect) { + return "null"; + } + + /** Tell the interop API that the value is nullish. */ + @ExportMessage + boolean isNull() { + return true; + } + + /** Tell the interop API that the value is a boolean like value. */ + @ExportMessage + boolean isBoolean() { + return true; + } + + /** Get the boolean like value from null, which is always false. */ + @ExportMessage + boolean asBoolean() { return false; } - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ + // ----- LKQL value methods ----- + @Override public boolean internalEquals(LKQLValue o) { return o == this; } - // ----- Override methods ----- - @Override - public boolean isNone() { - return true; + public boolean isTruthy() { + return false; } + // ----- Override methods ----- + @Override public String toString() { return "null"; } @Override - public boolean equals(Object obj) { - return obj == this; - } - - @Override - public int hashCode() { - return 0; + public boolean equals(Object o) { + return o == this; } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java index 067dd801c..7d3da31b0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java @@ -24,11 +24,11 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -126,12 +126,12 @@ protected Object indexIndexable(Indexable collection, long index) { @Specialization protected Object indexNode(Libadalang.AdaNode node, long index) { if (index > node.getChildrenCount()) { - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } else if (index < 1) { throw LKQLRuntimeException.invalidIndex((int) index, this); } Libadalang.AdaNode res = node.getChild((int) index - 1); - return res.isNone() ? NodeNull.getInstance() : res; + return res.isNone() ? LKQLNull.INSTANCE : res; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index 90c1184dd..1323620d4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; @@ -32,7 +33,6 @@ import com.adacore.lkql_jit.nodes.patterns.BasePattern; import com.adacore.lkql_jit.nodes.patterns.chained_patterns.ChainedNodePattern; import com.adacore.lkql_jit.runtime.values.DepthNode; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Iterator; @@ -187,7 +187,7 @@ else if (LKQLTypeSystemGen.isLKQLList(fromObject)) { } // Return the null value if there is none - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } } @@ -265,7 +265,7 @@ private Libadalang.AdaNode exploreFirst(VirtualFrame frame, Iterator nodeIterato } // Return the null value - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java index 8ebfbf7bc..b07555abf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/DotAccess.java @@ -27,12 +27,12 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLNamespace; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -175,7 +175,7 @@ protected Object onNodeUncached(Libadalang.AdaNode receiver) { } // Test if the node is null - if (receiver == NodeNull.getInstance()) { + if (receiver == LKQLNull.INSTANCE) { throw LKQLRuntimeException.nullReceiver(this); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java index 2e626312c..eb55850f2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/dot/SafeDotAccess.java @@ -26,11 +26,11 @@ import com.adacore.lkql_jit.LKQLContext; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.Identifier; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.CompilerDirectives; @@ -118,8 +118,8 @@ protected Object onNodeUncached(Libadalang.AdaNode receiver) { } // Test if the receiver is null - if (receiver == NodeNull.getInstance()) { - return NodeNull.getInstance(); + if (receiver == LKQLNull.INSTANCE) { + return LKQLNull.INSTANCE; } // Create the property reference diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/NullLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/NullLiteral.java index 4688a99f8..79a701f1b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/NullLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/NullLiteral.java @@ -23,8 +23,8 @@ package com.adacore.lkql_jit.nodes.expressions.literals; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -54,7 +54,7 @@ public NullLiteral(SourceLocation location) { */ @Override public Object executeGeneric(VirtualFrame frame) { - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } /** @@ -63,7 +63,7 @@ public Object executeGeneric(VirtualFrame frame) { */ @Override public Libadalang.AdaNode executeNode(VirtualFrame frame) { - return NodeNull.getInstance(); + return LKQLNull.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/NullPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/NullPattern.java index 6cf4738c8..2e701d786 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/NullPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/NullPattern.java @@ -23,7 +23,7 @@ package com.adacore.lkql_jit.nodes.patterns; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.runtime.values.NodeNull; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -54,7 +54,7 @@ public NullPattern(SourceLocation location) { */ @Override public boolean executeNode(VirtualFrame frame, Libadalang.AdaNode node) { - return node == NodeNull.getInstance(); + return node == LKQLNull.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java index be63d605f..2b0642483 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java @@ -23,7 +23,7 @@ package com.adacore.lkql_jit.nodes.patterns; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.runtime.values.NodeNull; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -62,7 +62,7 @@ public RegexPattern(SourceLocation location, String regex) { */ @Override public boolean executeNode(VirtualFrame frame, Libadalang.AdaNode node) { - return this.pattern.contains(node.getText()) && node != NodeNull.getInstance(); + return this.pattern.contains(node.getText()) && node != LKQLNull.INSTANCE; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodeKindPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodeKindPattern.java index 6d8095cf4..800aebf41 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodeKindPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/NodeKindPattern.java @@ -23,8 +23,8 @@ package com.adacore.lkql_jit.nodes.patterns.node_patterns; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -65,7 +65,7 @@ public NodeKindPattern(SourceLocation location, String kindName) { */ @Override public boolean executeNode(VirtualFrame frame, Libadalang.AdaNode node) { - return this.nodeClazz.isInstance(node) && node != NodeNull.getInstance(); + return this.nodeClazz.isInstance(node) && node != LKQLNull.INSTANCE; } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 1bb50164a..8ecb9e563 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -24,10 +24,10 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; -import com.adacore.lkql_jit.runtime.values.NodeNull; import com.oracle.truffle.api.CompilerDirectives; import java.math.BigInteger; @@ -240,7 +240,7 @@ else if (javaValue instanceof String) { // If the source is an AdaNode else if (javaValue instanceof Libadalang.AdaNode adaNode) { - return adaNode.isNone() ? NodeNull.getInstance() : adaNode; + return adaNode.isNone() ? LKQLNull.INSTANCE : adaNode; } // If the source is a token @@ -276,10 +276,10 @@ else if (javaValue instanceof Libadalang.Aspect aspect) { aspect.exists, aspect.inherited, aspect.node.node.isNull() - ? NodeNull.getInstance() + ? LKQLNull.INSTANCE : Libadalang.AdaNode.fromEntity(aspect.node), aspect.value.node.isNull() - ? NodeNull.getInstance() + ? LKQLNull.INSTANCE : Libadalang.AdaNode.fromEntity(aspect.value) }; return LKQLObject.createUncached(keys, values); @@ -291,7 +291,7 @@ else if (javaValue instanceof Libadalang.RefResult refResultStruct) { Object[] values = { toLKQLValue(refResultStruct.kind), refResultStruct.ref.node.isNull() - ? NodeNull.getInstance() + ? LKQLNull.INSTANCE : Libadalang.AdaNode.fromEntity(refResultStruct.ref) }; return LKQLObject.createUncached(keys, values); diff --git a/testsuite/tests/interop/null/Main.java b/testsuite/tests/interop/null/Main.java new file mode 100644 index 000000000..417d32951 --- /dev/null +++ b/testsuite/tests/interop/null/Main.java @@ -0,0 +1,28 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val my_null = null + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value myNull = namespace.getMember("my_null"); + System.out.println("=== Null interop messages:"); + print("toString()", myNull.toString()); + print("isNull()", myNull.isNull()); + print("isBoolean()", myNull.isBoolean()); + print("asBoolean()", myNull.asBoolean()); + } +} diff --git a/testsuite/tests/interop/null/test.out b/testsuite/tests/interop/null/test.out new file mode 100644 index 000000000..1ec3b8da0 --- /dev/null +++ b/testsuite/tests/interop/null/test.out @@ -0,0 +1,5 @@ +=== Null interop messages: + toString(): null + isNull(): true + isBoolean(): true + asBoolean(): false diff --git a/testsuite/tests/interop/null/test.yaml b/testsuite/tests/interop/null/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/null/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From 304df8b8ca31ac7f5b4ce90ea07fff54c9112bd4 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Fri, 13 Oct 2023 15:06:48 +0200 Subject: [PATCH 17/23] Rework the representaiton of the pattern values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 2 +- .../built_ins/functions/PatternFunction.java | 4 +- .../built_ins/methods/StrMethods.java | 10 +- .../values/LKQLPattern.java} | 151 ++++++++++++++---- .../nodes/expressions/operators/BinEq.java | 11 +- .../nodes/expressions/operators/BinNeq.java | 11 +- .../lkql_jit/nodes/patterns/RegexPattern.java | 6 +- .../lkql_jit/utils/LKQLTypesHelper.java | 2 +- testsuite/tests/interop/pattern/Main.java | 32 ++++ testsuite/tests/interop/pattern/test.out | 9 ++ testsuite/tests/interop/pattern/test.yaml | 1 + 11 files changed, 186 insertions(+), 53 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/Pattern.java => built_ins/values/LKQLPattern.java} (51%) create mode 100644 testsuite/tests/interop/pattern/Main.java create mode 100644 testsuite/tests/interop/pattern/test.out create mode 100644 testsuite/tests/interop/pattern/test.yaml diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index d05ae4793..0a1878d50 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -45,7 +45,7 @@ long.class, BigInteger.class, String.class, - Pattern.class, + LKQLPattern.class, LKQLFunction.class, LKQLSelector.class, LKQLProperty.class, 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 index 34bf50b73..8b2ba3a72 100644 --- 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 @@ -24,11 +24,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.LKQLPattern; 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.nodes.expressions.literals.BooleanLiteral; -import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; @@ -77,7 +77,7 @@ public static BuiltInFunctionValue getValue() { } // Create the pattern and return it - return new Pattern(call, regexString, caseSensitive); + return new LKQLPattern(call, regexString, caseSensitive); }); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java index 208c3f0db..a334fccf6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java @@ -26,10 +26,10 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.BaseNameFunction; +import com.adacore.lkql_jit.built_ins.values.LKQLPattern; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.Pattern; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -360,8 +360,8 @@ public Object executeGeneric(VirtualFrame frame) { } // If the argument is a pattern - else if (LKQLTypeSystemGen.isPattern(toFindObject)) { - Pattern pattern = LKQLTypeSystemGen.asPattern(toFindObject); + else if (LKQLTypeSystemGen.isLKQLPattern(toFindObject)) { + LKQLPattern pattern = LKQLTypeSystemGen.asLKQLPattern(toFindObject); contains = pattern.contains(receiver); } @@ -394,8 +394,8 @@ public Object executeGeneric(VirtualFrame frame) { } // If the argument is a pattern - else if (LKQLTypeSystemGen.isPattern(toFindObject)) { - Pattern pattern = LKQLTypeSystemGen.asPattern(toFindObject); + else if (LKQLTypeSystemGen.isLKQLPattern(toFindObject)) { + LKQLPattern pattern = LKQLTypeSystemGen.asLKQLPattern(toFindObject); index = pattern.find(receiver); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/Pattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java similarity index 51% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/Pattern.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index bb4cf430c..87b0dbc97 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/Pattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -20,37 +20,47 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.dsl.Fallback; +import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.exception.AbstractTruffleException; -import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.*; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.source.Source; +import com.oracle.truffle.api.utilities.TriState; /** * This class represents the pattern values in the LKQL language. Pattern values are compiled * regular expression. - * - * @author Hugo GUERRIER */ -public final class Pattern implements LKQLValue { +@ExportLibrary(InteropLibrary.class) +public final class LKQLPattern implements TruffleObject, LKQLValue { // ----- Attributes ----- - /** The string of the regex. */ + /** Members of the pattern LKQL value. */ + private final LKQLArrayList MEMBERS = new LKQLArrayList(new String[] {"contains", "find"}); + + /** The interop regex object from the TRegex language. */ + private final Object regexObject; + + /** The source string of the regex. */ private final String regexString; - /** If the regex is case-sensitive. */ + /** Whether the regex is case-sensitive. */ private final boolean caseSensitive; - /** The regex object. */ - private final Object regexObject; - // ----- Constructors ----- /** @@ -61,7 +71,8 @@ public final class Pattern implements LKQLValue { * @param caseSensitive Whether the regex is case-sensitive. */ @CompilerDirectives.TruffleBoundary - public Pattern(LKQLNode creator, String regexString, boolean caseSensitive) { + public LKQLPattern( + final LKQLNode creator, final String regexString, final boolean caseSensitive) { this.regexString = regexString; this.caseSensitive = caseSensitive; @@ -83,20 +94,9 @@ public Pattern(LKQLNode creator, String regexString, boolean caseSensitive) { } } - // ----- Getters ----- + // ----- Instance methods ----- - public String getRegexString() { - return regexString; - } - - // ----- Class methods ----- - - /** - * Get if the given string contains a substring that validate the regex. - * - * @param string The string to search in. - * @return True if the string validate the pattern, false else. - */ + /** Get whether the given string contains a substring that validate the regex. */ public boolean contains(String string) { try { Object resultObject = @@ -108,12 +108,7 @@ public boolean contains(String string) { } } - /** - * Get the index of the first matched group in the given string. - * - * @param string The string to match. - * @return The index of the first matcher group or -1. - */ + /** Get the index of the first matched group in the given string, return -1 if there is none. */ public int find(String string) { try { Object resultObject = @@ -127,14 +122,104 @@ public int find(String string) { // ----- Value methods ----- + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL patterns. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL patterns. */ + @Specialization + protected static TriState onPattern(final LKQLPattern left, final LKQLPattern right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLPattern receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL pattern. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLPattern receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + return "pattern<\"" + this.regexString + "\">"; + } + + /** Tell the interop library that the value has members. */ + @ExportMessage + boolean hasMembers() { + return true; + } + + /** Get the existing members on the pattern. */ + @ExportMessage + Object getMembers(@SuppressWarnings("unused") final boolean includeInternal) { + return MEMBERS; + } + + /** Tell the interop library whether the given member is invokable. */ + @ExportMessage + boolean isMemberInvocable(String member) { + return MEMBERS.contains(member); + } + /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) + * Call the given member on the pattern object. + * + * @throws ArityException If there is an error in the argument arity. + * @throws UnsupportedTypeException If the given arguments hasn't the good type. + * @throws UnknownIdentifierException If the provided member doesn't exist. */ + @ExportMessage + Object invokeMember(String member, Object... args) + throws ArityException, UnsupportedTypeException, UnknownIdentifierException { + // Verify the argument number + if (args.length < 1) { + throw ArityException.create(1, 1, args.length); + } + + // Get the first arguments as a string + if (!LKQLTypeSystemGen.isString(args[0])) { + throw UnsupportedTypeException.create(args, "String is required as first argument"); + } + final String arg = LKQLTypeSystemGen.asString(args[0]); + + // Call the valid method + return switch (member) { + case "contains" -> this.contains(arg); + case "find" -> this.find(arg); + default -> throw UnknownIdentifierException.create(member); + }; + } + + // ----- LKQL Value methods ----- + @Override public boolean internalEquals(LKQLValue o) { if (o == this) return true; - if (!(o instanceof Pattern other)) return false; + if (!(o instanceof LKQLPattern other)) return false; return other.regexString.equals(this.regexString) && (this.caseSensitive && other.caseSensitive); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index 0eb25727e..e4fe86150 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -25,7 +25,6 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; -import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; @@ -116,9 +115,13 @@ protected boolean eqStrings(String left, String right) { * @param right The right pattern value. * @return The result of the equality verification. */ - @Specialization - protected boolean eqPatterns(Pattern left, Pattern right) { - return left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean eqPatterns( + final LKQLPattern left, + final LKQLPattern right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index d62a670b4..dd1624529 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -25,7 +25,6 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; -import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; @@ -116,9 +115,13 @@ protected boolean neqString(String left, String right) { * @param right The right pattern value. * @return The result of the non-equality verification. */ - @Specialization - protected boolean neqPatterns(Pattern left, Pattern right) { - return !left.internalEquals(right); + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected boolean neqPatterns( + final LKQLPattern left, + final LKQLPattern right, + @CachedLibrary("left") InteropLibrary leftLibrary, + @CachedLibrary("right") InteropLibrary rightLibrary) { + return !leftLibrary.isIdentical(left, right, rightLibrary); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java index 2b0642483..ff624b256 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/RegexPattern.java @@ -24,7 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.LKQLNull; -import com.adacore.lkql_jit.runtime.values.Pattern; +import com.adacore.lkql_jit.built_ins.values.LKQLPattern; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -38,7 +38,7 @@ public final class RegexPattern extends ValuePattern { // ----- Attributes ----- /** The regex pattern to match the node text with. */ - private final Pattern pattern; + private final LKQLPattern pattern; // ----- Constructors ----- @@ -50,7 +50,7 @@ public final class RegexPattern extends ValuePattern { */ public RegexPattern(SourceLocation location, String regex) { super(location); - this.pattern = new Pattern(this, regex, true); + this.pattern = new LKQLPattern(this, regex, true); } // ----- Execution methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 8ecb9e563..2c79cc9dc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -136,7 +136,7 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_INTEGER; } else if (LKQLTypeSystemGen.isString(obj)) { return LKQL_STRING; - } else if (LKQLTypeSystemGen.isPattern(obj)) { + } else if (LKQLTypeSystemGen.isLKQLPattern(obj)) { return LKQL_PATTERN; } else if (LKQLTypeSystemGen.isLKQLFunction(obj)) { return LKQL_FUNCTION; diff --git a/testsuite/tests/interop/pattern/Main.java b/testsuite/tests/interop/pattern/Main.java new file mode 100644 index 000000000..58acdbe45 --- /dev/null +++ b/testsuite/tests/interop/pattern/Main.java @@ -0,0 +1,32 @@ +import org.graalvm.polyglot.Context; +import org.graalvm.polyglot.Value; + +public class Main { + private static final String LKQL_SOURCE = + """ + val my_pattern = pattern("he..o") + """; + + private static void print(String messageName, Object value) { + System.out.println(" " + messageName + ": " + value); + } + + public static void main(String[] args) { + Context context = Context.newBuilder("lkql") + .option("lkql.projectFile", "default_project/default.gpr") + .build(); + Value executable = context.parse("lkql", LKQL_SOURCE); + + Value namespace = executable.execute(false); + Value pattern = namespace.getMember("my_pattern"); + System.out.println("=== Property interop messages:"); + print("toString()", pattern.toString()); + print("hasMembers()", pattern.hasMembers()); + print("getMemberKeys()", pattern.getMemberKeys()); + print("canInvokeMember('contains')", pattern.canInvokeMember("contains")); + print("canInvokeMember('find')", pattern.canInvokeMember("find")); + print("invokeMember('contains', 'hello world')", pattern.invokeMember("contains", "hello world")); + print("invokeMember('contains', 'good morning world')", pattern.invokeMember("contains", "good morning world")); + print("invokeMember('find', 'this is hello world')", pattern.invokeMember("find", "this is hello world")); + } +} diff --git a/testsuite/tests/interop/pattern/test.out b/testsuite/tests/interop/pattern/test.out new file mode 100644 index 000000000..e6580eedc --- /dev/null +++ b/testsuite/tests/interop/pattern/test.out @@ -0,0 +1,9 @@ +=== Property interop messages: + toString(): pattern<"he..o"> + hasMembers(): true + getMemberKeys(): [contains, find] + canInvokeMember('contains'): true + canInvokeMember('find'): true + invokeMember('contains', 'hello world'): true + invokeMember('contains', 'good morning world'): false + invokeMember('find', 'this is hello world'): 8 diff --git a/testsuite/tests/interop/pattern/test.yaml b/testsuite/tests/interop/pattern/test.yaml new file mode 100644 index 000000000..33f2e79ec --- /dev/null +++ b/testsuite/tests/interop/pattern/test.yaml @@ -0,0 +1 @@ +driver: java \ No newline at end of file From a2b03fbf8a1bd08e817108f965b1d7a3626ba278 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Fri, 13 Oct 2023 16:18:33 +0200 Subject: [PATCH 18/23] Rework the representation of the depth node values --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 5 +- .../values/LKQLDepthNode.java} | 82 +++++++++++++++---- .../values/lists/LKQLSelectorList.java | 30 +++---- .../declarations/selector/SelectorArm.java | 12 +-- .../nodes/dispatchers/SelectorDispatcher.java | 8 +- .../lkql_jit/nodes/expressions/Expr.java | 1 - .../lkql_jit/nodes/expressions/Query.java | 6 +- .../lkql_jit/nodes/patterns/SelectorCall.java | 8 +- .../nodes/root_nodes/SelectorRootNode.java | 6 +- .../tests/interop/selector_list/Main.java | 4 +- .../tests/interop/selector_list/test.out | 3 + 11 files changed, 107 insertions(+), 58 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime/values/DepthNode.java => built_ins/values/LKQLDepthNode.java} (53%) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 0a1878d50..c7fba364d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -25,7 +25,6 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; -import com.adacore.lkql_jit.runtime.values.*; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.*; import com.oracle.truffle.api.CompilerDirectives; @@ -155,7 +154,7 @@ public static BigInteger longToBigInteger(long value) { */ @TypeCheck(Libadalang.AdaNode.class) public static boolean isAdaNode(Object nodeObject) { - return nodeObject instanceof Libadalang.AdaNode || nodeObject instanceof DepthNode; + return nodeObject instanceof Libadalang.AdaNode || nodeObject instanceof LKQLDepthNode; } /** @@ -172,7 +171,7 @@ public static Libadalang.AdaNode asAdaNode(Object nodeObject) { } // If the value is a depth node - else if (nodeObject instanceof DepthNode depthNode) { + else if (nodeObject instanceof LKQLDepthNode depthNode) { return depthNode.getNode(); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/DepthNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java similarity index 53% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/DepthNode.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java index 078db0fbc..23b431779 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/DepthNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java @@ -20,18 +20,27 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values; +package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; +import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +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.interop.TruffleObject; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; /** - * This class represents an ada node with the depth information. - * - * @author Hugo GUERRIER + * This class represents an ada node with the depth information. TODO : This value will change when + * all Libadalang objects will be wrapped in interop LKQL values (#154). */ -public final class DepthNode implements LKQLValue { +@ExportLibrary(InteropLibrary.class) +public final class LKQLDepthNode implements TruffleObject, LKQLValue { // ----- Attributes ----- @@ -43,13 +52,8 @@ public final class DepthNode implements LKQLValue { // ----- Constructors ----- - /** - * Create a new depth node. - * - * @param depth The depth of the node. - * @param node The node. - */ - public DepthNode(int depth, Libadalang.AdaNode node) { + /** Create a new depth node. */ + public LKQLDepthNode(int depth, Libadalang.AdaNode node) { this.depth = depth; this.node = node; } @@ -66,14 +70,56 @@ public Libadalang.AdaNode getNode() { // ----- Value methods ----- - /** - * @see - * com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue#internalEquals(com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue) - */ + /** Tell the interop library that the depth node has an associated language */ + @ExportMessage + boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two LKQL depth nodes. */ + @ExportMessage + static class IsIdenticalOrUndefined { + /** Compare two LKQL depth nodes. */ + @Specialization + protected static TriState onNode(final LKQLDepthNode left, final LKQLDepthNode right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + protected static TriState onOther( + @SuppressWarnings("unused") final LKQLDepthNode receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL depth node. */ + @ExportMessage + @CompilerDirectives.TruffleBoundary + static int identityHashCode(final LKQLDepthNode receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @ExportMessage + Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + return this.node.toString(); + } + + // ----- LKQL Value methods ----- + @Override public boolean internalEquals(LKQLValue o) { if (o == this) return true; - if (!(o instanceof DepthNode other)) return false; + if (!(o instanceof LKQLDepthNode other)) return false; return other.node.equals(this.node); } @@ -93,7 +139,7 @@ public int hashCode() { @Override public boolean equals(Object o) { if (o == this) return true; - if (!(o instanceof DepthNode other)) return false; + if (!(o instanceof LKQLDepthNode other)) return false; return this.node.equals(other.node); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java index d52611bb6..4e5dfdaea 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java @@ -24,11 +24,11 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.nodes.dispatchers.SelectorDispatcher; import com.adacore.lkql_jit.nodes.dispatchers.SelectorDispatcherNodeGen; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -53,10 +53,10 @@ public class LKQLSelectorList extends LKQLLazyList { private final SelectorDispatcher dispatcher; /** The cache of already explored nodes. */ - private final HashSet alreadyVisited; + private final HashSet alreadyVisited; /** The list of the node to recurs on. */ - private final List recursList; + private final List recursList; /** The maximal depth for the return. */ private final int maxDepth; @@ -95,7 +95,7 @@ public LKQLSelectorList( this.maxDepth = maxDepth; this.minDepth = minDepth; this.depth = depth; - this.recursList.add(new DepthNode(0, adaNode)); + this.recursList.add(new LKQLDepthNode(0, adaNode)); } // ----- Lazy list required methods ----- @@ -104,7 +104,7 @@ public LKQLSelectorList( public void initCache(int n) { while (!(this.recursList.size() == 0) && (this.cache.size() - 1 < n || n == -1)) { // Get the first recurse item and execute the selector on it - DepthNode nextNode = this.recursList.remove(0); + LKQLDepthNode nextNode = this.recursList.remove(0); SelectorRootNode.SelectorCallResult result = this.dispatcher.executeDispatch( this.rootNode, this.closure.getContent(), nextNode); @@ -124,15 +124,15 @@ public void initCache(int n) { @CompilerDirectives.TruffleBoundary private void addResult(Object toAdd) { // If the object is just a node - if (toAdd instanceof DepthNode node) { + if (toAdd instanceof LKQLDepthNode node) { if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); } } // If the object is an array of node - else if (toAdd instanceof DepthNode[] nodes) { - for (DepthNode node : nodes) { + else if (toAdd instanceof LKQLDepthNode[] nodes) { + for (LKQLDepthNode node : nodes) { if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); } @@ -144,15 +144,15 @@ else if (toAdd instanceof DepthNode[] nodes) { @CompilerDirectives.TruffleBoundary private void addRecurs(Object toAdd) { // If the object is just a node - if (toAdd instanceof DepthNode node) { + if (toAdd instanceof LKQLDepthNode node) { if (!this.alreadyVisited.contains(node)) { this.recursList.add(node); } } // If the object is an array of node - else if (toAdd instanceof DepthNode[] nodes) { - for (DepthNode node : nodes) { + else if (toAdd instanceof LKQLDepthNode[] nodes) { + for (LKQLDepthNode node : nodes) { if (!this.alreadyVisited.contains(node)) { this.recursList.add(node); } @@ -164,7 +164,7 @@ else if (toAdd instanceof DepthNode[] nodes) { @CompilerDirectives.TruffleBoundary private void addRecursAndResult(Object toAdd) { // If the object is just a node - if (toAdd instanceof DepthNode node) { + if (toAdd instanceof LKQLDepthNode node) { if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); this.recursList.add(node); @@ -172,8 +172,8 @@ private void addRecursAndResult(Object toAdd) { } // If the object is an array of node - else if (toAdd instanceof DepthNode[] nodes) { - for (DepthNode node : nodes) { + else if (toAdd instanceof LKQLDepthNode[] nodes) { + for (LKQLDepthNode node : nodes) { if (!this.alreadyVisited.contains(node)) { this.addNodeResult(node); this.recursList.add(node); @@ -184,7 +184,7 @@ else if (toAdd instanceof DepthNode[] nodes) { /** Add a node in the result and hashed cache with all verifications. */ @CompilerDirectives.TruffleBoundary - private void addNodeResult(DepthNode node) { + private void addNodeResult(LKQLDepthNode node) { // If there is no defined depth if (this.depth < 0) { if ((this.maxDepth < 0 || node.getDepth() <= this.maxDepth) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorArm.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorArm.java index e6c97ec20..ef1a3e3e4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorArm.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/declarations/selector/SelectorArm.java @@ -23,11 +23,11 @@ package com.adacore.lkql_jit.nodes.declarations.selector; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.patterns.BasePattern; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; @@ -97,20 +97,20 @@ public Object executeGeneric(VirtualFrame frame) { * @param node The node to match. * @return The result of the arm execution or null if the arm doesn't match. */ - public SelectorRootNode.SelectorCallResult executeArm(VirtualFrame frame, DepthNode node) { + public SelectorRootNode.SelectorCallResult executeArm(VirtualFrame frame, LKQLDepthNode node) { if (this.pattern.executeNode(frame, node.getNode())) { // Execute the selector expression Object res = this.expr.executeGeneric(frame); // If the result of the expression is an array if (res instanceof Object[] resList) { - List depthNodes = new ArrayList<>(resList.length); + List depthNodes = new ArrayList<>(resList.length); for (Object obj : resList) { // For each object of the array, verify that it is a node try { if (!LKQLTypeSystemGen.isNullish(obj)) { depthNodes.add( - new DepthNode( + new LKQLDepthNode( node.getDepth() + 1, LKQLTypeSystemGen.expectAdaNode(obj))); } @@ -123,7 +123,7 @@ public SelectorRootNode.SelectorCallResult executeArm(VirtualFrame frame, DepthN } } return new SelectorRootNode.SelectorCallResult( - this.expr.getMode(), depthNodes.toArray(new DepthNode[0])); + this.expr.getMode(), depthNodes.toArray(new LKQLDepthNode[0])); } // If the result of the expression is nullish @@ -135,7 +135,7 @@ else if (LKQLTypeSystemGen.isNullish(res)) { else if (LKQLTypeSystemGen.isAdaNode(res)) { return new SelectorRootNode.SelectorCallResult( this.expr.getMode(), - new DepthNode(node.getDepth() + 1, LKQLTypeSystemGen.asAdaNode(res))); + new LKQLDepthNode(node.getDepth() + 1, LKQLTypeSystemGen.asAdaNode(res))); } // Throw an exception diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/SelectorDispatcher.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/SelectorDispatcher.java index 8c99af17a..2bc47df35 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/SelectorDispatcher.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/dispatchers/SelectorDispatcher.java @@ -22,9 +22,9 @@ package com.adacore.lkql_jit.nodes.dispatchers; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Cell; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.nodes.DirectCallNode; @@ -40,7 +40,7 @@ public abstract class SelectorDispatcher extends Node { /** Function to execute the selector root node and get the result. */ public abstract SelectorRootNode.SelectorCallResult executeDispatch( - SelectorRootNode rootNode, Cell[] closure, DepthNode node); + SelectorRootNode rootNode, Cell[] closure, LKQLDepthNode node); /** * Execute the selector root node with the direct path. @@ -54,7 +54,7 @@ public abstract SelectorRootNode.SelectorCallResult executeDispatch( protected static SelectorRootNode.SelectorCallResult executeCached( SelectorRootNode rootNode, Cell[] closure, - DepthNode node, + LKQLDepthNode node, @Cached("create(rootNode.getRealCallTarget())") DirectCallNode directCallNode) { return (SelectorRootNode.SelectorCallResult) directCallNode.call(closure, node); } @@ -71,7 +71,7 @@ protected static SelectorRootNode.SelectorCallResult executeCached( protected static SelectorRootNode.SelectorCallResult executeUncached( SelectorRootNode rootNode, Cell[] closure, - DepthNode node, + LKQLDepthNode node, @Cached IndirectCallNode indirectCallNode) { return (SelectorRootNode.SelectorCallResult) indirectCallNode.call(rootNode.getRealCallTarget(), closure, node); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 34079e384..52bec1eb7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -27,7 +27,6 @@ import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.*; 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; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index 1323620d4..68bcf69c0 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -25,6 +25,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; @@ -32,7 +33,6 @@ import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; import com.adacore.lkql_jit.nodes.patterns.chained_patterns.ChainedNodePattern; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Iterator; @@ -210,7 +210,7 @@ private List exploreAll(VirtualFrame frame, Iterator nodeIte Libadalang.AdaNode adaNode = this.throughExpr == null ? (Libadalang.AdaNode) nodeIterator.next() - : ((DepthNode) nodeIterator.next()).getNode(); + : ((LKQLDepthNode) nodeIterator.next()).getNode(); // If the pattern is a chained one if (this.pattern instanceof ChainedNodePattern chainedNodePattern) { @@ -246,7 +246,7 @@ private Libadalang.AdaNode exploreFirst(VirtualFrame frame, Iterator nodeIterato Libadalang.AdaNode adaNode = this.throughExpr == null ? (Libadalang.AdaNode) nodeIterator.next() - : ((DepthNode) nodeIterator.next()).getNode(); + : ((LKQLDepthNode) nodeIterator.next()).getNode(); // If the pattern is a chained one if (this.pattern instanceof ChainedNodePattern chainedNodePattern) { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java index cb106e857..540f0d6af 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; @@ -34,7 +35,6 @@ import com.adacore.lkql_jit.nodes.arguments.ArgList; import com.adacore.lkql_jit.nodes.arguments.NamedArg; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -264,7 +264,7 @@ private boolean isAll( // Iterate on nodes Iterator iterator = selectorListValue.iterator(); while (iterator.hasNext()) { - DepthNode depthNode = (DepthNode) iterator.next(); + LKQLDepthNode depthNode = (LKQLDepthNode) iterator.next(); if (!pattern.executeNode(frame, depthNode.getNode())) return false; } @@ -285,7 +285,7 @@ private boolean isAny( // Iterate on nodes Iterator iterator = selectorListValue.iterator(); while (iterator.hasNext()) { - DepthNode depthNode = (DepthNode) iterator.next(); + LKQLDepthNode depthNode = (LKQLDepthNode) iterator.next(); if (pattern.executeNode(frame, depthNode.getNode())) return true; } @@ -309,7 +309,7 @@ private LKQLList getFilteredList( // Iterate on nodes Iterator iterator = selectorListValue.iterator(); while (iterator.hasNext()) { - DepthNode depthNode = (DepthNode) iterator.next(); + LKQLDepthNode depthNode = (LKQLDepthNode) iterator.next(); if (pattern.executeNode(frame, depthNode.getNode())) { resList.add(depthNode.getNode()); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java index da653d8a1..6a3a53251 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/root_nodes/SelectorRootNode.java @@ -22,10 +22,10 @@ package com.adacore.lkql_jit.nodes.root_nodes; +import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorArm; import com.adacore.lkql_jit.nodes.declarations.selector.SelectorExpr; -import com.adacore.lkql_jit.runtime.values.DepthNode; import com.adacore.lkql_jit.utils.functions.FrameUtils; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.frame.FrameDescriptor; @@ -37,7 +37,7 @@ * @author Hugo GUERRIER */ public final class SelectorRootNode - extends MemoizedRootNode { + extends MemoizedRootNode { // ----- Attributes ----- @@ -96,7 +96,7 @@ public Object execute(VirtualFrame frame) { this.initFrame(frame); // Get the node and set it into the frame - DepthNode node = (DepthNode) frame.getArguments()[1]; + LKQLDepthNode node = (LKQLDepthNode) frame.getArguments()[1]; // Try memoization if (this.isMemoized) { diff --git a/testsuite/tests/interop/selector_list/Main.java b/testsuite/tests/interop/selector_list/Main.java index c9cd8dfdc..89df22bfb 100644 --- a/testsuite/tests/interop/selector_list/Main.java +++ b/testsuite/tests/interop/selector_list/Main.java @@ -25,7 +25,9 @@ public static void main(String[] args) { print("getArraySize()", nodes.getArraySize()); print("isBoolean()", nodes.isBoolean()); print("asBoolean()", nodes.asBoolean()); - // TODO (LATER IN MR): Get first elements of the list when depth node are interop + print("getArrayElement(0)", nodes.getArrayElement(0)); + print("getArrayElement(1)", nodes.getArrayElement(1)); + print("getArrayElement(2)", nodes.getArrayElement(2)); print("hasIterator()", nodes.hasIterator()); } } diff --git a/testsuite/tests/interop/selector_list/test.out b/testsuite/tests/interop/selector_list/test.out index 7ef865e45..e9eeb3f00 100644 --- a/testsuite/tests/interop/selector_list/test.out +++ b/testsuite/tests/interop/selector_list/test.out @@ -4,4 +4,7 @@ getArraySize(): 57 isBoolean(): true asBoolean(): true + getArrayElement(0): + getArrayElement(1): + getArrayElement(2): hasIterator(): true From ad949556990e31300c26d61e5aeb77fda6477c06 Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 17 Oct 2023 10:44:46 +0200 Subject: [PATCH 19/23] Move 'interfaces' package to the new 'built_ins' package --- .../main/java/com/adacore/lkql_jit/LKQLTypeSystem.java | 4 ++-- .../adacore/lkql_jit/built_ins/functions/DocFunction.java | 2 +- .../lkql_jit/built_ins/functions/HelpFunction.java | 2 +- .../adacore/lkql_jit/built_ins/functions/MapFunction.java | 2 +- .../lkql_jit/built_ins/functions/ProfileFunction.java | 2 +- .../lkql_jit/built_ins/functions/ReduceFunction.java | 2 +- .../lkql_jit/built_ins/functions/UniqueFunction.java | 2 +- .../lkql_jit/built_ins/functions/UnitCheckerFunction.java | 2 +- .../lkql_jit/built_ins/methods/IterableMethods.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLDepthNode.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLFunction.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLNamespace.java | 2 +- .../com/adacore/lkql_jit/built_ins/values/LKQLNull.java | 6 +++--- .../com/adacore/lkql_jit/built_ins/values/LKQLObject.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLPattern.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLProperty.java | 2 +- .../adacore/lkql_jit/built_ins/values/LKQLSelector.java | 2 +- .../com/adacore/lkql_jit/built_ins/values/LKQLTuple.java | 4 ++-- .../com/adacore/lkql_jit/built_ins/values/LKQLUnit.java | 6 +++--- .../values/interfaces/Indexable.java | 2 +- .../values/interfaces/Iterable.java | 2 +- .../values/interfaces/LKQLValue.java | 2 +- .../{runtime => built_ins}/values/interfaces/Nullish.java | 2 +- .../{runtime => built_ins}/values/interfaces/Truthy.java | 2 +- .../adacore/lkql_jit/built_ins/values/lists/LKQLList.java | 8 ++++---- .../java/com/adacore/lkql_jit/nodes/expressions/Expr.java | 8 ++++---- .../com/adacore/lkql_jit/nodes/expressions/FunCall.java | 2 +- .../com/adacore/lkql_jit/nodes/expressions/Indexing.java | 2 +- .../com/adacore/lkql_jit/nodes/expressions/Query.java | 6 +++--- .../list_comprehension/ComprehensionAssoc.java | 2 +- .../list_comprehension/ComprehensionAssocList.java | 2 +- .../expressions/list_comprehension/ListComprehension.java | 2 +- .../lkql_jit/nodes/expressions/operators/InClause.java | 2 +- .../lkql_jit/nodes/expressions/operators/UnNot.java | 2 +- 34 files changed, 48 insertions(+), 48 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => built_ins}/values/interfaces/Indexable.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => built_ins}/values/interfaces/Iterable.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => built_ins}/values/interfaces/LKQLValue.java (97%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => built_ins}/values/interfaces/Nullish.java (96%) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/{runtime => built_ins}/values/interfaces/Truthy.java (97%) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index c7fba364d..1773c8b69 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -24,9 +24,9 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; +import com.adacore.lkql_jit.built_ins.values.interfaces.*; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; -import com.adacore.lkql_jit.runtime.values.interfaces.*; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.ImplicitCast; import com.oracle.truffle.api.dsl.TypeCast; 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 index 6e5519c7a..80a77fdd9 100644 --- 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 @@ -24,9 +24,9 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; 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; /** 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 index 10ade6a9e..0fbfe8d73 100644 --- 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 @@ -26,9 +26,9 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; 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.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.frame.VirtualFrame; 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 index d05d30578..475179e1f 100644 --- 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 @@ -26,10 +26,10 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLFunction; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; 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 index eb937de44..d83237ddc 100644 --- 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 @@ -24,9 +24,9 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; 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; /** 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 index a70f94024..bd758dfc6 100644 --- 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 @@ -26,9 +26,9 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLFunction; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; 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 index 675da84dd..828e7393b 100644 --- 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 @@ -24,11 +24,11 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; 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.interfaces.Indexable; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java index 5ccc00779..fc568d0d8 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/functions/UnitCheckerFunction.java @@ -31,10 +31,10 @@ import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.LKQLObject; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.LangkitException; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.checkers.UnitChecker; 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 7210662d2..4bbac4a00 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 @@ -26,9 +26,9 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.ReduceFunction; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.Iterator; import com.oracle.truffle.api.frame.VirtualFrame; import java.util.LinkedList; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java index 23b431779..37cb9d546 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java @@ -24,7 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java index bd63e097f..e5bf40f0b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java @@ -23,10 +23,10 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index 4058cf595..5c01347bc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.runtime.Cell; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java index 2fc800a8b..b45b2e680 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java @@ -24,9 +24,9 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; -import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; +import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index 4080f7fbb..c84571c78 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -23,8 +23,8 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index 87b0dbc97..beb3a0778 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -24,10 +24,10 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java index 265b57a8e..746ad9dfd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java @@ -24,9 +24,9 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ReflectionUtils; import com.adacore.lkql_jit.utils.source_location.Locatable; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java index 8737a6a4a..456c15f08 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java @@ -24,10 +24,10 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java index b9e347f10..281513e8b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java index d58e1c7d4..93e1bf15d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java @@ -23,9 +23,9 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; -import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; +import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.TruffleObject; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Indexable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Indexable.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java index eacaa35bc..812a3cbfd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Indexable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values.interfaces; +package com.adacore.lkql_jit.built_ins.values.interfaces; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Iterable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Iterable.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java index 157da637c..1b517a7a4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Iterable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values.interfaces; +package com.adacore.lkql_jit.built_ins.values.interfaces; import com.adacore.lkql_jit.utils.Iterator; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LKQLValue.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java index 470d16686..bc5e23b32 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/LKQLValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values.interfaces; +package com.adacore.lkql_jit.built_ins.values.interfaces; /** * This interface defines the LKQL values basic interface. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Nullish.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java similarity index 96% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Nullish.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java index 8702da630..f30160a53 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Nullish.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values.interfaces; +package com.adacore.lkql_jit.built_ins.values.interfaces; /** * This interface represents all nullish values in the LKQL language. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Truthy.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java similarity index 97% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Truthy.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java index 610f8342f..4d2b73bc4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/runtime/values/interfaces/Truthy.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java @@ -20,7 +20,7 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.runtime.values.interfaces; +package com.adacore.lkql_jit.built_ins.values.interfaces; /** * This class represents all LKQL values that can be interpreted as a boolean. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java index 093c38124..68a37cbc1 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java @@ -23,12 +23,12 @@ package com.adacore.lkql_jit.built_ins.values.lists; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.adacore.lkql_jit.built_ins.values.iterators.LKQLListIterator; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -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.interfaces.Truthy; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 52bec1eb7..2e3a6a5c6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -25,12 +25,12 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.*; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.LKQLNode; -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.interfaces.Nullish; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; import com.oracle.truffle.api.nodes.UnexpectedResultException; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java index b2e92d386..7341fca81 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/FunCall.java @@ -28,11 +28,11 @@ import com.adacore.lkql_jit.built_ins.values.LKQLProperty; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.Arg; import com.adacore.lkql_jit.nodes.arguments.ArgList; -import com.adacore.lkql_jit.runtime.values.interfaces.Nullish; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.functions.ArrayUtils; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java index 7d3da31b0..50e8c642e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Indexing.java @@ -27,9 +27,9 @@ import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLTuple; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.runtime.values.interfaces.Indexable; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index 68bcf69c0..be16770c1 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -28,13 +28,13 @@ import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; import com.adacore.lkql_jit.nodes.patterns.chained_patterns.ChainedNodePattern; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; -import com.adacore.lkql_jit.runtime.values.interfaces.LKQLValue; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -333,7 +333,7 @@ public ChildIterable(Libadalang.AdaNode root, boolean followGenerics) { // ----- Override methods ----- /** - * @see com.adacore.lkql_jit.runtime.values.interfaces.Iterable#iterator() + * @see Iterable#iterator() */ @Override public Iterator iterator() { diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssoc.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssoc.java index ce46ac259..cddd0bafa 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssoc.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssoc.java @@ -22,10 +22,10 @@ package com.adacore.lkql_jit.nodes.expressions.list_comprehension; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.nodes.expressions.Expr; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssocList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssocList.java index eafae3b74..2629620ab 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssocList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ComprehensionAssocList.java @@ -22,9 +22,9 @@ package com.adacore.lkql_jit.nodes.expressions.list_comprehension; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java index 1e50925a5..f64c29e3a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java @@ -23,12 +23,12 @@ package com.adacore.lkql_jit.nodes.expressions.list_comprehension; import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLListComprehension; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.root_nodes.ListComprehensionRootNode; import com.adacore.lkql_jit.runtime.Closure; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.ClosureDescriptor; import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.source_location.SourceLocation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java index 9d5bf5e5e..b4092cfbd 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java @@ -22,8 +22,8 @@ package com.adacore.lkql_jit.nodes.expressions.operators; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.runtime.values.interfaces.Iterable; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/UnNot.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/UnNot.java index f675211be..2ae48c20a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/UnNot.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/UnNot.java @@ -22,8 +22,8 @@ package com.adacore.lkql_jit.nodes.expressions.operators; +import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.adacore.lkql_jit.exception.LKQLRuntimeException; -import com.adacore.lkql_jit.runtime.values.interfaces.Truthy; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; From 44186084e1e8e2696bd59b6a019ce175fb80d5fa Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 14 Nov 2023 15:34:32 +0100 Subject: [PATCH 20/23] Split list and lazy list types Disable all computing of lazy lists --- .../com/adacore/lkql_jit/LKQLTypeSystem.java | 2 + .../built_ins/functions/ConcatFunction.java | 5 +- .../built_ins/functions/MapFunction.java | 4 +- .../functions/SpecifiedUnitsFunction.java | 4 +- .../built_ins/functions/UniqueFunction.java | 4 +- .../built_ins/functions/UnitsFunction.java | 4 +- .../methods/AnalysisUnitMethods.java | 4 +- .../built_ins/methods/IterableMethods.java | 4 +- .../built_ins/methods/ListMethods.java | 3 +- .../built_ins/methods/NodeMethods.java | 6 +- .../built_ins/methods/StrMethods.java | 4 +- .../built_ins/values/LKQLNamespace.java | 4 +- .../lkql_jit/built_ins/values/LKQLObject.java | 4 +- .../built_ins/values/LKQLPattern.java | 7 +- .../lkql_jit/built_ins/values/LKQLTuple.java | 4 +- .../values/interfaces/Indexable.java | 2 +- .../built_ins/values/interfaces/Iterable.java | 8 - .../LKQLLazyListIterator.java} | 56 ++-- .../values/iterators/LKQLListIterator.java | 2 +- .../built_ins/values/lists/BaseLKQLList.java | 257 ++++++++++++++++++ .../built_ins/values/lists/LKQLLazyList.java | 26 +- .../built_ins/values/lists/LKQLList.java | 230 ++-------------- .../values/lists/LKQLListComprehension.java | 2 +- .../values/lists/LKQLSelectorList.java | 2 +- .../lkql_jit/nodes/expressions/Expr.java | 12 + .../lkql_jit/nodes/expressions/Query.java | 8 +- .../list_comprehension/ListComprehension.java | 6 +- .../expressions/literals/ListLiteral.java | 3 +- .../expressions/operators/BinConcat.java | 7 +- .../nodes/expressions/operators/BinEq.java | 7 + .../nodes/expressions/operators/BinNeq.java | 7 + .../nodes/expressions/operators/InClause.java | 8 +- .../lkql_jit/nodes/patterns/SelectorCall.java | 5 +- .../lkql_jit/utils/LKQLTypesHelper.java | 6 +- 34 files changed, 403 insertions(+), 314 deletions(-) rename lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/{lists/LKQLArrayList.java => iterators/LKQLLazyListIterator.java} (59%) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java index 1773c8b69..5af1aa15c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/LKQLTypeSystem.java @@ -26,6 +26,7 @@ import com.adacore.lkql_jit.built_ins.values.*; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.interfaces.*; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.ImplicitCast; @@ -50,6 +51,7 @@ LKQLProperty.class, LKQLTuple.class, LKQLList.class, + LKQLLazyList.class, Indexable.class, Iterable.class, Libadalang.AdaNode.class, 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 index c26d35f1c..d7da7cc5b 100644 --- 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 @@ -24,7 +24,6 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; @@ -112,7 +111,7 @@ public static BuiltInFunctionValue getValue() { result, LKQLTypeSystemGen.asLKQLList(item).getContent()); } - return new LKQLArrayList(result); + return new LKQLList(result); } // Else there is an error @@ -125,7 +124,7 @@ public static BuiltInFunctionValue getValue() { // If the list is empty just return an empty list else { - return new LKQLArrayList(new Object[0]); + return new LKQLList(new Object[0]); } }); } 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 index 475179e1f..a2e06ca39 100644 --- 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 @@ -27,7 +27,7 @@ import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLFunction; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.Iterator; @@ -125,7 +125,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the result - return new LKQLArrayList(res); + return new LKQLList(res); } } } 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 index 2565a08ed..9c40d9907 100644 --- 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 @@ -24,7 +24,7 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; import com.oracle.truffle.api.frame.VirtualFrame; @@ -48,7 +48,7 @@ public static BuiltInFunctionValue getValue() { new String[] {}, new Expr[] {}, (VirtualFrame frame, FunCall call) -> { - return new LKQLArrayList(LKQLLanguage.getContext(call).getSpecifiedUnits()); + return 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 index 828e7393b..99fd92ad9 100644 --- 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 @@ -25,7 +25,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; @@ -70,7 +70,7 @@ public static BuiltInFunctionValue getValue() { Indexable indexable = LKQLTypeSystemGen.asIndexable(indexableObject); // Return the result list - return new LKQLArrayList( + return new LKQLList( ArrayUtils.unique(indexable.getContent()).toArray(new Object[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 index 771ee1aca..553568f15 100644 --- 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 @@ -24,7 +24,7 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.expressions.FunCall; import com.oracle.truffle.api.frame.VirtualFrame; @@ -48,6 +48,6 @@ public static BuiltInFunctionValue getValue() { new String[] {}, new Expr[] {}, (VirtualFrame frame, FunCall call) -> - new LKQLArrayList(LKQLLanguage.getContext(call).getAllUnits())); + 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 1cbfb3a92..0543b0c09 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 @@ -27,7 +27,7 @@ import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLNull; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.LKQLTypesHelper; import com.oracle.truffle.api.frame.VirtualFrame; @@ -148,7 +148,7 @@ public Object executeGeneric(VirtualFrame frame) { resList.add(current); current = current.next(); } - return new LKQLArrayList(resList.toArray(new Libadalang.Token[0])); + return new LKQLList(resList.toArray(new Libadalang.Token[0])); } } 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 4bbac4a00..177bdedeb 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 @@ -27,7 +27,7 @@ import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.ReduceFunction; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.Iterator; import com.oracle.truffle.api.frame.VirtualFrame; @@ -84,7 +84,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the new list value - return new LKQLArrayList(resList.toArray(new Object[0])); + return new LKQLList(resList.toArray(new Object[0])); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java index 516680dbb..c6eec3661 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/ListMethods.java @@ -25,7 +25,6 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.BuiltInFunctionValue; import com.adacore.lkql_jit.built_ins.functions.UniqueFunction; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; @@ -113,7 +112,7 @@ protected void initMethods() { throw LKQLRuntimeException.invalidIndex((int) highBound, call); } - return new LKQLArrayList( + return new LKQLList( Arrays.copyOfRange( list.getContent(), (int) lowBound - 1, diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java index 200ba7e47..1ccc87556 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/NodeMethods.java @@ -29,7 +29,7 @@ import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLUnit; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -187,7 +187,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the list value - return new LKQLArrayList(res); + return new LKQLList(res); } } @@ -269,7 +269,7 @@ public Object executeGeneric(VirtualFrame frame) { } // Return the result - return new LKQLArrayList(resList.toArray(new Libadalang.Token[0])); + return new LKQLList(resList.toArray(new Libadalang.Token[0])); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java index a334fccf6..951db28d4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/methods/StrMethods.java @@ -27,7 +27,7 @@ import com.adacore.lkql_jit.built_ins.BuiltinFunctionBody; import com.adacore.lkql_jit.built_ins.functions.BaseNameFunction; import com.adacore.lkql_jit.built_ins.values.LKQLPattern; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -340,7 +340,7 @@ public Object executeGeneric(VirtualFrame frame) { LKQLTypeSystemGen.asString(separatorObject)); // Return the list value of the split string - return new LKQLArrayList(separated); + return new LKQLList(separated); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index 5c01347bc..0afc7d2cf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -24,7 +24,7 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.Cell; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; @@ -205,7 +205,7 @@ boolean isMemberReadable( Object getMembers( @SuppressWarnings("unused") final boolean includeInternal, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new LKQLArrayList(objectLibrary.getKeyArray(this)); + return new LKQLList(objectLibrary.getKeyArray(this)); } /** Get the value of the wanted member in the receiver namespace. */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index c84571c78..695e67f97 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -24,7 +24,7 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; @@ -191,7 +191,7 @@ boolean isMemberReadable( Object getMembers( @SuppressWarnings("unused") final boolean includeInternal, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new LKQLArrayList(objectLibrary.getKeyArray(this)); + return new LKQLList(objectLibrary.getKeyArray(this)); } /** Get the value of the wanted member in the receiver object. */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index beb3a0778..8b91dbb94 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -25,9 +25,10 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; @@ -50,7 +51,7 @@ public final class LKQLPattern implements TruffleObject, LKQLValue { // ----- Attributes ----- /** Members of the pattern LKQL value. */ - private final LKQLArrayList MEMBERS = new LKQLArrayList(new String[] {"contains", "find"}); + private final LKQLList MEMBERS = new LKQLList(new String[] {"contains", "find"}); /** The interop regex object from the TRegex language. */ private final Object regexObject; @@ -182,7 +183,7 @@ Object getMembers(@SuppressWarnings("unused") final boolean includeInternal) { /** Tell the interop library whether the given member is invokable. */ @ExportMessage boolean isMemberInvocable(String member) { - return MEMBERS.contains(member); + return ObjectUtils.equals(member, "contains") || ObjectUtils.equals(member, "find"); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java index 281513e8b..498e26ec7 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -160,9 +160,9 @@ public Object readArrayElement(final long index) throws InvalidArrayIndexExcepti // ----- Indexable methods ----- @Override - public Object get(int index) throws InvalidIndexException { + public Object get(long index) throws InvalidIndexException { try { - return this.content[index]; + return this.content[(int) index]; } catch (IndexOutOfBoundsException e) { throw new InvalidIndexException(); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java index 812a3cbfd..789785cb4 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java @@ -38,7 +38,7 @@ public interface Indexable extends LKQLValue { * @return The element at the position. * @throws com.adacore.lkql_jit.exception.utils.InvalidIndexException If the index is not valid. */ - Object get(int index) throws InvalidIndexException; + Object get(long index) throws InvalidIndexException; /** * Get the content of the indexable value in an array. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java index 1b517a7a4..fea18036d 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java @@ -38,14 +38,6 @@ public interface Iterable extends LKQLValue { */ long size(); - /** - * Get if the iterable contains the given element. - * - * @param elem The element to look for. - * @return True if the iterable contains the element, false else. - */ - boolean contains(Object elem); - /** * Get the iterator for the iterable object. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLLazyListIterator.java similarity index 59% rename from lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java rename to lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLLazyListIterator.java index b5e4e3af0..e424fc99e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLArrayList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLLazyListIterator.java @@ -20,57 +20,49 @@ -- -- ----------------------------------------------------------------------------*/ -package com.adacore.lkql_jit.built_ins.values.lists; +package com.adacore.lkql_jit.built_ins.values.iterators; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.library.ExportLibrary; -import com.oracle.truffle.api.library.ExportMessage; -/** This class represents an array list in the LKQL language. */ -@ExportLibrary(InteropLibrary.class) -public final class LKQLArrayList extends LKQLList { +/** This class represents an iterator for an LKQL lazy list. */ +public class LKQLLazyListIterator extends LKQLIterator { // ----- Attributes ----- - /** The content of the array list. */ - private final Object[] content; + /** The lazy list to iterate on. */ + private final LKQLLazyList lazyList; + + /** The cursor for the iteration. */ + private long cursor; // ----- Constructors ----- - /** Create a new array list with its content. */ - public LKQLArrayList(final Object[] content) { - this.content = content; + /** Create a new lazy list iterator for the given lazy list. */ + public LKQLLazyListIterator(LKQLLazyList lazyList) { + this.lazyList = lazyList; + this.cursor = 0; } - // ----- List required methods ----- - - @Override - public long size() { - return this.content.length; - } + // ----- Iterator required methods ----- @Override - public Object get(int i) throws InvalidIndexException { + public boolean hasNext() { try { - return this.content[i]; - } catch (IndexOutOfBoundsException e) { - throw new InvalidIndexException(); + this.lazyList.get(cursor); + return true; + } catch (InvalidIndexException e) { + return false; } } @Override - public Object[] asArray() { - return this.content; + public Object next() { + return this.lazyList.get(this.cursor++); } - // ----- Value methods ----- - - /** Return the identity hash code for the given LKQL array list. */ - @CompilerDirectives.TruffleBoundary - @ExportMessage - public static int identityHashCode(LKQLArrayList receiver) { - return System.identityHashCode(receiver); + @Override + public void reset() { + this.cursor = 0; } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java index bcb8e1bdf..d6696a8d2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/iterators/LKQLListIterator.java @@ -37,7 +37,7 @@ public final class LKQLListIterator extends LKQLIterator { // ----- Constructors ----- - /** Create a new list iterator with the iterated list. */ + /** Create a new list iterator for the given list. */ public LKQLListIterator(final LKQLList list) { this.list = list; this.cursor = 0; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java new file mode 100644 index 000000000..bff0ca041 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java @@ -0,0 +1,257 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.lists; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; +import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; +import com.adacore.lkql_jit.built_ins.values.iterators.LKQLIterator; +import com.adacore.lkql_jit.exception.utils.InvalidIndexException; +import com.adacore.lkql_jit.utils.Constants; +import com.adacore.lkql_jit.utils.functions.StringUtils; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.TruffleLanguage; +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.interop.TruffleObject; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.utilities.TriState; +import java.util.Objects; + +/** This abstract class represents all list like values in the LKQL language. */ +@ExportLibrary(InteropLibrary.class) +public abstract class BaseLKQLList implements TruffleObject, Iterable, Indexable, Truthy { + + // ----- Constructors ----- + + protected BaseLKQLList() {} + + // ----- Basic list methods to fulfill ----- + + /** Get the size of the list as a long value. */ + public abstract long size(); + + /** + * Get the element at the given position in the list. + * + * @throws InvalidIndexException If the provided index is not in the list bounds. + */ + public abstract Object get(long i) throws InvalidIndexException; + + /** Get the iterator for the list. */ + public abstract LKQLIterator iterator(); + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + public boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + public Class> getLanguage() { + return LKQLLanguage.class; + } + + /** Exported message to compare two lists. */ + @ExportMessage + public static class IsIdenticalOrUndefined { + /** Compare two LKQL lists. */ + @Specialization + public static TriState onList(final BaseLKQLList left, final BaseLKQLList right) { + if (left.internalEquals(right)) return TriState.TRUE; + else return TriState.FALSE; + } + + /** Do the comparison with another element. */ + @Fallback + public static TriState onOther( + @SuppressWarnings("unused") final BaseLKQLList receiver, + @SuppressWarnings("unused") final Object other) { + return TriState.UNDEFINED; + } + } + + /** Return the identity hash code for the given LKQL list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(BaseLKQLList receiver) { + return System.identityHashCode(receiver); + } + + /** Get the displayable string for the interop library. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public Object toDisplayString( + @SuppressWarnings("unused") final boolean allowSideEffect, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary elems) { + // Prepare the result + StringBuilder resultBuilder = new StringBuilder("["); + + // Iterate over the list values + for (int i = 0; i < this.size(); i++) { + Object elem = this.get(i); + + // Get the element string + String elemString; + if (elem instanceof String) { + elemString = StringUtils.toRepr((String) elems.toDisplayString(elem)); + } else { + elemString = (String) elems.toDisplayString(elem); + } + + // Add the element string to the result + resultBuilder.append(elemString); + if (i < this.size() - 1) resultBuilder.append(", "); + } + + // Return the result + resultBuilder.append("]"); + return resultBuilder.toString(); + } + + /** Tell the interop API that the list can be cast to a boolean. */ + @ExportMessage + public boolean isBoolean() { + return true; + } + + /** Get the boolean representation of the list. */ + @ExportMessage + public boolean asBoolean() { + return this.isTruthy(); + } + + /** Tell the interop library that the value is array like. */ + @ExportMessage + public boolean hasArrayElements() { + return true; + } + + /** Get the array size for the interop library. */ + @ExportMessage + public long getArraySize() { + return this.size(); + } + + /** Tell the interop library if the wanted index is readable. */ + @ExportMessage + public boolean isArrayElementReadable(long index) { + try { + this.get((int) index); + return true; + } catch (InvalidIndexException e) { + return false; + } + } + + /** Get the array element of the given index. */ + @ExportMessage + public Object readArrayElement(long index) { + return this.get(index); + } + + /** Tell the interop library that the list has an iterator object. */ + @ExportMessage + public boolean hasIterator() { + return true; + } + + /** Get the iterator for the list. */ + @ExportMessage + public Object getIterator() { + return this.iterator(); + } + + // ----- Indexable required methods ----- + + @Override + public Object[] getContent() { + Object[] res = new Object[(int) this.size()]; + for (int i = 0; i < this.size(); i++) { + res[i] = this.get(i); + } + return res; + } + + // ----- Truthy required values ----- + + @Override + public boolean isTruthy() { + try { + this.get(0); + return true; + } catch (InvalidIndexException e) { + return false; + } + } + + // ----- LKQL value required methods ----- + + @Override + @CompilerDirectives.TruffleBoundary + public boolean internalEquals(LKQLValue o) { + if (this == o) return true; + if (!(o instanceof BaseLKQLList other)) return false; + + // Compare the list size + if (this.size() != other.size()) return false; + + // Then compare each element of the lists + for (long i = 0; i < this.size(); i++) { + Object thisElem = this.get(i); + Object otherElem = other.get(i); + if ((thisElem instanceof LKQLValue thisValue) + && (otherElem instanceof LKQLValue otherValue)) { + if (!thisValue.internalEquals(otherValue)) return false; + } else { + if (!Objects.equals(thisElem, otherElem)) return false; + } + } + + // If we get here, lists are equals + return true; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary listLibrary = InteropLibrary.getUncached(this); + return (String) listLibrary.toDisplayString(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BaseLKQLList other)) return false; + return this.internalEquals(other); + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java index b68770dd6..a0fe64c59 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLLazyList.java @@ -22,6 +22,8 @@ package com.adacore.lkql_jit.built_ins.values.lists; +import com.adacore.lkql_jit.built_ins.values.iterators.LKQLIterator; +import com.adacore.lkql_jit.built_ins.values.iterators.LKQLLazyListIterator; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.interop.InteropLibrary; @@ -32,7 +34,7 @@ /** This class represents the base of all LKQL lazy lists. */ @ExportLibrary(InteropLibrary.class) -public abstract class LKQLLazyList extends LKQLList { +public abstract class LKQLLazyList extends BaseLKQLList { // ----- Attributes ----- @@ -51,7 +53,7 @@ protected LKQLLazyList() { * Initialize the lazy list cache to the given index. If n < 0 then initialize all the lazy list * values. */ - public abstract void initCache(int n); + public abstract void initCache(long n); // ----- List required methods ----- @@ -62,22 +64,18 @@ public long size() { } @Override - public Object get(int i) throws InvalidIndexException { - if (i >= 0) { - this.initCache(i); - try { - return this.cache.get(i); - } catch (IndexOutOfBoundsException e) { - throw new InvalidIndexException(); - } + public Object get(long i) throws InvalidIndexException { + this.initCache(i); + try { + return this.cache.get((int) i); + } catch (IndexOutOfBoundsException e) { + throw new InvalidIndexException(); } - throw new InvalidIndexException(); } @Override - public Object[] asArray() { - this.initCache(-1); - return this.cache.toArray(new Object[0]); + public LKQLIterator iterator() { + return new LKQLLazyListIterator(this); } // ----- Value methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java index 68a37cbc1..880bca395 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLList.java @@ -22,238 +22,62 @@ package com.adacore.lkql_jit.built_ins.values.lists; -import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; -import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; +import com.adacore.lkql_jit.built_ins.values.iterators.LKQLIterator; import com.adacore.lkql_jit.built_ins.values.iterators.LKQLListIterator; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; -import com.adacore.lkql_jit.utils.Constants; -import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; -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.interop.TruffleObject; -import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.utilities.TriState; -import java.util.Objects; -/** This abstract class represents all list like values in the LKQL language. */ +/** This class represents an array list in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public abstract class LKQLList implements TruffleObject, Iterable, Indexable, Truthy { +public final class LKQLList extends BaseLKQLList { - // ----- Constructors ----- - - /** The protected constructor. */ - protected LKQLList() {} - - // ----- List required methods ----- - - /** Get the size of the list. */ - public abstract long size(); - - /** - * Get the list element at the given index. - * - * @throws InvalidIndexException If the given index is invalid. - */ - public abstract Object get(int i) throws InvalidIndexException; - - /** Get the list as a pure Java array. */ - public abstract Object[] asArray(); - - /** Get a new iterator on the list. */ - public LKQLListIterator iterator() { - return new LKQLListIterator(this); - } - - // ----- Value methods ----- - - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - public boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - public Class> getLanguage() { - return LKQLLanguage.class; - } - - /** Exported message to compare two lists. */ - @ExportMessage - public static class IsIdenticalOrUndefined { - /** Compare two LKQL lists. */ - @Specialization - public static TriState onList(final LKQLList left, final LKQLList right) { - if (left.internalEquals(right)) return TriState.TRUE; - else return TriState.FALSE; - } - - /** Do the comparison with another element. */ - @Fallback - public static TriState onOther( - @SuppressWarnings("unused") final LKQLList receiver, - @SuppressWarnings("unused") final Object other) { - return TriState.UNDEFINED; - } - } - - /** Return the identity hash code for the given LKQL list. */ - @CompilerDirectives.TruffleBoundary - @ExportMessage - public static int identityHashCode(LKQLList receiver) { - return System.identityHashCode(receiver); - } + // ----- Attributes ----- - /** Get the displayable string for the interop library. */ - @CompilerDirectives.TruffleBoundary - @ExportMessage - public Object toDisplayString( - @SuppressWarnings("unused") final boolean allowSideEffect, - @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { - // Prepare the result - StringBuilder resultBuilder = new StringBuilder("["); - - // Iterate over the list values - for (int i = 0; i < this.size(); i++) { - Object elem = this.get(i); - - // Get the element string - String elemString; - if (elem instanceof String) { - elemString = StringUtils.toRepr((String) interopLibrary.toDisplayString(elem)); - } else { - elemString = (String) interopLibrary.toDisplayString(elem); - } - - // Add the element string to the result - resultBuilder.append(elemString); - if (i < this.size() - 1) resultBuilder.append(", "); - } - - // Return the result - resultBuilder.append("]"); - return resultBuilder.toString(); - } + /** The content of the array list. */ + public final Object[] content; - /** Tell the interop API that the list can be cast to a boolean. */ - @ExportMessage - public boolean isBoolean() { - return true; - } - - /** Get the boolean representation of the list. */ - @ExportMessage - public boolean asBoolean() { - return this.isTruthy(); - } - - /** Tell the interop library that the value is array like. */ - @ExportMessage - public boolean hasArrayElements() { - return true; - } - - /** Get the array size for the interop library. */ - @ExportMessage - public long getArraySize() { - return this.size(); - } - - /** Tell the interop library if the wanted index is readable. */ - @ExportMessage - public boolean isArrayElementReadable(long index) { - try { - this.get((int) index); - return true; - } catch (InvalidIndexException e) { - return false; - } - } - - /** Get the array element of the given index. */ - @ExportMessage - public Object readArrayElement(long index) { - return this.get((int) index); - } - - /** Tell the interop library that the list has an iterator object. */ - @ExportMessage - public boolean hasIterator() { - return true; - } + // ----- Constructors ----- - /** Get the iterator for the list. */ - @ExportMessage - public Object getIterator() { - return this.iterator(); + /** Create a new array list with its content. */ + public LKQLList(final Object[] content) { + this.content = content; } - // ---- LKQL value methods ----- + // ----- List required methods ----- @Override - @CompilerDirectives.TruffleBoundary - public boolean internalEquals(final LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LKQLList other)) return false; - if (this.size() != other.size()) return false; - for (int i = 0; i < this.size(); i++) { - Object mineObject = this.get(i); - Object hisObject = other.get(i); - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; + public long size() { + return this.content.length; } @Override - public boolean isTruthy() { + public Object get(long i) throws InvalidIndexException { try { - this.get(0); - return true; - } catch (InvalidIndexException e) { - return false; + return this.content[(int) i]; + } catch (IndexOutOfBoundsException e) { + throw new InvalidIndexException(); } } @Override - public Object[] getContent() { - return this.asArray(); + public LKQLIterator iterator() { + return new LKQLListIterator(this); } @Override - @CompilerDirectives.TruffleBoundary - public boolean contains(Object elem) { - final LKQLListIterator iterator = this.iterator(); - while (iterator.hasNext()) { - Object val = iterator.next(); - if (elem.equals(val)) return true; - } - return false; + public Object[] getContent() { + return this.content; } - // ----- Override methods ----- - - @Override - public String toString() { - InteropLibrary listLibrary = InteropLibrary.getUncached(this); - return (String) listLibrary.toDisplayString(this); - } + // ----- Value methods ----- - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof LKQLList other)) return false; - return this.internalEquals(other); + /** Return the identity hash code for the given LKQL array list. */ + @CompilerDirectives.TruffleBoundary + @ExportMessage + public static int identityHashCode(LKQLList receiver) { + return System.identityHashCode(receiver); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java index da0589b47..55d41f86e 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLListComprehension.java @@ -80,7 +80,7 @@ public LKQLListComprehension( // ----- Lazy list required methods ----- @Override - public void initCache(int n) { + public void initCache(long n) { while (this.pointer < this.argumentsList.length && (this.cache.size() - 1 < n || n < 0)) { final Object[] currentArguments = this.argumentsList[this.pointer++]; System.arraycopy(currentArguments, 0, this.arguments, 1, currentArguments.length); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java index 4e5dfdaea..8cf4df625 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/LKQLSelectorList.java @@ -101,7 +101,7 @@ public LKQLSelectorList( // ----- Lazy list required methods ----- @Override - public void initCache(int n) { + public void initCache(long n) { while (!(this.recursList.size() == 0) && (this.cache.size() - 1 < n || n == -1)) { // Get the first recurse item and execute the selector on it LKQLDepthNode nextNode = this.recursList.remove(0); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java index 2e3a6a5c6..5db3973b2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Expr.java @@ -29,6 +29,7 @@ import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -177,6 +178,17 @@ public LKQLList executeList(VirtualFrame frame) throws UnexpectedResultException return LKQLTypeSystemGen.expectLKQLList(executeGeneric(frame)); } + /** + * Execute the expression as a lazy list value. + * + * @param frame The frame for execution. + * @return The result of the node execution as a lazy list value. + * @throws UnexpectedResultException If the node cannot be evaluated as a lazy list. + */ + public LKQLLazyList executeLazyList(VirtualFrame frame) throws UnexpectedResultException { + return LKQLTypeSystemGen.expectLKQLLazyList(executeGeneric(frame)); + } + /** * Execute the expression as an indexable value. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index be16770c1..ba3197d12 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -30,7 +30,6 @@ import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; @@ -175,7 +174,7 @@ else if (LKQLTypeSystemGen.isLKQLList(fromObject)) { } // Return the result list value - return new LKQLArrayList(resNodes.toArray(new Libadalang.AdaNode[0])); + return new LKQLList(resNodes.toArray(new Libadalang.AdaNode[0])); } // If the query mode is first @@ -347,11 +346,6 @@ public long size() { return -1; } - @Override - public boolean contains(Object elem) { - return false; - } - @Override public boolean internalEquals(LKQLValue o) { return false; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java index f64c29e3a..5565c60b9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/list_comprehension/ListComprehension.java @@ -24,7 +24,7 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLListComprehension; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.root_nodes.ListComprehensionRootNode; @@ -113,14 +113,14 @@ public ListComprehension( */ @Override public Object executeGeneric(VirtualFrame frame) { - return this.executeList(frame); + return this.executeLazyList(frame); } /** * @see Expr#executeList(VirtualFrame) */ @Override - public LKQLList executeList(VirtualFrame frame) { + public LKQLLazyList executeLazyList(VirtualFrame frame) { // Get the iterables for the list comprehension Iterable[] iterables = this.generators.executeCollections(frame); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java index 7e35dbdff..eae813422 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/literals/ListLiteral.java @@ -22,7 +22,6 @@ package com.adacore.lkql_jit.nodes.expressions.literals; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.utils.source_location.SourceLocation; @@ -79,7 +78,7 @@ public LKQLList executeList(VirtualFrame frame) { } // Return the list value - return new LKQLArrayList(values); + return new LKQLList(values); } // ----- Override methods ----- diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java index 90e9db916..42b7225f8 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinConcat.java @@ -23,7 +23,6 @@ package com.adacore.lkql_jit.nodes.expressions.operators; import com.adacore.lkql_jit.LKQLTypeSystemGen; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.utils.Constants; @@ -89,9 +88,9 @@ protected LKQLList concatLists( try { final int leftSize = (int) leftLibrary.getArraySize(left); final int rightSize = (int) rightLibrary.getArraySize(right); - final Object[] resContent = Arrays.copyOf(left.asArray(), leftSize + rightSize); - System.arraycopy(right.asArray(), 0, resContent, leftSize, rightSize); - return new LKQLArrayList(resContent); + final Object[] resContent = Arrays.copyOf(left.content, leftSize + rightSize); + System.arraycopy(right.content, 0, resContent, leftSize, rightSize); + return new LKQLList(resContent); } catch (UnsupportedMessageException e) { throw LKQLRuntimeException.fromJavaException(e, this); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java index e4fe86150..9e9eb2035 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinEq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -204,6 +205,12 @@ protected boolean eqLists( return leftLibrary.isIdentical(left, right, rightLibrary); } + /** Do the equality verification in lazy lists. */ + @Specialization + protected boolean onLazyLists(final LKQLLazyList left, final LKQLLazyList right) { + return left == right; + } + /** * Do the equality verification on nodes. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java index dd1624529..1fe2328ff 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/BinNeq.java @@ -24,6 +24,7 @@ import com.adacore.libadalang.Libadalang; import com.adacore.lkql_jit.built_ins.values.*; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLLazyList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.BigIntegerUtils; @@ -204,6 +205,12 @@ protected boolean neqLists( return !leftLibrary.isIdentical(left, right, rightLibrary); } + /** Do the non-equality verification on lazy lists. */ + @Specialization + protected boolean neqLazyLists(final LKQLLazyList left, final LKQLLazyList right) { + return left != right; + } + /** * Do the non-equality verification on nodes. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java index b4092cfbd..abd36a0e9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/operators/InClause.java @@ -24,7 +24,9 @@ import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; import com.adacore.lkql_jit.exception.LKQLRuntimeException; +import com.adacore.lkql_jit.utils.Iterator; import com.adacore.lkql_jit.utils.LKQLTypesHelper; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.source_location.DummyLocation; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.dsl.Fallback; @@ -62,7 +64,11 @@ protected InClause( */ @Specialization protected boolean inIterable(Object elem, Iterable iterable) { - return iterable.contains(elem); + Iterator iterator = iterable.iterator(); + while (iterator.hasNext()) { + if (ObjectUtils.equals(elem, iterator.next())) return true; + } + return false; } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java index 540f0d6af..5e64eabea 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/SelectorCall.java @@ -26,7 +26,6 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLDepthNode; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; @@ -160,7 +159,7 @@ public LKQLList executeFiltering( if (this.isAll(frame, selectorListValue, pattern)) { res = this.getFilteredList(frame, selectorListValue, pattern); } else { - res = new LKQLArrayList(new Libadalang.AdaNode[0]); + res = new LKQLList(new Libadalang.AdaNode[0]); } } @@ -316,7 +315,7 @@ private LKQLList getFilteredList( } // Return the result - return new LKQLArrayList(resList.toArray(new Libadalang.AdaNode[0])); + return new LKQLList(resList.toArray(new Libadalang.AdaNode[0])); } /** diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java index 2c79cc9dc..4064b903c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/LKQLTypesHelper.java @@ -26,7 +26,7 @@ import com.adacore.lkql_jit.LKQLTypeSystemGen; import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLObject; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLArrayList; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.utils.UnsupportedTypeException; import com.oracle.truffle.api.CompilerDirectives; import java.math.BigInteger; @@ -148,6 +148,8 @@ public static String fromJava(Object obj, String defaultValue) { return LKQL_TUPLE; } else if (LKQLTypeSystemGen.isLKQLList(obj)) { return LKQL_LIST; + } else if (LKQLTypeSystemGen.isLKQLLazyList(obj)) { + return LKQL_LAZY_LIST; } else if (LKQLTypeSystemGen.isAdaNode(obj)) { return ADA_NODE; } else if (LKQLTypeSystemGen.isToken(obj)) { @@ -261,7 +263,7 @@ else if (javaValue instanceof Libadalang.ArrayBase array) { res[i] = toLKQLValue(obj); i++; } - return new LKQLArrayList(res); + return new LKQLList(res); } // If the source is an enum From 3f72f365b4c1e41ed44ee1a38314e077c3918d5c Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 21 Nov 2023 15:26:49 +0100 Subject: [PATCH 21/23] Make 'LKQLValue' interface subclass of 'TruffleObject', as all LKQL values are interop values Remove relation between other interfaces and 'LKQLValue' to allow more flexible composing. --- .../built_ins/functions/DocFunction.java | 2 +- .../built_ins/functions/HelpFunction.java | 4 +-- .../built_ins/functions/ProfileFunction.java | 2 +- .../built_ins/values/LKQLDepthNode.java | 21 ++---------- .../built_ins/values/LKQLFunction.java | 7 ++-- .../built_ins/values/LKQLNamespace.java | 8 ++--- .../lkql_jit/built_ins/values/LKQLNull.java | 5 ++- .../lkql_jit/built_ins/values/LKQLObject.java | 11 +++---- .../built_ins/values/LKQLPattern.java | 6 ++-- .../built_ins/values/LKQLProperty.java | 6 ++-- .../built_ins/values/LKQLSelector.java | 6 ++-- .../lkql_jit/built_ins/values/LKQLTuple.java | 11 +++---- .../lkql_jit/built_ins/values/LKQLUnit.java | 5 ++- .../values/interfaces/Indexable.java | 2 +- .../built_ins/values/interfaces/Iterable.java | 2 +- .../values/interfaces/LKQLValue.java | 32 ++++++------------- .../built_ins/values/interfaces/Nullish.java | 2 +- .../built_ins/values/interfaces/Truthy.java | 2 +- .../built_ins/values/lists/BaseLKQLList.java | 11 +++---- .../lkql_jit/nodes/expressions/Query.java | 6 ---- .../patterns/node_patterns/DetailExpr.java | 2 +- 21 files changed, 57 insertions(+), 96 deletions(-) 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 index 80a77fdd9..0b72ebcf2 100644 --- 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 @@ -55,7 +55,7 @@ public static BuiltInFunctionValue getValue() { // If the argument is an LKQL value, read the documentation from ir if (LKQLTypeSystemGen.isLKQLValue(arg)) { - return ((LKQLValue) arg).getDocumentation(); + return ((LKQLValue) arg).lkqlDocumentation(); } // Return the default empty documentation 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 index 0fbfe8d73..d43fb9a2c 100644 --- 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 @@ -62,9 +62,9 @@ public static BuiltInFunctionValue getValue() { LKQLLanguage.getContext(call) .println( StringUtils.concat( - value.getProfile(), + value.lkqlProfile(), "\n", - value.getDocumentation())); + value.lkqlDocumentation())); } // Return the default empty documentation 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 index d83237ddc..845beb945 100644 --- 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 @@ -55,7 +55,7 @@ public static BuiltInFunctionValue getValue() { // If the argument is an LKQL value, read the documentation from ir if (LKQLTypeSystemGen.isLKQLValue(arg)) { - return ((LKQLValue) arg).getProfile(); + return ((LKQLValue) arg).lkqlProfile(); } // Return the default empty documentation diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java index 37cb9d546..38b086403 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java @@ -23,14 +23,11 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; 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.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; @@ -40,7 +37,7 @@ * all Libadalang objects will be wrapped in interop LKQL values (#154). */ @ExportLibrary(InteropLibrary.class) -public final class LKQLDepthNode implements TruffleObject, LKQLValue { +public final class LKQLDepthNode implements LKQLValue { // ----- Attributes ----- @@ -70,25 +67,13 @@ public Libadalang.AdaNode getNode() { // ----- Value methods ----- - /** Tell the interop library that the depth node has an associated language */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL depth nodes. */ @ExportMessage static class IsIdenticalOrUndefined { /** Compare two LKQL depth nodes. */ @Specialization protected static TriState onNode(final LKQLDepthNode left, final LKQLDepthNode right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -117,7 +102,7 @@ Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffect // ----- LKQL Value methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (o == this) return true; if (!(o instanceof LKQLDepthNode other)) return false; return other.node.equals(this.node); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java index e5bf40f0b..ad95b0515 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java @@ -34,7 +34,6 @@ 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.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.nodes.DirectCallNode; @@ -43,7 +42,7 @@ /** This class represents the function values in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLFunction implements TruffleObject, LKQLValue { +public class LKQLFunction implements LKQLValue { // ----- Attributes ----- @@ -227,14 +226,14 @@ Object getExecutableName() { // ----- LKQL values methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (this == o) return true; if (!(o instanceof LKQLFunction other)) return false; return this.rootNode == other.rootNode; } @Override - public String getDocumentation() { + public String lkqlDocumentation() { return this.documentation; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index 0afc7d2cf..52be4bb30 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -129,7 +129,7 @@ static class IsIdenticalOrUndefined { @Specialization protected static TriState onLKQLNamespace( final LKQLNamespace left, final LKQLNamespace right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -222,7 +222,7 @@ Object readMember( @Override @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (this == o) return true; if (!(o instanceof LKQLNamespace other)) return false; @@ -247,7 +247,7 @@ public boolean internalEquals(LKQLValue o) { Object otherObject = otherLib.getOrDefault(other, key, null); if ((thisObject instanceof LKQLValue thisValue) && (otherObject instanceof LKQLValue otherValue)) { - if (!thisValue.internalEquals(otherValue)) return false; + if (!thisValue.lkqlEquals(otherValue)) return false; } else { if (!Objects.equals(thisObject, otherObject)) return false; } @@ -267,7 +267,7 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLNamespace other)) return false; - return this.internalEquals(other); + return this.lkqlEquals(other); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java index b45b2e680..6702d516c 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java @@ -29,14 +29,13 @@ import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; /** This class represents the null value in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLNull extends Libadalang.AdaNode implements TruffleObject, Nullish, Truthy { +public class LKQLNull extends Libadalang.AdaNode implements LKQLValue, Nullish, Truthy { // ----- Attributes ----- @@ -126,7 +125,7 @@ boolean asBoolean() { // ----- LKQL value methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { return o == this; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index 695e67f97..4c3c3de86 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -33,7 +33,6 @@ 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.interop.TruffleObject; import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; @@ -47,7 +46,7 @@ /** This class represents an object value in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public final class LKQLObject extends DynamicObject implements TruffleObject, LKQLValue { +public final class LKQLObject extends DynamicObject implements LKQLValue { // ----- Class attributes ----- @@ -114,7 +113,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL objects. */ @Specialization protected static TriState onLKQLObject(final LKQLObject left, final LKQLObject right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -208,7 +207,7 @@ Object readMember( @Override @CompilerDirectives.TruffleBoundary - public boolean internalEquals(final LKQLValue o) { + public boolean lkqlEquals(final LKQLValue o) { if (this == o) return true; if (!(o instanceof LKQLObject other)) return false; @@ -233,7 +232,7 @@ public boolean internalEquals(final LKQLValue o) { Object otherObject = otherLib.getOrDefault(other, key, null); if ((thisObject instanceof LKQLValue thisValue) && (otherObject instanceof LKQLValue otherValue)) { - if (!thisValue.internalEquals(otherValue)) return false; + if (!thisValue.lkqlEquals(otherValue)) return false; } else { if (!Objects.equals(thisObject, otherObject)) return false; } @@ -255,7 +254,7 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLObject other)) return false; - return this.internalEquals(other); + return this.lkqlEquals(other); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index 8b91dbb94..669fac492 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -46,7 +46,7 @@ * regular expression. */ @ExportLibrary(InteropLibrary.class) -public final class LKQLPattern implements TruffleObject, LKQLValue { +public final class LKQLPattern implements LKQLValue { // ----- Attributes ----- @@ -141,7 +141,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL patterns. */ @Specialization protected static TriState onPattern(final LKQLPattern left, final LKQLPattern right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -218,7 +218,7 @@ Object invokeMember(String member, Object... args) // ----- LKQL Value methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (o == this) return true; if (!(o instanceof LKQLPattern other)) return false; return other.regexString.equals(this.regexString) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java index 746ad9dfd..d28547fa9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java @@ -41,7 +41,7 @@ /** This class represents a Libadalang property access in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLProperty implements TruffleObject, LKQLValue { +public class LKQLProperty implements LKQLValue { // ----- Attributes ----- @@ -135,7 +135,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL properties. */ @Specialization protected static TriState onProperty(final LKQLProperty left, final LKQLProperty right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -181,7 +181,7 @@ Object execute(Object[] arguments) @Override @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (this == o) return true; if (!(o instanceof LKQLProperty other)) return false; return this.description.equals(other.description); diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java index 456c15f08..7ac6fd3d8 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java @@ -39,7 +39,7 @@ /** This class represents the selector values in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLSelector implements TruffleObject, LKQLValue { +public class LKQLSelector implements LKQLValue { // ----- Attributes ----- @@ -162,14 +162,14 @@ Object execute(Object[] arguments) // ----- LKQL value methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (o == this) return true; if (!(o instanceof LKQLSelector other)) return false; return this.rootNode == other.rootNode; } @Override - public String getDocumentation() { + public String lkqlDocumentation() { return this.documentation; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java index 498e26ec7..89f318da5 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -34,7 +34,6 @@ import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.interop.InvalidArrayIndexException; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -44,7 +43,7 @@ /** This class represents a tuple in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLTuple implements TruffleObject, Indexable { +public class LKQLTuple implements LKQLValue, Indexable { // ----- Attributes ----- @@ -78,7 +77,7 @@ public static class IsIdenticalOrUndefined { /** Compare two LKQL tuples. */ @Specialization public static TriState onTuple(final LKQLTuple left, final LKQLTuple right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -177,7 +176,7 @@ public Object[] getContent() { @Override @CompilerDirectives.TruffleBoundary - public boolean internalEquals(final LKQLValue o) { + public boolean lkqlEquals(final LKQLValue o) { if (o == this) return true; if (!(o instanceof LKQLTuple other)) return false; if (other.content.length != this.content.length) return false; @@ -185,7 +184,7 @@ public boolean internalEquals(final LKQLValue o) { Object mineObject = this.content[i]; Object hisObject = other.content[i]; if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.internalEquals(his)) return false; + if (!mine.lkqlEquals(his)) return false; } else { if (!Objects.equals(mineObject, hisObject)) return false; } @@ -205,7 +204,7 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLTuple other)) return false; - return this.internalEquals(other); + return this.lkqlEquals(other); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java index 93e1bf15d..962b79251 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java @@ -28,14 +28,13 @@ import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.TruffleObject; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; /** This class represents the unit value in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public class LKQLUnit implements TruffleObject, LKQLValue, Truthy, Nullish { +public class LKQLUnit implements LKQLValue, Truthy, Nullish { // ----- Attributes ----- @@ -107,7 +106,7 @@ boolean asBoolean() { // ----- LKQL value methods ----- @Override - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { return o == this; } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java index 789785cb4..e1ba0dbb9 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Indexable.java @@ -29,7 +29,7 @@ * * @author Hugo GUERRIER */ -public interface Indexable extends LKQLValue { +public interface Indexable { /** * Get the element at the given index. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java index fea18036d..395316e44 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Iterable.java @@ -29,7 +29,7 @@ * * @author Hugo GUERRIER */ -public interface Iterable extends LKQLValue { +public interface Iterable { /** * Get the size of the iterable collection. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java index bc5e23b32..9343903c1 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java @@ -22,36 +22,24 @@ package com.adacore.lkql_jit.built_ins.values.interfaces; -/** - * This interface defines the LKQL values basic interface. - * - * @author Hugo GUERRIER - */ -public interface LKQLValue { +import com.oracle.truffle.api.interop.TruffleObject; - /** - * Get the documentation for the LKQL value. - * - * @return A string representing the LKQL documentation. - */ - default String getDocumentation() { +/** This interface defines the LKQL values basic interface. */ +public interface LKQLValue extends TruffleObject { + /** Get a documentation string for the LKQL value. */ + default String lkqlDocumentation() { return ""; } - /** - * Get the profile for the callable LKQL value. - * - * @return The string representing the callable profile. - */ - default String getProfile() { + /** Get a string representing the LKQL colling profile. */ + default String lkqlProfile() { return "TODO : Implement the profile information"; } /** - * Do an internal equality verification. + * Do an equality verification with the LKQL semantics. * - * @param o The other lkql value. - * @return True of the values are LKQLy equals, false else. + * @return Whether the given value is equals to the current LKQL value. */ - boolean internalEquals(LKQLValue o); + boolean lkqlEquals(LKQLValue o); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java index f30160a53..d077b0915 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Nullish.java @@ -27,4 +27,4 @@ * * @author Hugo GUERRIER */ -public interface Nullish extends LKQLValue {} +public interface Nullish {} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java index 4d2b73bc4..b9f811958 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/Truthy.java @@ -27,7 +27,7 @@ * * @author Hugo GUERRIER */ -public interface Truthy extends LKQLValue { +public interface Truthy { /** * Get the boolean representation of the object. diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java index bff0ca041..80b749221 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java @@ -36,7 +36,6 @@ 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.interop.TruffleObject; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -45,7 +44,7 @@ /** This abstract class represents all list like values in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public abstract class BaseLKQLList implements TruffleObject, Iterable, Indexable, Truthy { +public abstract class BaseLKQLList implements LKQLValue, Iterable, Indexable, Truthy { // ----- Constructors ----- @@ -86,7 +85,7 @@ public static class IsIdenticalOrUndefined { /** Compare two LKQL lists. */ @Specialization public static TriState onList(final BaseLKQLList left, final BaseLKQLList right) { - if (left.internalEquals(right)) return TriState.TRUE; + if (left.lkqlEquals(right)) return TriState.TRUE; else return TriState.FALSE; } @@ -217,7 +216,7 @@ public boolean isTruthy() { @Override @CompilerDirectives.TruffleBoundary - public boolean internalEquals(LKQLValue o) { + public boolean lkqlEquals(LKQLValue o) { if (this == o) return true; if (!(o instanceof BaseLKQLList other)) return false; @@ -230,7 +229,7 @@ public boolean internalEquals(LKQLValue o) { Object otherElem = other.get(i); if ((thisElem instanceof LKQLValue thisValue) && (otherElem instanceof LKQLValue otherValue)) { - if (!thisValue.internalEquals(otherValue)) return false; + if (!thisValue.lkqlEquals(otherValue)) return false; } else { if (!Objects.equals(thisElem, otherElem)) return false; } @@ -252,6 +251,6 @@ public String toString() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof BaseLKQLList other)) return false; - return this.internalEquals(other); + return this.lkqlEquals(other); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java index ba3197d12..861b17875 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/expressions/Query.java @@ -29,7 +29,6 @@ import com.adacore.lkql_jit.built_ins.values.LKQLNull; import com.adacore.lkql_jit.built_ins.values.LKQLSelector; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.patterns.BasePattern; @@ -345,11 +344,6 @@ public Iterator iterator() { public long size() { return -1; } - - @Override - public boolean internalEquals(LKQLValue o) { - return false; - } } /** This class is the iterator for a query without through */ diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java index d87ef7689..19c01c6cc 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java @@ -70,7 +70,7 @@ public boolean executeDetailValue(VirtualFrame frame, Object value) { // Verify the equality if (LKQLTypeSystemGen.isLKQLValue(value) && LKQLTypeSystemGen.isLKQLValue(expected)) { return LKQLTypeSystemGen.asLKQLValue(value) - .internalEquals(LKQLTypeSystemGen.asLKQLValue(expected)); + .lkqlEquals(LKQLTypeSystemGen.asLKQLValue(expected)); } else { return ObjectUtils.equals(value, expected); } From 41d976620fec61f1a24de7163c787e82937ed5ab Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Tue, 21 Nov 2023 18:06:37 +0100 Subject: [PATCH 22/23] Remove the 'internalEquals' method and rely on the interop library for equality verification --- .../built_ins/values/LKQLDepthNode.java | 12 +-- .../built_ins/values/LKQLFunction.java | 10 +-- .../built_ins/values/LKQLNamespace.java | 80 ++++++++----------- .../lkql_jit/built_ins/values/LKQLNull.java | 5 -- .../lkql_jit/built_ins/values/LKQLObject.java | 77 ++++++++---------- .../built_ins/values/LKQLPattern.java | 15 +--- .../built_ins/values/LKQLProperty.java | 14 +--- .../built_ins/values/LKQLSelector.java | 10 +-- .../lkql_jit/built_ins/values/LKQLTuple.java | 61 ++++++++------ .../lkql_jit/built_ins/values/LKQLUnit.java | 5 -- .../values/interfaces/LKQLValue.java | 7 -- .../built_ins/values/lists/BaseLKQLList.java | 68 ++++++++-------- .../exception/LKQLRuntimeException.java | 10 +++ .../patterns/node_patterns/DetailExpr.java | 6 +- 14 files changed, 158 insertions(+), 222 deletions(-) diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java index 38b086403..4df26d329 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java @@ -73,8 +73,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL depth nodes. */ @Specialization protected static TriState onNode(final LKQLDepthNode left, final LKQLDepthNode right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + return TriState.valueOf(left.node.equals(right.node)); } /** Do the comparison with another element. */ @@ -99,15 +98,6 @@ Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffect return this.node.toString(); } - // ----- LKQL Value methods ----- - - @Override - public boolean lkqlEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LKQLDepthNode other)) return false; - return other.node.equals(this.node); - } - // ----- Override methods ----- @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java index ad95b0515..ce570e7d2 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java @@ -155,8 +155,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL functions. */ @Specialization protected static TriState onFunction(final LKQLFunction left, final LKQLFunction right) { - if (left.rootNode == right.rootNode) return TriState.TRUE; - else return TriState.FALSE; + return TriState.valueOf(left.rootNode == right.rootNode); } /** Do the comparison with another element. */ @@ -225,13 +224,6 @@ Object getExecutableName() { // ----- LKQL values methods ----- - @Override - public boolean lkqlEquals(LKQLValue o) { - if (this == o) return true; - if (!(o instanceof LKQLFunction other)) return false; - return this.rootNode == other.rootNode; - } - @Override public String lkqlDocumentation() { return this.documentation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index 52be4bb30..f541cf8d6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.runtime.Cell; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; @@ -47,7 +48,6 @@ import java.util.Arrays; import java.util.HashMap; import java.util.Map; -import java.util.Objects; /** This class represents the namespaces in the LKQL language. */ @ExportLibrary(InteropLibrary.class) @@ -126,11 +126,34 @@ Class> getLanguage() { @ExportMessage static class IsIdenticalOrUndefined { /** Compare two LKQL namespaces. */ - @Specialization + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) protected static TriState onLKQLNamespace( - final LKQLNamespace left, final LKQLNamespace right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + final LKQLNamespace left, + final LKQLNamespace right, + @CachedLibrary("left") DynamicObjectLibrary lefts, + @CachedLibrary("right") DynamicObjectLibrary rights, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftValues, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightValues) { + // Get the namespaces key sets and compare their size + Object[] leftKeys = lefts.getKeyArray(left); + Object[] rightKeys = rights.getKeyArray(right); + if (leftKeys.length != rightKeys.length) return TriState.FALSE; + + // Then compare each value + for (Object key : leftKeys) { + if (!rights.containsKey(right, key)) return TriState.FALSE; + Object leftValue = lefts.getOrDefault(left, key, null); + Object rightValue = rights.getOrDefault(right, key, null); + if (leftValues.hasIdentity(leftValue)) { + if (!leftValues.isIdentical(leftValue, rightValue, rightValues)) + return TriState.FALSE; + } else { + if (!ObjectUtils.equals(leftValue, rightValue)) return TriState.FALSE; + } + } + + // If we get here, the namespace are equals + return TriState.TRUE; } /** Do the comparison with another element. */ @@ -155,7 +178,7 @@ static int identityHashCode(final LKQLNamespace receiver) { Object toDisplayString( @SuppressWarnings("unused") final boolean allowSideEffects, @CachedLibrary("this") DynamicObjectLibrary thisLibrary, - @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary interopLibrary) { + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary elemLibrary) { // Prepare the result string builder and get the keys of the object StringBuilder resultBuilder = new StringBuilder("Namespace("); Object[] keys = thisLibrary.getKeyArray(this); @@ -169,9 +192,9 @@ Object toDisplayString( // Create the string of the value String valueString; if (value instanceof String) { - valueString = StringUtils.toRepr((String) interopLibrary.toDisplayString(value)); + valueString = StringUtils.toRepr((String) elemLibrary.toDisplayString(value)); } else { - valueString = (String) interopLibrary.toDisplayString(value); + valueString = (String) elemLibrary.toDisplayString(value); } // Add the strings to the result @@ -218,43 +241,6 @@ Object readMember( return result; } - // ----- LKQL value methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public boolean lkqlEquals(LKQLValue o) { - if (this == o) return true; - if (!(o instanceof LKQLNamespace other)) return false; - - // Create the libraries to access object fields - DynamicObjectLibrary thisLib = DynamicObjectLibrary.getFactory().getUncached(this); - DynamicObjectLibrary otherLib = DynamicObjectLibrary.getFactory().getUncached(other); - - // Get the keys - Object[] thisKeys = thisLib.getKeyArray(this); - Object[] otherKeys = otherLib.getKeyArray(other); - - // Check the key array length - if (thisKeys.length != otherKeys.length) return false; - - // Iterate over the keys and verify their values - for (Object key : thisKeys) { - // Ensure that the other contains the key - if (!otherLib.containsKey(other, key)) return false; - - // Compare the values - Object thisObject = thisLib.getOrDefault(this, key, null); - Object otherObject = otherLib.getOrDefault(other, key, null); - if ((thisObject instanceof LKQLValue thisValue) - && (otherObject instanceof LKQLValue otherValue)) { - if (!thisValue.lkqlEquals(otherValue)) return false; - } else { - if (!Objects.equals(thisObject, otherObject)) return false; - } - } - return true; - } - // ----- Override methods ----- @Override @@ -267,7 +253,9 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLNamespace other)) return false; - return this.lkqlEquals(other); + InteropLibrary thisLibrary = InteropLibrary.getUncached(this); + InteropLibrary otherLibrary = InteropLibrary.getUncached(other); + return thisLibrary.isIdentical(this, other, otherLibrary); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java index 6702d516c..91071d2a3 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNull.java @@ -124,11 +124,6 @@ boolean asBoolean() { // ----- LKQL value methods ----- - @Override - public boolean lkqlEquals(LKQLValue o) { - return o == this; - } - @Override public boolean isTruthy() { return false; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index 4c3c3de86..a07816376 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -27,6 +27,7 @@ import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.utils.Constants; import com.adacore.lkql_jit.utils.functions.ArrayUtils; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; @@ -42,7 +43,6 @@ import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.utilities.TriState; import java.util.Arrays; -import java.util.Objects; /** This class represents an object value in the LKQL language. */ @ExportLibrary(InteropLibrary.class) @@ -111,10 +111,34 @@ Class> getLanguage() { @ExportMessage static class IsIdenticalOrUndefined { /** Compare two LKQL objects. */ - @Specialization - protected static TriState onLKQLObject(final LKQLObject left, final LKQLObject right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + protected static TriState onLKQLObject( + final LKQLObject left, + final LKQLObject right, + @CachedLibrary("left") DynamicObjectLibrary lefts, + @CachedLibrary("right") DynamicObjectLibrary rights, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftValues, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightValues) { + // Get the objects key sets and compare their size + Object[] leftKeys = lefts.getKeyArray(left); + Object[] rightKeys = rights.getKeyArray(right); + if (leftKeys.length != rightKeys.length) return TriState.FALSE; + + // Then compare each value + for (Object key : leftKeys) { + if (!rights.containsKey(right, key)) return TriState.FALSE; + Object leftValue = lefts.getOrDefault(left, key, null); + Object rightValue = rights.getOrDefault(right, key, null); + if (leftValues.hasIdentity(leftValue)) { + if (!leftValues.isIdentical(leftValue, rightValue, rightValues)) + return TriState.FALSE; + } else { + if (!ObjectUtils.equals(leftValue, rightValue)) return TriState.FALSE; + } + } + + // If we get here, the objects are equals + return TriState.TRUE; } /** Do the comparison with another element. */ @@ -203,45 +227,6 @@ Object readMember( return result; } - // ----- LKQL value methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public boolean lkqlEquals(final LKQLValue o) { - if (this == o) return true; - if (!(o instanceof LKQLObject other)) return false; - - // Create the libraries to access object fields - DynamicObjectLibrary thisLib = DynamicObjectLibrary.getFactory().getUncached(this); - DynamicObjectLibrary otherLib = DynamicObjectLibrary.getFactory().getUncached(other); - - // Get the keys - Object[] thisKeys = thisLib.getKeyArray(this); - Object[] otherKeys = otherLib.getKeyArray(other); - - // Check the key array length - if (thisKeys.length != otherKeys.length) return false; - - // Iterate over the keys and verify their values - for (Object key : thisKeys) { - // Ensure that the other contains the key - if (!otherLib.containsKey(other, key)) return false; - - // Compare the values - Object thisObject = thisLib.getOrDefault(this, key, null); - Object otherObject = otherLib.getOrDefault(other, key, null); - if ((thisObject instanceof LKQLValue thisValue) - && (otherObject instanceof LKQLValue otherValue)) { - if (!thisValue.lkqlEquals(otherValue)) return false; - } else { - if (!Objects.equals(thisObject, otherObject)) return false; - } - } - - // Return the success - return true; - } - // ----- Override methods ----- @Override @@ -254,7 +239,9 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLObject other)) return false; - return this.lkqlEquals(other); + InteropLibrary thisLibrary = InteropLibrary.getUncached(this); + InteropLibrary otherLibrary = InteropLibrary.getUncached(other); + return thisLibrary.isIdentical(this, other, otherLibrary); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index 669fac492..847ff4d84 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -141,8 +141,9 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL patterns. */ @Specialization protected static TriState onPattern(final LKQLPattern left, final LKQLPattern right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + return TriState.valueOf( + left.regexString.equals(right.regexString) + && left.caseSensitive == right.caseSensitive); } /** Do the comparison with another element. */ @@ -215,16 +216,6 @@ Object invokeMember(String member, Object... args) }; } - // ----- LKQL Value methods ----- - - @Override - public boolean lkqlEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LKQLPattern other)) return false; - return other.regexString.equals(this.regexString) - && (this.caseSensitive && other.caseSensitive); - } - // ----- Override methods ----- @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java index d28547fa9..82968712f 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java @@ -28,6 +28,7 @@ import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.ArgList; import com.adacore.lkql_jit.utils.LKQLTypesHelper; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.ReflectionUtils; import com.adacore.lkql_jit.utils.source_location.Locatable; import com.oracle.truffle.api.CompilerDirectives; @@ -135,8 +136,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL properties. */ @Specialization protected static TriState onProperty(final LKQLProperty left, final LKQLProperty right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + return TriState.valueOf(ObjectUtils.equals(left.description, right.description)); } /** Do the comparison with another element. */ @@ -177,16 +177,6 @@ Object execute(Object[] arguments) return null; } - // ----- LKQL values methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public boolean lkqlEquals(LKQLValue o) { - if (this == o) return true; - if (!(o instanceof LKQLProperty other)) return false; - return this.description.equals(other.description); - } - // ----- Override methods ----- @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java index 7ac6fd3d8..3b1b6afac 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java @@ -116,8 +116,7 @@ static class IsIdenticalOrUndefined { /** Compare two LKQL selectors. */ @Specialization protected static TriState onSelector(final LKQLSelector left, final LKQLSelector right) { - if (left.rootNode == right.rootNode) return TriState.TRUE; - else return TriState.FALSE; + return TriState.valueOf(left.rootNode == right.rootNode); } /** Do the comparison with another element. */ @@ -161,13 +160,6 @@ Object execute(Object[] arguments) // ----- LKQL value methods ----- - @Override - public boolean lkqlEquals(LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LKQLSelector other)) return false; - return this.rootNode == other.rootNode; - } - @Override public String lkqlDocumentation() { return this.documentation; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java index 89f318da5..1b3945a76 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -25,8 +25,10 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.adacore.lkql_jit.utils.Constants; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; @@ -39,7 +41,6 @@ import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; import java.util.Arrays; -import java.util.Objects; /** This class represents a tuple in LKQL. */ @ExportLibrary(InteropLibrary.class) @@ -75,10 +76,36 @@ public Class> getLanguage() { @ExportMessage public static class IsIdenticalOrUndefined { /** Compare two LKQL tuples. */ - @Specialization - public static TriState onTuple(final LKQLTuple left, final LKQLTuple right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + public static TriState onTuple( + final LKQLTuple left, + final LKQLTuple right, + @CachedLibrary("left") InteropLibrary lefts, + @CachedLibrary("right") InteropLibrary rights, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftElems, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightElems) { + try { + // Get the left tuple size and compare it with the right tuple + long size = lefts.getArraySize(left); + if (size != rights.getArraySize(right)) return TriState.FALSE; + + // Then compare each element of the tuples + for (long i = 0; i < size; i++) { + Object leftElem = lefts.readArrayElement(left, i); + Object rightElem = rights.readArrayElement(right, i); + if (leftElems.hasIdentity(leftElem)) { + if (!leftElems.isIdentical(leftElem, rightElem, rightElems)) + return TriState.FALSE; + } else { + if (!ObjectUtils.equals(leftElem, rightElem)) return TriState.FALSE; + } + } + + // If we get here, tuples are equal + return TriState.TRUE; + } catch (Exception e) { + throw LKQLRuntimeException.shouldNotHappen("Tuples comparison"); + } } /** Do the comparison with another element. */ @@ -172,26 +199,6 @@ public Object[] getContent() { return this.content; } - // ----- LKQL value methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public boolean lkqlEquals(final LKQLValue o) { - if (o == this) return true; - if (!(o instanceof LKQLTuple other)) return false; - if (other.content.length != this.content.length) return false; - for (int i = 0; i < this.content.length; i++) { - Object mineObject = this.content[i]; - Object hisObject = other.content[i]; - if ((mineObject instanceof LKQLValue mine) && (hisObject instanceof LKQLValue his)) { - if (!mine.lkqlEquals(his)) return false; - } else { - if (!Objects.equals(mineObject, hisObject)) return false; - } - } - return true; - } - // ----- Override methods ----- @Override @@ -204,7 +211,9 @@ public String toString() { public boolean equals(final Object o) { if (o == this) return true; if (!(o instanceof LKQLTuple other)) return false; - return this.lkqlEquals(other); + InteropLibrary thisLibrary = InteropLibrary.getUncached(this); + InteropLibrary otherLibrary = InteropLibrary.getUncached(other); + return thisLibrary.isIdentical(this, other, otherLibrary); } @Override diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java index 962b79251..cd1544602 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java @@ -105,11 +105,6 @@ boolean asBoolean() { // ----- LKQL value methods ----- - @Override - public boolean lkqlEquals(LKQLValue o) { - return o == this; - } - @Override public boolean isTruthy() { return false; diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java index 9343903c1..59162bfa6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/interfaces/LKQLValue.java @@ -35,11 +35,4 @@ default String lkqlDocumentation() { default String lkqlProfile() { return "TODO : Implement the profile information"; } - - /** - * Do an equality verification with the LKQL semantics. - * - * @return Whether the given value is equals to the current LKQL value. - */ - boolean lkqlEquals(LKQLValue o); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java index 80b749221..0715dc83a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java @@ -28,8 +28,10 @@ import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.adacore.lkql_jit.built_ins.values.iterators.LKQLIterator; +import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.adacore.lkql_jit.utils.Constants; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.TruffleLanguage; @@ -40,7 +42,6 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; -import java.util.Objects; /** This abstract class represents all list like values in the LKQL language. */ @ExportLibrary(InteropLibrary.class) @@ -83,10 +84,36 @@ public Class> getLanguage() { @ExportMessage public static class IsIdenticalOrUndefined { /** Compare two LKQL lists. */ - @Specialization - public static TriState onList(final BaseLKQLList left, final BaseLKQLList right) { - if (left.lkqlEquals(right)) return TriState.TRUE; - else return TriState.FALSE; + @Specialization(limit = Constants.SPECIALIZED_LIB_LIMIT) + public static TriState onList( + final BaseLKQLList left, + final BaseLKQLList right, + @CachedLibrary("left") InteropLibrary lefts, + @CachedLibrary("right") InteropLibrary rights, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftElems, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightElems) { + try { + // Get the left list size and compare it with the right list + long size = lefts.getArraySize(left); + if (size != rights.getArraySize(right)) return TriState.FALSE; + + // Then compare each element of the lists + for (long i = 0; i < size; i++) { + Object leftElem = lefts.readArrayElement(left, i); + Object rightElem = rights.readArrayElement(right, i); + if (leftElems.hasIdentity(leftElem)) { + if (!leftElems.isIdentical(leftElem, rightElem, rightElems)) + return TriState.FALSE; + } else { + if (!ObjectUtils.equals(leftElem, rightElem)) return TriState.FALSE; + } + } + + // If we get here, lists are equal + return TriState.TRUE; + } catch (Exception e) { + throw LKQLRuntimeException.shouldNotHappen("Lists comparison"); + } } /** Do the comparison with another element. */ @@ -212,33 +239,6 @@ public boolean isTruthy() { } } - // ----- LKQL value required methods ----- - - @Override - @CompilerDirectives.TruffleBoundary - public boolean lkqlEquals(LKQLValue o) { - if (this == o) return true; - if (!(o instanceof BaseLKQLList other)) return false; - - // Compare the list size - if (this.size() != other.size()) return false; - - // Then compare each element of the lists - for (long i = 0; i < this.size(); i++) { - Object thisElem = this.get(i); - Object otherElem = other.get(i); - if ((thisElem instanceof LKQLValue thisValue) - && (otherElem instanceof LKQLValue otherValue)) { - if (!thisValue.lkqlEquals(otherValue)) return false; - } else { - if (!Objects.equals(thisElem, otherElem)) return false; - } - } - - // If we get here, lists are equals - return true; - } - // ----- Override methods ----- @Override @@ -251,6 +251,8 @@ public String toString() { public boolean equals(Object o) { if (this == o) return true; if (!(o instanceof BaseLKQLList other)) return false; - return this.lkqlEquals(other); + InteropLibrary thisLibrary = InteropLibrary.getUncached(this); + InteropLibrary otherLibrary = InteropLibrary.getUncached(other); + return thisLibrary.isIdentical(this, other, otherLibrary); } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/exception/LKQLRuntimeException.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/exception/LKQLRuntimeException.java index 31b59be16..b18126800 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/exception/LKQLRuntimeException.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/exception/LKQLRuntimeException.java @@ -108,6 +108,16 @@ public static LKQLRuntimeException shouldNotExecute(Locatable location) { return new LKQLRuntimeException(fullErrorText("Should not execute", location)); } + /** + * Create an exception which should not happened during a normal execution. + * + * @param message Additional message. + */ + @CompilerDirectives.TruffleBoundary + public static LKQLRuntimeException shouldNotHappen(String message) { + return new LKQLRuntimeException("This exception should not happen: " + message); + } + /** * Create a new exception for a parsing exception in the LKQL sources. * diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java index 19c01c6cc..4e09c9149 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/nodes/patterns/node_patterns/DetailExpr.java @@ -27,6 +27,7 @@ import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.source_location.SourceLocation; import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.interop.InteropLibrary; /** * This node represents an expression detail value in the LKQL language. @@ -69,8 +70,9 @@ public boolean executeDetailValue(VirtualFrame frame, Object value) { // Verify the equality if (LKQLTypeSystemGen.isLKQLValue(value) && LKQLTypeSystemGen.isLKQLValue(expected)) { - return LKQLTypeSystemGen.asLKQLValue(value) - .lkqlEquals(LKQLTypeSystemGen.asLKQLValue(expected)); + InteropLibrary valueLibrary = InteropLibrary.getUncached(value); + InteropLibrary expectedLibrary = InteropLibrary.getUncached(expected); + return valueLibrary.isIdentical(value, expected, expectedLibrary); } else { return ObjectUtils.equals(value, expected); } From 8601955569d9609f1f2869261ab929e936044c7d Mon Sep 17 00:00:00 2001 From: Hugo Guerrier Date: Wed, 22 Nov 2023 12:52:33 +0100 Subject: [PATCH 23/23] Add base classes for basic, object, and array values to factorize code Make all message methods public to avoid visibility conflicts during inheritance. --- .../built_ins/values/LKQLDepthNode.java | 10 +- .../built_ins/values/LKQLFunction.java | 40 +--- .../built_ins/values/LKQLNamespace.java | 137 +----------- .../lkql_jit/built_ins/values/LKQLObject.java | 138 +----------- .../built_ins/values/LKQLPattern.java | 39 +--- .../built_ins/values/LKQLProperty.java | 36 +--- .../built_ins/values/LKQLSelector.java | 36 +--- .../lkql_jit/built_ins/values/LKQLTuple.java | 79 +------ .../lkql_jit/built_ins/values/LKQLUnit.java | 48 +---- .../values/bases/ArrayLKQLValue.java | 94 +++++++++ .../values/bases/BasicLKQLValue.java | 89 ++++++++ .../values/bases/ObjectLKQLValue.java | 196 ++++++++++++++++++ .../built_ins/values/lists/BaseLKQLList.java | 47 +---- .../lkql_jit/utils/functions/ObjectUtils.java | 6 + 14 files changed, 471 insertions(+), 524 deletions(-) create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ArrayLKQLValue.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/BasicLKQLValue.java create mode 100644 lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ObjectLKQLValue.java diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java index 4df26d329..dd95351ca 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLDepthNode.java @@ -23,7 +23,7 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.oracle.truffle.api.CompilerDirectives; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -37,7 +37,7 @@ * all Libadalang objects will be wrapped in interop LKQL values (#154). */ @ExportLibrary(InteropLibrary.class) -public final class LKQLDepthNode implements LKQLValue { +public final class LKQLDepthNode extends BasicLKQLValue { // ----- Attributes ----- @@ -69,7 +69,7 @@ public Libadalang.AdaNode getNode() { /** Exported message to compare two LKQL depth nodes. */ @ExportMessage - static class IsIdenticalOrUndefined { + public static class IsIdenticalOrUndefined { /** Compare two LKQL depth nodes. */ @Specialization protected static TriState onNode(final LKQLDepthNode left, final LKQLDepthNode right) { @@ -88,13 +88,13 @@ protected static TriState onOther( /** Return the identity hash code for the given LKQL depth node. */ @ExportMessage @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLDepthNode receiver) { + public static int identityHashCode(final LKQLDepthNode receiver) { return System.identityHashCode(receiver); } /** Get the displayable string for the interop library. */ @ExportMessage - Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + public String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { return this.node.toString(); } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java index ce570e7d2..479dab521 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLFunction.java @@ -22,14 +22,12 @@ package com.adacore.lkql_jit.built_ins.values; -import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.adacore.lkql_jit.nodes.expressions.Expr; import com.adacore.lkql_jit.nodes.root_nodes.FunctionRootNode; import com.adacore.lkql_jit.runtime.Closure; import com.oracle.truffle.api.CallTarget; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Cached; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; @@ -42,7 +40,7 @@ /** This class represents the function values in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLFunction implements LKQLValue { +public class LKQLFunction extends BasicLKQLValue { // ----- Attributes ----- @@ -137,21 +135,9 @@ public Expr getBody() { // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL functions. */ @ExportMessage - static class IsIdenticalOrUndefined { + public static class IsIdenticalOrUndefined { /** Compare two LKQL functions. */ @Specialization protected static TriState onFunction(final LKQLFunction left, final LKQLFunction right) { @@ -170,26 +156,27 @@ protected static TriState onOther( /** Return the identity hash code for the given LKQL function. */ @ExportMessage @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLFunction receiver) { + public static int identityHashCode(final LKQLFunction receiver) { return System.identityHashCode(receiver); } /** Get the displayable string for the interop library. */ + @Override @ExportMessage @CompilerDirectives.TruffleBoundary - Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + public String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { return "function<" + this.name + ">"; } /** Tell the interop library that the value is executable. */ @ExportMessage - boolean isExecutable() { + public boolean isExecutable() { return true; } /** Inner class for the function execution. */ @ExportMessage - static class Execute { + public static class Execute { /** Execute the function with the cached strategy. */ @Specialization(guards = "callTarget == directCallNode.getCallTarget()") protected static Object doCached( @@ -212,13 +199,13 @@ protected static Object doUncached( /** Tell the interop library that this value has an executable name. */ @ExportMessage - boolean hasExecutableName() { + public boolean hasExecutableName() { return true; } /** Return the function name to the interop library. */ @ExportMessage - Object getExecutableName() { + public Object getExecutableName() { return this.name; } @@ -228,11 +215,4 @@ Object getExecutableName() { public String lkqlDocumentation() { return this.documentation; } - - // ----- Override methods ----- - - @Override - public String toString() { - return "function<" + this.name + ">"; - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java index f541cf8d6..5485a77aa 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLNamespace.java @@ -22,41 +22,29 @@ package com.adacore.lkql_jit.built_ins.values; -import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.bases.ObjectLKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.runtime.Cell; import com.adacore.lkql_jit.utils.Constants; -import com.adacore.lkql_jit.utils.functions.ArrayUtils; -import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.frame.FrameDescriptor; import com.oracle.truffle.api.frame.MaterializedFrame; import com.oracle.truffle.api.interop.InteropLibrary; -import com.oracle.truffle.api.interop.UnknownIdentifierException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.DynamicObjectLibrary; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.utilities.TriState; -import java.util.Arrays; import java.util.HashMap; import java.util.Map; /** This class represents the namespaces in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public class LKQLNamespace extends DynamicObject implements LKQLValue { - - // ----- Attributes ----- - - /** The dynamic object library to perform uncached operations on the LKQL namespace. */ - private static final DynamicObjectLibrary objectLibrary = DynamicObjectLibrary.getUncached(); +public class LKQLNamespace extends ObjectLKQLValue implements LKQLValue { // ----- Constructors ----- @@ -85,43 +73,13 @@ public static LKQLNamespace createUncached(MaterializedFrame frame) { // Return the new namespace LKQLNamespace res = new LKQLNamespace(Shape.newBuilder().build()); for (String key : symbols.keySet()) { - objectLibrary.put(res, key, symbols.get(key)); + uncachedObjectLibrary.put(res, key, symbols.get(key)); } return res; } - // ----- Instance methods ----- - - /** - * Get the value in the LKQL namespace at the given key with the uncached strategy. This method - * uses an uncached library so this is not design for performance critical usages. - */ - public Object getUncached(final Object key) { - return objectLibrary.getOrDefault(this, key, null); - } - - /** - * Get the key array from the namespace value. This method uses an uncached library so this is - * not designed for performance critical usages. - */ - public Object[] keysUncached() { - return objectLibrary.getKeyArray(this); - } - // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL namespaces. */ @ExportMessage static class IsIdenticalOrUndefined { @@ -134,26 +92,8 @@ protected static TriState onLKQLNamespace( @CachedLibrary("right") DynamicObjectLibrary rights, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftValues, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightValues) { - // Get the namespaces key sets and compare their size - Object[] leftKeys = lefts.getKeyArray(left); - Object[] rightKeys = rights.getKeyArray(right); - if (leftKeys.length != rightKeys.length) return TriState.FALSE; - - // Then compare each value - for (Object key : leftKeys) { - if (!rights.containsKey(right, key)) return TriState.FALSE; - Object leftValue = lefts.getOrDefault(left, key, null); - Object rightValue = rights.getOrDefault(right, key, null); - if (leftValues.hasIdentity(leftValue)) { - if (!leftValues.isIdentical(leftValue, rightValue, rightValues)) - return TriState.FALSE; - } else { - if (!ObjectUtils.equals(leftValue, rightValue)) return TriState.FALSE; - } - } - - // If we get here, the namespace are equals - return TriState.TRUE; + return TriState.valueOf( + objectValueEquals(left, right, lefts, rights, leftValues, rightValues)); } /** Do the comparison with another element. */ @@ -165,10 +105,10 @@ protected static TriState onOther( } } - /** Return the identity hash code for the given LKQL namespace. */ - @ExportMessage + /** Get the identity hash code for the given namespace */ @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLNamespace receiver) { + @ExportMessage + public static int identityHashCode(LKQLNamespace receiver) { return System.identityHashCode(receiver); } @@ -206,65 +146,4 @@ Object toDisplayString( resultBuilder.append(")"); return resultBuilder.toString(); } - - /** Tell the interop library that this value has members. */ - @ExportMessage - boolean hasMembers() { - return true; - } - - /** - * Get if the given member is in the receiver namespace. All members are readable but not - * modifiable. - */ - @ExportMessage - boolean isMemberReadable( - final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return objectLibrary.containsKey(this, member); - } - - /** Get the existing members for the receiver namespace. */ - @ExportMessage - Object getMembers( - @SuppressWarnings("unused") final boolean includeInternal, - @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new LKQLList(objectLibrary.getKeyArray(this)); - } - - /** Get the value of the wanted member in the receiver namespace. */ - @ExportMessage - Object readMember( - final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) - throws UnknownIdentifierException { - final Object result = objectLibrary.getOrDefault(this, member, null); - if (result == null) throw UnknownIdentifierException.create(member); - return result; - } - - // ----- Override methods ----- - - @Override - public String toString() { - InteropLibrary interopLibrary = InteropLibrary.getUncached(this); - return (String) interopLibrary.toDisplayString(this); - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof LKQLNamespace other)) return false; - InteropLibrary thisLibrary = InteropLibrary.getUncached(this); - InteropLibrary otherLibrary = InteropLibrary.getUncached(other); - return thisLibrary.isIdentical(this, other, otherLibrary); - } - - @Override - public int hashCode() { - Object[] keys = this.keysUncached(); - Object[] values = new Object[keys.length]; - for (int i = 0; i < keys.length; i++) { - values[i] = this.getUncached(keys[i]); - } - return Arrays.hashCode(ArrayUtils.concat(keys, values)); - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java index a07816376..74f6558bf 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLObject.java @@ -22,36 +22,24 @@ package com.adacore.lkql_jit.built_ins.values; -import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.bases.ObjectLKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.utils.Constants; -import com.adacore.lkql_jit.utils.functions.ArrayUtils; -import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; 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.interop.UnknownIdentifierException; import com.oracle.truffle.api.library.CachedLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; -import com.oracle.truffle.api.object.DynamicObject; import com.oracle.truffle.api.object.DynamicObjectLibrary; import com.oracle.truffle.api.object.Shape; import com.oracle.truffle.api.utilities.TriState; -import java.util.Arrays; /** This class represents an object value in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public final class LKQLObject extends DynamicObject implements LKQLValue { - - // ----- Class attributes ----- - - /** An uncached dynamic object library. */ - private static final DynamicObjectLibrary objectLibrary = DynamicObjectLibrary.getUncached(); +public final class LKQLObject extends ObjectLKQLValue implements LKQLValue { // ----- Constructors ----- @@ -69,44 +57,13 @@ public LKQLObject(final Shape shape) { public static LKQLObject createUncached(final Object[] keys, final Object[] values) { final LKQLObject res = new LKQLObject(Shape.newBuilder().build()); for (int i = 0; i < keys.length; i++) { - objectLibrary.put(res, keys[i], values[i]); + uncachedObjectLibrary.put(res, keys[i], values[i]); } return res; } - // ----- Instance methods ------ - - /** - * Get the value in the LKQL object at the given key with the uncached strategy. If the key - * doesn't exist then a null value is returned. This method uses an uncached library so this is - * not design for performance critical usages. - */ - public Object getUncached(final Object key) { - return objectLibrary.getOrDefault(this, key, null); - } - - /** - * Get the key array from the object value. This method uses an uncached library so this is no - * designed for performance critical usages. - */ - public Object[] keysUncached() { - return objectLibrary.getKeyArray(this); - } - // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL objects. */ @ExportMessage static class IsIdenticalOrUndefined { @@ -119,26 +76,8 @@ protected static TriState onLKQLObject( @CachedLibrary("right") DynamicObjectLibrary rights, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftValues, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightValues) { - // Get the objects key sets and compare their size - Object[] leftKeys = lefts.getKeyArray(left); - Object[] rightKeys = rights.getKeyArray(right); - if (leftKeys.length != rightKeys.length) return TriState.FALSE; - - // Then compare each value - for (Object key : leftKeys) { - if (!rights.containsKey(right, key)) return TriState.FALSE; - Object leftValue = lefts.getOrDefault(left, key, null); - Object rightValue = rights.getOrDefault(right, key, null); - if (leftValues.hasIdentity(leftValue)) { - if (!leftValues.isIdentical(leftValue, rightValue, rightValues)) - return TriState.FALSE; - } else { - if (!ObjectUtils.equals(leftValue, rightValue)) return TriState.FALSE; - } - } - - // If we get here, the objects are equals - return TriState.TRUE; + return TriState.valueOf( + objectValueEquals(left, right, lefts, rights, leftValues, rightValues)); } /** Do the comparison with another element. */ @@ -150,10 +89,10 @@ protected static TriState onOther( } } - /** Return the identity hash code for the given LKQL object. */ - @ExportMessage + /** Get the identity hash code for the given object */ @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLObject receiver) { + @ExportMessage + public static int identityHashCode(LKQLObject receiver) { return System.identityHashCode(receiver); } @@ -192,65 +131,4 @@ Object toDisplayString( resultBuilder.append("}"); return resultBuilder.toString(); } - - /** Tell the interop library that the value has members. */ - @ExportMessage - boolean hasMembers() { - return true; - } - - /** - * Get if the given member is in the receiver object. All members are readable but not - * modifiable. - */ - @ExportMessage - boolean isMemberReadable( - final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return objectLibrary.containsKey(this, member); - } - - /** Get the existing members for the receiver object. */ - @ExportMessage - Object getMembers( - @SuppressWarnings("unused") final boolean includeInternal, - @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { - return new LKQLList(objectLibrary.getKeyArray(this)); - } - - /** Get the value of the wanted member in the receiver object. */ - @ExportMessage - Object readMember( - final String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) - throws UnknownIdentifierException { - Object result = objectLibrary.getOrDefault(this, member, null); - if (result == null) throw UnknownIdentifierException.create(member); - return result; - } - - // ----- Override methods ----- - - @Override - public String toString() { - InteropLibrary objectLib = InteropLibrary.getUncached(this); - return (String) objectLib.toDisplayString(this); - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof LKQLObject other)) return false; - InteropLibrary thisLibrary = InteropLibrary.getUncached(this); - InteropLibrary otherLibrary = InteropLibrary.getUncached(other); - return thisLibrary.isIdentical(this, other, otherLibrary); - } - - @Override - public int hashCode() { - Object[] keys = this.keysUncached(); - Object[] values = new Object[keys.length]; - for (int i = 0; i < keys.length; i++) { - values[i] = this.getUncached(keys[i]); - } - return Arrays.hashCode(ArrayUtils.concat(keys, values)); - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java index 847ff4d84..3210203d6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLPattern.java @@ -24,14 +24,13 @@ import com.adacore.lkql_jit.LKQLLanguage; import com.adacore.lkql_jit.LKQLTypeSystemGen; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.LKQLNode; import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.exception.AbstractTruffleException; @@ -46,7 +45,7 @@ * regular expression. */ @ExportLibrary(InteropLibrary.class) -public final class LKQLPattern implements LKQLValue { +public final class LKQLPattern extends BasicLKQLValue { // ----- Attributes ----- @@ -123,21 +122,9 @@ public int find(String string) { // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL patterns. */ @ExportMessage - static class IsIdenticalOrUndefined { + public static class IsIdenticalOrUndefined { /** Compare two LKQL patterns. */ @Specialization protected static TriState onPattern(final LKQLPattern left, final LKQLPattern right) { @@ -158,32 +145,33 @@ protected static TriState onOther( /** Return the identity hash code for the given LKQL pattern. */ @ExportMessage @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLPattern receiver) { + public static int identityHashCode(final LKQLPattern receiver) { return System.identityHashCode(receiver); } /** Get the displayable string for the interop library. */ + @Override @ExportMessage @CompilerDirectives.TruffleBoundary - String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + public String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { return "pattern<\"" + this.regexString + "\">"; } /** Tell the interop library that the value has members. */ @ExportMessage - boolean hasMembers() { + public boolean hasMembers() { return true; } /** Get the existing members on the pattern. */ @ExportMessage - Object getMembers(@SuppressWarnings("unused") final boolean includeInternal) { + public Object getMembers(@SuppressWarnings("unused") final boolean includeInternal) { return MEMBERS; } /** Tell the interop library whether the given member is invokable. */ @ExportMessage - boolean isMemberInvocable(String member) { + public boolean isMemberInvocable(String member) { return ObjectUtils.equals(member, "contains") || ObjectUtils.equals(member, "find"); } @@ -195,7 +183,7 @@ boolean isMemberInvocable(String member) { * @throws UnknownIdentifierException If the provided member doesn't exist. */ @ExportMessage - Object invokeMember(String member, Object... args) + public Object invokeMember(String member, Object... args) throws ArityException, UnsupportedTypeException, UnknownIdentifierException { // Verify the argument number if (args.length < 1) { @@ -215,11 +203,4 @@ Object invokeMember(String member, Object... args) default -> throw UnknownIdentifierException.create(member); }; } - - // ----- Override methods ----- - - @Override - public String toString() { - return this.regexString; - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java index 82968712f..c7faf2f18 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLProperty.java @@ -23,8 +23,7 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.nodes.arguments.ArgList; import com.adacore.lkql_jit.utils.LKQLTypesHelper; @@ -32,7 +31,6 @@ import com.adacore.lkql_jit.utils.functions.ReflectionUtils; import com.adacore.lkql_jit.utils.source_location.Locatable; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.*; @@ -42,7 +40,7 @@ /** This class represents a Libadalang property access in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLProperty implements LKQLValue { +public class LKQLProperty extends BasicLKQLValue { // ----- Attributes ----- @@ -118,21 +116,9 @@ public Object executeAsField(Locatable caller) { // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL properties. */ @ExportMessage - static class IsIdenticalOrUndefined { + public static class IsIdenticalOrUndefined { /** Compare two LKQL properties. */ @Specialization protected static TriState onProperty(final LKQLProperty left, final LKQLProperty right) { @@ -151,36 +137,30 @@ protected static TriState onOther( /** Return the identity hash code for the given LKQL property. */ @ExportMessage @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLProperty receiver) { + public static int identityHashCode(final LKQLProperty receiver) { return System.identityHashCode(receiver); } /** Get the displayable string for the interop library. */ + @Override @ExportMessage @CompilerDirectives.TruffleBoundary - Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + public String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { return "property<" + this.name + ">"; } /** Tell the interop library that the value is not executable. */ @ExportMessage - boolean isExecutable() { + public boolean isExecutable() { // TODO (issue #143): Make the LKQLSelector executable as LKQLFunctions return false; } /** Placeholder function for the Truffle DSL. */ @ExportMessage - Object execute(Object[] arguments) + public Object execute(Object[] arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException { // TODO (issue #143): implement this method to execute the property as a simple function return null; } - - // ----- Override methods ----- - - @Override - public String toString() { - return "property<" + this.name + ">"; - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java index 3b1b6afac..d07e52363 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLSelector.java @@ -23,13 +23,11 @@ package com.adacore.lkql_jit.built_ins.values; import com.adacore.libadalang.Libadalang; -import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.adacore.lkql_jit.built_ins.values.lists.LKQLSelectorList; import com.adacore.lkql_jit.nodes.root_nodes.SelectorRootNode; import com.adacore.lkql_jit.runtime.Closure; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.*; @@ -39,7 +37,7 @@ /** This class represents the selector values in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLSelector implements LKQLValue { +public class LKQLSelector extends BasicLKQLValue { // ----- Attributes ----- @@ -98,21 +96,9 @@ public LKQLSelectorList getList( // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two LKQL selectors. */ @ExportMessage - static class IsIdenticalOrUndefined { + public static class IsIdenticalOrUndefined { /** Compare two LKQL selectors. */ @Specialization protected static TriState onSelector(final LKQLSelector left, final LKQLSelector right) { @@ -131,27 +117,28 @@ protected static TriState onOther( /** Return the identity hash code for the given LKQL selector. */ @ExportMessage @CompilerDirectives.TruffleBoundary - static int identityHashCode(final LKQLSelector receiver) { + public static int identityHashCode(final LKQLSelector receiver) { return System.identityHashCode(receiver); } /** Get the displayable string for the interop library. */ + @Override @ExportMessage @CompilerDirectives.TruffleBoundary - Object toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { + public String toDisplayString(@SuppressWarnings("unused") final boolean allowSideEffects) { return "selector<" + this.name + ">"; } /** Tell the interop library that the value is not executable. */ @ExportMessage - boolean isExecutable() { + public boolean isExecutable() { // TODO (issue #143): Make the LKQLSelector executable as LKQLFunctions return false; } /** Placeholder function for the Truffle DSL. */ @ExportMessage - Object execute(Object[] arguments) + public Object execute(Object[] arguments) throws UnsupportedTypeException, ArityException, UnsupportedMessageException { // TODO (issue #143): implement this method to execute the selector as a simple function // returning a selector list @@ -164,11 +151,4 @@ Object execute(Object[] arguments) public String lkqlDocumentation() { return this.documentation; } - - // ----- Override methods ----- - - @Override - public String toString() { - return "selector<" + this.name + ">"; - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java index 1b3945a76..c271a6a16 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLTuple.java @@ -22,16 +22,12 @@ package com.adacore.lkql_jit.built_ins.values; -import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.bases.ArrayLKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; -import com.adacore.lkql_jit.exception.LKQLRuntimeException; import com.adacore.lkql_jit.exception.utils.InvalidIndexException; import com.adacore.lkql_jit.utils.Constants; -import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; @@ -40,11 +36,10 @@ import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; import com.oracle.truffle.api.utilities.TriState; -import java.util.Arrays; /** This class represents a tuple in LKQL. */ @ExportLibrary(InteropLibrary.class) -public class LKQLTuple implements LKQLValue, Indexable { +public class LKQLTuple extends ArrayLKQLValue implements Indexable { // ----- Attributes ----- @@ -60,18 +55,6 @@ public LKQLTuple(final Object[] content) { // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - public boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - public Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two tuples. */ @ExportMessage public static class IsIdenticalOrUndefined { @@ -84,28 +67,8 @@ public static TriState onTuple( @CachedLibrary("right") InteropLibrary rights, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary leftElems, @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary rightElems) { - try { - // Get the left tuple size and compare it with the right tuple - long size = lefts.getArraySize(left); - if (size != rights.getArraySize(right)) return TriState.FALSE; - - // Then compare each element of the tuples - for (long i = 0; i < size; i++) { - Object leftElem = lefts.readArrayElement(left, i); - Object rightElem = rights.readArrayElement(right, i); - if (leftElems.hasIdentity(leftElem)) { - if (!leftElems.isIdentical(leftElem, rightElem, rightElems)) - return TriState.FALSE; - } else { - if (!ObjectUtils.equals(leftElem, rightElem)) return TriState.FALSE; - } - } - - // If we get here, tuples are equal - return TriState.TRUE; - } catch (Exception e) { - throw LKQLRuntimeException.shouldNotHappen("Tuples comparison"); - } + return TriState.valueOf( + arrayValueEquals(left, right, lefts, rights, leftElems, rightElems)); } /** Do the comparison with another element. */ @@ -117,11 +80,13 @@ public static TriState onOther( } } - /** Return the identity hash code for the given LKQL tuple. */ - @CompilerDirectives.TruffleBoundary + /** Get the identity hash code for the given LKQL tuple */ @ExportMessage - public static int identityHashCode(final LKQLTuple receiver) { - return System.identityHashCode(receiver); + public static int identityHashCode( + LKQLTuple receiver, + @CachedLibrary("receiver") InteropLibrary receivers, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary elems) { + return arrayValueHashCode(receiver, receivers, elems); } /** Get the displayable string for the interop library. */ @@ -155,7 +120,7 @@ public Object toDisplayString( return resultBuilder.toString(); } - /** Tell the interop library that the value is array like. */ + /** Tell the interop library that tuple has array elements. */ @ExportMessage public boolean hasArrayElements() { return true; @@ -198,26 +163,4 @@ public Object get(long index) throws InvalidIndexException { public Object[] getContent() { return this.content; } - - // ----- Override methods ----- - - @Override - public String toString() { - InteropLibrary tupleLib = InteropLibrary.getUncached(this); - return (String) tupleLib.toDisplayString(this); - } - - @Override - public boolean equals(final Object o) { - if (o == this) return true; - if (!(o instanceof LKQLTuple other)) return false; - InteropLibrary thisLibrary = InteropLibrary.getUncached(this); - InteropLibrary otherLibrary = InteropLibrary.getUncached(other); - return thisLibrary.isIdentical(this, other, otherLibrary); - } - - @Override - public int hashCode() { - return Arrays.hashCode(this.content); - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java index cd1544602..e9e53cd0a 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/LKQLUnit.java @@ -22,11 +22,9 @@ package com.adacore.lkql_jit.built_ins.values; -import com.adacore.lkql_jit.LKQLLanguage; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.bases.BasicLKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Nullish; import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.interop.InteropLibrary; import com.oracle.truffle.api.library.ExportLibrary; import com.oracle.truffle.api.library.ExportMessage; @@ -34,7 +32,7 @@ /** This class represents the unit value in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public class LKQLUnit implements LKQLValue, Truthy, Nullish { +public class LKQLUnit extends BasicLKQLValue implements Truthy, Nullish { // ----- Attributes ----- @@ -51,21 +49,9 @@ private LKQLUnit() {} // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - Class> getLanguage() { - return LKQLLanguage.class; - } - /** Tell the interop API if the receiver is identical to the other. */ @ExportMessage - static TriState isIdenticalOrUndefined( + public static TriState isIdenticalOrUndefined( @SuppressWarnings("unused") final LKQLUnit receiver, final Object other) { return TriState.valueOf(receiver == other); } @@ -75,31 +61,32 @@ static TriState isIdenticalOrUndefined( * singleton). */ @ExportMessage - static int identityHashCode(@SuppressWarnings("unused") final LKQLUnit receiver) { + public static int identityHashCode(@SuppressWarnings("unused") final LKQLUnit receiver) { return IDENTITY_HASH; } /** Get the displayable string for the interop library. */ + @Override @ExportMessage - Object toDisplayString(@SuppressWarnings("unused") boolean allowSideEffect) { + public String toDisplayString(@SuppressWarnings("unused") boolean allowSideEffect) { return "()"; } /** Tell the interop API that the value is nullish. */ @ExportMessage - boolean isNull() { + public boolean isNull() { return true; } /** Tell the interop API that the value is a boolean like value. */ @ExportMessage - boolean isBoolean() { + public boolean isBoolean() { return true; } /** Get the boolean like value from unit, which is always false. */ @ExportMessage - boolean asBoolean() { + public boolean asBoolean() { return false; } @@ -109,21 +96,4 @@ boolean asBoolean() { public boolean isTruthy() { return false; } - - // ----- Override methods ----- - - @Override - public boolean equals(Object o) { - return o == this; - } - - @Override - public int hashCode() { - return super.hashCode(); - } - - @Override - public String toString() { - return "()"; - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ArrayLKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ArrayLKQLValue.java new file mode 100644 index 000000000..063329f07 --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ArrayLKQLValue.java @@ -0,0 +1,94 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.bases; + +import com.adacore.lkql_jit.exception.LKQLRuntimeException; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; +import com.oracle.truffle.api.interop.InteropLibrary; + +/** This class is the base for all array like LKQL values. */ +public abstract class ArrayLKQLValue extends BasicLKQLValue { + /** + * Internal method to perform equality checking on two LKQL array like values. + * + * @param lefts Interop library to access 'left' messages. + * @param rights Interop library to access 'right' messages. + * @param leftElems Interop library to access 'left' elements messages. + * @param rightElems Interop library to access 'right' elements messages. + */ + protected static boolean arrayValueEquals( + ArrayLKQLValue left, + ArrayLKQLValue right, + InteropLibrary lefts, + InteropLibrary rights, + InteropLibrary leftElems, + InteropLibrary rightElems) { + try { + // Get the left tuple size and compare it with the right tuple + long size = lefts.getArraySize(left); + if (size != rights.getArraySize(right)) return false; + + // Then compare each element of the tuples + for (long i = 0; i < size; i++) { + Object leftElem = lefts.readArrayElement(left, i); + Object rightElem = rights.readArrayElement(right, i); + if (leftElems.hasIdentity(leftElem)) { + if (!leftElems.isIdentical(leftElem, rightElem, rightElems)) return false; + } else { + if (!ObjectUtils.equals(leftElem, rightElem)) return false; + } + } + + // If we get here, tuples are equal + return true; + } catch (Exception e) { + throw LKQLRuntimeException.shouldNotHappen("Tuples comparison"); + } + } + + /** + * Internal method to compute the hash code of a given LKQL array like value. + * + * @param receivers Interop library to access the receiver messages. + * @param elems Interop library to access the receiver elements messages. + */ + protected static int arrayValueHashCode( + ArrayLKQLValue receiver, InteropLibrary receivers, InteropLibrary elems) { + try { + final long size = receivers.getArraySize(receiver); + int result = 1; + for (long i = 0; i < size; i++) { + Object elem = receivers.readArrayElement(receiver, i); + result = + 31 * result + + (elems.hasIdentity(elem) + ? elems.identityHashCode(elem) + : ObjectUtils.hashCode(elem)); + } + return result; + } catch (Exception e) { + throw LKQLRuntimeException.shouldNotHappen( + "Error in array like value hash code computing"); + } + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/BasicLKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/BasicLKQLValue.java new file mode 100644 index 000000000..71463048b --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/BasicLKQLValue.java @@ -0,0 +1,89 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.bases; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.exception.LKQLRuntimeException; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; + +/** This class is the base for all "basic" LKQL values. */ +@ExportLibrary(InteropLibrary.class) +public abstract class BasicLKQLValue implements LKQLValue { + + // ----- Attributes ----- + + protected final InteropLibrary thisUncachedLibrary = InteropLibrary.getUncached(this); + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + public boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + public Class> getLanguage() { + return LKQLLanguage.class; + } + + /** + * Get the default displayable string, exporting because this message is abstract and all + * classes which export the interop library must implement it. + */ + @ExportMessage + public String toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) { + return ""; + } + + // ----- Override methods ----- + + @Override + public String toString() { + return (String) thisUncachedLibrary.toDisplayString(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BasicLKQLValue other)) return false; + InteropLibrary otherUncached = InteropLibrary.getUncached(other); + return thisUncachedLibrary.isIdentical(this, other, otherUncached); + } + + @Override + public int hashCode() { + try { + return thisUncachedLibrary.identityHashCode(this); + } catch (UnsupportedMessageException e) { + throw LKQLRuntimeException.shouldNotHappen( + "All LKQL values must export an 'identityHashCode' message"); + } + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ObjectLKQLValue.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ObjectLKQLValue.java new file mode 100644 index 000000000..2bb303fcd --- /dev/null +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/bases/ObjectLKQLValue.java @@ -0,0 +1,196 @@ +/*---------------------------------------------------------------------------- +-- L K Q L J I T -- +-- -- +-- Copyright (C) 2022-2023, AdaCore -- +-- -- +-- This library is free software; you can redistribute it and/or modify it -- +-- under terms of the GNU General Public License as published by the Free -- +-- Software Foundation; either version 3, or (at your option) any later -- +-- version. This library is distributed in the hope that it will be useful, -- +-- but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHAN- -- +-- TABILITY or FITNESS FOR A PARTICULAR PURPOSE. -- +-- -- +-- As a special exception under Section 7 of GPL version 3, you are granted -- +-- additional permissions described in the GCC Runtime Library Exception, -- +-- version 3.1, as published by the Free Software Foundation. -- +-- -- +-- You should have received a copy of the GNU General Public License and -- +-- a copy of the GCC Runtime Library Exception along with this program; -- +-- see the files COPYING3 and COPYING.RUNTIME respectively. If not, see -- +-- -- +----------------------------------------------------------------------------*/ + +package com.adacore.lkql_jit.built_ins.values.bases; + +import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; +import com.adacore.lkql_jit.built_ins.values.lists.LKQLList; +import com.adacore.lkql_jit.exception.LKQLRuntimeException; +import com.adacore.lkql_jit.utils.functions.ObjectUtils; +import com.oracle.truffle.api.TruffleLanguage; +import com.oracle.truffle.api.interop.InteropLibrary; +import com.oracle.truffle.api.interop.UnknownIdentifierException; +import com.oracle.truffle.api.interop.UnsupportedMessageException; +import com.oracle.truffle.api.library.CachedLibrary; +import com.oracle.truffle.api.library.ExportLibrary; +import com.oracle.truffle.api.library.ExportMessage; +import com.oracle.truffle.api.object.DynamicObject; +import com.oracle.truffle.api.object.DynamicObjectLibrary; +import com.oracle.truffle.api.object.Shape; + +/** This class is the base for all LKQL object-like values. */ +@ExportLibrary(InteropLibrary.class) +public abstract class ObjectLKQLValue extends DynamicObject implements LKQLValue { + + protected static final DynamicObjectLibrary uncachedObjectLibrary = + DynamicObjectLibrary.getUncached(); + ; + + // ----- Constructors ----- + + public ObjectLKQLValue(Shape shape) { + super(shape); + } + + // ----- Uncached access methods ----- + + /** + * Get the value in the LKQL object at the given key with the uncached strategy. If the key + * doesn't exist then a null value is returned. This method uses an uncached library so this is + * not design for performance critical usages. + */ + public Object getUncached(final Object key) { + return uncachedObjectLibrary.getOrDefault(this, key, null); + } + + /** + * Get the key array from the object value. This method uses an uncached library so this is no + * designed for performance critical usages. + */ + public Object[] keysUncached() { + return uncachedObjectLibrary.getKeyArray(this); + } + + // ----- Class methods ----- + + /** + * Internal method to perform equality checking on object like LKQL values. + * + * @param lefts The library to access 'left' messages. + * @param rights The library to access 'right' messages. + * @param leftValues Interop library to access the 'left' values messages. + * @param rightValues Interop library to access the 'right' values messages. + */ + protected static boolean objectValueEquals( + ObjectLKQLValue left, + ObjectLKQLValue right, + DynamicObjectLibrary lefts, + DynamicObjectLibrary rights, + InteropLibrary leftValues, + InteropLibrary rightValues) { + // Get the objects key sets and compare their size + Object[] leftKeys = lefts.getKeyArray(left); + Object[] rightKeys = rights.getKeyArray(right); + if (leftKeys.length != rightKeys.length) return false; + + // Then compare each value + for (Object key : leftKeys) { + if (!rights.containsKey(right, key)) return false; + Object leftValue = lefts.getOrDefault(left, key, null); + Object rightValue = rights.getOrDefault(right, key, null); + if (leftValues.hasIdentity(leftValue)) { + if (!leftValues.isIdentical(leftValue, rightValue, rightValues)) return false; + } else { + if (!ObjectUtils.equals(leftValue, rightValue)) return false; + } + } + + // If we get here, the objects are equals + return true; + } + + // ----- Value methods ----- + + /** Tell the interop API that the value has an associated language. */ + @ExportMessage + public boolean hasLanguage() { + return true; + } + + /** Give the LKQL language class to the interop library. */ + @ExportMessage + public Class> getLanguage() { + return LKQLLanguage.class; + } + + /** + * Get the default displayable string, exporting because this message is abstract and all + * classes which export the interop library must implement it. + */ + @ExportMessage + public String toDisplayString(@SuppressWarnings("unused") boolean allowSideEffects) { + return ""; + } + + /** Tell the interop library that this value has members. */ + @ExportMessage + public boolean hasMembers() { + return true; + } + + /** + * Get if the given member is in the receiver object like value. All members are readable but + * not modifiable. + */ + @ExportMessage + public boolean isMemberReadable( + String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return objectLibrary.containsKey(this, member); + } + + /** Get the existing members for the receiver object like value. */ + @ExportMessage + public Object getMembers( + @SuppressWarnings("unused") boolean includeInternal, + @CachedLibrary("this") DynamicObjectLibrary objectLibrary) { + return new LKQLList(objectLibrary.getKeyArray(this)); + } + + /** Get the value of the wanted member in the receiver object like value. */ + @ExportMessage + public Object readMember( + String member, @CachedLibrary("this") DynamicObjectLibrary objectLibrary) + throws UnknownIdentifierException { + final Object result = objectLibrary.getOrDefault(this, member, null); + if (result == null) throw UnknownIdentifierException.create(member); + return result; + } + + // ----- Override methods ----- + + @Override + public String toString() { + InteropLibrary thisUncached = InteropLibrary.getUncached(this); + return (String) thisUncached.toDisplayString(this); + } + + @Override + public boolean equals(Object o) { + if (this == o) return true; + if (!(o instanceof BasicLKQLValue other)) return false; + InteropLibrary thisUncached = InteropLibrary.getUncached(this); + InteropLibrary otherUncached = InteropLibrary.getUncached(other); + return thisUncached.isIdentical(this, other, otherUncached); + } + + @Override + public int hashCode() { + try { + InteropLibrary thisUncached = InteropLibrary.getUncached(this); + return thisUncached.identityHashCode(this); + } catch (UnsupportedMessageException e) { + throw LKQLRuntimeException.shouldNotHappen( + "All LKQL values must export an 'identityHashCode' message"); + } + } +} diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java index 0715dc83a..c017bc98b 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/built_ins/values/lists/BaseLKQLList.java @@ -22,10 +22,9 @@ package com.adacore.lkql_jit.built_ins.values.lists; -import com.adacore.lkql_jit.LKQLLanguage; +import com.adacore.lkql_jit.built_ins.values.bases.ArrayLKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Indexable; import com.adacore.lkql_jit.built_ins.values.interfaces.Iterable; -import com.adacore.lkql_jit.built_ins.values.interfaces.LKQLValue; import com.adacore.lkql_jit.built_ins.values.interfaces.Truthy; import com.adacore.lkql_jit.built_ins.values.iterators.LKQLIterator; import com.adacore.lkql_jit.exception.LKQLRuntimeException; @@ -34,7 +33,6 @@ import com.adacore.lkql_jit.utils.functions.ObjectUtils; import com.adacore.lkql_jit.utils.functions.StringUtils; import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.TruffleLanguage; import com.oracle.truffle.api.dsl.Fallback; import com.oracle.truffle.api.dsl.Specialization; import com.oracle.truffle.api.interop.InteropLibrary; @@ -45,7 +43,7 @@ /** This abstract class represents all list like values in the LKQL language. */ @ExportLibrary(InteropLibrary.class) -public abstract class BaseLKQLList implements LKQLValue, Iterable, Indexable, Truthy { +public abstract class BaseLKQLList extends ArrayLKQLValue implements Iterable, Indexable, Truthy { // ----- Constructors ----- @@ -68,18 +66,6 @@ protected BaseLKQLList() {} // ----- Value methods ----- - /** Tell the interop API that the value has an associated language. */ - @ExportMessage - public boolean hasLanguage() { - return true; - } - - /** Give the LKQL language class to the interop library. */ - @ExportMessage - public Class> getLanguage() { - return LKQLLanguage.class; - } - /** Exported message to compare two lists. */ @ExportMessage public static class IsIdenticalOrUndefined { @@ -125,11 +111,13 @@ public static TriState onOther( } } - /** Return the identity hash code for the given LKQL list. */ - @CompilerDirectives.TruffleBoundary + /** Get the identity hash code for the given LKQL list */ @ExportMessage - public static int identityHashCode(BaseLKQLList receiver) { - return System.identityHashCode(receiver); + public static int identityHashCode( + BaseLKQLList receiver, + @CachedLibrary("receiver") InteropLibrary receivers, + @CachedLibrary(limit = Constants.DISPATCHED_LIB_LIMIT) InteropLibrary elems) { + return arrayValueHashCode(receiver, receivers, elems); } /** Get the displayable string for the interop library. */ @@ -175,7 +163,7 @@ public boolean asBoolean() { return this.isTruthy(); } - /** Tell the interop library that the value is array like. */ + /** Tell the interop library that tuple has array elements. */ @ExportMessage public boolean hasArrayElements() { return true; @@ -238,21 +226,4 @@ public boolean isTruthy() { return false; } } - - // ----- Override methods ----- - - @Override - public String toString() { - InteropLibrary listLibrary = InteropLibrary.getUncached(this); - return (String) listLibrary.toDisplayString(this); - } - - @Override - public boolean equals(Object o) { - if (this == o) return true; - if (!(o instanceof BaseLKQLList other)) return false; - InteropLibrary thisLibrary = InteropLibrary.getUncached(this); - InteropLibrary otherLibrary = InteropLibrary.getUncached(other); - return thisLibrary.isIdentical(this, other, otherLibrary); - } } diff --git a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ObjectUtils.java b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ObjectUtils.java index abcbc24d5..6549ba4d6 100644 --- a/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ObjectUtils.java +++ b/lkql_jit/language/src/main/java/com/adacore/lkql_jit/utils/functions/ObjectUtils.java @@ -44,6 +44,12 @@ public static boolean equals(Object left, Object right) { return Objects.equals(left, right); } + /** Bounded method to access an object hash code. */ + @CompilerDirectives.TruffleBoundary + public static int hashCode(Object o) { + return o.hashCode(); + } + /** * Get the string representation of the object. *