Skip to content

Commit

Permalink
Merge pull request #184 from corywalker/corywalker
Browse files Browse the repository at this point in the history
Refactor code into packages
  • Loading branch information
corywalker committed Nov 1, 2018
2 parents 4a91670 + e06fc74 commit 8a509db
Show file tree
Hide file tree
Showing 95 changed files with 6,469 additions and 5,821 deletions.
2 changes: 0 additions & 2 deletions .travis.yml
Expand Up @@ -4,8 +4,6 @@ os:
language: go

go:
- "1.6"
- "1.7"
- "1.8"
- "1.9"
- "1.10"
Expand Down
36 changes: 17 additions & 19 deletions expreduce.go
@@ -1,17 +1,21 @@
package main

import (
"bufio"
"bytes"
"flag"
"fmt"
"github.com/corywalker/expreduce/expreduce"
"gopkg.in/readline.v1"
"log"
"os"
"bytes"
"bufio"
"runtime/pprof"
"net/http"
_ "net/http/pprof"
"os"
"runtime/pprof"

"github.com/corywalker/expreduce/expreduce"
"github.com/corywalker/expreduce/expreduce/atoms"
"github.com/corywalker/expreduce/expreduce/parser"
"github.com/corywalker/expreduce/pkg/expreduceapi"
"gopkg.in/readline.v1"
)

