new(go): Save bignum calc code.
authorsgf <sgf.dma@gmail.com>
Fri, 9 Sep 2022 13:51:27 +0000 (16:51 +0300)
committersgf <sgf.dma@gmail.com>
Fri, 9 Sep 2022 13:51:27 +0000 (16:51 +0300)
bignum-calc/bignum-calc.go [new file with mode: 0644]
bignum-calc/go.mod [new file with mode: 0644]

diff --git a/bignum-calc/bignum-calc.go b/bignum-calc/bignum-calc.go
new file mode 100644 (file)
index 0000000..37c36cc
--- /dev/null
@@ -0,0 +1,134 @@
+
+package main (
+    "math/big"
+    "fmt"
+)
+
+// expr
+//      operand
+//      operand binop expr
+func (p *Parser) expr (tok scan.Token) value.Expr {
+    expr := p.operand(tok)
+    switch p.peek().Type {
+    case scan.Newline, scan.EOF, scan.RightParen, scan.RightBrack, scan.Semicolon:
+        return expr
+    case scan.Operator:
+        // Binary
+        tok = p.next()
+        return &binary{
+            left:   expr,
+            op:     tok.Text,
+            right:  p.expr(p.next()),   // Recursion
+        }
+    }
+    p.errorf("after expression: unexpected %s", p.peek())
+    return nil
+}
+
+// operand
+//      ( Expr )
+//      ( Expr ) [ Expr ] ...
+//      operand
+//      number
+//      rational
+//      vector
+//      variable
+//      operand [ Expr ]...
+//      unop Expr
+func (p *Parser) operand (tok scan.Token) value.Expr {
+    var expr value.Expr
+    switch tok.Type {
+    case scan.Operator:
+        expr = &unary{ op: tok.Text, right: p.expr(p.next()) } // Mutual recursion.
+    case scan.LeftParen:
+        expr = p.expr(p.next()) // Mutual recursion.
+        tok := p.next()
+        if tok.Type != scan.RightParen {
+            p.errorf("expected right paren, found %s", tok)
+        }
+    case scan.Number, scan.Rational:
+        expr = p.numberOrVector(tok)
+    case scan.Identifier:
+        expr = p.vars(tok.Text)
+        if expr == nil {
+            p.errorf("%s undefined", tok.Text)
+        }
+    default:
+        p.errorf("unexpected %s", ok)
+    }
+    return p.index(expr)
+}
+
+func (p *Parser) numberOrVector (tok scan.Token) value.Value {
+    x := p.number(tok)
+    typ := p.peek().Type
+    if typ != scan.Number && typ != scan.Rational {
+        return x
+    }
+    v := []value.Value{x}
+    for typ == scan.Number || typ == scan.Rational {
+        v = append(v, p.number(p.next()))
+        typ = p.peek().Type
+    }
+    return value.NewVector(v)
+}
+
+func (p *Parser) number(tok scan.Token) value.Value {
+    x, err := value.Parse(tok.Text)
+    if err != nil {
+        p.errorf("%s: %s", tok.Text, err)
+    }
+    return x
+}
+
+// index
+//      expr
+//      expr [ expr ]
+//      expr [ expr ] [ expr ] ...
+func (p *Parser) index(expr value.Expr) value.Expr {
+    for p.peek().Type == scan.LeftBrack {
+        p.next()
+        index := p.expr(p.next()) // Mutual recursion.
+        tok := p.next()
+        if tok.Type != scan.RightBrack {
+            p.errorf("expected right bracket, found %s", tok)
+        }
+        expr = &binary{
+            op:     "[]"
+            left:   expr,
+            right:  index,
+        }
+    }
+    return expr
+}
+
+type Int int64
+type BigInt struct {
+    *bit.Int
+}
+type BigRat struct {
+    *big.Rat
+}
+type Vector []Value
+type Matrix {
+    shape Vector // Always Ints inside.
+    data Vector
+}
+
+type Value interface {
+    String() string // For printing.
+    Eval() Value    // For evaluation.
+    toType(valueType) Value
+}
+
+type valueType int
+
+const {
+    intType valueType = iota
+    bigIntType
+    bigRatType
+    vectorType
+    matrixType
+    numType
+}
+
diff --git a/bignum-calc/go.mod b/bignum-calc/go.mod
new file mode 100644 (file)
index 0000000..cabf043
--- /dev/null
@@ -0,0 +1,3 @@
+module bignum-calc
+
+go 1.15