Make great documentation goal 1.2, and plan the README's reorganisation and the nested-template gaps #33
+3
-1
@@ -16,6 +16,8 @@ import (
|
||||
const (
|
||||
maxLen = 1 << 20
|
||||
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
|
||||
@@ -100,7 +102,7 @@ func chars(alphabet string) func([]string) callFn {
|
||||
|
||||
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 {
|
||||
s := strconv.FormatFloat(v, 'f', dp, 64)
|
||||
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
|
||||
// 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 {
|
||||
expr, err := parseCalc(args[0])
|
||||
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 {
|
||||
if len(args) == 2 {
|
||||
return atoi(args[1])
|
||||
}
|
||||
return -1
|
||||
return shortestDecimals
|
||||
}
|
||||
|
||||
// indexVars replaces each operand name with its position in the values expand reads.
|
||||
|
||||
@@ -125,10 +125,14 @@ type builtin struct {
|
||||
// operands names the fields the call reads, which expand renders for it; nil
|
||||
// for a builtin that reads none.
|
||||
operands func(args []string) []string
|
||||
// proveNumber proves what a call prints, token its body: the bounds of its number and the
|
||||
// datatype of its text, prints or one inside it; nil for a builtin whose text is no number.
|
||||
// proveNumber bounds the number a call's text reads as, token its body, and says which
|
||||
// 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
|
||||
prints DataType
|
||||
// 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
|
||||
}
|
||||
|
||||
// funcCall splits a "{token}" body shaped name(args) into its parts; ok is false
|
||||
|
||||
@@ -26,8 +26,6 @@ least modify.
|
||||
|
||||
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;
|
||||
`table.category` is a bare name beside the dotted `category` of `resolveLink`;
|
||||
`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)) }
|
||||
|
||||
// printedNumber is what a token printing v to dp decimals holds: an integer when whole
|
||||
// and within int64, else a number.
|
||||
// printedNumber is what a token printing v to dp decimals holds.
|
||||
func printedNumber(token string, v proven, dp int) proven {
|
||||
if dp >= 0 {
|
||||
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 && !(dp < 0 && v.integral) {
|
||||
if dp == shortestDecimals {
|
||||
if v.integral { // a whole value prints with no point
|
||||
return printedInteger(token, 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)
|
||||
if !(magnitude(v) < math.MaxInt64) {
|
||||
v.not[DataTypeInteger] = fmt.Sprintf("{%s} is not proven within int64", token)
|
||||
|
||||
Reference in New Issue
Block a user