diff --git a/app/gui/src/controller/graph/widget.rs b/app/gui/src/controller/graph/widget.rs index 6765b5dd9d06..8b97e20b230d 100644 --- a/app/gui/src/controller/graph/widget.rs +++ b/app/gui/src/controller/graph/widget.rs @@ -392,7 +392,7 @@ impl QueryData { /// Generate visualization metadata for this query. fn visualization_metadata(&self) -> Metadata { let arguments: Vec = vec![ - Self::escape_visualization_argument(&self.method_name).into(), + format!("(self.{}...)", &self.method_name).into(), Self::arg_sequence(&self.arguments).into(), ]; diff --git a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso index d004a1f1c7cd..4c2d993c1eb6 100644 --- a/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso +++ b/distribution/lib/Standard/Base/0.0.0-dev/src/Errors/Common.enso @@ -163,7 +163,7 @@ type No_Such_Method Convert the No_Such_Method error to a human-readable format. to_display_text : Text to_display_text self = - target_type_name = if Meta.is_polyglot self.target then self.target.to_display_text else (Meta.type_of self.target).to_display_text + target_type_name = if Meta.meta self.target . is_a Meta.Polyglot then self.target.to_display_text else (Meta.type_of self.target).to_display_text "Method `"+self.method_name+"` of type "+target_type_name+" could not be found." @Builtin_Type 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..05455f5f4be6 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`. @@ -365,14 +380,16 @@ 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 : Any -> Atom | Constructor | Primitive | Polyglot | Unresolved_Symbol | Error | Function +meta value = + fac_vec = [ Function.Value, Atom.Value, Constructor.Value, Polyglot.Value, Unresolved_Symbol.Value, Error.Value, Type.Value, Primitive.Value ] + factories = fac_vec.to_array + case meta_builtin -1 value... factories of + index : Integer -> meta_builtin index value.catch factories + ret -> ret + +## PRIVATE +meta_builtin index value factories = @Builtin_Method "Meta.meta_builtin" ## PRIVATE ADVANCED @@ -439,59 +456,6 @@ type Language An unknown language. Unknown -## PRIVATE - - Checks if the provided value is an atom constructor. - - Arguments: - - value: The value to check. -is_atom_constructor : Any -> Boolean -is_atom_constructor value = @Builtin_Method "Meta.is_atom_constructor" - -## PRIVATE - - Checks if the provided value is an atom. - - Arguments: - - value: The value to check. -is_atom : Any -> Boolean -is_atom value = @Builtin_Method "Meta.is_atom" - -## PRIVATE - - Checks if the provided value is a runtime error. - - Arguments: - - value: The value to check. -is_error : Any -> Boolean -is_error value = @Builtin_Method "Meta.is_error" - -## PRIVATE - - Checks if the provided value is a type. - - Arguments: - - value: The value to check. -is_type : Any -> Boolean -is_type value = @Builtin_Method "Meta.is_type" - -## PRIVATE - - Checks if the provided value is a polyglot value. - - Arguments: - - value: The value to check. -is_polyglot : Any -> Boolean -is_polyglot value = @Builtin_Method "Meta.is_polyglot" - -## PRIVATE - - Checks if the provided value is an unresolved symbol. - - Arguments: - - value: The value to check. -is_unresolved_symbol : Any -> Boolean -is_unresolved_symbol value = @Builtin_Method "Meta.is_unresolved_symbol" ## PRIVATE diff --git a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Widgets.enso b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Widgets.enso index 01ce017d3a0a..8a1dd95e7f78 100644 --- a/distribution/lib/Standard/Visualization/0.0.0-dev/src/Widgets.enso +++ b/distribution/lib/Standard/Visualization/0.0.0-dev/src/Widgets.enso @@ -6,10 +6,22 @@ from Standard.Base import all Returns full annotation data for all requested arguments. get_widget_json : Any -> Text -> Vector Text -> Text get_widget_json value call_name argument_names = - read_annotation argument = - annotation = Warning.clear <| Meta.get_annotation value call_name argument - case annotation of - _ : Function -> annotation value - _ -> annotation - annotations = argument_names.map (arg -> [arg, read_annotation arg]) + meta = Meta.meta call_name... + annotations = case meta of + _ : Meta.Function -> + read_new_annotation argument = + annotation = Warning.clear <| meta.get_annotation argument + case annotation of + _ : Function -> annotation value + _ -> annotation + argument_names.map (arg -> [arg, read_new_annotation arg]) + _ -> + read_annotation argument = + annotation = Warning.clear <| Meta.get_annotation value call_name argument + case annotation of + _ : Function -> annotation value + _ -> annotation + + argument_names.map (arg -> [arg, read_annotation arg]) + annotations.to_json diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAnnotationNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAnnotationNode.java index bbd28da2867c..d3720942df5b 100644 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAnnotationNode.java +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/GetAnnotationNode.java @@ -1,5 +1,10 @@ package org.enso.interpreter.node.expression.builtin.meta; +import com.oracle.truffle.api.CompilerDirectives; +import com.oracle.truffle.api.dsl.Cached; +import com.oracle.truffle.api.dsl.Specialization; +import com.oracle.truffle.api.frame.VirtualFrame; +import com.oracle.truffle.api.library.CachedLibrary; import org.enso.interpreter.dsl.BuiltinMethod; import org.enso.interpreter.node.BaseNode; import org.enso.interpreter.node.callable.thunk.ThunkExecutorNode; @@ -13,12 +18,6 @@ import org.enso.interpreter.runtime.scope.ModuleScope; import org.enso.interpreter.runtime.state.State; -import com.oracle.truffle.api.CompilerDirectives; -import com.oracle.truffle.api.dsl.Cached; -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.frame.VirtualFrame; -import com.oracle.truffle.api.library.CachedLibrary; - @BuiltinMethod( type = "Meta", name = "get_annotation", @@ -29,6 +28,27 @@ public abstract class GetAnnotationNode extends BaseNode { abstract Object execute( VirtualFrame frame, State state, Object target, Object method, Object parameter); + @Specialization + Object doExecute( + VirtualFrame frame, + State state, + Function methodFunction, + Object method, + Object parameter, + @CachedLibrary(limit = "3") TypesLibrary types, + @Cached ThunkExecutorNode thunkExecutorNode, + @Cached ExpectStringNode expectStringNode + ) { + String parameterName = expectStringNode.execute(parameter); + Annotation annotation = methodFunction.getSchema().getAnnotation(parameterName); + if (annotation != null) { + Function thunk = + Function.thunk(annotation.getExpression().getCallTarget(), frame.materialize()); + return thunkExecutorNode.executeThunk(frame, thunk, state, getTailStatus()); + } + return EnsoContext.get(this).getNothing(); + } + @Specialization Object doExecute( VirtualFrame frame, diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomConstructorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomConstructorNode.java deleted file mode 100644 index 46abd9e29f0c..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomConstructorNode.java +++ /dev/null @@ -1,17 +0,0 @@ -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_atom_constructor", - description = "Checks if the argument is a constructor.", - autoRegister = false) -public class IsAtomConstructorNode extends Node { - boolean execute(@AcceptsError Object value) { - return TypesGen.isAtomConstructor(value); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomNode.java deleted file mode 100644 index 9d9bf28d214d..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsAtomNode.java +++ /dev/null @@ -1,17 +0,0 @@ -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.callable.atom.Atom; - -@BuiltinMethod( - type = "Meta", - name = "is_atom", - description = "Checks if the argument is an atom", - autoRegister = false) -public class IsAtomNode extends Node { - boolean execute(@AcceptsError Object value) { - return value instanceof Atom; - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsErrorNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsErrorNode.java deleted file mode 100644 index cdb5f804b5fc..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsErrorNode.java +++ /dev/null @@ -1,17 +0,0 @@ -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_error", - description = "Checks if the argument is an error.", - autoRegister = false) -public class IsErrorNode extends Node { - boolean execute(@AcceptsError Object value) { - return TypesGen.isDataflowError(value); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsPolyglotNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsPolyglotNode.java deleted file mode 100644 index 2abda29de27c..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsPolyglotNode.java +++ /dev/null @@ -1,25 +0,0 @@ -package org.enso.interpreter.node.expression.builtin.meta; - -import com.oracle.truffle.api.dsl.Specialization; -import com.oracle.truffle.api.nodes.Node; -import org.enso.interpreter.dsl.AcceptsError; -import org.enso.interpreter.dsl.BuiltinMethod; -import org.enso.interpreter.runtime.EnsoContext; - -@BuiltinMethod( - type = "Meta", - name = "is_polyglot", - description = "Checks if the argument is a polyglot value.", - autoRegister = false) -public abstract class IsPolyglotNode extends Node { - static IsPolyglotNode build() { - return IsPolyglotNodeGen.create(); - } - - abstract boolean execute(@AcceptsError Object value); - - @Specialization - boolean doExecute(Object value) { - return EnsoContext.get(this).getEnvironment().isHostObject(value); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsTypeNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsTypeNode.java deleted file mode 100644 index 18aa16120c61..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsTypeNode.java +++ /dev/null @@ -1,17 +0,0 @@ -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.data.Type; - -@BuiltinMethod( - type = "Meta", - name = "is_type", - description = "Checks if the argument is a type", - autoRegister = false) -public class IsTypeNode extends Node { - boolean execute(@AcceptsError Object value) { - return value instanceof Type; - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsUnresolvedSymbolNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsUnresolvedSymbolNode.java deleted file mode 100644 index 69f9d0ada567..000000000000 --- a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/IsUnresolvedSymbolNode.java +++ /dev/null @@ -1,17 +0,0 @@ -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_unresolved_symbol", - description = "Checks if the argument is an unresolved symbol.", - autoRegister = false) -public class IsUnresolvedSymbolNode extends Node { - boolean execute(@AcceptsError Object value) { - return TypesGen.isUnresolvedSymbol(value) || TypesGen.isUnresolvedConversion(value); - } -} diff --git a/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/MetaBuiltinNode.java b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/MetaBuiltinNode.java new file mode 100644 index 000000000000..4551777e6a86 --- /dev/null +++ b/engine/runtime/src/main/java/org/enso/interpreter/node/expression/builtin/meta/MetaBuiltinNode.java @@ -0,0 +1,55 @@ +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.EnsoContext; +import org.enso.interpreter.runtime.callable.atom.Atom; +import org.enso.interpreter.runtime.callable.atom.AtomConstructor; +import org.enso.interpreter.runtime.data.Array; +import org.enso.interpreter.runtime.type.TypesGen; + +@BuiltinMethod( + type = "Meta", + name = "meta_builtin", + description = "Find the type and constructs a Meta instances.", + autoRegister = false) +public class MetaBuiltinNode extends Node { + Object execute(long index, @AcceptsError Object value, Array factories) { + if (index < 0) { + index = findIndex(value); + } + if (index < 0) { + return -index; + } + var factory = (AtomConstructor) factories.getItems()[(int) index]; + return factory.newInstance(value); + } + + private int findIndex(Object value) { + if (TypesGen.isFunction(value)) { + return 0; + } + if (value instanceof Atom) { + return 1; + } + if (TypesGen.isAtomConstructor(value)) { + return 2; + } + if (TypesGen.isUnresolvedSymbol(value) || TypesGen.isUnresolvedConversion(value)) { + return 4; + } + if (TypesGen.isDataflowError(value)) { + return -5; + } + if (TypesGen.isType(value)) { + return 6; + } + var ctx = EnsoContext.get(this); + if (ctx.getEnvironment().isHostObject(value)) { + return 3; + } + // primitive value + return 7; + } +} 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_Extensions.enso b/test/Tests/src/Semantic/Meta_Define_Extensions.enso new file mode 100644 index 000000000000..55768b3de113 --- /dev/null +++ b/test/Tests/src/Semantic/Meta_Define_Extensions.enso @@ -0,0 +1,7 @@ +import project.Semantic.Meta_Define_Type.Meta_Spec_Type + + +@which (self -> self.b + self.a) +Meta_Spec_Type.describe_better self which = case which of + "mul" -> self.a * self.b + _ -> self.a / self.b diff --git a/test/Tests/src/Semantic/Meta_Define_Type.enso b/test/Tests/src/Semantic/Meta_Define_Type.enso new file mode 100644 index 000000000000..7e5850fb409d --- /dev/null +++ b/test/Tests/src/Semantic/Meta_Define_Type.enso @@ -0,0 +1,8 @@ +type Meta_Spec_Type + Value a b + + @which (self -> self.a+self.b) + describe self which="first" = case which of + "first" -> self.a + _ -> self.b + diff --git a/test/Tests/src/Semantic/Meta_Define_Usage.enso b/test/Tests/src/Semantic/Meta_Define_Usage.enso new file mode 100644 index 000000000000..d4ae2d85acfa --- /dev/null +++ b/test/Tests/src/Semantic/Meta_Define_Usage.enso @@ -0,0 +1,9 @@ +from Standard.Base import Meta, Nothing +import project.Semantic.Meta_Define_Type.Meta_Spec_Type +import project.Semantic.Meta_Define_Extensions + +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... + Meta.meta fn diff --git a/test/Tests/src/Semantic/Meta_Spec.enso b/test/Tests/src/Semantic/Meta_Spec.enso index 9ce2e1f17fef..9e068ea8ab2f 100644 --- a/test/Tests/src/Semantic/Meta_Spec.enso +++ b/test/Tests/src/Semantic/Meta_Spec.enso @@ -16,6 +16,9 @@ from Standard.Test import Test, Test_Suite import Standard.Test.Extensions import Standard.Test.Test_Result.Test_Result +import project.Semantic.Meta_Define_Type.Meta_Spec_Type +import project.Semantic.Meta_Define_Usage + type My_Type @foo (test_method) @baz (My_Type.Value 1 2 3) @@ -209,7 +212,6 @@ spec = Test.specify "constructors of Boolean" <| typ = Boolean - Meta.is_atom typ . should_be_false meta_typ = Meta.meta typ meta_typ . should_be_a Meta.Type meta_typ.name . should_equal "Boolean" @@ -225,7 +227,6 @@ spec = Test.specify "constructors of MyType" <| typ = My_Type - Meta.is_atom typ . should_be_false meta_typ = Meta.meta typ meta_typ . should_be_a Meta.Type meta_typ.name . should_equal "My_Type" @@ -242,7 +243,6 @@ spec = Test.specify "methods of MyType" <| typ = My_Type - Meta.is_atom typ . should_be_false meta_typ = Meta.meta typ meta_typ . should_be_a Meta.Type methods = case meta_typ of @@ -326,7 +326,7 @@ spec = atom = pair.value fill = pair.fill - Meta.is_atom atom . should_be_true + Meta.meta atom . is_a Meta.Atom . should_be_true atom.foo . should_equal 1 atom.baz . should_equal 3 @@ -366,7 +366,7 @@ spec = atom = pair.value fill = pair.fill - Meta.is_atom atom . should_be_true + Meta.meta atom . is_a Meta.Atom . should_be_true case atom.foo of n : Number -> Test.fail "Shouldn't be number yet: "+n @@ -390,11 +390,40 @@ spec = case atom.bar of n : Number -> Test.fail "Not changed to number: "+n _ -> Nothing - Test.group "Unresolved symbol" + + Test.group "Unresolved symbol" <| Test.specify "should be treated as a Function" <| (_.is_nothing) . is_a Function . should_equal True (.is_nothing) . is_a Function . should_equal True 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 + + Test.specify "verify calling everything works" <| + it.describe . should_equal 6 + it.describe "second" . should_equal 7 + Panic.catch Any (it.describe_better) (_->"Not executed") . should_equal "Not executed" + Meta_Define_Usage.call_describe_better it "mul" . should_equal 42 + + Test.specify "verify calling everything works" <| + 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 + meta_fn = Meta_Define_Usage.obtain_describe_better it + # we can query annotations for the resolved function + describe_better_anno = meta_fn.get_annotation "which" + describe_better_anno it . should_equal 13 + main = Test_Suite.run_main spec