diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso index 3f224cedc8d5..0828aa95f424 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso @@ -11,6 +11,7 @@ import project.Data.Time.Time_Of_Day.Time_Of_Day import project.Data.Time.Time_Zone.Time_Zone import project.Data.Vector.Vector import project.Nothing.Nothing +import project.Function.Function as Std_Function import project.Polyglot.Java import project.Error.Error as Base_Error @@ -217,6 +218,20 @@ type Polyglot lang_str = get_polyglot_language self.value if lang_str == "java" then Language.Java else Language.Unknown +type Function + ## PRIVATE + Value value + + ## PRIVATE + ADVANCED + + Given a type object, method name and a parameter name, return the associated annotation if it exists. + + Arguments: + - parameter_name: The name of the parameter to get the attribute for. + get_annotation : Text -> Any + get_annotation self parameter_name = Meta.get_annotation self.value... Nothing parameter_name + ## ADVANCED Checks whether `self` represents the same underlying reference as `value`. @@ -366,13 +381,14 @@ atom_with_hole factory = @Builtin_Method "Meta.atom_with_hole_builtin" Arguments: - value: The runtime entity to get the meta representation of. meta : Any -> Atom | Constructor | Primitive | Polyglot | Unresolved_Symbol | Error -meta value = if is_atom value then Atom.Value value else - if is_atom_constructor value then Constructor.Value value else - if is_polyglot value then Polyglot.Value value else - if is_unresolved_symbol value then Unresolved_Symbol.Value value else - if is_error value then Error.Value value.catch else - if is_type value then Type.Value value.catch else - Primitive.Value value +meta value = if is_function value... then Function.Value value... else + if is_atom value then Atom.Value value else + if is_atom_constructor value then Constructor.Value value else + if is_polyglot value then Polyglot.Value value else + if is_unresolved_symbol value then Unresolved_Symbol.Value value else + if is_error value then Error.Value value.catch else + if is_type value then Type.Value value.catch else + Primitive.Value value ## PRIVATE ADVANCED @@ -457,6 +473,15 @@ is_atom_constructor value = @Builtin_Method "Meta.is_atom_constructor" is_atom : Any -> Boolean is_atom value = @Builtin_Method "Meta.is_atom" +## PRIVATE + + Checks if the provided value is a function. + + Arguments: + - value: The value to check. +is_function : Any -> Boolean +is_function value = @Builtin_Method "Meta.is_function" + ## PRIVATE Checks if the provided value is a runtime error. diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsFunctionNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsFunctionNode.java new file mode 100644 index 000000000000..47db53d397e6 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsFunctionNode.java @@ -0,0 +1,17 @@ +package org.enso.interpreter.node.expression.builtin.meta; + +import com.oracle.truffle.api.nodes.Node; +import org.enso.interpreter.dsl.AcceptsError; +import org.enso.interpreter.dsl.BuiltinMethod; +import org.enso.interpreter.runtime.type.TypesGen; + +@BuiltinMethod( + type = "Meta", + name = "is_function", + description = "Checks if the argument is an function.", + autoRegister = false) +public class IsFunctionNode extends Node { + boolean execute(@AcceptsError Object value) { + return TypesGen.isFunction(value); + } +} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java index 72f2d0f1d7b2..f9734bbddeaa 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/runtime/scope/ModuleScope.java @@ -1,15 +1,7 @@ package org.enso.interpreter.runtime.scope; -import com.oracle.truffle.api.CompilerDirectives.CompilationFinal; import com.oracle.truffle.api.CompilerDirectives.TruffleBoundary; import com.oracle.truffle.api.interop.TruffleObject; -import org.enso.interpreter.runtime.EnsoContext; -import org.enso.interpreter.runtime.Module; -import org.enso.interpreter.runtime.callable.function.Function; -import org.enso.interpreter.runtime.data.Type; -import org.enso.interpreter.runtime.error.RedefinedMethodException; -import org.enso.interpreter.runtime.error.RedefinedConversionException; - import java.util.Collection; import java.util.HashMap; import java.util.HashSet; @@ -18,6 +10,12 @@ import java.util.Objects; import java.util.Optional; import java.util.Set; +import org.enso.interpreter.runtime.EnsoContext; +import org.enso.interpreter.runtime.Module; +import org.enso.interpreter.runtime.callable.function.Function; +import org.enso.interpreter.runtime.data.Type; +import org.enso.interpreter.runtime.error.RedefinedConversionException; +import org.enso.interpreter.runtime.error.RedefinedMethodException; /** A representation of Enso's per-file top-level scope. */ public final class ModuleScope implements TruffleObject { @@ -194,11 +192,14 @@ public Function lookupMethodDefinition(Type type, String name) { return definedHere; } - return imports.stream() - .map(scope -> scope.getExportedMethod(type, name)) - .filter(Objects::nonNull) - .findFirst() - .orElse(null); + for (var scope : imports) { + var method = scope.getExportedMethod(type, name); + if (method != null) { + return method; + } + } + + return null; } @TruffleBoundary diff --git a/test/Tests/src/Semantic/Meta_Define_Usage.enso b/test/Tests/src/Semantic/Meta_Define_Usage.enso index 9bf85d26f139..d4ae2d85acfa 100644 --- a/test/Tests/src/Semantic/Meta_Define_Usage.enso +++ b/test/Tests/src/Semantic/Meta_Define_Usage.enso @@ -6,6 +6,4 @@ call_describe_better it = it.describe_better annotate_describe_better it = Meta.get_annotation it "describe_better" "which" obtain_describe_better it = fn = it.describe_better... - anno = Meta.get_annotation fn... Nothing "which" - anno.is_nothing - fn... + Meta.meta fn diff --git a/test/Tests/src/Semantic/Meta_Spec.enso b/test/Tests/src/Semantic/Meta_Spec.enso index 7c9ca91d5870..852ab4f05024 100644 --- a/test/Tests/src/Semantic/Meta_Spec.enso +++ b/test/Tests/src/Semantic/Meta_Spec.enso @@ -401,6 +401,13 @@ spec = Meta.type_of (_.is_nothing) . should_equal Function Meta.type_of (.is_nothing) . should_equal Function + Test.group "Meta for functions" <| + Test.specify "Meta for lambda" <| + fn_meta = Meta.meta (x-> 2 * x) + case fn_meta of + _ : Meta.Function -> Nothing + _ -> Test.fail "Expecting Meta.Function: " + (Meta.type_of fn_meta).to_text + Test.group "Extension methods and get_annotation" <| it = Meta_Spec_Type.Value 6 7 @@ -411,15 +418,15 @@ spec = Meta_Define_Usage.call_describe_better it "mul" . should_equal 42 Test.specify "verify calling everything works" <| - describe_anno = Meta.get_annotation it.describe... Nothing "which" + wrap = Meta.meta it.describe... + describe_anno = wrap.get_annotation "which" describe_anno it . should_equal 13 # Meta_Define_Usage can resolve the describe_better method - fn = (Meta_Define_Usage.obtain_describe_better it)... - fn.is_nothing . should_be_false + meta_fn = Meta_Define_Usage.obtain_describe_better it # we can query annotations for the resolved function - describe_better_anno = Meta.get_annotation fn... Nothing "which" + describe_better_anno = meta_fn.get_annotation "which" describe_better_anno it . should_equal 13 main = Test_Suite.run_main spec