var debug = flag.Bool("debug", false, "Debug mode. No initial definitions.")
Expand All @@ -21,13 +25,10 @@ var netprofile = flag.Bool("netprofile", false, "Enable live profiling at http:/
var scriptfile = flag.String("script", "", "script `file` to read from")
var initfile = flag.String("initfile", "", "A script to run on initialization.")




func main() {
flag.Parse()

if *cpuprofile != "" {
if *cpuprofile != "" {
f, err := os.Create(*cpuprofile)
if err != nil {
log.Fatal(err)
Expand Down Expand Up @@ -74,14 +75,12 @@ func main() {
}
}


func scriptSession(es *expreduce.EvalState, srcText string, srcPath string) {
exp := expreduce.EvalInterpMany(srcText, srcPath, es)
res := exp.Eval(es)
res := es.Eval(exp)
res = es.ProcessTopLevelResult(res, res)
}


func interactiveSession(es *expreduce.EvalState) {
rl, err := readline.NewEx(&readline.Config{
HistoryFile: "/tmp/readline.tmp",
Expand Down Expand Up @@ -113,19 +112,18 @@ func interactiveSession(es *expreduce.EvalState) {
}
fmt.Printf("\n")

exp := expreduce.Interp(line, es)
res := exp.Eval(es)
exp := parser.Interp(line, es)
res := es.Eval(exp)
res = es.ProcessTopLevelResult(exp, res)

printFormattedOutput(es, res, true, promptNum)
promptNum += 1
}
}


func printFormattedOutput(es *expreduce.EvalState, res expreduce.Ex, isInteractive bool, promptNum int) {
func printFormattedOutput(es *expreduce.EvalState, res expreduceapi.Ex, isInteractive bool, promptNum int) {
isNull := false
asSym, isSym := res.(*expreduce.Symbol)
asSym, isSym := res.(*atoms.Symbol)
if isSym {
if asSym.Name == "System`Null" {
isNull = true
Expand All @@ -140,7 +138,7 @@ func printFormattedOutput(es *expreduce.EvalState, res expreduce.Ex, isInteracti
}
wasSpecialForm := false
for _, specialForm := range specialForms {
asSpecialForm, isSpecialForm := expreduce.HeadAssertion(
asSpecialForm, isSpecialForm := atoms.HeadAssertion(
res, specialForm)
if !isSpecialForm {
continue
Expand Down
141 changes: 141 additions & 0 deletions expreduce/atoms/calculator.go
@@ -0,0 +1,141 @@
package atoms

import "github.com/corywalker/expreduce/pkg/expreduceapi"

type foldFn int

const (
// FoldFnAdd designates that values should be added.
FoldFnAdd foldFn = iota
// FoldFnMul designates that values should be multiplied.
FoldFnMul
)

func typedRealPart(fn foldFn, i *Integer, r *Rational, f *Flt, c *Complex) expreduceapi.Ex {
if c != nil {
toReturn := c
if f != nil {
if fn == FoldFnAdd {
toReturn.addF(f)
} else if fn == FoldFnMul {
toReturn.mulF(f)
}
}
if r != nil {
if fn == FoldFnAdd {
toReturn.addR(r)
} else if fn == FoldFnMul {
toReturn.mulR(r)
}
}
if i != nil {
if fn == FoldFnAdd {
toReturn.addI(i)
} else if fn == FoldFnMul {
toReturn.mulI(i)
}
}
return toReturn
}
if f != nil {
toReturn := f
if r != nil {
if fn == FoldFnAdd {
toReturn.addR(r)
} else if fn == FoldFnMul {
toReturn.mulR(r)
}
}
if i != nil {
if fn == FoldFnAdd {
toReturn.addI(i)
} else if fn == FoldFnMul {
toReturn.mulI(i)
}
}
return toReturn
}
if r != nil {
toReturn := r
if i != nil {
if fn == FoldFnAdd {
toReturn.addI(i)
} else if fn == FoldFnMul {
toReturn.mulI(i)
}
}
return toReturn
}
if i != nil {
return i
}
return nil
}

func ComputeNumericPart(fn foldFn, e expreduceapi.ExpressionInterface) (expreduceapi.Ex, int) {
var foldedInt *Integer
var foldedRat *Rational
var foldedFlt *Flt
var foldedComp *Complex
for i := 1; i < len(e.GetParts()); i++ {
// TODO: implement short circuiting if we encounter a zero while
// multiplying.
asInt, isInt := e.GetParts()[i].(*Integer)
if isInt {
if foldedInt == nil {
// Try deepcopy if problems. I think this does not cause
// problems now because we will only modify the value if we end
// up creating an entirely new expression.
foldedInt = asInt.DeepCopy().(*Integer)
continue
}
if fn == FoldFnAdd {
foldedInt.addI(asInt)
} else if fn == FoldFnMul {
foldedInt.mulI(asInt)
}
continue
}
asRat, isRat := e.GetParts()[i].(*Rational)
if isRat {
if foldedRat == nil {
foldedRat = asRat.DeepCopy().(*Rational)
continue
}
if fn == FoldFnAdd {
foldedRat.addR(asRat)
} else if fn == FoldFnMul {
foldedRat.mulR(asRat)
}
continue
}
asFlt, isFlt := e.GetParts()[i].(*Flt)
if isFlt {
if foldedFlt == nil {
foldedFlt = asFlt.DeepCopy().(*Flt)
continue
}
if fn == FoldFnAdd {
foldedFlt.addF(asFlt)
} else if fn == FoldFnMul {
foldedFlt.mulF(asFlt)
}
continue
}
asComp, isComp := e.GetParts()[i].(*Complex)
if isComp {
if foldedComp == nil {
foldedComp = asComp.DeepCopy().(*Complex)
continue
}
if fn == FoldFnAdd {
foldedComp.addC(asComp)
} else if fn == FoldFnMul {
foldedComp.mulC(asComp)
}
continue
}
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt, foldedComp), i
}
return typedRealPart(fn, foldedInt, foldedRat, foldedFlt, foldedComp), -1
}
136 changes: 136 additions & 0 deletions expreduce/atoms/ex_complex.go
@@ -0,0 +1,136 @@
package atoms

import (
"encoding/binary"
"fmt"
"hash/fnv"

"github.com/corywalker/expreduce/pkg/expreduceapi"
)

type Complex struct {
Re expreduceapi.Ex
Im expreduceapi.Ex
needsEval bool
}

func (cmplx *Complex) StringForm(p expreduceapi.ToStringParams) string {
if p.Form == "FullForm" {
return fmt.Sprintf("Complex[%v, %v]", cmplx.Re, cmplx.Im)
}
reInt, reIsInt := cmplx.Re.(*Integer)
imInt, imIsInt := cmplx.Im.(*Integer)
if reIsInt && reInt.Val.Sign() == 0 {
if imIsInt && imInt.Val.Int64() == 1 {
return "I"
}
p.PreviousHead = "System`Times"
return fmt.Sprintf("(%v*I)", cmplx.Im.StringForm(p))
}
p.PreviousHead = "System`Plus"
return fmt.Sprintf("(%v + %v*I)", cmplx.Re.StringForm(p), cmplx.Im.StringForm(p))
}

func (cmplx *Complex) IsEqual(other expreduceapi.Ex) string {
otherConv, otherIsComplex := other.(*Complex)
if !otherIsComplex {
return "EQUAL_FALSE"
}
if (cmplx.Re.IsEqual(otherConv.Re) != "EQUAL_TRUE") || (cmplx.Im.IsEqual(otherConv.Im) != "EQUAL_TRUE") {
return "EQUAL_FALSE"
}
return "EQUAL_TRUE"
}

func (cmplx *Complex) DeepCopy() expreduceapi.Ex {
return &Complex{cmplx.Re.DeepCopy(), cmplx.Im.DeepCopy(), cmplx.needsEval}
}

func (cmplx *Complex) Copy() expreduceapi.Ex {
return cmplx.DeepCopy()
}

func (cmplx *Complex) NeedsEval() bool {
return cmplx.needsEval
}

func NewComplex(r expreduceapi.Ex, i expreduceapi.Ex) *Complex {
return &Complex{r, i, true}
}

func (cmplx *Complex) Hash() uint64 {
h := fnv.New64a()
h.Write([]byte{82, 226, 223, 39, 113, 26, 149, 249})
b := make([]byte, 8)
binary.LittleEndian.PutUint64(b, cmplx.Re.Hash())
h.Write(b)
binary.LittleEndian.PutUint64(b, cmplx.Im.Hash())
h.Write(b)
return h.Sum64()
}

func (cmplx *Complex) addReal(e expreduceapi.Ex) {
a, _ := ComputeNumericPart(FoldFnAdd, E(S("Dummy"), cmplx.Re, e))
cmplx.Re = a
cmplx.needsEval = true
}

func (cmplx *Complex) addI(i *Integer) {
cmplx.addReal(i)
}

func (cmplx *Complex) addF(f *Flt) {
cmplx.addReal(f)
}

func (cmplx *Complex) addR(r *Rational) {
cmplx.addReal(r)
}

func (cmplx *Complex) addC(c *Complex) {
a, _ := ComputeNumericPart(FoldFnAdd, E(S("Dummy"), cmplx.Re, c.Re))
b, _ := ComputeNumericPart(FoldFnAdd, E(S("Dummy"), cmplx.Im, c.Im))
cmplx.Re = a
cmplx.Im = b
cmplx.needsEval = true
}

func (cmplx *Complex) mulReal(e expreduceapi.Ex) {
a, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), cmplx.Re, e))
b, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), cmplx.Im, e))
cmplx.Re = a
cmplx.Im = b
cmplx.needsEval = true
}

func (cmplx *Complex) mulI(i *Integer) {
cmplx.mulReal(i)
}

func (cmplx *Complex) mulF(f *Flt) {
cmplx.mulReal(f)
}

func (cmplx *Complex) mulR(r *Rational) {
cmplx.mulReal(r)
}

func (cmplx *Complex) mulC(c *Complex) {
// HoldPattern[Complex[x_, y_]*Complex[u_, v_]*rest___] -> Complex[x*u + (y*v)*(-1), x*v + y*u]*rest)
// cmplx is ugly. Need to refactor.
// Perhaps create "Calculator" utility??
// TODO(corywalker) Remove the definition that cmplx implements in code.
a, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), cmplx.Re, c.Re))
b, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), NewInt(-1), cmplx.Im, c.Im))
cc, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), cmplx.Re, c.Im))
d, _ := ComputeNumericPart(FoldFnMul, E(S("Dummy"), cmplx.Im, c.Re))
e, _ := ComputeNumericPart(FoldFnAdd, E(S("Dummy"), a, b))
f, _ := ComputeNumericPart(FoldFnAdd, E(S("Dummy"), cc, d))
cmplx.Re = e
cmplx.Im = f
cmplx.needsEval = true
}

func (cmplx *Complex) SetNeedsEval(newVal bool) {
cmplx.needsEval = newVal
}

0 comments on commit 8a509db

Please sign in to comment.