Skip to content

Commit

Permalink
Special Meta.Function to work as a handle to Function
Browse files Browse the repository at this point in the history
  • Loading branch information
JaroslavTulach committed Jun 12, 2023
1 parent 67fb583 commit 5d87c9c
Show file tree
Hide file tree
Showing 5 changed files with 75 additions and 27 deletions.
39 changes: 32 additions & 7 deletions distribution/lib/Standard/Base/0.0.0-dev/src/Meta.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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`.
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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.
Expand Down
Original file line number Diff line number Diff line change
@@ -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);
}
}
Original file line number Diff line number Diff line change
@@ -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;
Expand All @@ -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 {
Expand Down Expand Up @@ -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
Expand Down
4 changes: 1 addition & 3 deletions test/Tests/src/Semantic/Meta_Define_Usage.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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
15 changes: 11 additions & 4 deletions test/Tests/src/Semantic/Meta_Spec.enso
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand All @@ -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

0 comments on commit 5d87c9c

Please sign in to comment.