mirror of
https://github.com/enso-org/enso.git
synced 2024-12-23 00:52:09 +03:00
Implement Generic Programming Facilities (#1216)
This commit is contained in:
parent
0a9e2a42ce
commit
2a44a858a7
@ -3,4 +3,4 @@ from Base import all
|
|||||||
## Returns the method name of the method that could not be found.
|
## Returns the method name of the method that could not be found.
|
||||||
No_Such_Method_Error.method_name : Text
|
No_Such_Method_Error.method_name : Text
|
||||||
No_Such_Method_Error.method_name =
|
No_Such_Method_Error.method_name =
|
||||||
Meta.get_unresolved_symbol_name this.symbol
|
Meta.meta this.symbol . name
|
||||||
|
@ -4,11 +4,13 @@ import Base.Number.Extensions
|
|||||||
import Base.Text.Extensions
|
import Base.Text.Extensions
|
||||||
import Base.System.File
|
import Base.System.File
|
||||||
import Base.Meta.Enso_Project
|
import Base.Meta.Enso_Project
|
||||||
|
import Base.Meta.Meta
|
||||||
import Base.Error.Extensions
|
import Base.Error.Extensions
|
||||||
import Base.Polyglot.Java
|
import Base.Polyglot.Java
|
||||||
from Builtins import Unit, Number, Integer, Any, True, False
|
from Builtins import Unit, Number, Integer, Any, True, False, Cons
|
||||||
|
|
||||||
from Builtins export all
|
export Base.Meta.Meta
|
||||||
|
from Builtins export all hiding Meta
|
||||||
|
|
||||||
from Base.Meta.Enso_Project export all
|
from Base.Meta.Enso_Project export all
|
||||||
from Base.List export Nil, Cons
|
from Base.List export Nil, Cons
|
||||||
@ -68,3 +70,26 @@ type Math
|
|||||||
to its diameter.
|
to its diameter.
|
||||||
Math.pi : Decimal
|
Math.pi : Decimal
|
||||||
Math.pi = 3.141592653589793
|
Math.pi = 3.141592653589793
|
||||||
|
|
||||||
|
## Generic equality of arbitrary values.
|
||||||
|
Any.== : Any -> Boolean
|
||||||
|
Any.== that = if Meta.is_same_object this that then True else
|
||||||
|
this_meta = Meta.meta this
|
||||||
|
that_meta = Meta.meta that
|
||||||
|
case Cons this_meta that_meta of
|
||||||
|
Cons (Meta.Atom _) (Meta.Atom _) ->
|
||||||
|
c_1 = this_meta.constructor
|
||||||
|
c_2 = that_meta.constructor
|
||||||
|
if not (Meta.is_same_object c_1 c_2) then False else
|
||||||
|
f_1 = this_meta.fields
|
||||||
|
f_2 = that_meta.fields
|
||||||
|
0.upto f_1.length . every i-> (f_1.at i) == (f_2.at i)
|
||||||
|
Cons (Meta.Error _) (Meta.Error _) -> this_meta.payload == that_meta.payload
|
||||||
|
Cons (Meta.Polyglot o_1) (Meta.Polyglot o_2) ->
|
||||||
|
langs_match = this_meta.language == Meta.Java && that_meta.language == Meta.Java
|
||||||
|
if not langs_match then False else o_1.equals [o_2]
|
||||||
|
## Constructor comparison is covered by the identity equality.
|
||||||
|
Primitive objects should define their own equality.
|
||||||
|
Therefore, there is no more cases to handle in this method.
|
||||||
|
_ -> False
|
||||||
|
|
||||||
|
88
distribution/std-lib/Base/src/Meta/Meta.enso
Normal file
88
distribution/std-lib/Base/src/Meta/Meta.enso
Normal file
@ -0,0 +1,88 @@
|
|||||||
|
from Base import all
|
||||||
|
import Builtins
|
||||||
|
|
||||||
|
## Represents a polyglot language.
|
||||||
|
type Language
|
||||||
|
## The Java laguage.
|
||||||
|
type Java
|
||||||
|
## Unknown language.
|
||||||
|
type Unknown
|
||||||
|
|
||||||
|
## A meta-representation of a runtime value.
|
||||||
|
|
||||||
|
! Warning
|
||||||
|
The functionality contained in this module exposes certain implementation
|
||||||
|
details of the language. As such, the API has no stability guarantees and
|
||||||
|
is subject to change as the Enso interpreter evolves.
|
||||||
|
type Meta
|
||||||
|
## An Atom meta-representation.
|
||||||
|
type Atom value
|
||||||
|
## A constructor meta-representation.
|
||||||
|
type Constructor value
|
||||||
|
## A primitive value meta-prepresentation.
|
||||||
|
type Primitive value
|
||||||
|
## An unresolved symbol meta-representation.
|
||||||
|
type Unresolved_Symbol value
|
||||||
|
## An error meta-representation.
|
||||||
|
type Error value
|
||||||
|
## A polyglot value meta-representation.
|
||||||
|
type Polyglot value
|
||||||
|
|
||||||
|
## Returns a vector of field values of the given atom.
|
||||||
|
Atom.fields : Vector
|
||||||
|
Atom.fields = Vector (Builtins.Meta.get_atom_fields this.value)
|
||||||
|
|
||||||
|
## Returns a constructor value of the given atom.
|
||||||
|
Atom.constructor : Any
|
||||||
|
Atom.constructor = Builtins.Meta.get_atom_constructor this.value
|
||||||
|
|
||||||
|
## Returns a new unresolved symbol with its name changed to the provided
|
||||||
|
argument.
|
||||||
|
Unresolved_Symbol.rename : Text -> Any
|
||||||
|
Unresolved_Symbol.rename new_name =
|
||||||
|
Builtins.Meta.create_unresolved_symbol new_name this.scope
|
||||||
|
|
||||||
|
## Returns the name of an unresolved symbol.
|
||||||
|
Unresolved_Symbol.name : Text
|
||||||
|
Unresolved_Symbol.name = Builtins.Meta.get_unresolved_symbol_name this.value
|
||||||
|
|
||||||
|
## Returns the definition scope of an unresolved symbol.
|
||||||
|
Unresolved_Symbol.scope : Any
|
||||||
|
Unresolved_Symbol.scope = Builtins.Meta.get_unresolved_symbol_scope this.value
|
||||||
|
|
||||||
|
## Returns the payload carried by an error value.
|
||||||
|
Error.payload : Any
|
||||||
|
Error.payload = this.value.catch e->e
|
||||||
|
|
||||||
|
## Returns a vector of field names defined by a constructor.
|
||||||
|
Constructor.fields : Vector
|
||||||
|
Constructor.fields = Vector (Builtins.Meta.get_constructor_fields this.value)
|
||||||
|
|
||||||
|
## Returns the name of a constructor.
|
||||||
|
Constructor.name : Text
|
||||||
|
Constructor.name = Builtins.Meta.get_constructor_name this.value
|
||||||
|
|
||||||
|
## Creates a new atom of the given constructor, with field values provided
|
||||||
|
in the `fields` vector.
|
||||||
|
Constructor.new : Vector -> Any
|
||||||
|
Constructor.new fields = Builtins.Meta.new_atom this.value fields.to_array
|
||||||
|
|
||||||
|
## Returns the language of a polyglot value.
|
||||||
|
Polyglot.get_language : Language
|
||||||
|
Polyglot.get_language =
|
||||||
|
lang_str = Builtins.Meta.get_polyglot_language
|
||||||
|
if lang_str == "java" then Java else Unknown
|
||||||
|
|
||||||
|
## Returns a meta-representation of a given runtime entity.
|
||||||
|
meta : Any -> Meta
|
||||||
|
meta value = if Builtins.Meta.is_atom value then Atom value else
|
||||||
|
if Builtins.Meta.is_constructor value then Constructor value else
|
||||||
|
if Builtins.Meta.is_polyglot value then Polyglot value else
|
||||||
|
if Builtins.Meta.is_unresolved_symbol value then Unresolved_Symbol value else
|
||||||
|
if Builtins.Meta.is_error value then Error value else
|
||||||
|
Primitive value
|
||||||
|
|
||||||
|
## Checks whether two objects are represented by the same underlying reference.
|
||||||
|
This is a power-user feature, that is only useful for certain optimizations.
|
||||||
|
is_same_object : Any -> Any -> Boolean
|
||||||
|
is_same_object value_1 value_2 = Builtins.Meta.is_same_object value_1 value_2
|
@ -83,3 +83,11 @@ Integer.upto n = Range this n
|
|||||||
Returns `True` when `this` and `that` are at most `epsilon` apart.
|
Returns `True` when `this` and `that` are at most `epsilon` apart.
|
||||||
Number.equals : Number -> Number -> Boolean
|
Number.equals : Number -> Number -> Boolean
|
||||||
Number.equals that epsilon=0.0 = (this - that).abs <= epsilon
|
Number.equals that epsilon=0.0 = (this - that).abs <= epsilon
|
||||||
|
|
||||||
|
## Returns the smaller value of `this` and `that`.
|
||||||
|
Number.min : Number -> Number
|
||||||
|
Number.min that = if this < that then this else that
|
||||||
|
|
||||||
|
## Returns the larger value of `this` and `that`.
|
||||||
|
Number.max : Number -> Number
|
||||||
|
Number.max that = if this > that then this else that
|
||||||
|
@ -197,6 +197,22 @@ type Vector
|
|||||||
take_right count = if count >= this.length then this else
|
take_right count = if count >= this.length then this else
|
||||||
this.drop (this.length - count)
|
this.drop (this.length - count)
|
||||||
|
|
||||||
|
## Performs a pair-wise operation passed in `function` on consecutive
|
||||||
|
elements of `this` and `that`.
|
||||||
|
The result of this function is a vector of length being the shorter of
|
||||||
|
`this` and `that`, containing results of calling `function`.
|
||||||
|
> Example
|
||||||
|
To pairwise-sum two vectors:
|
||||||
|
zip [1, 2, 3] [4, 5, 6] (+) == [5, 7, 9]
|
||||||
|
When the `function` is not provided, it defaults to creating a pair
|
||||||
|
of both elements:
|
||||||
|
zip [1, 2, 3] [4, 5, 6] == [[1, 4], [2, 5], [3, 6]]
|
||||||
|
zip : Vector -> (Any -> Any -> Any) -> Vector
|
||||||
|
zip that function=[_,_] =
|
||||||
|
len = min this.length that.length
|
||||||
|
Vector.new len i-> function (this.at i) (that.at i)
|
||||||
|
|
||||||
|
|
||||||
## A builder type for Enso vectors.
|
## A builder type for Enso vectors.
|
||||||
|
|
||||||
A vector builder is a mutable data structure, that allows to gather a
|
A vector builder is a mutable data structure, that allows to gather a
|
||||||
|
@ -434,6 +434,8 @@ public abstract class MethodResolverNode extends Node {
|
|||||||
return context.getBuiltins().polyglot().getPolyglotToTextFunction();
|
return context.getBuiltins().polyglot().getPolyglotToTextFunction();
|
||||||
} else if (symbol.getName().equals("catch")) {
|
} else if (symbol.getName().equals("catch")) {
|
||||||
return symbol.resolveFor(context.getBuiltins().any());
|
return symbol.resolveFor(context.getBuiltins().any());
|
||||||
|
} else if (symbol.getName().equals("==")) {
|
||||||
|
return symbol.resolveFor(context.getBuiltins().any());
|
||||||
} else {
|
} else {
|
||||||
return context.getBuiltins().polyglot().buildPolyglotMethodDispatch(symbol);
|
return context.getBuiltins().polyglot().buildPolyglotMethodDispatch(symbol);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_atom_constructor",
|
||||||
|
description = "Gets the constructor of an atom.")
|
||||||
|
public class GetAtomConstructorNode extends Node {
|
||||||
|
AtomConstructor execute(Object _this, Atom atom) {
|
||||||
|
return atom.getConstructor();
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.callable.UnresolvedSymbol;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.data.Array;
|
||||||
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_atom_fields",
|
||||||
|
description = "Gets the fields of an unresolved atom.")
|
||||||
|
public class GetAtomFieldsNode extends Node {
|
||||||
|
Array execute(Object _this, Atom atom) {
|
||||||
|
return new Array(atom.getFields());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,24 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.callable.argument.ArgumentDefinition;
|
||||||
|
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.data.text.Text;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_constructor_fields",
|
||||||
|
description = "Gets the field names of a constructor.")
|
||||||
|
public class GetConstructorFieldNamesNode extends Node {
|
||||||
|
Array execute(Object _this, AtomConstructor atom_constructor) {
|
||||||
|
ArgumentDefinition[] fields = atom_constructor.getFields();
|
||||||
|
Object[] result = new Object[fields.length];
|
||||||
|
for (int i = 0; i < fields.length; i++) {
|
||||||
|
result[i] = Text.create(fields[i].getName());
|
||||||
|
}
|
||||||
|
return new Array(result);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,17 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.Atom;
|
||||||
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_constructor_name",
|
||||||
|
description = "Gets the name of a constructor.")
|
||||||
|
public class GetConstructorNameNode extends Node {
|
||||||
|
Text execute(Object _this, AtomConstructor atom_constructor) {
|
||||||
|
return Text.create(atom_constructor.getName());
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,34 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.Cached;
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.data.text.Text;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "get_polyglot_language",
|
||||||
|
description = "Returns a text representation of a language of origin of a given value.")
|
||||||
|
public abstract class GetPolyglotLanguageNode extends Node {
|
||||||
|
static GetPolyglotLanguageNode build() {
|
||||||
|
return GetPolyglotLanguageNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
private final Text java = Text.create("java");
|
||||||
|
private final Text unknown = Text.create("unknown");
|
||||||
|
|
||||||
|
abstract Text execute(Object _this, Object value);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
Text doExecute(Object _this, Object value, @CachedContext(Language.class) Context context) {
|
||||||
|
if (context.getEnvironment().isHostObject(value)) {
|
||||||
|
return java;
|
||||||
|
} else {
|
||||||
|
return unknown;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
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.")
|
||||||
|
public class IsAtomConstructorNode extends Node {
|
||||||
|
boolean execute(Object _this, Object value) {
|
||||||
|
return TypesGen.isAtomConstructor(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "is_atom",
|
||||||
|
description = "Checks if the argument is an atom")
|
||||||
|
public class IsAtomNode extends Node {
|
||||||
|
boolean execute(Object _this, Object value) {
|
||||||
|
return TypesGen.isAtom(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
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.")
|
||||||
|
public class IsErrorNode extends Node {
|
||||||
|
boolean execute(Object _this, Object value) {
|
||||||
|
return TypesGen.isRuntimeError(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,23 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.dsl.CachedContext;
|
||||||
|
import com.oracle.truffle.api.dsl.Specialization;
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.Language;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.Context;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
|
@BuiltinMethod(type = "Meta", name = "is_polyglot", description = "Checks if the argument is a polyglot value.")
|
||||||
|
public abstract class IsPolyglotNode extends Node {
|
||||||
|
static IsPolyglotNode build() {
|
||||||
|
return IsPolyglotNodeGen.create();
|
||||||
|
}
|
||||||
|
|
||||||
|
abstract boolean execute(Object _this, Object value);
|
||||||
|
|
||||||
|
@Specialization
|
||||||
|
boolean doExecute(Object _this, Object value, @CachedContext(Language.class) Context context) {
|
||||||
|
return context.getEnvironment().isHostObject(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
import org.enso.interpreter.runtime.type.TypesGen;
|
||||||
|
|
||||||
|
@BuiltinMethod(
|
||||||
|
type = "Meta",
|
||||||
|
name = "is_same_object",
|
||||||
|
description = "Checks if the two arguments share an underlying reference.")
|
||||||
|
public class IsSameObjectNode extends Node {
|
||||||
|
boolean execute(Object _this, Object value_1, Object value_2) {
|
||||||
|
return value_1 == value_2;
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,15 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
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.")
|
||||||
|
public class IsUnresolvedSymbolNode extends Node {
|
||||||
|
boolean execute(Object _this, Object value) {
|
||||||
|
return TypesGen.isUnresolvedSymbol(value);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,18 @@
|
|||||||
|
package org.enso.interpreter.node.expression.builtin.meta;
|
||||||
|
|
||||||
|
import com.oracle.truffle.api.nodes.Node;
|
||||||
|
import org.enso.interpreter.dsl.BuiltinMethod;
|
||||||
|
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 = "new_atom",
|
||||||
|
description = "Creates a new atom with given constructor and fields.")
|
||||||
|
public class NewAtomInstanceNode extends Node {
|
||||||
|
Atom execute(Object _this, AtomConstructor constructor, Array fields) {
|
||||||
|
return constructor.newInstance(fields.getItems());
|
||||||
|
}
|
||||||
|
}
|
@ -1,9 +1,7 @@
|
|||||||
package org.enso.interpreter.runtime.builtin;
|
package org.enso.interpreter.runtime.builtin;
|
||||||
|
|
||||||
import org.enso.interpreter.Language;
|
import org.enso.interpreter.Language;
|
||||||
import org.enso.interpreter.node.expression.builtin.meta.CreateUnresolvedSymbolMethodGen;
|
import org.enso.interpreter.node.expression.builtin.meta.*;
|
||||||
import org.enso.interpreter.node.expression.builtin.meta.GetUnresolvedSymbolNameMethodGen;
|
|
||||||
import org.enso.interpreter.node.expression.builtin.meta.GetUnresolvedSymbolScopeMethodGen;
|
|
||||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||||
|
|
||||||
@ -20,6 +18,9 @@ public class Meta {
|
|||||||
AtomConstructor meta = new AtomConstructor("Meta", scope).initializeFields();
|
AtomConstructor meta = new AtomConstructor("Meta", scope).initializeFields();
|
||||||
scope.registerConstructor(meta);
|
scope.registerConstructor(meta);
|
||||||
|
|
||||||
|
|
||||||
|
scope.registerMethod(
|
||||||
|
meta, "is_unresolved_symbol", IsUnresolvedSymbolMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(
|
scope.registerMethod(
|
||||||
meta,
|
meta,
|
||||||
"get_unresolved_symbol_name",
|
"get_unresolved_symbol_name",
|
||||||
@ -30,5 +31,25 @@ public class Meta {
|
|||||||
GetUnresolvedSymbolScopeMethodGen.makeFunction(language));
|
GetUnresolvedSymbolScopeMethodGen.makeFunction(language));
|
||||||
scope.registerMethod(
|
scope.registerMethod(
|
||||||
meta, "create_unresolved_symbol", CreateUnresolvedSymbolMethodGen.makeFunction(language));
|
meta, "create_unresolved_symbol", CreateUnresolvedSymbolMethodGen.makeFunction(language));
|
||||||
|
|
||||||
|
scope.registerMethod(meta, "is_constructor", IsAtomConstructorMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(
|
||||||
|
meta, "get_constructor_name", GetConstructorNameMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(
|
||||||
|
meta, "get_constructor_fields", GetConstructorFieldNamesMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(meta, "new_atom", NewAtomInstanceMethodGen.makeFunction(language));
|
||||||
|
|
||||||
|
|
||||||
|
scope.registerMethod(meta, "is_atom", IsAtomMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(meta, "get_atom_fields", GetAtomFieldsMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(
|
||||||
|
meta, "get_atom_constructor", GetAtomConstructorMethodGen.makeFunction(language));
|
||||||
|
|
||||||
|
scope.registerMethod(meta, "is_error", IsErrorMethodGen.makeFunction(language));
|
||||||
|
|
||||||
|
scope.registerMethod(meta, "is_polyglot", IsPolyglotMethodGen.makeFunction(language));
|
||||||
|
scope.registerMethod(meta, "get_polyglot_language", GetPolyglotLanguageMethodGen.makeFunction(language));
|
||||||
|
|
||||||
|
scope.registerMethod(meta, "is_same_object", IsSameObjectMethodGen.makeFunction(language));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -196,8 +196,18 @@ public class AtomConstructor implements TruffleObject {
|
|||||||
return newInstance(arguments);
|
return newInstance(arguments);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ExportMessage
|
||||||
|
String toDisplayString(boolean allowSideEffects) {
|
||||||
|
return "Constructor<" + name + ">";
|
||||||
|
}
|
||||||
|
|
||||||
/** @return the fully qualified name of this constructor. */
|
/** @return the fully qualified name of this constructor. */
|
||||||
public QualifiedName getQualifiedName() {
|
public QualifiedName getQualifiedName() {
|
||||||
return definitionScope.getModule().getName().createChild(getName());
|
return definitionScope.getModule().getName().createChild(getName());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/** @return the fields defined by this constructor. */
|
||||||
|
public ArgumentDefinition[] getFields() {
|
||||||
|
return constructorFunction.getSchema().getArgumentInfos();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -148,10 +148,12 @@ case object ShadowedPatternFields extends IRPass {
|
|||||||
name = IR.Name.Blank(location = name.location)
|
name = IR.Name.Blank(location = name.location)
|
||||||
)
|
)
|
||||||
.addDiagnostic(warning)
|
.addDiagnostic(warning)
|
||||||
} else {
|
} else if (!name.isInstanceOf[IR.Name.Blank]) {
|
||||||
lastSeen(name.name) = named
|
lastSeen(name.name) = named
|
||||||
seenNames += name.name
|
seenNames += name.name
|
||||||
named
|
named
|
||||||
|
} else {
|
||||||
|
named
|
||||||
}
|
}
|
||||||
case cons @ Pattern.Constructor(_, fields, _, _, _) =>
|
case cons @ Pattern.Constructor(_, fields, _, _, _) =>
|
||||||
val newFields = fields.reverse.map(go(_, seenNames)).reverse
|
val newFields = fields.reverse.map(go(_, seenNames)).reverse
|
||||||
|
@ -152,6 +152,10 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
val (processedArgList, newBody) =
|
val (processedArgList, newBody) =
|
||||||
computeReplacedExpressions(newArgNames, lastBody, usageIdsForShadowed)
|
computeReplacedExpressions(newArgNames, lastBody, usageIdsForShadowed)
|
||||||
|
|
||||||
|
val consolidatedArgs = processedArgList.map(
|
||||||
|
_.mapExpressions(runExpression(_, inlineContext))
|
||||||
|
)
|
||||||
|
|
||||||
val newLocation = chainedLambdas.head.location match {
|
val newLocation = chainedLambdas.head.location match {
|
||||||
case Some(location) =>
|
case Some(location) =>
|
||||||
Some(
|
Some(
|
||||||
@ -167,7 +171,7 @@ case object LambdaConsolidate extends IRPass {
|
|||||||
}
|
}
|
||||||
|
|
||||||
lam.copy(
|
lam.copy(
|
||||||
arguments = processedArgList,
|
arguments = consolidatedArgs,
|
||||||
body = runExpression(newBody, inlineContext),
|
body = runExpression(newBody, inlineContext),
|
||||||
location = newLocation,
|
location = newLocation,
|
||||||
canBeTCO = chainedLambdas.last.canBeTCO
|
canBeTCO = chainedLambdas.last.canBeTCO
|
||||||
|
@ -198,6 +198,17 @@ class LambdaConsolidateTest extends CompilerTest {
|
|||||||
.suspended shouldEqual true
|
.suspended shouldEqual true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"work properly with arguments defaulted to lambdas" in {
|
||||||
|
implicit val inlineContext: InlineContext = mkContext
|
||||||
|
val ir = """
|
||||||
|
|x -> (y = x->y->z) -> y x
|
||||||
|
|""".stripMargin.preprocessExpression.get.optimise.asInstanceOf[IR.Function.Lambda]
|
||||||
|
ir.arguments.length shouldEqual 2
|
||||||
|
val defaultExpr = ir.arguments(1).defaultValue.get
|
||||||
|
defaultExpr shouldBe a[IR.Function.Lambda]
|
||||||
|
defaultExpr.asInstanceOf[IR.Function.Lambda].arguments.length shouldEqual 2
|
||||||
|
}
|
||||||
|
|
||||||
"collapse lambdas with multiple parameters" in {
|
"collapse lambdas with multiple parameters" in {
|
||||||
implicit val inlineContext: InlineContext = mkContext
|
implicit val inlineContext: InlineContext = mkContext
|
||||||
|
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
from Base import all
|
from Base import all
|
||||||
|
import Builtins
|
||||||
import Base.Bench_Utils
|
import Base.Bench_Utils
|
||||||
|
|
||||||
gen_list len = 0.upto len . fold Nil (l -> i -> Cons i+1 l)
|
gen_list len = 0.upto len . fold Nil (l -> i -> Cons i+1 l)
|
||||||
@ -11,11 +12,22 @@ sum_vec vec =
|
|||||||
res = sumator 0 0
|
res = sumator 0 0
|
||||||
res
|
res
|
||||||
|
|
||||||
|
sum_list_meta list =
|
||||||
|
nil_cons = Meta.meta Nil . constructor
|
||||||
|
folder acc list =
|
||||||
|
meta_list = Meta.meta list
|
||||||
|
if meta_list.constructor == nil_cons then acc else
|
||||||
|
fs = meta_list.fields
|
||||||
|
folder (acc + fs.at 0) (fs.at 1)
|
||||||
|
res = folder 0 list
|
||||||
|
res
|
||||||
|
|
||||||
main =
|
main =
|
||||||
mil = 1000000
|
mil = 1000000
|
||||||
list = here.gen_list mil
|
list = here.gen_list mil
|
||||||
vec = Vector.new mil (ix -> ix + 1)
|
vec = Vector.new mil (ix -> ix + 1)
|
||||||
vec_decimal = Vector.new mil (ix -> ix + 0.0)
|
vec_decimal = Vector.new mil (ix -> ix + 0.0)
|
||||||
Bench_Utils.measure (vec.fold 0 (+)) "vector fold" 1000 10
|
Bench_Utils.measure (here.sum_list_meta list) "list meta-fold" 1000 10
|
||||||
Bench_Utils.measure (list.fold 0 (+)) "list fold" 1000 10
|
Bench_Utils.measure (list.fold 0 (+)) "list fold" 1000 10
|
||||||
|
Bench_Utils.measure (vec.fold 0 (+)) "vector fold" 1000 10
|
||||||
Bench_Utils.measure (vec_decimal.fold 0 (+)) "vector decimal fold" 1000 10
|
Bench_Utils.measure (vec_decimal.fold 0 (+)) "vector decimal fold" 1000 10
|
||||||
|
@ -5,6 +5,7 @@ import Test.Semantic.Deep_Export.Spec as Deep_Export_Spec
|
|||||||
import Test.Semantic.Java_Interop_Spec
|
import Test.Semantic.Java_Interop_Spec
|
||||||
import Test.Semantic.Error_Spec
|
import Test.Semantic.Error_Spec
|
||||||
import Test.Semantic.Names_Spec
|
import Test.Semantic.Names_Spec
|
||||||
|
import Test.Semantic.Meta_Spec
|
||||||
|
|
||||||
import Test.List_Spec
|
import Test.List_Spec
|
||||||
import Test.Number_Spec
|
import Test.Number_Spec
|
||||||
@ -29,3 +30,4 @@ main = Test.Suite.runMain <|
|
|||||||
Text_Spec.spec
|
Text_Spec.spec
|
||||||
Time_Spec.spec
|
Time_Spec.spec
|
||||||
File_Spec.spec
|
File_Spec.spec
|
||||||
|
Meta_Spec.spec
|
||||||
|
24
test/Test/src/Semantic/Meta_Spec.enso
Normal file
24
test/Test/src/Semantic/Meta_Spec.enso
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
from Base import all
|
||||||
|
import Base.Test
|
||||||
|
|
||||||
|
type My_Type foo bar baz
|
||||||
|
|
||||||
|
My_Type.my_method = this.foo + this.bar + this.baz
|
||||||
|
|
||||||
|
spec = describe "Meta-Value Manipulation" <|
|
||||||
|
it "should allow manipulating unresolved symbols" <|
|
||||||
|
sym = does_not_exist
|
||||||
|
meta_sym = Meta.meta sym
|
||||||
|
meta_sym.name.should equal "does_not_exist"
|
||||||
|
new_sym = meta_sym . rename "my_method"
|
||||||
|
object = My_Type 1 2 3
|
||||||
|
new_sym object . should equal 6
|
||||||
|
it "should allow manipulating atoms" <|
|
||||||
|
atom = My_Type 1 "foo" Unit
|
||||||
|
meta_atom = Meta.meta atom
|
||||||
|
meta_atom.constructor.should equal My_Type
|
||||||
|
meta_atom.fields.should equal [1, "foo", Unit]
|
||||||
|
Meta.meta (meta_atom.constructor) . new [1, "foo", Unit] . should equal atom
|
||||||
|
it "should correctly return representations of different classes of objects" <|
|
||||||
|
Meta.meta 1 . should equal (Meta.Primitive 1)
|
||||||
|
Meta.meta "foo" . should equal (Meta.Primitive "foo")
|
Loading…
Reference in New Issue
Block a user