From da0d0dfc18b69427ffc5210adf3cee351017080d Mon Sep 17 00:00:00 2001 From: Brian Picciano Date: Thu, 28 Jul 2016 13:57:17 -0600 Subject: [PATCH] got macro statements working --- expr/expr.go | 34 ++++++++++++++++++++++++++-------- expr/macros.go | 34 ++++++++++++++++++++++++++++++++++ main.go | 20 +++++--------------- 3 files changed, 65 insertions(+), 23 deletions(-) create mode 100644 expr/macros.go diff --git a/expr/expr.go b/expr/expr.go index d201326..3e5db02 100644 --- a/expr/expr.go +++ b/expr/expr.go @@ -26,7 +26,7 @@ type Actual interface { // are equal. Equal(Actual) bool - // Initializes an llvm.Value and returns it + // Initializes an llvm.Value and returns it. LLVMVal(llvm.Builder) llvm.Value } @@ -148,7 +148,7 @@ func (m Macro) Equal(e Actual) bool { } func (m Macro) LLVMVal(builder llvm.Builder) llvm.Value { - return llvm.Value{} + panic("Macros have no inherent LLVMVal") } //////////////////////////////////////////////////////////////////////////////// @@ -188,6 +188,8 @@ func (tup Tuple) LLVMVal(builder llvm.Builder) llvm.Value { // Pipe represents a set of expressions which operate on values and return new // values. The inputs of one expression in the pipe is the output of the // previous expression +// +// TODO remove this, sorry Pipe type Pipe []Expr func (p Pipe) String() string { @@ -222,22 +224,37 @@ func (p Pipe) LLVMVal(builder llvm.Builder) llvm.Value { // used as the input to the pipe, and the output of the pipe is the output of // the statement type Statement struct { - in Expr - pipe Pipe + In Expr + To Expr } func (s Statement) String() string { - return fmt.Sprintf("(%v > %s)", s.in.Actual, s.pipe.String()) + return fmt.Sprintf("(%v > %s)", s.In.Actual, s.To.Actual) } // Equal implements the Actual method func (s Statement) Equal(e Actual) bool { ss, ok := e.(Statement) - return ok && s.in.Actual.Equal(ss.in.Actual) && s.pipe.Equal(ss.pipe) + return ok && s.In.Actual.Equal(ss.In.Actual) && s.To.Actual.Equal(ss.To.Actual) } func (s Statement) LLVMVal(builder llvm.Builder) llvm.Value { - return llvm.Value{} + m, ok := s.To.Actual.(Macro) + if !ok { + // TODO proper error + panic("statement To is not a macro") + } + fn, ok := macros[m] + if !ok { + // TODO proper error + panic(fmt.Sprintf("unknown macro %q", m)) + } + newe, err := fn(s.In) + if err != nil { + // TODO proper error + panic(err) + } + return newe.LLVMVal(builder) } //////////////////////////////////////////////////////////////////////////////// @@ -513,7 +530,8 @@ func parseConnectingPunct(toks []lexer.Token, root Expr) (Expr, []lexer.Token, e if !ok { pipe = Pipe{expr} } - return Expr{Token: root.Token, Actual: Statement{in: root, pipe: pipe}}, toks, nil + pipeExpr := Expr{Actual: pipe, Token: expr.Token} + return Expr{Token: root.Token, Actual: Statement{In: root, To: pipeExpr}}, toks, nil } return root, toks, nil diff --git a/expr/macros.go b/expr/macros.go new file mode 100644 index 0000000..401f8b3 --- /dev/null +++ b/expr/macros.go @@ -0,0 +1,34 @@ +package expr + +import ( + "errors" + + "llvm.org/llvm/bindings/go/llvm" +) + +type addActual []Expr + +func (aa addActual) Equal(Actual) bool { return false } + +func (aa addActual) LLVMVal(builder llvm.Builder) llvm.Value { + a := builder.CreateLoad(aa[0].LLVMVal(builder), "") + for i := range aa[1:] { + b := builder.CreateLoad(aa[i+1].LLVMVal(builder), "") + a = builder.CreateAdd(a, b, "") + } + return a +} + +var macros = map[Macro]func(Expr) (Expr, error){ + "add": func(e Expr) (Expr, error) { + tup, ok := e.Actual.(Tuple) + if !ok { + // TODO proper error + return Expr{}, errors.New("add only accepts a tuple") + } + return Expr{ + Actual: addActual(tup), + Token: e.Token, + }, nil + }, +} diff --git a/main.go b/main.go index 1d85739..e33217d 100644 --- a/main.go +++ b/main.go @@ -8,19 +8,6 @@ import ( "llvm.org/llvm/bindings/go/llvm" ) -type addActual []expr.Expr - -func (aa addActual) Equal(expr.Actual) bool { return false } - -func (aa addActual) LLVMVal(builder llvm.Builder) llvm.Value { - a := builder.CreateLoad(aa[0].LLVMVal(builder), "") - for i := range aa[1:] { - b := builder.CreateLoad(aa[i+1].LLVMVal(builder), "") - a = builder.CreateAdd(a, b, "") - } - return a -} - func main() { //ee, err := expr.Parse(os.Stdin) //if err != nil { @@ -47,8 +34,11 @@ func main() { a := expr.Expr{Actual: expr.Int(1)} b := expr.Expr{Actual: expr.Int(2)} c := expr.Expr{Actual: expr.Int(3)} - add := addActual{a, b, c} - result := add.LLVMVal(builder) + tup := expr.Expr{Actual: expr.Tuple{a, b, c}} + addMacro := expr.Expr{Actual: expr.Macro("add")} + stmt := expr.Expr{Actual: expr.Statement{In: tup, To: addMacro}} + + result := stmt.LLVMVal(builder) builder.CreateRet(result) // verify it's all good