got macro statements working

This commit is contained in:
Brian Picciano 2016-07-28 13:57:17 -06:00
parent fd125b3dcd
commit da0d0dfc18
3 changed files with 65 additions and 23 deletions

View File

@ -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

34
expr/macros.go Normal file
View File

@ -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
},
}

20
main.go
View File

@ -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