Compare commits
8 Commits
6211be8a8f
...
v0.29.0
| Author | SHA1 | Date | |
|---|---|---|---|
| cca3b76baa | |||
| 24e31997fc | |||
| 646710e180 | |||
| b38327b841 | |||
| fd912b2eb1 | |||
| 0e55f83d56 | |||
| 4725145d1c | |||
| edf8818f51 |
@@ -8,6 +8,7 @@ import (
|
||||
"fmt"
|
||||
"math"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
|
||||
const (
|
||||
@@ -188,6 +189,30 @@ func fractFunc(ctx ExprContext, name string, args map[string]any) (result any, e
|
||||
// return
|
||||
// }
|
||||
|
||||
func evalFunc(ctx ExprContext, name string, args map[string]any) (result any, err error) {
|
||||
if source, ok := args[ParamSource].(string); ok {
|
||||
var expr Expr
|
||||
|
||||
parser := NewParser()
|
||||
if ctx == nil {
|
||||
ctx = NewSimpleStore()
|
||||
}
|
||||
|
||||
r := strings.NewReader(source)
|
||||
scanner := NewScanner(r, DefaultTranslations())
|
||||
|
||||
if expr, err = parser.Parse(scanner); err == nil {
|
||||
CtrlEnable(ctx, control_export_all)
|
||||
result, err = expr.Eval(ctx)
|
||||
}
|
||||
} else {
|
||||
err = ErrWrongParamType(name, ParamSource, TypeString, args[ParamSource])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//// import
|
||||
|
||||
func ImportBuiltinsFuncs(ctx ExprContext) {
|
||||
anyParams := []ExprFuncParam{
|
||||
NewFuncParam(ParamValue),
|
||||
@@ -211,6 +236,10 @@ func ImportBuiltinsFuncs(ctx ExprContext) {
|
||||
NewFuncParam(ParamValue),
|
||||
NewFuncParamFlagDef(ParamDenominator, PfDefault, int64(1)),
|
||||
})
|
||||
|
||||
ctx.RegisterFunc("eval", NewGolangFunctor(evalFunc), TypeAny, []ExprFuncParam{
|
||||
NewFuncParam(ParamSource),
|
||||
})
|
||||
}
|
||||
|
||||
func init() {
|
||||
|
||||
+18
-1
@@ -55,8 +55,25 @@ func ErrInvalidParameterValue(funcName, paramName string, paramValue any) error
|
||||
return fmt.Errorf("%s(): invalid value %s (%v) for parameter %q", funcName, TypeName(paramValue), paramValue, paramName)
|
||||
}
|
||||
|
||||
func undefArticle(s string) (article string) {
|
||||
if len(s) > 0 && strings.Contains("aeiou", s[0:1]) {
|
||||
article = "an"
|
||||
} else {
|
||||
article = "a"
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func prependUndefArticle(s string) (result string) {
|
||||
return undefArticle(s) + " " + s
|
||||
}
|
||||
|
||||
func ErrWrongParamType(funcName, paramName, paramType string, paramValue any) error {
|
||||
return fmt.Errorf("%s(): the %q parameter must be a %s, got a %s (%v)", funcName, paramName, paramType, TypeName(paramValue), paramValue)
|
||||
var artWantType, artGotType string
|
||||
gotType := TypeName(paramValue)
|
||||
artGotType = prependUndefArticle(gotType)
|
||||
artWantType = prependUndefArticle(paramType)
|
||||
return fmt.Errorf("%s(): the %q parameter must be %s, got %s (%v)", funcName, paramName, artWantType, artGotType, paramValue)
|
||||
}
|
||||
|
||||
func ErrUnknownParam(funcName, paramName string) error {
|
||||
|
||||
+1
-1
@@ -29,7 +29,7 @@ func exportObjects(destCtx, sourceCtx ExprContext) {
|
||||
exportAll := CtrlIsEnabled(sourceCtx, control_export_all)
|
||||
// fmt.Printf("Exporting from sourceCtx [%p] to destCtx [%p] -- exportAll=%t\n", sourceCtx, destCtx, exportAll)
|
||||
// Export variables
|
||||
for _, refName := range sourceCtx.EnumVars(func(name string) bool { return exportAll || name[0] == '@' }) {
|
||||
for _, refName := range sourceCtx.EnumVars(func(name string) bool { return (exportAll || name[0] == '@') && !(name[0] == '_') }) {
|
||||
// fmt.Printf("\tExporting %q\n", refName)
|
||||
refValue, _ := sourceCtx.GetVar(refName)
|
||||
exportVar(destCtx, refName, refValue)
|
||||
|
||||
+34
-31
@@ -127,22 +127,22 @@ dev-expr -- Expressions calculator v1.10.0(build 14),2024/06/17 (celestino.amoro
|
||||
9.5
|
||||
>>> 0xFD + 0b1 + 0o1 <1>
|
||||
255
|
||||
>>> 1|2 + 2|3 <2>
|
||||
7|6
|
||||
>>> 1:2 + 2:3 <2>
|
||||
7:6
|
||||
>>> ml <3>
|
||||
>>> 1|2 + 2|3
|
||||
>>> 1:2 + 2:3
|
||||
7
|
||||
-
|
||||
6
|
||||
>>> 4+2 but 5|2+0.5 <4>
|
||||
>>> 4+2 but 5:2+0.5 <4>
|
||||
3
|
||||
>>> 4+2; 5|2+0.5 <5>
|
||||
>>> 4+2; 5:2+0.5 <5>
|
||||
3
|
||||
>>>
|
||||
----
|
||||
|
||||
<1> Number bases: 0x = _hexadecimal_, 0o = _octal_, 0b = _binary_.
|
||||
<2> Fractions: _numerator_ | _denominator_.
|
||||
<2> Fractions: _numerator_ : _denominator_.
|
||||
<3> Activate multi-line output of fractions.
|
||||
<4> But operator, see <<_but_operator>>.
|
||||
<5> Multi-expression: the same result of the previous single expression but this it is obtained with two separated calculations.
|
||||
@@ -236,11 +236,11 @@ _dec-seq_ = _see-integer-literal-syntax_
|
||||
|===
|
||||
|
||||
==== Fractions
|
||||
_Expr_ also supports fractions. Fraction literals are made with two integers separated by a vertical bar `|`.
|
||||
_Expr_ also supports fractions. Fraction literals are made with two integers separated by a colon character `:`.
|
||||
|
||||
.Fraction literal syntax
|
||||
====
|
||||
*_fraction_* = [__sign__] (_num-den-spec_ | _float-spec_) +
|
||||
*_fraction_* = [__sign__] (_num-den-spec_ "**:**" _float-spec_) +
|
||||
_sign_ = "**+**" | "**-**" +
|
||||
_num-den-spec_ = _digit-seq_ "**|**" _digit-seq_ +
|
||||
_float-spec_ = _dec-seq_ "**.**" [_dec-seq_] "**(**" _dec-seq_ "**)**" +
|
||||
@@ -249,44 +249,44 @@ _digit-seq_ = _see-integer-literal-syntax_
|
||||
====
|
||||
|
||||
.Examples
|
||||
`>>>` [blue]`1 | 2` +
|
||||
[green]`1|2`
|
||||
`>>>` [blue]`1 : 2` +
|
||||
[green]`1:2`
|
||||
|
||||
`>>>` [blue]`4|6` [gray]_// Fractions are always reduced to their lowest terms_ +
|
||||
[green]`2|3`
|
||||
`>>>` [blue]`4:6` [gray]_// Fractions are always reduced to their lowest terms_ +
|
||||
[green]`2:3`
|
||||
|
||||
`>>>` [blue]`1|2 + 2|3` +
|
||||
[green]`7|6`
|
||||
`>>>` [blue]`1:2 + 2:3` +
|
||||
[green]`7:6`
|
||||
|
||||
`>>>` [blue]`1|2 * 2|3` +
|
||||
[green]`1|3`
|
||||
`>>>` [blue]`1:2 * 2:3` +
|
||||
[green]`1:3`
|
||||
|
||||
`>>>` [blue]`1|2 / 1|3` +
|
||||
[green]`3|2`
|
||||
`>>>` [blue]`1:2 / 1:3` +
|
||||
[green]`3:2`
|
||||
|
||||
`>>>` [blue]`1|2 ./ 1|3` [gray]_// Force decimal division_ +
|
||||
`>>>` [blue]`1:2 ./ 1:3` [gray]_// Force decimal division_ +
|
||||
[green]`1.5`
|
||||
|
||||
`>>>` [blue]`-1|2` +
|
||||
[green]`-1|2`
|
||||
`>>>` [blue]`-1:2` +
|
||||
[green]`-1:2`
|
||||
|
||||
`>>>` [blue]`1|-2` [gray]_// Invalid sign specification_ +
|
||||
[red]_Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1_
|
||||
`>>>` [blue]`1:-2` [gray]_// Invalid sign specification_ +
|
||||
[red]_Eval Error: [1:3] infix operator ":" requires two non-nil operands, got 1_
|
||||
|
||||
`>>>` [blue]`1|(-2)` +
|
||||
[green]`-1|2`
|
||||
`>>>` [blue]`1:(-2)` +
|
||||
[green]`-1:2`
|
||||
|
||||
|
||||
Fractions can be used together with integers and floats in expressions.
|
||||
|
||||
.Examples
|
||||
`>>>` [blue]`1|2 + 5` +
|
||||
[green]`11|2`
|
||||
`>>>` [blue]`1:2 + 5` +
|
||||
[green]`11:2`
|
||||
|
||||
`>>>` [blue]`4 - 1|2` +
|
||||
[green]`7|2`
|
||||
`>>>` [blue]`4 - 1:2` +
|
||||
[green]`7:2`
|
||||
|
||||
`>>>` [blue]`1.0 + 1|2` +
|
||||
`>>>` [blue]`1.0 + 1:2` +
|
||||
[green]`1.5`
|
||||
|
||||
|
||||
@@ -753,7 +753,7 @@ The table below shows all supported operators by decreasing priorities.
|
||||
| [blue]`#` | _Prefix_ | _Size-of_ | `#` _iterator_ -> _integer_
|
||||
.2+|*SELECT*| [blue]`? : ::` | _Multi-Infix_ | _Case-Selector_ | _any-expr_ `?` _case-list_ _case-expr_ `:` _case-list_ _case-expr_ ... `::` _default-expr_ -> _any_
|
||||
| [blue]`? : ::` | _Multi-Infix_ | _Index-Selector_ | _int-expr_ `?` _case-expr_ `:` _case-expr_ ... `::` _default-expr_ -> _any_
|
||||
.1+|*FRACT*| [blue]`\|` | _Infix_ | _Fraction_ | _integer_ `\|` _integer_ -> _fraction_
|
||||
.1+|*FRACT*| [blue]`:` | _Infix_ | _Fraction_ | _integer_ `:` _integer_ -> _fraction_
|
||||
.5+|*PROD*| [blue]`*` | _Infix_ | _Product_ | _number_ `*` _number_ -> _number_
|
||||
| [blue]`*` | _Infix_ | _String-repeat_ | _string_ `*` _integer_ -> _string_
|
||||
| [blue]`/` | _Infix_ | _Division_ | _number_ `/` _number_ -> _number_
|
||||
@@ -765,6 +765,9 @@ The table below shows all supported operators by decreasing priorities.
|
||||
| [blue]`+` | _Infix_ | _Dict-join_ | _dict_ `+` _dict_ -> _dict_
|
||||
| [blue]`-` | _Infix_ | _Subtraction_ | _number_ `-` _number_ -> _number_
|
||||
| [blue]`-` | _Infix_ | _List-difference_ | _list_ `-` _list_ -> _list_
|
||||
.3+|*BINARY*| [blue]`&` | _Infix_ | _Binary And_ | _number_ `&` _number_ -> _number_
|
||||
| [blue]`\|` | _Infix_ | _Binary Or_ | _number_ `\|` _number_ -> _number_
|
||||
| [blue]`~` | _Prefix_ | _Binary Not_ | `~` _number_ -> _number_
|
||||
.8+|*RELATION*| [blue]`<` | _Infix_ | _Less_ | _comparable_ `<` _comparable_ -> _boolean_
|
||||
| [blue]`\<=` | _Infix_ | _less-equal_ | _comparable_ `\<=` _comparable_ -> _boolean_
|
||||
| [blue]`>` | _Infix_ | _Greater_ | _comparable_ `>` _comparable_ -> _boolean_
|
||||
|
||||
+62
-33
@@ -474,6 +474,16 @@ pre.rouge .gh {
|
||||
color: #b8bb26;
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .ge {
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .ges {
|
||||
font-weight: bold;
|
||||
font-style: italic;
|
||||
}
|
||||
pre.rouge .gs {
|
||||
font-weight: bold;
|
||||
}
|
||||
pre.rouge .k, pre.rouge .kn, pre.rouge .kp, pre.rouge .kr, pre.rouge .kv {
|
||||
color: #fb4934;
|
||||
}
|
||||
@@ -745,16 +755,16 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
|
||||
9.5
|
||||
<span class="o">>>></span> 0xFD + 0b1 + 0o1 <i class="conum" data-value="1"></i><b>(1)</b>
|
||||
255
|
||||
<span class="o">>>></span> 1|2 + 2|3 <i class="conum" data-value="2"></i><b>(2)</b>
|
||||
7|6
|
||||
<span class="o">>>></span> 1:2 + 2:3 <i class="conum" data-value="2"></i><b>(2)</b>
|
||||
7:6
|
||||
<span class="o">>>></span> ml <i class="conum" data-value="3"></i><b>(3)</b>
|
||||
<span class="o">>>></span> 1|2 + 2|3
|
||||
<span class="o">>>></span> 1:2 + 2:3
|
||||
7
|
||||
-
|
||||
6
|
||||
<span class="o">>>></span> 4+2 but 5|2+0.5 <i class="conum" data-value="4"></i><b>(4)</b>
|
||||
<span class="o">>>></span> 4+2 but 5:2+0.5 <i class="conum" data-value="4"></i><b>(4)</b>
|
||||
3
|
||||
<span class="o">>>></span> 4+2<span class="p">;</span> 5|2+0.5 <i class="conum" data-value="5"></i><b>(5)</b>
|
||||
<span class="o">>>></span> 4+2<span class="p">;</span> 5:2+0.5 <i class="conum" data-value="5"></i><b>(5)</b>
|
||||
3
|
||||
<span class="o">>>></span></code></pre>
|
||||
</div>
|
||||
@@ -767,7 +777,7 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i class="conum" data-value="2"></i><b>2</b></td>
|
||||
<td>Fractions: <em>numerator</em> | <em>denominator</em>.</td>
|
||||
<td>Fractions: <em>numerator</em> : <em>denominator</em>.</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><i class="conum" data-value="3"></i><b>3</b></td>
|
||||
@@ -981,13 +991,13 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
|
||||
<div class="sect3">
|
||||
<h4 id="_fractions"><a class="anchor" href="#_fractions"></a><a class="link" href="#_fractions">2.1.3. Fractions</a></h4>
|
||||
<div class="paragraph">
|
||||
<p><em>Expr</em> also supports fractions. Fraction literals are made with two integers separated by a vertical bar <code>|</code>.</p>
|
||||
<p><em>Expr</em> also supports fractions. Fraction literals are made with two integers separated by a colon character <code>:</code>.</p>
|
||||
</div>
|
||||
<div class="exampleblock">
|
||||
<div class="title">Example 3. Fraction literal syntax</div>
|
||||
<div class="content">
|
||||
<div class="paragraph">
|
||||
<p><strong><em>fraction</em></strong> = [<em>sign</em>] (<em>num-den-spec</em> | <em>float-spec</em>)<br>
|
||||
<p><strong><em>fraction</em></strong> = [<em>sign</em>] (<em>num-den-spec</em> "<strong>:</strong>" <em>float-spec</em>)<br>
|
||||
<em>sign</em> = "<strong>+</strong>" | "<strong>-</strong>"<br>
|
||||
<em>num-den-spec</em> = <em>digit-seq</em> "<strong>|</strong>" <em>digit-seq</em><br>
|
||||
<em>float-spec</em> = <em>dec-seq</em> "<strong>.</strong>" [<em>dec-seq</em>] "<strong>(</strong>" <em>dec-seq</em> "<strong>)</strong>"<br>
|
||||
@@ -998,55 +1008,55 @@ dev-expr <span class="nt">--</span> Expressions calculator v1.10.0<span class="o
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<div class="title">Examples</div>
|
||||
<p><code>>>></code> <code class="blue">1 | 2</code><br>
|
||||
<code class="green">1|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">1 : 2</code><br>
|
||||
<code class="green">1:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">4|6</code> <em class="gray">// Fractions are always reduced to their lowest terms</em><br>
|
||||
<code class="green">2|3</code></p>
|
||||
<p><code>>>></code> <code class="blue">4:6</code> <em class="gray">// Fractions are always reduced to their lowest terms</em><br>
|
||||
<code class="green">2:3</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|2 + 2|3</code><br>
|
||||
<code class="green">7|6</code></p>
|
||||
<p><code>>>></code> <code class="blue">1:2 + 2:3</code><br>
|
||||
<code class="green">7:6</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|2 * 2|3</code><br>
|
||||
<code class="green">1|3</code></p>
|
||||
<p><code>>>></code> <code class="blue">1:2 * 2:3</code><br>
|
||||
<code class="green">1:3</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|2 / 1|3</code><br>
|
||||
<code class="green">3|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">1:2 / 1:3</code><br>
|
||||
<code class="green">3:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|2 ./ 1|3</code> <em class="gray">// Force decimal division</em><br>
|
||||
<p><code>>>></code> <code class="blue">1:2 ./ 1:3</code> <em class="gray">// Force decimal division</em><br>
|
||||
<code class="green">1.5</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">-1|2</code><br>
|
||||
<code class="green">-1|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">-1:2</code><br>
|
||||
<code class="green">-1:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|-2</code> <em class="gray">// Invalid sign specification</em><br>
|
||||
<em class="red">Eval Error: [1:3] infix operator "|" requires two non-nil operands, got 1</em></p>
|
||||
<p><code>>>></code> <code class="blue">1:-2</code> <em class="gray">// Invalid sign specification</em><br>
|
||||
<em class="red">Eval Error: [1:3] infix operator ":" requires two non-nil operands, got 1</em></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1|(-2)</code><br>
|
||||
<code class="green">-1|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">1:(-2)</code><br>
|
||||
<code class="green">-1:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p>Fractions can be used together with integers and floats in expressions.</p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<div class="title">Examples</div>
|
||||
<p><code>>>></code> <code class="blue">1|2 + 5</code><br>
|
||||
<code class="green">11|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">1:2 + 5</code><br>
|
||||
<code class="green">11:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">4 - 1|2</code><br>
|
||||
<code class="green">7|2</code></p>
|
||||
<p><code>>>></code> <code class="blue">4 - 1:2</code><br>
|
||||
<code class="green">7:2</code></p>
|
||||
</div>
|
||||
<div class="paragraph">
|
||||
<p><code>>>></code> <code class="blue">1.0 + 1|2</code><br>
|
||||
<p><code>>>></code> <code class="blue">1.0 + 1:2</code><br>
|
||||
<code class="green">1.5</code></p>
|
||||
</div>
|
||||
</div>
|
||||
@@ -1992,10 +2002,10 @@ These operators have a high priority, in particular higher than the operator <co
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><strong>FRACT</strong></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">|</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">:</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Fraction</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>|</code> <em>integer</em> → <em>fraction</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>integer</em> <code>:</code> <em>integer</em> → <em>fraction</em></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top" rowspan="5"><p class="tableblock"><strong>PROD</strong></p></td>
|
||||
@@ -2066,6 +2076,25 @@ These operators have a high priority, in particular higher than the operator <co
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>list</em> <code>-</code> <em>list</em> → <em>list</em></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top" rowspan="3"><p class="tableblock"><strong>BINARY</strong></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">&</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary And</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>&</code> <em>number</em> → <em>number</em></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">|</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Or</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>number</em> <code>|</code> <em>number</em> → <em>number</em></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue">~</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Prefix</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Binary Not</em></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code>~</code> <em>number</em> → <em>number</em></p></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td class="tableblock halign-center valign-top" rowspan="8"><p class="tableblock"><strong>RELATION</strong></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><code class="blue"><</code></p></td>
|
||||
<td class="tableblock halign-center valign-top"><p class="tableblock"><em>Infix</em></p></td>
|
||||
@@ -2432,7 +2461,7 @@ g(@p):any{}`
|
||||
</div>
|
||||
<div id="footer">
|
||||
<div id="footer-text">
|
||||
Last updated 2024-09-30 07:29:03 +0200
|
||||
Last updated 2024-12-23 07:20:48 +0100
|
||||
</div>
|
||||
</div>
|
||||
</body>
|
||||
|
||||
+10
-8
@@ -126,34 +126,36 @@ func (f *FractionType) ToString(opt FmtOpt) string {
|
||||
if opt&MultiLine == 0 {
|
||||
sb.WriteString(fmt.Sprintf("%d:%d", f.num, f.den))
|
||||
} else {
|
||||
var s, num string
|
||||
var sign, num string
|
||||
if f.num < 0 && opt&TTY == 0 {
|
||||
num = strconv.FormatInt(-f.num, 10)
|
||||
s = "-"
|
||||
sign = "-"
|
||||
} else {
|
||||
num = strconv.FormatInt(f.num, 10)
|
||||
}
|
||||
den := strconv.FormatInt(f.den, 10)
|
||||
size := max(len(num), len(den))
|
||||
if opt&TTY != 0 {
|
||||
sb.WriteString(fmt.Sprintf("\x1b[4m%[1]*s\x1b[0m\n", -size, fmt.Sprintf("%[1]*s", (size+len(num))/2, s+num)))
|
||||
sNum := fmt.Sprintf("\x1b[4m%[1]*s\x1b[0m\n", -size, fmt.Sprintf("%[1]*s", (size+len(num))/2, sign+num))
|
||||
sb.WriteString(sNum)
|
||||
} else {
|
||||
if len(s) > 0 {
|
||||
if len(sign) > 0 {
|
||||
sb.WriteString(" ")
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%[1]*s", -size, fmt.Sprintf("%[1]*s", (size+len(num))/2, num)))
|
||||
sb.WriteByte('\n')
|
||||
if len(s) > 0 {
|
||||
sb.WriteString(s)
|
||||
if len(sign) > 0 {
|
||||
sb.WriteString(sign)
|
||||
sb.WriteByte(' ')
|
||||
}
|
||||
sb.WriteString(strings.Repeat("-", size))
|
||||
sb.WriteByte('\n')
|
||||
if len(s) > 0 {
|
||||
if len(sign) > 0 {
|
||||
sb.WriteString(" ")
|
||||
}
|
||||
}
|
||||
sb.WriteString(fmt.Sprintf("%[1]*s", -size, fmt.Sprintf("%[1]*s", (size+len(den))/2, den)))
|
||||
sDen := fmt.Sprintf("%[1]*s", size, fmt.Sprintf("%[1]*s", (size+len(den))/2, den))
|
||||
sb.WriteString(sDen)
|
||||
}
|
||||
|
||||
return sb.String()
|
||||
|
||||
+4
-4
@@ -5,7 +5,7 @@
|
||||
package expr
|
||||
|
||||
import (
|
||||
"errors"
|
||||
// "errors"
|
||||
"fmt"
|
||||
)
|
||||
|
||||
@@ -43,6 +43,6 @@ func errNoOperation(name string) error {
|
||||
return fmt.Errorf("no %s() function defined in the data-source", name)
|
||||
}
|
||||
|
||||
func errInvalidDataSource() error {
|
||||
return errors.New("invalid data-source")
|
||||
}
|
||||
// func errInvalidDataSource() error {
|
||||
// return errors.New("invalid data-source")
|
||||
// }
|
||||
|
||||
+3
-3
@@ -11,7 +11,7 @@ func newBinNotTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 1),
|
||||
position: posPrefix,
|
||||
priority: priNot,
|
||||
priority: priBinary,
|
||||
evalFunc: evalBinaryNot,
|
||||
}
|
||||
}
|
||||
@@ -39,7 +39,7 @@ func newBinAndTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priAnd,
|
||||
priority: priBinary,
|
||||
evalFunc: evalBinaryAnd,
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ func newBinOrTerm(tk *Token) (inst *term) {
|
||||
tk: *tk,
|
||||
children: make([]*term, 0, 2),
|
||||
position: posInfix,
|
||||
priority: priOr,
|
||||
priority: priBinary,
|
||||
evalFunc: evalBinaryOr,
|
||||
}
|
||||
}
|
||||
|
||||
+1
-1
@@ -20,7 +20,7 @@ func evalContextValue(ctx ExprContext, opTerm *term) (v any, err error) {
|
||||
var childValue any
|
||||
|
||||
var sourceCtx ExprContext
|
||||
if opTerm.children == nil || len(opTerm.children) == 0 {
|
||||
if len(opTerm.children) == 0 {
|
||||
sourceCtx = ctx
|
||||
} else if opTerm.children[0].symbol() == SymVariable && opTerm.children[0].source() == "global" {
|
||||
sourceCtx = globalCtx
|
||||
|
||||
@@ -441,6 +441,9 @@ func (parser *parser) parseGeneral(scanner *scanner, ctx parserContext, termSymb
|
||||
tk.Sym = SymChangeSign
|
||||
} else if tk.Sym == SymPlus {
|
||||
tk.Sym = SymUnchangeSign
|
||||
} else if tk.IsSymbol(SymExclamation) {
|
||||
err = tk.Errorf("postfix opertor %q requires an operand on its left", tk)
|
||||
break
|
||||
}
|
||||
firstToken = false
|
||||
}
|
||||
|
||||
+1
-1
@@ -460,7 +460,7 @@ func (scanner *scanner) parseNumber(firstCh byte) (tk *Token) {
|
||||
tk = scanner.makeErrorToken(err)
|
||||
} else {
|
||||
var value any
|
||||
err = scanner.sync(err) // TODO: Check this function
|
||||
_ = scanner.sync(err) // TODO: Check this function
|
||||
txt := sb.String()
|
||||
if sym == SymFloat {
|
||||
value, err = strconv.ParseFloat(txt, 64)
|
||||
|
||||
@@ -56,11 +56,12 @@ func TestFuncBase(t *testing.T) {
|
||||
/* 42 */ {`dec(false)`, float64(0), nil},
|
||||
/* 43 */ {`dec(1:2)`, float64(0.5), nil},
|
||||
/* 44 */ {`dec([1])`, nil, `dec(): can't convert list to float`},
|
||||
/* 45 */ {`eval("a=3"); a`, int64(3), nil},
|
||||
// /* 45 */ {`string([1])`, nil, `string(): can't convert list to string`},
|
||||
}
|
||||
|
||||
t.Setenv("EXPR_PATH", ".")
|
||||
|
||||
// runTestSuiteSpec(t, section, inputs, 30)
|
||||
// runTestSuiteSpec(t, section, inputs, 45)
|
||||
runTestSuite(t, section, inputs)
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ func TestFuncString(t *testing.T) {
|
||||
/* 1 */ {`builtin "string"; strJoin("-", "one", "two", "three")`, "one-two-three", nil},
|
||||
/* 2 */ {`builtin "string"; strJoin("-", ["one", "two", "three"])`, "one-two-three", nil},
|
||||
/* 3 */ {`builtin "string"; ls= ["one", "two", "three"]; strJoin("-", ls)`, "one-two-three", nil},
|
||||
/* 4 */ {`builtin "string"; ls= ["one", "two", "three"]; strJoin(1, ls)`, nil, `strJoin(): the "separator" parameter must be a string, got a integer (1)`},
|
||||
/* 4 */ {`builtin "string"; ls= ["one", "two", "three"]; strJoin(1, ls)`, nil, `strJoin(): the "separator" parameter must be a string, got an integer (1)`},
|
||||
/* 5 */ {`builtin "string"; ls= ["one", 2, "three"]; strJoin("-", ls)`, nil, `strJoin(): expected string, got integer (2)`},
|
||||
/* 6 */ {`builtin "string"; "<"+strTrim(" bye bye ")+">"`, "<bye bye>", nil},
|
||||
/* 7 */ {`builtin "string"; strSub("0123456789", 1,2)`, "12", nil},
|
||||
|
||||
+2
-3
@@ -59,10 +59,9 @@ func TestFractionToStringMultiline(t *testing.T) {
|
||||
}
|
||||
}
|
||||
|
||||
// TODO Check this test: the output string ends with a space
|
||||
func _TestToStringMultilineTty(t *testing.T) {
|
||||
func TestToStringMultilineTty(t *testing.T) {
|
||||
source := newFraction(-1, 2)
|
||||
want := "\x1b[4m-1\x1b[0m\n2"
|
||||
want := "\x1b[4m-1\x1b[0m\n 2"
|
||||
got := source.ToString(MultiLine | TTY)
|
||||
if got != want {
|
||||
t.Errorf(`(1,2) -> result = %#v [%T], want = %#v [%T]`, got, got, want, want)
|
||||
|
||||
+11
-11
@@ -8,18 +8,18 @@ import (
|
||||
"testing"
|
||||
)
|
||||
|
||||
func _TestImportPlugin(t *testing.T) {
|
||||
t.Setenv("PLUGINS", "${HOME}/go/src/git.portale-stac.it/go")
|
||||
t.Setenv("EXPR_PLUGIN_PATH","${PLUGINS}/expr-json-plugin:${PLUGINS}/expr-csv-plugin")
|
||||
// func TestImportPlugin(t *testing.T) {
|
||||
// t.Setenv("PLUGINS", "${HOME}/go/src/git.portale-stac.it/go")
|
||||
// t.Setenv("EXPR_PLUGIN_PATH","${PLUGINS}/expr-json-plugin:${PLUGINS}/expr-csv-plugin")
|
||||
|
||||
gotCount, gotErr := importPluginFromSearchPath("json")
|
||||
if gotCount != 1 {
|
||||
t.Errorf("Import count: got=%d, want=1", gotCount)
|
||||
}
|
||||
if gotErr != nil {
|
||||
t.Errorf("importPlugin() failed: %v", gotErr)
|
||||
}
|
||||
}
|
||||
// gotCount, gotErr := importPluginFromSearchPath("json")
|
||||
// if gotCount != 1 {
|
||||
// t.Errorf("Import count: got=%d, want=1", gotCount)
|
||||
// }
|
||||
// if gotErr != nil {
|
||||
// t.Errorf("importPlugin() failed: %v", gotErr)
|
||||
// }
|
||||
// }
|
||||
|
||||
func TestPluginExists(t *testing.T) {
|
||||
name := "json"
|
||||
|
||||
Reference in New Issue
Block a user