mirror of
https://github.com/enso-org/enso.git
synced 2024-12-22 13:41:39 +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.
|
||||
No_Such_Method_Error.method_name : Text
|
||||
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.System.File
|
||||
import Base.Meta.Enso_Project
|
||||
import Base.Meta.Meta
|
||||
import Base.Error.Extensions
|
||||
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.List export Nil, Cons
|
||||
@ -68,3 +70,26 @@ type Math
|
||||
to its diameter.
|
||||
Math.pi : Decimal
|
||||
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.
|
||||
Number.equals : Number -> Number -> Boolean
|
||||
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
|
||||
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 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();
|
||||
} else if (symbol.getName().equals("catch")) {
|
||||
return symbol.resolveFor(context.getBuiltins().any());
|
||||
} else if (symbol.getName().equals("==")) {
|
||||
return symbol.resolveFor(context.getBuiltins().any());
|
||||
} else {
|
||||
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;
|
||||
|
||||
import org.enso.interpreter.Language;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.CreateUnresolvedSymbolMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.GetUnresolvedSymbolNameMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.GetUnresolvedSymbolScopeMethodGen;
|
||||
import org.enso.interpreter.node.expression.builtin.meta.*;
|
||||
import org.enso.interpreter.runtime.callable.atom.AtomConstructor;
|
||||
import org.enso.interpreter.runtime.scope.ModuleScope;
|
||||
|
||||
@ -20,6 +18,9 @@ public class Meta {
|
||||
AtomConstructor meta = new AtomConstructor("Meta", scope).initializeFields();
|
||||
scope.registerConstructor(meta);
|
||||
|
||||
|
||||
scope.registerMethod(
|
||||
meta, "is_unresolved_symbol", IsUnresolvedSymbolMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
meta,
|
||||
"get_unresolved_symbol_name",
|
||||
@ -30,5 +31,25 @@ public class Meta {
|
||||
GetUnresolvedSymbolScopeMethodGen.makeFunction(language));
|
||||
scope.registerMethod(
|
||||
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);
|
||||
}
|
||||
|
||||
@ExportMessage
|
||||
String toDisplayString(boolean allowSideEffects) {
|
||||
return "Constructor<" + name + ">";
|
||||
}
|
||||
|
||||
/** @return the fully qualified name of this constructor. */
|
||||
public QualifiedName getQualifiedName() {
|
||||
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)
|
||||
)
|
||||
.addDiagnostic(warning)
|
||||
} else {
|
||||
} else if (!name.isInstanceOf[IR.Name.Blank]) {
|
||||
lastSeen(name.name) = named
|
||||
seenNames += name.name
|
||||
named
|
||||
} else {
|
||||
named
|
||||
}
|
||||
case cons @ Pattern.Constructor(_, fields, _, _, _) =>
|
||||
val newFields = fields.reverse.map(go(_, seenNames)).reverse
|
||||
|
@ -152,6 +152,10 @@ case object LambdaConsolidate extends IRPass {
|
||||
val (processedArgList, newBody) =
|
||||
computeReplacedExpressions(newArgNames, lastBody, usageIdsForShadowed)
|
||||
|
||||
val consolidatedArgs = processedArgList.map(
|
||||
_.mapExpressions(runExpression(_, inlineContext))
|
||||
)
|
||||
|
||||
val newLocation = chainedLambdas.head.location match {
|
||||
case Some(location) =>
|
||||
Some(
|
||||
@ -167,7 +171,7 @@ case object LambdaConsolidate extends IRPass {
|
||||
}
|
||||
|
||||
lam.copy(
|
||||
arguments = processedArgList,
|
||||
arguments = consolidatedArgs,
|
||||
body = runExpression(newBody, inlineContext),
|
||||
location = newLocation,
|
||||
canBeTCO = chainedLambdas.last.canBeTCO
|
||||
|
@ -198,6 +198,17 @@ class LambdaConsolidateTest extends CompilerTest {
|
||||
.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 {
|
||||
implicit val inlineContext: InlineContext = mkContext
|
||||
|
||||
|
@ -1,4 +1,5 @@
|
||||
from Base import all
|
||||
import Builtins
|
||||
import Base.Bench_Utils
|
||||
|
||||
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
|
||||
|
||||
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 =
|
||||
mil = 1000000
|
||||
list = here.gen_list mil
|
||||
vec = Vector.new mil (ix -> ix + 1)
|
||||
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 (vec.fold 0 (+)) "vector 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.Error_Spec
|
||||
import Test.Semantic.Names_Spec
|
||||
import Test.Semantic.Meta_Spec
|
||||
|
||||
import Test.List_Spec
|
||||
import Test.Number_Spec
|
||||
@ -29,3 +30,4 @@ main = Test.Suite.runMain <|
|
||||
Text_Spec.spec
|
||||
Time_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