DefineExpr
From Erights
Kevin Reid (Talk | contribs) (specify DefineExpr) |
Kevin Reid (Talk | contribs) (add tests, rename fields (MarkM agrees)) |
||
Line 1: | Line 1: | ||
[[DefineExpr]] is a [[Kernel-E]] node which matches a [[pattern]] against a specified value. | [[DefineExpr]] is a [[Kernel-E]] node which matches a [[pattern]] against a specified value. | ||
- | "def" <var>pattern</var> ("exit" <var> | + | "def" <var>pattern</var> ("exit" <var>optExitExpr</var>)? ":=" <var>specimen</var> |
Note that the syntax is identical to [[DefrecExpr]], the nonkernel expression which allows ''recursive'' definitions; DefineExpr rejects such uses. | Note that the syntax is identical to [[DefrecExpr]], the nonkernel expression which allows ''recursive'' definitions; DefineExpr rejects such uses. | ||
Line 8: | Line 8: | ||
* <var>pattern</var> :[[Pattern]] | * <var>pattern</var> :[[Pattern]] | ||
- | * <var> | + | * <var>optExitExpr</var> :[[nullOk]]<nowiki>[</nowiki>[[EExpr]]] |
- | * <var> | + | * <var>specimen</var> :[[EExpr]] |
== Scope == | == Scope == | ||
- | [[Node scope rules|seq]](<var>pattern</var>, <var> | + | [[Node scope rules|seq]](<var>pattern</var>, <var>optExitExpr</var>, <var>specimen</var>) |
+ | |||
+ | Note that this order differs from the evaluation order; the static constraints prevent this from being impossible without [[promise]]s. | ||
== Evaluation == | == Evaluation == | ||
- | # If present, <var> | + | # If present, <var>optExitExpr</var> is evaluated. |
- | # <var> | + | # <var>specimen</var> is evaluated. |
- | #<var>pattern</var> is matched against the result of <var> | + | #<var>pattern</var> is matched against the result of <var>specimen</var>, with the result of <var>optExitExpr</var>, or [[throw]] if not present, as the ejector. |
== Static constraints == | == Static constraints == | ||
- | * <var> | + | * <var>specimen</var> may not use nouns bound by <var>pattern</var>. (See [[DefrecExpr]].) |
- | * <var> | + | * <var>optExitExpr</var> may not use nouns bound by <var>pattern</var>. |
- | * <var>pattern</var> may not use nouns bound by <var> | + | * <var>pattern</var> may not use nouns bound by <var>specimen</var>. |
- | * <var>pattern</var> may not use nouns bound by <var> | + | * <var>pattern</var> may not use nouns bound by <var>optExitExpr</var>. |
+ | |||
+ | == Examples == | ||
+ | |||
+ | Simple uses with [[FinalPattern]], [[VarPattern]] and [[LiteralExpr]]: | ||
+ | |||
+ | ? def pi := 3.14159 | ||
+ | # value: 3.14159 | ||
+ | |||
+ | ? pi | ||
+ | # value: 3.14159 | ||
+ | |||
+ | ? def var x := 1 | ||
+ | > x | ||
+ | # value: 1 | ||
+ | |||
+ | ? x := 2 | ||
+ | > x | ||
+ | # value: 2 | ||
+ | |||
+ | With optEjectorExpr specified, but making no difference: | ||
+ | |||
+ | ? def x :int exit throw := 9 | ||
+ | # value: 9 | ||
+ | |||
+ | ? x | ||
+ | # value: 9 | ||
+ | |||
+ | ? def x :String exit throw := 9 | ||
+ | # problem: the int 9 doesn't coerce to a String | ||
+ | |||
+ | With optEjectorExpr different: | ||
+ | |||
+ | ? def x :int exit def _(e) :void { print(e); throw("biff") } := 9 | ||
+ | # value: 9 | ||
+ | |||
+ | ? def x :String exit def _(e) :void { print(e); throw("biff") } := 9 | ||
+ | # stdout: problem: the int 9 doesn't coerce to a String | ||
+ | |||
+ | # problem: biff | ||
+ | |||
+ | Demonstration of the evaluation order: | ||
+ | |||
+ | ? def [[ViaPattern|via]] (fn s,_ {println("patt"); throw("exit")}) x \ | ||
+ | > exit (println("ejector"); null) \ | ||
+ | > := (println("specimen"); 8) | ||
+ | # stdout: ejector | ||
+ | # specimen | ||
+ | # patt | ||
+ | # | ||
+ | |||
+ | # problem: exit | ||
+ | |||
+ | A bogus exit, which does not return when it should (this is [[throw.eject]] behavior): | ||
+ | |||
+ | XXX in [[E-on-Java]] this creates a note in the trace that the ejector returned and proceeds as if the ejector was null; the shown behavior is from [[E-on-CL]]; which to pick? | ||
+ | |||
+ | ? def x :String exit def _(_) :void {} := 9 | ||
+ | # problem: optEjector <__main$_> returned: null | ||
+ | |||
+ | Scope tests: | ||
+ | |||
+ | ? {def y := 0; {def ==0 exit (def y := null) := y}} | ||
+ | # problem: null is not 0 | ||
+ | |||
+ | XXX write more scope tests | ||
[[Category:E language specification]] | [[Category:E language specification]] | ||
[[Category:Kernel-E nodes]] | [[Category:Kernel-E nodes]] |
Revision as of 05:49, 4 January 2009
DefineExpr is a Kernel-E node which matches a pattern against a specified value.
"def" pattern ("exit" optExitExpr)? ":=" specimen
Note that the syntax is identical to DefrecExpr, the nonkernel expression which allows recursive definitions; DefineExpr rejects such uses.
Contents |
Fields
Scope
seq(pattern, optExitExpr, specimen)
Note that this order differs from the evaluation order; the static constraints prevent this from being impossible without promises.
Evaluation
- If present, optExitExpr is evaluated.
- specimen is evaluated.
- pattern is matched against the result of specimen, with the result of optExitExpr, or throw if not present, as the ejector.
Static constraints
- specimen may not use nouns bound by pattern. (See DefrecExpr.)
- optExitExpr may not use nouns bound by pattern.
- pattern may not use nouns bound by specimen.
- pattern may not use nouns bound by optExitExpr.
Examples
Simple uses with FinalPattern, VarPattern and LiteralExpr:
? def pi := 3.14159 # value: 3.14159 ? pi # value: 3.14159
? def var x := 1 > x # value: 1 ? x := 2 > x # value: 2
With optEjectorExpr specified, but making no difference:
? def x :int exit throw := 9 # value: 9 ? x # value: 9 ? def x :String exit throw := 9 # problem: the int 9 doesn't coerce to a String
With optEjectorExpr different:
? def x :int exit def _(e) :void { print(e); throw("biff") } := 9 # value: 9
? def x :String exit def _(e) :void { print(e); throw("biff") } := 9 # stdout: problem: the int 9 doesn't coerce to a String # problem: biff
Demonstration of the evaluation order:
? def via (fn s,_ {println("patt"); throw("exit")}) x \ > exit (println("ejector"); null) \ > := (println("specimen"); 8) # stdout: ejector # specimen # patt # # problem: exit
A bogus exit, which does not return when it should (this is throw.eject behavior):
XXX in E-on-Java this creates a note in the trace that the ejector returned and proceeds as if the ejector was null; the shown behavior is from E-on-CL; which to pick?
? def x :String exit def _(_) :void {} := 9 # problem: optEjector <__main$_> returned: null
Scope tests:
? {def y := 0; {def ==0 exit (def y := null) := y}} # problem: null is not 0
XXX write more scope tests