Name printedNumber's dp cases, and say what prints and proveNumber a builtin sets
This commit is contained in:
+3
-1
@@ -16,6 +16,8 @@ import (
|
|||||||
const (
|
const (
|
||||||
maxLen = 1 << 20
|
maxLen = 1 << 20
|
||||||
maxDecimals = 1024
|
maxDecimals = 1024
|
||||||
|
// shortestDecimals prints the fewest digits that read back as the same float64.
|
||||||
|
shortestDecimals = -1
|
||||||
)
|
)
|
||||||
|
|
||||||
// builtins is the registry of {name(args)} functions. Derivations read the digits
|
// builtins is the registry of {name(args)} functions. Derivations read the digits
|
||||||
@@ -100,7 +102,7 @@ func chars(alphabet string) func([]string) callFn {
|
|||||||
|
|
||||||
const hexDigits = "0123456789abcdef"
|
const hexDigits = "0123456789abcdef"
|
||||||
|
|
||||||
// formatFloat prints v to dp decimals, -1 for the shortest form, and a zero unsigned.
|
// formatFloat prints v to dp decimals, or shortestDecimals, and a zero unsigned.
|
||||||
func formatFloat(v float64, dp int) string {
|
func formatFloat(v float64, dp int) string {
|
||||||
s := strconv.FormatFloat(v, 'f', dp, 64)
|
s := strconv.FormatFloat(v, 'f', dp, 64)
|
||||||
if strings.HasPrefix(s, "-") && strings.Trim(s, "-0.") == "" {
|
if strings.HasPrefix(s, "-") && strings.Trim(s, "-0.") == "" {
|
||||||
|
|||||||
@@ -187,7 +187,7 @@ func neverNumeric(n node) (text string, never bool) {
|
|||||||
|
|
||||||
// calcPrep parses the expression and decimals once, at compile time, and places each
|
// calcPrep parses the expression and decimals once, at compile time, and places each
|
||||||
// operand name at the position expand will read it into. checkCalc proved both args
|
// operand name at the position expand will read it into. checkCalc proved both args
|
||||||
// valid, so no step here can fail; dp -1 prints the minimal form.
|
// valid, so no step here can fail.
|
||||||
func calcPrep(args []string) callFn {
|
func calcPrep(args []string) callFn {
|
||||||
expr, err := parseCalc(args[0])
|
expr, err := parseCalc(args[0])
|
||||||
if err != nil { // a nil AST would be a nil dereference per render, with no message
|
if err != nil { // a nil AST would be a nil dereference per render, with no message
|
||||||
@@ -204,12 +204,12 @@ func calcPrep(args []string) callFn {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// calcDecimals is a calc's decimals count, or -1 for the shortest form.
|
// calcDecimals is a calc's decimals count, or shortestDecimals where it names none.
|
||||||
func calcDecimals(args []string) int {
|
func calcDecimals(args []string) int {
|
||||||
if len(args) == 2 {
|
if len(args) == 2 {
|
||||||
return atoi(args[1])
|
return atoi(args[1])
|
||||||
}
|
}
|
||||||
return -1
|
return shortestDecimals
|
||||||
}
|
}
|
||||||
|
|
||||||
// indexVars replaces each operand name with its position in the values expand reads.
|
// indexVars replaces each operand name with its position in the values expand reads.
|
||||||
|
|||||||
@@ -125,9 +125,13 @@ type builtin struct {
|
|||||||
// operands names the fields the call reads, which expand renders for it; nil
|
// operands names the fields the call reads, which expand renders for it; nil
|
||||||
// for a builtin that reads none.
|
// for a builtin that reads none.
|
||||||
operands func(args []string) []string
|
operands func(args []string) []string
|
||||||
// proveNumber proves what a call prints, token its body: the bounds of its number and the
|
// proveNumber bounds the number a call's text reads as, token its body, and says which
|
||||||
// datatype of its text, prints or one inside it; nil for a builtin whose text is no number.
|
// datatypes that text is not; set it where every render reads as a finite number, which
|
||||||
|
// makes the call a calc operand, and leave it nil otherwise.
|
||||||
proveNumber func(token string, prints DataType, args []string) proven
|
proveNumber func(token string, prints DataType, args []string) proven
|
||||||
|
// prints is the datatype every render's text is, which a typed column holds the call to:
|
||||||
|
// DataTypeString where it reads as a number but no column should type it, as digits'
|
||||||
|
// leading zeros; unset where proveNumber is nil.
|
||||||
prints DataType
|
prints DataType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -26,8 +26,6 @@ least modify.
|
|||||||
|
|
||||||
This round, in order:
|
This round, in order:
|
||||||
|
|
||||||
- Name `printedNumber`'s `dp` cases, and say on `builtin` what `prints` and
|
|
||||||
`proveNumber` a new builtin sets: the extender copied `digits` by analogy.
|
|
||||||
- Rename the names that mislead: `table.pinnedRow` is the row node, not a pinned row;
|
- Rename the names that mislead: `table.pinnedRow` is the row node, not a pinned row;
|
||||||
`table.category` is a bare name beside the dotted `category` of `resolveLink`;
|
`table.category` is a bare name beside the dotted `category` of `resolveLink`;
|
||||||
`checkRenders` renders nothing; `fieldAlternation` is a plain `{name}` too; and
|
`checkRenders` renders nothing; `fieldAlternation` is a plain `{name}` too; and
|
||||||
|
|||||||
@@ -261,16 +261,23 @@ func bounded(lo, hi float64, integral bool) proven {
|
|||||||
|
|
||||||
func magnitude(v proven) float64 { return math.Max(math.Abs(v.lo), math.Abs(v.hi)) }
|
func magnitude(v proven) float64 { return math.Max(math.Abs(v.lo), math.Abs(v.hi)) }
|
||||||
|
|
||||||
// printedNumber is what a token printing v to dp decimals holds: an integer when whole
|
// printedNumber is what a token printing v to dp decimals holds.
|
||||||
// and within int64, else a number.
|
|
||||||
func printedNumber(token string, v proven, dp int) proven {
|
func printedNumber(token string, v proven, dp int) proven {
|
||||||
if dp >= 0 {
|
if dp == shortestDecimals {
|
||||||
half, _ := strconv.ParseFloat("5e-"+strconv.Itoa(dp+1), 64)
|
if v.integral { // a whole value prints with no point
|
||||||
v = proven{lo: v.lo - half, hi: v.hi + half, nonZero: math.Max(0, v.nonZero-half), integral: v.integral || dp == 0}
|
return printedInteger(token, v)
|
||||||
}
|
}
|
||||||
if dp != 0 && !(dp < 0 && v.integral) {
|
|
||||||
return printing(token, DataTypeNumber, v)
|
return printing(token, DataTypeNumber, v)
|
||||||
}
|
}
|
||||||
|
half, _ := strconv.ParseFloat("5e-"+strconv.Itoa(dp+1), 64)
|
||||||
|
v = proven{lo: v.lo - half, hi: v.hi + half, nonZero: math.Max(0, v.nonZero-half), integral: v.integral || dp == 0}
|
||||||
|
if dp == 0 {
|
||||||
|
return printedInteger(token, v)
|
||||||
|
}
|
||||||
|
return printing(token, DataTypeNumber, v)
|
||||||
|
}
|
||||||
|
|
||||||
|
func printedInteger(token string, v proven) proven {
|
||||||
v = printing(token, DataTypeInteger, v)
|
v = printing(token, DataTypeInteger, v)
|
||||||
if !(magnitude(v) < math.MaxInt64) {
|
if !(magnitude(v) < math.MaxInt64) {
|
||||||
v.not[DataTypeInteger] = fmt.Sprintf("{%s} is not proven within int64", token)
|
v.not[DataTypeInteger] = fmt.Sprintf("{%s} is not proven within int64", token)
|
||||||
|
|||||||
Reference in New Issue
Block a user