mirror of
https://github.com/johnkerl/miller.git
synced 2026-01-23 10:15:36 +00:00
mlrval/interpreter iterate
This commit is contained in:
parent
3a0654899c
commit
52255a070f
13 changed files with 1559 additions and 1094 deletions
|
|
@ -1091,7 +1091,7 @@ static mv_t minus_n_ii(mv_t* pa, mv_t* pb) {
|
|||
}
|
||||
|
||||
if (overflowed) {
|
||||
return mv_from_float((double)a + (double)b);
|
||||
return mv_from_float((double)a - (double)b);
|
||||
} else {
|
||||
return mv_from_int(c);
|
||||
}
|
||||
|
|
@ -1193,7 +1193,7 @@ static mv_t divide_f_if(mv_t* pa, mv_t* pb) {
|
|||
double b = pb->u.fltv;
|
||||
return mv_from_float(a / b);
|
||||
}
|
||||
static mv_t divide_i_ii(mv_t* pa, mv_t* pb) {
|
||||
static mv_t divide_n_ii(mv_t* pa, mv_t* pb) {
|
||||
long long a = pa->u.intv;
|
||||
long long b = pb->u.intv;
|
||||
if (b == 0LL) { // Compute inf/nan as with floats rather than fatal runtime FPE on integer divide by zero
|
||||
|
|
@ -1214,7 +1214,7 @@ static mv_binary_func_t* divide_dispositions[MT_DIM][MT_DIM] = {
|
|||
/*ABSENT*/ {_err, _a, _a, _err, _i0, _f0, _err},
|
||||
/*EMPTY*/ {_err, _a, _emt, _err, _emt, _emt, _err},
|
||||
/*STRING*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
/*INT*/ {_err, _1, _emt, _err, divide_i_ii, divide_f_if, _err},
|
||||
/*INT*/ {_err, _1, _emt, _err, divide_n_ii, divide_f_if, _err},
|
||||
/*FLOAT*/ {_err, _1, _emt, _err, divide_f_fi, divide_f_ff, _err},
|
||||
/*BOOL*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
};
|
||||
|
|
|
|||
|
|
@ -2422,7 +2422,7 @@ SEE ALSO
|
|||
|
||||
|
||||
|
||||
2020-08-25 MILLER(1)
|
||||
2020-08-31 MILLER(1)
|
||||
</pre>
|
||||
</div>
|
||||
<p/>
|
||||
|
|
|
|||
|
|
@ -2348,4 +2348,4 @@ SEE ALSO
|
|||
|
||||
|
||||
|
||||
2020-08-25 MILLER(1)
|
||||
2020-08-31 MILLER(1)
|
||||
|
|
|
|||
|
|
@ -2,12 +2,12 @@
|
|||
.\" Title: mlr
|
||||
.\" Author: [see the "AUTHOR" section]
|
||||
.\" Generator: ./mkman.rb
|
||||
.\" Date: 2020-08-25
|
||||
.\" Date: 2020-08-31
|
||||
.\" Manual: \ \&
|
||||
.\" Source: \ \&
|
||||
.\" Language: English
|
||||
.\"
|
||||
.TH "MILLER" "1" "2020-08-25" "\ \&" "\ \&"
|
||||
.TH "MILLER" "1" "2020-08-31" "\ \&" "\ \&"
|
||||
.\" -----------------------------------------------------------------
|
||||
.\" * Portability definitions
|
||||
.\" ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
|
||||
|
|
|
|||
|
|
@ -8,9 +8,10 @@ import (
|
|||
type TNodeType string
|
||||
|
||||
const (
|
||||
NodeTypeStringLiteral TNodeType = "StringLiteral"
|
||||
NodeTypeNumberLiteral = "NumberLiteral"
|
||||
NodeTypeBooleanLiteral = "BooleanLiteral"
|
||||
NodeTypeStringLiteral TNodeType = "StringLiteral"
|
||||
NodeTypeIntLiteral = "IntLiteral"
|
||||
NodeTypeFloatLiteral = "FloatLiteral"
|
||||
NodeTypeBoolLiteral = "BoolLiteral"
|
||||
|
||||
NodeTypeDirectFieldName = "DirectFieldName"
|
||||
NodeTypeIndirectFieldName = "IndirectFieldName"
|
||||
|
|
|
|||
|
|
@ -2,16 +2,16 @@ package dsl
|
|||
|
||||
import (
|
||||
"errors"
|
||||
"strconv"
|
||||
|
||||
"miller/containers"
|
||||
"miller/lib"
|
||||
"miller/runtime"
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Just a very temporary CST-free, AST-only interpreter to get me executing
|
||||
// some DSL code with a minimum of keystroking, while I work out other issues
|
||||
// including mlrval-valued lrecs.
|
||||
// including mlrval-valued lrecs, and port of mvfuncs from C to Go.
|
||||
type Interpreter struct {
|
||||
}
|
||||
|
||||
|
|
@ -19,6 +19,7 @@ func NewInterpreter() *Interpreter {
|
|||
return &Interpreter{}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func (this *Interpreter) InterpretOnInputRecord(
|
||||
inrec *containers.Lrec,
|
||||
context *runtime.Context,
|
||||
|
|
@ -51,19 +52,21 @@ func (this *Interpreter) InterpretOnInputRecord(
|
|||
rhsNode := child.Children[1]
|
||||
|
||||
fieldName := string(lhsNode.Token.Lit)[1:] // strip off leading '$'
|
||||
value, defined, err := this.evaluateNode(rhsNode, inrec, context)
|
||||
mvalue, err := this.evaluateNode(rhsNode, inrec, context)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if defined {
|
||||
inrec.Put(&fieldName, &value)
|
||||
} else {
|
||||
// xxx temp -- srec values are going to be mlrvals all the way through
|
||||
svalue := mvalue.String()
|
||||
inrec.Put(&fieldName, &svalue)
|
||||
}
|
||||
}
|
||||
|
||||
return inrec, nil
|
||||
}
|
||||
|
||||
// xxx make into ASTNode method
|
||||
// ----------------------------------------------------------------
|
||||
// xxx make into ASTNode method?
|
||||
func (this *Interpreter) checkArity(
|
||||
node *ASTNode,
|
||||
arity int,
|
||||
|
|
@ -75,12 +78,12 @@ func (this *Interpreter) checkArity(
|
|||
}
|
||||
}
|
||||
|
||||
// xxx needs null/undefined/string/error. then, string->mlrval.
|
||||
// ----------------------------------------------------------------
|
||||
func (this *Interpreter) evaluateNode(
|
||||
node *ASTNode,
|
||||
inrec *containers.Lrec,
|
||||
context *runtime.Context,
|
||||
) (string, bool, error) {
|
||||
) (lib.Mlrval, error) {
|
||||
var sval = ""
|
||||
if node.Token != nil {
|
||||
sval = string(node.Token.Lit)
|
||||
|
|
@ -89,31 +92,33 @@ func (this *Interpreter) evaluateNode(
|
|||
switch node.NodeType {
|
||||
|
||||
case NodeTypeStringLiteral:
|
||||
// xxx temp -- fix this in the grammar or ast-insert?
|
||||
return sval[1 : len(sval)-1], true, nil
|
||||
case NodeTypeNumberLiteral:
|
||||
return sval, true, nil // xxx temp -- to mlrval
|
||||
case NodeTypeBooleanLiteral:
|
||||
return sval, true, nil // xxx temp -- to mlrval
|
||||
// xxx temp "..." strip -- fix this in the grammar or ast-insert
|
||||
return lib.MlrvalFromString(sval[1 : len(sval)-1]), nil
|
||||
case NodeTypeIntLiteral:
|
||||
return lib.MlrvalFromInt64String(sval), nil
|
||||
case NodeTypeFloatLiteral:
|
||||
return lib.MlrvalFromFloat64String(sval), nil
|
||||
case NodeTypeBoolLiteral:
|
||||
return lib.MlrvalFromBoolString(sval), nil
|
||||
|
||||
case NodeTypeDirectFieldName:
|
||||
fieldName := sval[1:] // xxx temp -- fix this in the grammar or ast-insert?
|
||||
fieldValue := inrec.Get(&fieldName)
|
||||
if fieldValue == nil {
|
||||
return "", false, nil
|
||||
return lib.MlrvalFromAbsent(), nil
|
||||
} else {
|
||||
return *fieldValue, true, nil
|
||||
return lib.MlrvalFromInferredType(*fieldValue), nil
|
||||
}
|
||||
break
|
||||
case NodeTypeIndirectFieldName:
|
||||
return "", true, errors.New("unhandled")
|
||||
return lib.MlrvalFromError(), errors.New("unhandled1")
|
||||
break
|
||||
|
||||
case NodeTypeStatementBlock:
|
||||
return "", true, errors.New("unhandled")
|
||||
return lib.MlrvalFromError(), errors.New("unhandled2")
|
||||
break
|
||||
case NodeTypeAssignment:
|
||||
return "", true, errors.New("unhandled")
|
||||
return lib.MlrvalFromError(), errors.New("unhandled3")
|
||||
break
|
||||
case NodeTypeOperator:
|
||||
this.checkArity(node, 2) // xxx temp -- binary-only for now
|
||||
|
|
@ -125,54 +130,57 @@ func (this *Interpreter) evaluateNode(
|
|||
break
|
||||
|
||||
}
|
||||
return "", true, errors.New("unhandled")
|
||||
return lib.MlrvalFromError(), errors.New("unhandled4")
|
||||
}
|
||||
|
||||
func (this *Interpreter) evaluateContextVariableNode(
|
||||
node *ASTNode,
|
||||
context *runtime.Context,
|
||||
) (string, bool, error) {
|
||||
) (lib.Mlrval, error) {
|
||||
if node.Token == nil {
|
||||
return "", true, errors.New("internal coding error") // xxx libify
|
||||
return lib.MlrvalFromError(), errors.New("internal coding error") // xxx libify
|
||||
}
|
||||
sval := string(node.Token.Lit)
|
||||
switch sval {
|
||||
case "FILENAME":
|
||||
return context.FILENAME, true, nil
|
||||
return lib.MlrvalFromString(context.FILENAME), nil
|
||||
break
|
||||
case "FILENUM":
|
||||
return strconv.FormatInt(context.FILENUM, 10), true, nil
|
||||
return lib.MlrvalFromInt64(context.FILENUM), nil
|
||||
break
|
||||
case "NF":
|
||||
return strconv.FormatInt(context.NF, 10), true, nil
|
||||
return lib.MlrvalFromInt64(context.NF), nil
|
||||
break
|
||||
case "NR":
|
||||
return strconv.FormatInt(context.NR, 10), true, nil
|
||||
return lib.MlrvalFromInt64(context.NR), nil
|
||||
break
|
||||
case "FNR":
|
||||
return strconv.FormatInt(context.FNR, 10), true, nil
|
||||
return lib.MlrvalFromInt64(context.FNR), nil
|
||||
break
|
||||
|
||||
case "IPS":
|
||||
return context.IPS, true, nil
|
||||
return lib.MlrvalFromString(context.IPS), nil
|
||||
break
|
||||
case "IFS":
|
||||
return context.IFS, true, nil
|
||||
return lib.MlrvalFromString(context.IFS), nil
|
||||
break
|
||||
case "IRS":
|
||||
return context.IRS, true, nil
|
||||
return lib.MlrvalFromString(context.IRS), nil
|
||||
break
|
||||
|
||||
case "OPS":
|
||||
return context.OPS, true, nil
|
||||
return lib.MlrvalFromString(context.OPS), nil
|
||||
break
|
||||
case "OFS":
|
||||
return context.OFS, true, nil
|
||||
return lib.MlrvalFromString(context.OFS), nil
|
||||
break
|
||||
case "ORS":
|
||||
return context.ORS, true, nil
|
||||
return lib.MlrvalFromString(context.ORS), nil
|
||||
break
|
||||
|
||||
break
|
||||
}
|
||||
return "", true, errors.New("internal coding error") // xxx libify
|
||||
return lib.MlrvalFromError(), errors.New("internal coding error") // xxx libify
|
||||
}
|
||||
|
||||
func (this *Interpreter) evaluateBinaryOperatorNode(
|
||||
|
|
@ -181,81 +189,36 @@ func (this *Interpreter) evaluateBinaryOperatorNode(
|
|||
rightChild *ASTNode,
|
||||
inrec *containers.Lrec,
|
||||
context *runtime.Context,
|
||||
) (string, bool, error) {
|
||||
sval := string(node.Token.Lit)
|
||||
) (lib.Mlrval, error) {
|
||||
sop := string(node.Token.Lit)
|
||||
|
||||
leftValue, leftDefined, leftErr := this.evaluateNode(leftChild, inrec, context)
|
||||
leftValue, leftErr := this.evaluateNode(leftChild, inrec, context)
|
||||
if leftErr != nil {
|
||||
return "", true, leftErr
|
||||
return lib.MlrvalFromError(), leftErr
|
||||
}
|
||||
if !leftDefined {
|
||||
return "", false, nil
|
||||
}
|
||||
rightValue, rightDefined, rightErr := this.evaluateNode(rightChild, inrec, context)
|
||||
rightValue, rightErr := this.evaluateNode(rightChild, inrec, context)
|
||||
if rightErr != nil {
|
||||
return "", true, rightErr
|
||||
}
|
||||
if !rightDefined {
|
||||
return "", false, nil
|
||||
return lib.MlrvalFromError(), rightErr
|
||||
}
|
||||
|
||||
switch sval {
|
||||
case ".":
|
||||
return leftValue + rightValue, true, nil
|
||||
break
|
||||
}
|
||||
|
||||
switch sval {
|
||||
switch sop {
|
||||
case "+":
|
||||
// xxx make a lib method -- Itoa64
|
||||
//return lib.Itoa64(leftInt + rightInt), true, nil
|
||||
a := lib.MlrvalFromInt64String(leftValue)
|
||||
b := lib.MlrvalFromInt64String(rightValue)
|
||||
c := lib.MlrvalPlus(&a, &b)
|
||||
return c.String(), true, nil
|
||||
return lib.MlrvalPlus(&leftValue, &rightValue), nil
|
||||
break
|
||||
}
|
||||
|
||||
// make a helper method for int-pairings
|
||||
leftInt, lerr := strconv.ParseInt(leftValue, 10, 0)
|
||||
if lerr != nil {
|
||||
// to do: consider error-propagation through the AST evaluator, with
|
||||
// null/undefined/error in the binop matrices etc.
|
||||
//
|
||||
// need to separate internal coding errors, from data-dependent ones
|
||||
//
|
||||
//return "", true, lerr
|
||||
return "(error)", true, nil
|
||||
}
|
||||
rightInt, rerr := strconv.ParseInt(rightValue, 10, 0)
|
||||
if rerr != nil {
|
||||
//return "", true, rerr
|
||||
return "(error)", true, nil
|
||||
}
|
||||
|
||||
switch sval {
|
||||
case "-":
|
||||
return lib.Itoa64(leftInt - rightInt), true, nil
|
||||
return lib.MlrvalMinus(&leftValue, &rightValue), nil
|
||||
break
|
||||
case "*":
|
||||
return lib.Itoa64(leftInt * rightInt), true, nil
|
||||
return lib.MlrvalTimes(&leftValue, &rightValue), nil
|
||||
break
|
||||
case "/":
|
||||
return lib.Itoa64(leftInt / rightInt), true, nil
|
||||
break
|
||||
case "^":
|
||||
return lib.Itoa64(leftInt ^ rightInt), true, nil
|
||||
break
|
||||
case "&":
|
||||
return lib.Itoa64(leftInt & rightInt), true, nil
|
||||
break
|
||||
case "|":
|
||||
return lib.Itoa64(leftInt | rightInt), true, nil
|
||||
return lib.MlrvalDivide(&leftValue, &rightValue), nil
|
||||
break
|
||||
case "//":
|
||||
return "", true, errors.New("unhandled")
|
||||
return lib.MlrvalIntDivide(&leftValue, &rightValue), nil
|
||||
break
|
||||
// xxx continue ...
|
||||
}
|
||||
|
||||
return "", true, errors.New("internal coding error") // xxx libify
|
||||
return lib.MlrvalFromError(), errors.New("internal coding error") // xxx libify
|
||||
}
|
||||
|
|
|
|||
|
|
@ -2,82 +2,59 @@ package lib
|
|||
|
||||
import (
|
||||
"fmt"
|
||||
"math"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
// Two kinds of null: absent (key not present in a record) and void (key
|
||||
// present with empty value). Note void is an acceptable string (empty string)
|
||||
// but not an acceptable number. (In Javascript, similarly, there are null and
|
||||
// undefined.) Void-valued mlrvals have u.strv = "".
|
||||
|
||||
// #define MT_ERROR 0 // E.g. error encountered in one eval & it propagates up the AST.
|
||||
|
||||
// --> JS undefined -- rename this -- or maybe MT_ABSENT ok ...
|
||||
// #define MT_ABSENT 1 // No such key, e.g. $z in 'x=,y=2'
|
||||
|
||||
// --> JS null -- rename this -- or maybe MT_VOID
|
||||
// xxx note it seralizes to "" ... which is kinda whack ...
|
||||
// #define MT_EMPTY 2 // Empty value, e.g. $x in 'x=,y=2'
|
||||
|
||||
// #define MT_STRING 3
|
||||
// #define MT_INT 4
|
||||
// #define MT_FLOAT 5
|
||||
// #define MT_BOOL 6
|
||||
// #define MT_DIM 7
|
||||
|
||||
// typedef struct _mv_t {
|
||||
// union {
|
||||
// char* strv; // MT_STRING and MT_EMPTY
|
||||
// long long intv; // MT_INT, and == 0 for MT_ABSENT and MT_ERROR
|
||||
// double fltv; // MT_FLOAT
|
||||
// int boolv; // MT_BOOL
|
||||
// } u;
|
||||
// unsigned char type;
|
||||
// } mv_t;
|
||||
|
||||
// Requirements:
|
||||
// ================================================================
|
||||
// Requirements for mlrvals:
|
||||
//
|
||||
// * Keep original string-formatting even if parseable/parsed as int
|
||||
// o E.g. if 005 (octal), pass through as 005 unless math is done on it
|
||||
// o Likewise with number of decimal places -- 7.4 not 7.400 or (worse) 7.399999999
|
||||
// * Invalidate the string-formatting as the output of a computational result
|
||||
// * Have number-to-string formatting methods in the API/DSL which stick the string format
|
||||
// * Final to-string method
|
||||
|
||||
//
|
||||
// Also:
|
||||
// * split current C mvfuncs into mlrval-private (dispo matrices etc) and new
|
||||
// * Split current C mvfuncs into mlrval-private (dispo matrices etc) and new
|
||||
// mvfuncs.go where the latter don't need access to private members
|
||||
// ================================================================
|
||||
|
||||
// Question:
|
||||
// * What to do with disposition matrices from the C impl?
|
||||
// Example:
|
||||
//static mv_binary_func_t* plus_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
// /*ABSENT*/ {_err, _a, _a, _err, _2___, _2___, _err},
|
||||
// /*EMPTY*/ {_err, _a, _emt, _err, _emt, _emt, _err},
|
||||
// /*STRING*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
// /*INT*/ {_err, _1___, _emt, _err, plus_n_ii, plus_f_if, _err},
|
||||
// /*FLOAT*/ {_err, _1___, _emt, _err, plus_f_fi, plus_f_ff, _err},
|
||||
// /*BOOL*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
//};
|
||||
// ================================================================
|
||||
// There are two kinds of null: ABSENT (key not present in a record) and VOID
|
||||
// (key present with empty value). Note void is an acceptable string (empty
|
||||
// string) but not an acceptable number. (In Javascript, similarly, there are
|
||||
// undefined and null, respectively.)
|
||||
// ================================================================
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// ================================================================
|
||||
type MVType int
|
||||
|
||||
const (
|
||||
// E.g. error encountered in one eval & it propagates up the AST at evaluation time:
|
||||
MT_ERROR MVType = 0
|
||||
|
||||
// Key not present in input record, e.g. 'foo = $nosuchkey'
|
||||
MT_ABSENT = 1
|
||||
|
||||
// Key present in input record with empty value, e.g. input data '$x=,$y=2'
|
||||
MT_VOID = 2
|
||||
|
||||
MT_STRING = 3
|
||||
|
||||
MT_INT = 4
|
||||
|
||||
MT_FLOAT = 5
|
||||
|
||||
MT_BOOL = 6
|
||||
|
||||
// Not a type -- this is a dimension for disposition matrices
|
||||
MT_DIM = 7
|
||||
)
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// ================================================================
|
||||
type Mlrval struct {
|
||||
mvtype MVType
|
||||
printrep string
|
||||
|
|
@ -87,7 +64,7 @@ type Mlrval struct {
|
|||
boolval bool
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// ================================================================
|
||||
func MlrvalFromError() Mlrval {
|
||||
return Mlrval{
|
||||
MT_ERROR,
|
||||
|
|
@ -115,6 +92,7 @@ func MlrvalFromVoid() Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func MlrvalFromString(input string) Mlrval {
|
||||
return Mlrval{
|
||||
MT_STRING,
|
||||
|
|
@ -124,17 +102,16 @@ func MlrvalFromString(input string) Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx comment why two -- one for from parsed user data; other for from math ops
|
||||
func MlrvalFromInt64String(input string) Mlrval {
|
||||
// xxx handle octal, hex, ......
|
||||
ival, err := strconv.ParseInt(input, 10, 64)
|
||||
ival, ok := tryInt64FromString(input)
|
||||
// xxx comment assummption is input-string already deemed parseable so no error return
|
||||
if err != nil {
|
||||
if !ok {
|
||||
// xxx get file/line info here .......
|
||||
fmt.Fprintf(os.Stderr, "Internal coding error detected\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
return Mlrval{
|
||||
MT_INT,
|
||||
input,
|
||||
|
|
@ -148,7 +125,7 @@ func MlrvalFromInt64String(input string) Mlrval {
|
|||
func MlrvalFromInt64(input int64) Mlrval {
|
||||
return Mlrval{
|
||||
MT_INT,
|
||||
"(uninit)",
|
||||
"(bug-if-you-see-this)",
|
||||
false,
|
||||
input,
|
||||
0.0,
|
||||
|
|
@ -156,13 +133,25 @@ func MlrvalFromInt64(input int64) Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
func tryInt64FromString(input string) (int64, bool) {
|
||||
// xxx need to handle octal, hex, ......
|
||||
ival, err := strconv.ParseInt(input, 10, 64)
|
||||
if err == nil {
|
||||
return ival, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// xxx comment why two -- one for from parsed user data; other for from math ops
|
||||
// xxx comment assummption is input-string already deemed parseable so no error return
|
||||
|
||||
func MlrvalFromFloat64String(input string) Mlrval {
|
||||
fval, err := strconv.ParseFloat(input, 64)
|
||||
fval, ok := tryFloat64FromString(input)
|
||||
// xxx comment assummption is input-string already deemed parseable so no error return
|
||||
if err != nil {
|
||||
// xxx panic ?
|
||||
if !ok {
|
||||
// xxx get file/line info here .......
|
||||
fmt.Fprintf(os.Stderr, "Internal coding error detected\n")
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
@ -179,7 +168,7 @@ func MlrvalFromFloat64String(input string) Mlrval {
|
|||
func MlrvalFromFloat64(input float64) Mlrval {
|
||||
return Mlrval{
|
||||
MT_FLOAT,
|
||||
"(uninit)",
|
||||
"(bug-if-you-see-this)",
|
||||
false,
|
||||
0,
|
||||
input,
|
||||
|
|
@ -187,6 +176,16 @@ func MlrvalFromFloat64(input float64) Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
func tryFloat64FromString(input string) (float64, bool) {
|
||||
ival, err := strconv.ParseFloat(input, 64)
|
||||
if err == nil {
|
||||
return ival, true
|
||||
} else {
|
||||
return 0, false
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func MlrvalFromTrue() Mlrval {
|
||||
return Mlrval{
|
||||
MT_BOOL,
|
||||
|
|
@ -209,15 +208,50 @@ func MlrvalFromFalse() Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
func MlrvalFromBoolean(input bool) Mlrval {
|
||||
if input == true {
|
||||
func MlrvalFromBoolString(input string) Mlrval {
|
||||
if input == "true" {
|
||||
return MlrvalFromTrue()
|
||||
} else {
|
||||
return MlrvalFromFalse()
|
||||
}
|
||||
// else panic
|
||||
}
|
||||
|
||||
func tryBoolFromBoolString(input string) (bool, bool) {
|
||||
if input == "true" {
|
||||
return true, true
|
||||
} else if input == "false" {
|
||||
return false, true
|
||||
} else {
|
||||
return false, false
|
||||
}
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
func MlrvalFromInferredType(input string) Mlrval {
|
||||
// xxx the parsing has happened so stash it ...
|
||||
// xxx emphasize the invariant that a non-invalid printrep always
|
||||
// matches the nval ...
|
||||
_, iok := tryInt64FromString(input)
|
||||
if iok {
|
||||
return MlrvalFromInt64String(input)
|
||||
}
|
||||
|
||||
_, fok := tryFloat64FromString(input)
|
||||
if fok {
|
||||
return MlrvalFromFloat64String(input)
|
||||
}
|
||||
|
||||
_, bok := tryBoolFromBoolString(input)
|
||||
if bok {
|
||||
return MlrvalFromBoolString(input)
|
||||
}
|
||||
|
||||
return MlrvalFromString(input)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
// xxx comment about JIT-parsing of string backings
|
||||
func (this *Mlrval) setPrintRep() {
|
||||
if !this.printrepValid {
|
||||
// xxx do it -- disposition vector
|
||||
|
|
@ -230,7 +264,7 @@ func (this *Mlrval) setPrintRep() {
|
|||
// Callsites should be using absence to do non-assigns, so flag
|
||||
// this clearly visually if it should (buggily) slip through to
|
||||
// user-level visibility.
|
||||
this.printrep = "(absent)" // xxx constdef at top of file
|
||||
this.printrep = "(bug-if-you-see-this)" // xxx constdef at top of file
|
||||
break
|
||||
case MT_VOID:
|
||||
this.printrep = "" // xxx constdef at top of file
|
||||
|
|
@ -278,8 +312,86 @@ func _1___(val1, val2 *Mlrval) Mlrval {
|
|||
func _2___(val1, val2 *Mlrval) Mlrval {
|
||||
return *val2
|
||||
}
|
||||
func _i0__(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromInt64(0)
|
||||
}
|
||||
func _f0__(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(0.0)
|
||||
}
|
||||
|
||||
// xxx comment
|
||||
type dyadicFunc func(*Mlrval, *Mlrval) Mlrval
|
||||
|
||||
// ================================================================
|
||||
|
||||
//static mv_t dot_strings(char* string1, char* string2) {
|
||||
// int len1 = strlen(string1);
|
||||
// int len2 = strlen(string2);
|
||||
// int len3 = len1 + len2 + 1; // for the null-terminator byte
|
||||
// char* string3 = mlr_malloc_or_die(len3);
|
||||
// strcpy(&string3[0], string1);
|
||||
// strcpy(&string3[len1], string2);
|
||||
// return mv_from_string_with_free(string3);
|
||||
//}
|
||||
//
|
||||
//mv_t dot_s_ss(mv_t* pval1, mv_t* pval2) {
|
||||
// mv_t rv = dot_strings(pval1->u.strv, pval2->u.strv);
|
||||
// mv_free(pval1);
|
||||
// mv_free(pval2);
|
||||
// return rv;
|
||||
//}
|
||||
//
|
||||
//mv_t dot_s_xs(mv_t* pval1, mv_t* pval2) {
|
||||
// mv_t sval1 = s_x_string_func(pval1);
|
||||
// mv_free(pval1);
|
||||
// mv_t rv = dot_strings(sval1.u.strv, pval2->u.strv);
|
||||
// mv_free(&sval1);
|
||||
// mv_free(pval2);
|
||||
// return rv;
|
||||
//}
|
||||
//
|
||||
//mv_t dot_s_sx(mv_t* pval1, mv_t* pval2) {
|
||||
// mv_t sval2 = s_x_string_func(pval2);
|
||||
// mv_free(pval2);
|
||||
// mv_t rv = dot_strings(pval1->u.strv, sval2.u.strv);
|
||||
// mv_free(pval1);
|
||||
// mv_free(&sval2);
|
||||
// return rv;
|
||||
//}
|
||||
//
|
||||
//mv_t dot_s_xx(mv_t* pval1, mv_t* pval2) {
|
||||
// mv_t sval1 = s_x_string_func(pval1);
|
||||
// mv_t sval2 = s_x_string_func(pval2);
|
||||
// mv_t rv = dot_strings(sval1.u.strv, sval2.u.strv);
|
||||
// mv_free(&sval1);
|
||||
// mv_free(&sval2);
|
||||
// return rv;
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* dot_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _void, _2, _s2, _s2, _s2},
|
||||
// /*EMPTY*/ {_erro, _void, _void, _2, _s2, _s2, _s2},
|
||||
// /*STRING*/ {_erro, _1, _1, dot_s_ss, dot_s_sx, dot_s_sx, dot_s_sx},
|
||||
// /*INT*/ {_erro, _s1, _s1, dot_s_xs, dot_s_xx, dot_s_xx, dot_s_xx},
|
||||
// /*FLOAT*/ {_erro, _s1, _s1, dot_s_xs, dot_s_xx, dot_s_xx, dot_s_xx},
|
||||
// /*BOOL*/ {_erro, _s1, _s1, dot_s_xs, dot_s_xx, dot_s_xx, dot_s_xx},
|
||||
//};
|
||||
//
|
||||
//mv_t s_xx_dot_func(mv_t* pval1, mv_t* pval2) { return (dot_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
|
||||
// ================================================================
|
||||
func plus_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval + float64(val2.intval))
|
||||
}
|
||||
func plus_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(float64(val1.intval) + val2.floatval)
|
||||
}
|
||||
func plus_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval + val2.floatval)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
// Auto-overflows up to float. Additions & subtractions overflow by at most
|
||||
// one bit so it suffices to check sign-changes.
|
||||
func plus_n_ii(val1, val2 *Mlrval) Mlrval {
|
||||
|
|
@ -305,19 +417,6 @@ func plus_n_ii(val1, val2 *Mlrval) Mlrval {
|
|||
}
|
||||
}
|
||||
|
||||
func plus_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval + float64(val2.intval))
|
||||
}
|
||||
func plus_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(float64(val1.intval) + val2.floatval)
|
||||
}
|
||||
func plus_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval + val2.floatval)
|
||||
}
|
||||
|
||||
// // var pfunc func(*Mlrval, *Mlrval) Mlrval
|
||||
type dyadicFunc func(*Mlrval, *Mlrval) Mlrval
|
||||
|
||||
var plusDispositions = [MT_DIM][MT_DIM]dyadicFunc{
|
||||
// ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
/*ERROR */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
|
|
@ -333,18 +432,419 @@ func MlrvalPlus(val1, val2 *Mlrval) Mlrval {
|
|||
return plusDispositions[val1.mvtype][val2.mvtype](val1, val2)
|
||||
}
|
||||
|
||||
// ----------------------------------------------------------------
|
||||
//static mv_binary_func_t* plus_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
// /*ABSENT*/ {_err, _a, _a, _err, _2___, _2___, _err},
|
||||
// /*EMPTY*/ {_err, _a, _emt, _err, _emt, _emt, _err},
|
||||
// /*STRING*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
// /*INT*/ {_err, _1___, _emt, _err, plus_n_ii, plus_f_if, _err},
|
||||
// /*FLOAT*/ {_err, _1___, _emt, _err, plus_f_fi, plus_f_ff, _err},
|
||||
// /*BOOL*/ {_err, _err, _err, _err, _err, _err, _err},
|
||||
// ================================================================
|
||||
func minus_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval - val2.floatval)
|
||||
}
|
||||
func minus_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval - float64(val2.intval))
|
||||
}
|
||||
func minus_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(float64(val1.intval) - val2.floatval)
|
||||
}
|
||||
|
||||
// Adds & subtracts overflow by at most one bit so it suffices to check
|
||||
// sign-changes.
|
||||
func minus_n_ii(val1, val2 *Mlrval) Mlrval {
|
||||
a := val1.intval
|
||||
b := val2.intval
|
||||
c := a - b
|
||||
|
||||
overflowed := false
|
||||
if a > 0 {
|
||||
if b < 0 && c < 0 {
|
||||
overflowed = true
|
||||
}
|
||||
} else if a < 0 {
|
||||
if b > 0 && c > 0 {
|
||||
overflowed = true
|
||||
}
|
||||
}
|
||||
|
||||
if overflowed {
|
||||
return MlrvalFromFloat64(float64(a) - float64(b))
|
||||
} else {
|
||||
return MlrvalFromInt64(c)
|
||||
}
|
||||
}
|
||||
|
||||
var minusDispositions = [MT_DIM][MT_DIM]dyadicFunc{
|
||||
// ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
/*ERROR */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*ABSENT */ {_erro, _absn, _absn, _erro, _2___, _2___, _erro},
|
||||
/*EMPTY */ {_erro, _absn, _void, _erro, _void, _void, _erro},
|
||||
/*STRING */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*INT */ {_erro, _1___, _void, _erro, minus_n_ii, minus_f_if, _erro},
|
||||
/*FLOAT */ {_erro, _1___, _void, _erro, minus_f_fi, minus_f_ff, _erro},
|
||||
/*BOOL */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
}
|
||||
|
||||
func MlrvalMinus(val1, val2 *Mlrval) Mlrval {
|
||||
return minusDispositions[val1.mvtype][val2.mvtype](val1, val2)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
func times_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval * float64(val2.intval))
|
||||
}
|
||||
func times_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(float64(val1.intval) * val2.floatval)
|
||||
}
|
||||
func times_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval * val2.floatval)
|
||||
}
|
||||
|
||||
// Auto-overflows up to float.
|
||||
//
|
||||
// Unlike adds & subtracts which overflow by at most one bit, multiplies can
|
||||
// overflow by a word size. Thus detecting sign-changes does not suffice to
|
||||
// detect overflow. Instead we test whether the floating-point product exceeds
|
||||
// the representable integer range. Now 64-bit integers have 64-bit precision
|
||||
// while IEEE-doubles have only 52-bit mantissas -- so, 53 bits including
|
||||
// implicit leading one.
|
||||
//
|
||||
// The following experiment explicitly demonstrates the resolution at this range:
|
||||
//
|
||||
// 64-bit integer 64-bit integer Casted to double Back to 64-bit
|
||||
// in hex in decimal integer
|
||||
// 0x7ffffffffffff9ff 9223372036854774271 9223372036854773760.000000 0x7ffffffffffff800
|
||||
// 0x7ffffffffffffa00 9223372036854774272 9223372036854773760.000000 0x7ffffffffffff800
|
||||
// 0x7ffffffffffffbff 9223372036854774783 9223372036854774784.000000 0x7ffffffffffffc00
|
||||
// 0x7ffffffffffffc00 9223372036854774784 9223372036854774784.000000 0x7ffffffffffffc00
|
||||
// 0x7ffffffffffffdff 9223372036854775295 9223372036854774784.000000 0x7ffffffffffffc00
|
||||
// 0x7ffffffffffffe00 9223372036854775296 9223372036854775808.000000 0x8000000000000000
|
||||
// 0x7ffffffffffffffe 9223372036854775806 9223372036854775808.000000 0x8000000000000000
|
||||
// 0x7fffffffffffffff 9223372036854775807 9223372036854775808.000000 0x8000000000000000
|
||||
//
|
||||
// That is, we cannot check an integer product to see if it is greater than
|
||||
// 2**63-1 (or is less than -2**63) using integer arithmetic (it may have
|
||||
// already overflowed) *or* using double-precision (granularity). Instead we
|
||||
// check if the absolute value of the product exceeds the largest representable
|
||||
// double less than 2**63. (An alterative would be to do all integer multiplies
|
||||
// using handcrafted multi-word 128-bit arithmetic).
|
||||
|
||||
func times_n_ii(val1, val2 *Mlrval) Mlrval {
|
||||
a := val1.intval
|
||||
b := val2.intval
|
||||
c := float64(a) * float64(b)
|
||||
|
||||
if math.Abs(c) > 9223372036854774784.0 {
|
||||
return MlrvalFromFloat64(c)
|
||||
} else {
|
||||
return MlrvalFromInt64(a * b)
|
||||
}
|
||||
}
|
||||
|
||||
var timesDispositions = [MT_DIM][MT_DIM]dyadicFunc{
|
||||
// ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
/*ERROR */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*ABSENT */ {_erro, _absn, _absn, _erro, _2___, _2___, _erro},
|
||||
/*EMPTY */ {_erro, _absn, _void, _erro, _void, _void, _erro},
|
||||
/*STRING */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*INT */ {_erro, _1___, _void, _erro, times_n_ii, times_f_if, _erro},
|
||||
/*FLOAT */ {_erro, _1___, _void, _erro, times_f_fi, times_f_ff, _erro},
|
||||
/*BOOL */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
}
|
||||
|
||||
func MlrvalTimes(val1, val2 *Mlrval) Mlrval {
|
||||
return timesDispositions[val1.mvtype][val2.mvtype](val1, val2)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
func divide_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval / float64(val2.intval))
|
||||
}
|
||||
func divide_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(float64(val1.intval) / val2.floatval)
|
||||
}
|
||||
func divide_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(val1.floatval / val2.floatval)
|
||||
}
|
||||
|
||||
func divide_n_ii(val1, val2 *Mlrval) Mlrval {
|
||||
a := val1.intval
|
||||
b := val2.intval
|
||||
|
||||
if b == 0 {
|
||||
// Compute inf/nan as with floats rather than fatal runtime FPE on integer divide by zero
|
||||
return MlrvalFromFloat64(float64(a) / float64(b))
|
||||
}
|
||||
|
||||
// Pythonic division, not C division.
|
||||
if a%b == 0 {
|
||||
return MlrvalFromInt64(a / b)
|
||||
} else {
|
||||
return MlrvalFromFloat64(float64(a) / float64(b))
|
||||
}
|
||||
|
||||
c := float64(a) * float64(b)
|
||||
|
||||
if math.Abs(c) > 9223372036854774784.0 {
|
||||
return MlrvalFromFloat64(c)
|
||||
} else {
|
||||
return MlrvalFromInt64(a * b)
|
||||
}
|
||||
}
|
||||
|
||||
var divideDispositions = [MT_DIM][MT_DIM]dyadicFunc{
|
||||
// ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
/*ERROR */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*ABSENT */ {_erro, _absn, _absn, _erro, _i0__, _f0__, _erro},
|
||||
/*EMPTY */ {_erro, _absn, _void, _erro, _void, _void, _erro},
|
||||
/*STRING */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*INT */ {_erro, _1___, _void, _erro, divide_n_ii, divide_f_if, _erro},
|
||||
/*FLOAT */ {_erro, _1___, _void, _erro, divide_f_fi, divide_f_ff, _erro},
|
||||
/*BOOL */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
}
|
||||
|
||||
func MlrvalDivide(val1, val2 *Mlrval) Mlrval {
|
||||
return divideDispositions[val1.mvtype][val2.mvtype](val1, val2)
|
||||
}
|
||||
|
||||
// ================================================================
|
||||
func int_divide_f_fi(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(math.Floor(val1.floatval / float64(val2.intval)))
|
||||
}
|
||||
func int_divide_f_if(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(math.Floor(float64(val1.intval) / val2.floatval))
|
||||
}
|
||||
func int_divide_f_ff(val1, val2 *Mlrval) Mlrval {
|
||||
return MlrvalFromFloat64(math.Floor(val1.floatval / val2.floatval))
|
||||
}
|
||||
|
||||
func int_divide_n_ii(val1, val2 *Mlrval) Mlrval {
|
||||
a := val1.intval
|
||||
b := val2.intval
|
||||
|
||||
if b == 0 {
|
||||
// Compute inf/nan as with floats rather than fatal runtime FPE on integer divide by zero
|
||||
return MlrvalFromFloat64(float64(a) / float64(b))
|
||||
}
|
||||
|
||||
// Pythonic division, not C division.
|
||||
q := a / b
|
||||
r := a % b
|
||||
if a < 0 {
|
||||
if b > 0 {
|
||||
if r != 0 {
|
||||
q--
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if b < 0 {
|
||||
if r != 0 {
|
||||
q--
|
||||
}
|
||||
}
|
||||
}
|
||||
return MlrvalFromInt64(q)
|
||||
}
|
||||
|
||||
var int_divideDispositions = [MT_DIM][MT_DIM]dyadicFunc{
|
||||
// ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
/*ERROR */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*ABSENT */ {_erro, _absn, _absn, _erro, _i0__, _f0__, _erro},
|
||||
/*EMPTY */ {_erro, _absn, _void, _erro, _void, _void, _erro},
|
||||
/*STRING */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
/*INT */ {_erro, _1___, _void, _erro, int_divide_n_ii, int_divide_f_if, _erro},
|
||||
/*FLOAT */ {_erro, _1___, _void, _erro, int_divide_f_fi, int_divide_f_ff, _erro},
|
||||
/*BOOL */ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
}
|
||||
|
||||
func MlrvalIntDivide(val1, val2 *Mlrval) Mlrval {
|
||||
return int_divideDispositions[val1.mvtype][val2.mvtype](val1, val2)
|
||||
}
|
||||
|
||||
//// ================================================================
|
||||
//static mv_t oplus_f_ff(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a + b);
|
||||
//}
|
||||
//static mv_t oplus_f_fi(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = (double)pb->u.intv;
|
||||
// return mv_from_float(a + b);
|
||||
//}
|
||||
//static mv_t oplus_f_if(mv_t* pa, mv_t* pb) {
|
||||
// double a = (double)pa->u.intv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a + b);
|
||||
//}
|
||||
//static mv_t oplus_n_ii(mv_t* pa, mv_t* pb) {
|
||||
// long long a = pa->u.intv;
|
||||
// long long b = pb->u.intv;
|
||||
// long long c = a + b;
|
||||
// return mv_from_int(c);
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* oplus_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _a, _erro, _2, _2, _erro},
|
||||
// /*EMPTY*/ {_erro, _a, _void, _erro, _void, _void, _erro},
|
||||
// /*STRING*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*INT*/ {_erro, _1, _void, _erro, oplus_n_ii, oplus_f_if, _erro},
|
||||
// /*FLOAT*/ {_erro, _1, _void, _erro, oplus_f_fi, oplus_f_ff, _erro},
|
||||
// /*BOOL*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
//};
|
||||
// mv_t x_xx_plus_func(mv_t* pval1, mv_t* pval2) { return (plus_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
// func MvPlus(val1, val2 *Mlrval) Mlrval {
|
||||
// return plusDispositions[val1.mvtype][val2.mvtype]
|
||||
// }
|
||||
//
|
||||
//mv_t x_xx_oplus_func(mv_t* pval1, mv_t* pval2) { return (oplus_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//static mv_t ominus_f_ff(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a - b);
|
||||
//}
|
||||
//static mv_t ominus_f_fi(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = (double)pb->u.intv;
|
||||
// return mv_from_float(a - b);
|
||||
//}
|
||||
//static mv_t ominus_f_if(mv_t* pa, mv_t* pb) {
|
||||
// double a = (double)pa->u.intv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a - b);
|
||||
//}
|
||||
//static mv_t ominus_n_ii(mv_t* pa, mv_t* pb) {
|
||||
// long long a = pa->u.intv;
|
||||
// long long b = pb->u.intv;
|
||||
// long long c = a - b;
|
||||
// return mv_from_int(c);
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* ominus_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _a, _erro, _2, _2, _erro},
|
||||
// /*EMPTY*/ {_erro, _a, _void, _erro, _void, _void, _erro},
|
||||
// /*STRING*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*INT*/ {_erro, _1, _void, _erro, ominus_n_ii, ominus_f_if, _erro},
|
||||
// /*FLOAT*/ {_erro, _1, _void, _erro, ominus_f_fi, ominus_f_ff, _erro},
|
||||
// /*BOOL*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
//};
|
||||
//
|
||||
//mv_t x_xx_ominus_func(mv_t* pval1, mv_t* pval2) { return (ominus_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//static mv_t otimes_f_ff(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a * b);
|
||||
//}
|
||||
//static mv_t otimes_f_fi(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = (double)pb->u.intv;
|
||||
// return mv_from_float(a * b);
|
||||
//}
|
||||
//static mv_t otimes_f_if(mv_t* pa, mv_t* pb) {
|
||||
// double a = (double)pa->u.intv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a * b);
|
||||
//}
|
||||
//static mv_t otimes_n_ii(mv_t* pa, mv_t* pb) {
|
||||
// long long a = pa->u.intv;
|
||||
// long long b = pb->u.intv;
|
||||
// return mv_from_int(a * b);
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* otimes_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _a, _erro, _2, _2, _erro},
|
||||
// /*EMPTY*/ {_erro, _a, _void, _erro, _void, _void, _erro},
|
||||
// /*STRING*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*INT*/ {_erro, _1, _void, _erro, otimes_n_ii, otimes_f_if, _erro},
|
||||
// /*FLOAT*/ {_erro, _1, _void, _erro, otimes_f_fi, otimes_f_ff, _erro},
|
||||
// /*BOOL*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
//};
|
||||
//
|
||||
//mv_t x_xx_otimes_func(mv_t* pval1, mv_t* pval2) { return (otimes_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//static mv_t odivide_f_ff(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a / b);
|
||||
//}
|
||||
//static mv_t odivide_f_fi(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = (double)pb->u.intv;
|
||||
// return mv_from_float(a / b);
|
||||
//}
|
||||
//static mv_t odivide_f_if(mv_t* pa, mv_t* pb) {
|
||||
// double a = (double)pa->u.intv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(a / b);
|
||||
//}
|
||||
//static mv_t odivide_i_ii(mv_t* pa, mv_t* pb) {
|
||||
// long long a = pa->u.intv;
|
||||
// long long b = pb->u.intv;
|
||||
// return mv_from_int(a / b);
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* odivide_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _a, _erro, _i0, _f0, _erro},
|
||||
// /*EMPTY*/ {_erro, _a, _void, _erro, _void, _void, _erro},
|
||||
// /*STRING*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*INT*/ {_erro, _1, _void, _erro, odivide_i_ii, odivide_f_if, _erro},
|
||||
// /*FLOAT*/ {_erro, _1, _void, _erro, odivide_f_fi, odivide_f_ff, _erro},
|
||||
// /*BOOL*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
//};
|
||||
//
|
||||
//mv_t x_xx_odivide_func(mv_t* pval1, mv_t* pval2) { return (odivide_dispositions[pval1->type][pval2->type])(pval1,pval2); }
|
||||
//
|
||||
//// ----------------------------------------------------------------
|
||||
//static mv_t oidiv_f_ff(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(floor(a / b));
|
||||
//}
|
||||
//static mv_t oidiv_f_fi(mv_t* pa, mv_t* pb) {
|
||||
// double a = pa->u.fltv;
|
||||
// double b = (double)pb->u.intv;
|
||||
// return mv_from_float(floor(a / b));
|
||||
//}
|
||||
//static mv_t oidiv_f_if(mv_t* pa, mv_t* pb) {
|
||||
// double a = (double)pa->u.intv;
|
||||
// double b = pb->u.fltv;
|
||||
// return mv_from_float(floor(a / b));
|
||||
//}
|
||||
//static mv_t oidiv_i_ii(mv_t* pa, mv_t* pb) {
|
||||
// long long a = pa->u.intv;
|
||||
// long long b = pb->u.intv;
|
||||
//
|
||||
// // Pythonic division, not C division.
|
||||
// long long q = a / b;
|
||||
// long long r = a % b;
|
||||
// if (a < 0) {
|
||||
// if (b > 0) {
|
||||
// if (r != 0)
|
||||
// q--;
|
||||
// }
|
||||
// } else {
|
||||
// if (b < 0) {
|
||||
// if (r != 0)
|
||||
// q--;
|
||||
// }
|
||||
// }
|
||||
// return mv_from_int(q);
|
||||
//}
|
||||
//
|
||||
//static mv_binary_func_t* oidiv_dispositions[MT_DIM][MT_DIM] = {
|
||||
// // ERROR ABSENT EMPTY STRING INT FLOAT BOOL
|
||||
// /*ERROR*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*ABSENT*/ {_erro, _a, _a, _erro, _i0, _f0, _erro},
|
||||
// /*EMPTY*/ {_erro, _a, _void, _erro, _void, _void, _erro},
|
||||
// /*STRING*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
// /*INT*/ {_erro, _1, _void, _erro, oidiv_i_ii, oidiv_f_if, _erro},
|
||||
// /*FLOAT*/ {_erro, _1, _void, _erro, oidiv_f_fi, oidiv_f_ff, _erro},
|
||||
// /*BOOL*/ {_erro, _erro, _erro, _erro, _erro, _erro, _erro},
|
||||
//};
|
||||
//
|
||||
//mv_t x_xx_int_odivide_func(mv_t* pval1, mv_t* pval2) {
|
||||
// return (oidiv_dispositions[pval1->type][pval2->type])(pval1,pval2);
|
||||
//}
|
||||
|
|
|
|||
|
|
@ -77,11 +77,11 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S14
|
||||
Accept: 58,
|
||||
Accept: 59,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S15
|
||||
Accept: 58,
|
||||
Accept: 59,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S16
|
||||
|
|
@ -157,7 +157,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S34
|
||||
Accept: 60,
|
||||
Accept: 58,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S35
|
||||
|
|
@ -237,7 +237,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S54
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S55
|
||||
|
|
@ -361,7 +361,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S85
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S86
|
||||
|
|
@ -373,11 +373,11 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S88
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S89
|
||||
Accept: 58,
|
||||
Accept: 59,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S90
|
||||
|
|
@ -441,7 +441,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S105
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S106
|
||||
|
|
@ -453,11 +453,11 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S108
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S109
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S110
|
||||
|
|
@ -473,7 +473,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S113
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S114
|
||||
|
|
@ -481,11 +481,11 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S115
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S116
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S117
|
||||
|
|
@ -497,7 +497,7 @@ var ActTab = ActionTable{
|
|||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S119
|
||||
Accept: 59,
|
||||
Accept: 60,
|
||||
Ignore: "",
|
||||
},
|
||||
ActionRow{ // S120
|
||||
|
|
|
|||
|
|
@ -2637,10 +2637,10 @@ IndirectFieldName
|
|||
// to the lrecs, with mlrvals there! :)
|
||||
|
||||
AtomOrFunction
|
||||
: md_token_int_literal << dsl.NewASTNode($0, dsl.NodeTypeNumberLiteral) >>
|
||||
| md_token_float_literal << dsl.NewASTNode($0, dsl.NodeTypeNumberLiteral) >>
|
||||
| md_token_string_literal << dsl.NewASTNode($0, dsl.NodeTypeStringLiteral) >>
|
||||
| md_token_boolean_literal << dsl.NewASTNode($0, dsl.NodeTypeBooleanLiteral) >>
|
||||
: md_token_string_literal << dsl.NewASTNode($0, dsl.NodeTypeStringLiteral) >>
|
||||
| md_token_int_literal << dsl.NewASTNode($0, dsl.NodeTypeIntLiteral) >>
|
||||
| md_token_float_literal << dsl.NewASTNode($0, dsl.NodeTypeFloatLiteral) >>
|
||||
| md_token_boolean_literal << dsl.NewASTNode($0, dsl.NodeTypeBoolLiteral) >>
|
||||
;
|
||||
|
||||
//AtomOrFunction(A) ::= md_regexi(B). {
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load diff
|
|
@ -830,44 +830,44 @@ var productionsTable = ProdTab{
|
|||
return dsl.NewASTNodeUnary(X[0], X[1], dsl.NodeTypeIndirectFieldName)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_int_literal << dsl.NewASTNode(X[0], dsl.NodeTypeNumberLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 81,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeNumberLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_float_literal << dsl.NewASTNode(X[0], dsl.NodeTypeNumberLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 82,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeNumberLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_string_literal << dsl.NewASTNode(X[0], dsl.NodeTypeStringLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 83,
|
||||
Index: 81,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeStringLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_boolean_literal << dsl.NewASTNode(X[0], dsl.NodeTypeBooleanLiteral) >>`,
|
||||
String: `AtomOrFunction : md_token_int_literal << dsl.NewASTNode(X[0], dsl.NodeTypeIntLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 82,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeIntLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_float_literal << dsl.NewASTNode(X[0], dsl.NodeTypeFloatLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 83,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeFloatLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
String: `AtomOrFunction : md_token_boolean_literal << dsl.NewASTNode(X[0], dsl.NodeTypeBoolLiteral) >>`,
|
||||
Id: "AtomOrFunction",
|
||||
NTType: 21,
|
||||
Index: 84,
|
||||
NumSymbols: 1,
|
||||
ReduceFunc: func(X []Attrib) (Attrib, error) {
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeBooleanLiteral)
|
||||
return dsl.NewASTNode(X[0], dsl.NodeTypeBoolLiteral)
|
||||
},
|
||||
},
|
||||
ProdTabEntry{
|
||||
|
|
|
|||
|
|
@ -177,9 +177,9 @@ var TokMap = TokenMap{
|
|||
"md_token_field_name",
|
||||
"$[",
|
||||
"]",
|
||||
"md_token_string_literal",
|
||||
"md_token_int_literal",
|
||||
"md_token_float_literal",
|
||||
"md_token_string_literal",
|
||||
"md_token_boolean_literal",
|
||||
"md_token_IPS",
|
||||
"md_token_IFS",
|
||||
|
|
@ -253,9 +253,9 @@ var TokMap = TokenMap{
|
|||
"md_token_field_name": 55,
|
||||
"$[": 56,
|
||||
"]": 57,
|
||||
"md_token_int_literal": 58,
|
||||
"md_token_float_literal": 59,
|
||||
"md_token_string_literal": 60,
|
||||
"md_token_string_literal": 58,
|
||||
"md_token_int_literal": 59,
|
||||
"md_token_float_literal": 60,
|
||||
"md_token_boolean_literal": 61,
|
||||
"md_token_IPS": 62,
|
||||
"md_token_IFS": 63,
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ func NewContext() *Context {
|
|||
func (this *Context) UpdateForStartOfFile(filename string) {
|
||||
this.FILENAME = filename
|
||||
this.FILENUM++
|
||||
this.FNR = 0
|
||||
}
|
||||
|
||||
func (this *Context) UpdateForInputRecord(inrec *containers.Lrec) {
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue