curry.expressions module
Building Curry expressions from Python.
expr is the typed builder: it types the expression over the schemes of
the front end, converts Python values by the expected type, and supplies
the class dictionaries (see curry.typecheck.builder). raw_expr
is the untyped builder, which converts by the Python type alone and checks
only the arity; it serves the runtime and the tests of the runtime. The
markers of this module (anchor, choice, cons,
fail, free, nil, ref, typed,
unboxed) describe the parts of an expression that are no Python
value.
- class curry.expressions.anchor(value, name=None)[source]
Bases:
objectUsed with
expr()to create an anchor in an expression. This can be used to construct nonlinear expressions.When no argument is supplied, the anchor name is automatically generated from the sequence _1, _2, …, according to its position in a left-to-right, depth-first traversal.
- class curry.expressions.choice(cid, lhs, rhs=None)[source]
Bases:
objectUsed with
expr()to place a choice into a Curry expression.Through
expr, the choice is a call ofPrelude.?, whose rewrite step draws a fresh id from the interpreter;cidis not used. Throughraw_expr, it is aChoicenode with the idcid, 0 by default.
- class curry.expressions.cons(head, tail0, *tail)[source]
Bases:
objectUsed with
expr()to place one or more list constructors into a Curry expression.
- curry.expressions.describe(interp, *args, **kwds)[source]
The description of an expression: the arguments of
expr()as a tree, typed only when a consumer asks for its node. The DSL builds descriptions at every operator and types them once at the boundary, so that an outer context fixes the types of the inner parts. A description is an argument ofexpr()and ofeval;strprints it in Curry syntax; its methodtypeofgives its type. The keywordexprtypestates the type of the description; the other keywords are its anchors. SeeDescription.
- curry.expressions.expr(interp, *args, **kwds)[source]
Builds a Curry expression.
The expression is typed before it is built (see
curry.typecheck.builder): the type schemes of the symbols are read from the FlatCurry interfaces of their modules, the arguments are unified with the parameter types, the class constraints are defaulted with the table of the PAKCS REPL, and the class dictionaries are supplied. Soexpr(curry.symbol('Prelude.+'), 1, 2)builds the call of the method atInt, andexpr(P.show, [P.Just, 1])finds theShowinstance ofMaybe Int. A typing failure raisesCurryTypeErrorat construction; nothing is evaluated. The flagtyped_exprturns the typing off.The arguments specify the expression to build. Each positional argument must be directly convertible to Curry or describe a node. A Python value converts by the type its position expects:
bool: Converted toPrelude.Bool.intPrelude.Int;Prelude.FloatunderFloat; thefromIntconversion under anotherNuminstance.floatConverted toPrelude.Float.strUnder[Char]one string of any length. Elsewhere a string of length one is aPrelude.Char, and another string is[Char].listConverted to a Curry list, in a loop. Every element takes the element type, so[1, 2.5]is[Float].tupleConverted to a Curry tuple.iteratorLazily converted to a Curry list. The element type is fixed when the expression is built; an item that does not convert ends the evaluation with anEvaluationError.NoneAn error that names the expected type.a Curry node Typed by a walk of its content, up to 100000 nodes;
curry.typed(node, 'T')states the type instead. A node alone passes through untouched.
Any (possibly nested) sequence whose first element is an instance of
NodeInfospecifies a node. The remaining arguments are recursively converted to Curry expressions to form the successors list. Thus, given suitable definitions, it is possible to build the Curry list[0,1,2]with the following code:expr([Cons, 0, [Cons, 1, [Cons, 2, Nil]]])
Fewer arguments than the symbol takes give a partial application; more arguments go through
Prelude.applywhen the result is a function. A symbol without a type scheme (a module without a FlatCurry interface, or a built-in of Sprite’s own Prelude) is built untyped when it stands alone, as the goal of a saved module does, and is an error when it is applied to arguments;typeof()refuses it either way.Several special symbols are provided. See
anchor,choice,cons,fail,free,nil,ref,typed, andunboxed. Afreemarker becomes a call ofPrelude.unknown, one node per marker, and achoicemarker a call ofPrelude.?, so the runtime assigns the ids.raw_exprbuilds the rawFreeandChoicenodes instead. Anunboxedmarker stands only as the payload of a primitive,[Prelude.Int, curry.unboxed(3)]; anywhere else it is aCurryTypeError.- Parameters:
interp – An interpreter object.
*args – Positional arguments used to construct expressions.
**kwds – Keyword arguments specifying subexpressions that may be referenced via
ref. Each keyword specifies the name of an anchor. See the examples below.exprtype – Keyword-only argument. The type of the expression in Curry syntax, for example
'Maybe Float'. Its type variables are rigid.target – Reserved keyword-only argument. If a target is supplied, then it will be rewritten with the specified expression. Otherwise a new node is created.
- Returns:
A Curry expression. Its type is recorded, so
typeof()answers for it, andevalconverts its values by it.
- curry.expressions.fail = <curry.expressions._failcls object>
Used with
expr()to place a failure into a Curry expression.
- class curry.expressions.free(vid=0, exprtype=None)[source]
Bases:
objectUsed with
expr()to place a free variable into a Curry expression.Through
expr, one marker is one variable. The builder makes one node for the marker, a call ofPrelude.unknownapplied to theDatadictionary of its type, and reuses it for every occurrence of the marker, in that expression and in later ones. The first rewrite step on the node creates the variable with a fresh id and forwards the node to it. The node belongs to one interpreter state:curry.resetinstalls a new state, and the marker becomes a new variable there.exprtypefixes the type of the variable, in Curry syntax; without it the type comes from the context, and a variable whose type stays polymorphic gets the dictionary ofBool, whichunknownnever reads. Throughraw_expr, every occurrence is a separateFreenode with the idvid, 0 by default; that form serves the tests of the runtime.
- class curry.expressions.fwd(value)[source]
Bases:
objectUsed with
expr()to place a forward node into a Curry expression.
- curry.expressions.nil = <curry.expressions._nilcls object>
Used with
expr()to place a list terminator into a Curry expression.
- curry.expressions.raw_expr(interp, *args, **kwds)[source]
The untyped builder. Equivalent to
expr()without the types: every Python value converts by its Python type, only the arity of a symbol is checked, no dictionary is supplied, afreemarker becomes a rawFreenode with the id of the marker, a new node per occurrence, and achoicemarker a rawChoicenode with the id of the marker. Fewer arguments than the arity of a symbol give a partial application; a function applied to more goes throughPrelude.apply, one node per surplus argument, as a point-free definition needs; a constructor applied to more is an error. An expression that is not well typed evaluates with undefined behaviour.
- class curry.expressions.ref(name=None)[source]
Bases:
objectUsed with
expr()to create a reference to a named subexpression. This can be used to construct nonlinear expressions.The argument is optional when the expression contains exactly one anchor at the point where the reference appears.
- curry.expressions.result_type(interp, node)[source]
The defaulted type
expr()recorded for a node, or None.
- class curry.expressions.typed(value, exprtype)[source]
Bases:
objectUsed with
expr()to annotate a part of an expression with its type:curry.typed(value, 'T')convertsvalueat the typeT, in Curry syntax, and unifiesTwith the type the context expects. Socurry.typed('a', 'String')is the string"a", andcurry.typed(node, '[Int]')states the type of a large value instead of a walk of its content.raw_exprbuilds the value and ignores the annotation.
- curry.expressions.typeof(e, defaulted=False)[source]
The type of an expression in Curry syntax. Without
defaultedthe undefaulted scheme, what:typeprints:typeof(expr(plus, 1, 2))isNum a => a. Withdefaultedthe type after the table of the PAKCS REPL:Int.eis a nodeexpr()returned, any other Curry node (typed by its content), a symbol, a description ofdescribe(), or any argumentexpr()accepts.
- class curry.expressions.unboxed(value)[source]
Bases:
objectUsed with
expr()to place the unboxed payload of a primitive into a Curry expression:[Prelude.Int, curry.unboxed(3)]is the node<Int 3>, andPrelude.CharandPrelude.Floattake the marker the same way. A plain Python value builds the same node, so the marker is seldom needed. The payload must fit the primitive: a PythonintunderInt, astrof length one underChar, afloatunderFloat; another value is aCurryTypeErrorfrom both builders (unboxed_payload()). Anywhere else the marker is aCurryTypeErrorat construction, from both builders: alone, in a list or a tuple, or as the argument of another symbol, a node is expected, and an unboxed value in its place is an ill-formed node, which ended the process on the C++ backend (issue #107). An item of an iterator is converted when the list is demanded, so the marker there is anEvaluationErrorat that time.
- curry.expressions.untyped_expr(interp, *args, **kwds)[source]
The untyped builder with the markers of
expr(): afreemarker is its sharedunknownnode and achoicemarker a call ofPrelude.?. This isexpr()with the flagtyped_exproff. The interpreter uses it for the expressions it builds around compiled code, whose types the front end checked.