refactor the Equal method out of the Actual interface
This commit is contained in:
parent
9c9c8afb7d
commit
d48bcf34b8
135
expr/expr.go
135
expr/expr.go
@ -14,27 +14,22 @@ import (
|
|||||||
// TODO empty blocks
|
// TODO empty blocks
|
||||||
// TODO empty parenthesis
|
// TODO empty parenthesis
|
||||||
|
|
||||||
// TODO having Equal as part of the Actual interface is going to be annoying.
|
|
||||||
// The built in macros which return their own expressions don't really care
|
|
||||||
// about it, and it's really only needed for tests I think.
|
|
||||||
//
|
|
||||||
// Alternatively, don't have token be embedded in the expression. I'm not sure
|
|
||||||
// if that's actually possible.
|
|
||||||
|
|
||||||
// TODO need to figure out how to test LLVMVal stuff
|
// TODO need to figure out how to test LLVMVal stuff
|
||||||
|
|
||||||
// Actual represents the actual expression in question, and has certain
|
// Actual represents the actual expression in question, and has certain
|
||||||
// properties. It is wrapped by Expr which also holds onto contextual
|
// properties. It is wrapped by Expr which also holds onto contextual
|
||||||
// information, like the token to which Actual was originally parsed from
|
// information, like the token to which Actual was originally parsed from
|
||||||
type Actual interface {
|
type Actual interface {
|
||||||
// Equal should return true if the type and value of the other expression
|
|
||||||
// are equal.
|
|
||||||
Equal(Actual) bool
|
|
||||||
|
|
||||||
// Initializes an llvm.Value and returns it.
|
// Initializes an llvm.Value and returns it.
|
||||||
LLVMVal(llvm.Builder) llvm.Value
|
LLVMVal(llvm.Builder) llvm.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// equaler is used to compare two expressions. The comparison should not take
|
||||||
|
// into account Token values, only the actual value being represented
|
||||||
|
type equaler interface {
|
||||||
|
equal(equaler) bool
|
||||||
|
}
|
||||||
|
|
||||||
// Expr contains the actual expression as well as some contextual information
|
// Expr contains the actual expression as well as some contextual information
|
||||||
// wrapping it. Most interactions will be with this and not with the Actual
|
// wrapping it. Most interactions will be with this and not with the Actual
|
||||||
// directly.
|
// directly.
|
||||||
@ -47,6 +42,9 @@ type Expr struct {
|
|||||||
val *llvm.Value
|
val *llvm.Value
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// LLVMVal passes its arguments to the underlying Actual instance. It caches the
|
||||||
|
// result, so if this is called multiple times the underlying one is only called
|
||||||
|
// the first time.
|
||||||
func (e Expr) LLVMVal(builder llvm.Builder) llvm.Value {
|
func (e Expr) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
if e.val == nil {
|
if e.val == nil {
|
||||||
v := e.Actual.LLVMVal(builder)
|
v := e.Actual.LLVMVal(builder)
|
||||||
@ -55,13 +53,27 @@ func (e Expr) LLVMVal(builder llvm.Builder) llvm.Value {
|
|||||||
return *e.val
|
return *e.val
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// will panic if either Expr's Actual doesn't implement equaler
|
||||||
|
func (e Expr) equal(e2 Expr) bool {
|
||||||
|
eq1, ok1 := e.Actual.(equaler)
|
||||||
|
eq2, ok2 := e2.Actual.(equaler)
|
||||||
|
if !ok1 || !ok2 {
|
||||||
|
panic(fmt.Sprintf("can't compare %T and %T", e.Actual, e2.Actual))
|
||||||
|
}
|
||||||
|
return eq1.equal(eq2)
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Bool represents a true or false value
|
// Bool represents a true or false value
|
||||||
type Bool bool
|
type Bool bool
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (b Bool) Equal(e Actual) bool {
|
func (b Bool) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Bool) equal(e equaler) bool {
|
||||||
bb, ok := e.(Bool)
|
bb, ok := e.(Bool)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@ -69,17 +81,19 @@ func (b Bool) Equal(e Actual) bool {
|
|||||||
return bb == b
|
return bb == b
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Bool) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
return llvm.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Int represents an integer value
|
// Int represents an integer value
|
||||||
type Int int64
|
type Int int64
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (i Int) Equal(e Actual) bool {
|
func (i Int) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
v := builder.CreateAlloca(llvm.Int64Type(), "")
|
||||||
|
builder.CreateStore(llvm.ConstInt(llvm.Int64Type(), uint64(i), false), v)
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i Int) equal(e equaler) bool {
|
||||||
ii, ok := e.(Int)
|
ii, ok := e.(Int)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@ -87,20 +101,17 @@ func (i Int) Equal(e Actual) bool {
|
|||||||
return ii == i
|
return ii == i
|
||||||
}
|
}
|
||||||
|
|
||||||
// LLVMVal creates a new llvm value using the builder and returns it
|
|
||||||
func (i Int) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
v := builder.CreateAlloca(llvm.Int64Type(), "")
|
|
||||||
builder.CreateStore(llvm.ConstInt(llvm.Int64Type(), uint64(i), false), v)
|
|
||||||
return v
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// String represents a string value
|
// String represents a string value
|
||||||
type String string
|
type String string
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (s String) Equal(e Actual) bool {
|
func (s String) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s String) equal(e equaler) bool {
|
||||||
ss, ok := e.(String)
|
ss, ok := e.(String)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@ -108,18 +119,18 @@ func (s String) Equal(e Actual) bool {
|
|||||||
return ss == s
|
return ss == s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s String) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
return llvm.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Identifier represents a binding to some other value which has been given a
|
// Identifier represents a binding to some other value which has been given a
|
||||||
// name
|
// name
|
||||||
type Identifier string
|
type Identifier string
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (id Identifier) Equal(e Actual) bool {
|
func (id Identifier) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (id Identifier) equal(e equaler) bool {
|
||||||
idid, ok := e.(Identifier)
|
idid, ok := e.(Identifier)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@ -127,10 +138,6 @@ func (id Identifier) Equal(e Actual) bool {
|
|||||||
return idid == id
|
return idid == id
|
||||||
}
|
}
|
||||||
|
|
||||||
func (id Identifier) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
return llvm.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Macro is an identifier for a macro which can be used to transform
|
// Macro is an identifier for a macro which can be used to transform
|
||||||
@ -143,8 +150,12 @@ func (m Macro) String() string {
|
|||||||
return "%" + string(m)
|
return "%" + string(m)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (m Macro) Equal(e Actual) bool {
|
func (m Macro) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
panic("Macros have no inherent LLVMVal")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m Macro) equal(e equaler) bool {
|
||||||
mm, ok := e.(Macro)
|
mm, ok := e.(Macro)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
@ -152,10 +163,6 @@ func (m Macro) Equal(e Actual) bool {
|
|||||||
return m == mm
|
return m == mm
|
||||||
}
|
}
|
||||||
|
|
||||||
func (m Macro) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
panic("Macros have no inherent LLVMVal")
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Tuple represents a fixed set of expressions which are interacted with as if
|
// Tuple represents a fixed set of expressions which are interacted with as if
|
||||||
@ -170,24 +177,24 @@ func (tup Tuple) String() string {
|
|||||||
return "(" + strings.Join(strs, ", ") + ")"
|
return "(" + strings.Join(strs, ", ") + ")"
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (tup Tuple) Equal(e Actual) bool {
|
func (tup Tuple) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (tup Tuple) equal(e equaler) bool {
|
||||||
tuptup, ok := e.(Tuple)
|
tuptup, ok := e.(Tuple)
|
||||||
if !ok || len(tuptup) != len(tup) {
|
if !ok || len(tuptup) != len(tup) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i := range tup {
|
for i := range tup {
|
||||||
if !tup[i].Actual.Equal(tuptup[i].Actual) {
|
if !tup[i].equal(tuptup[i]) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (tup Tuple) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
return llvm.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Statement represents an actual action which will be taken. The input value is
|
// Statement represents an actual action which will be taken. The input value is
|
||||||
@ -202,12 +209,7 @@ func (s Statement) String() string {
|
|||||||
return fmt.Sprintf("(%v > %s)", s.In.Actual, s.To.Actual)
|
return fmt.Sprintf("(%v > %s)", s.In.Actual, s.To.Actual)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (s Statement) Equal(e Actual) bool {
|
|
||||||
ss, ok := e.(Statement)
|
|
||||||
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 {
|
func (s Statement) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
m, ok := s.To.Actual.(Macro)
|
m, ok := s.To.Actual.(Macro)
|
||||||
if !ok {
|
if !ok {
|
||||||
@ -227,6 +229,11 @@ func (s Statement) LLVMVal(builder llvm.Builder) llvm.Value {
|
|||||||
return newe.LLVMVal(builder)
|
return newe.LLVMVal(builder)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s Statement) equal(e equaler) bool {
|
||||||
|
ss, ok := e.(Statement)
|
||||||
|
return ok && s.In.equal(ss.In) && s.To.equal(ss.To)
|
||||||
|
}
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
// Block represents a set of statements which share a scope, i.e. If one
|
// Block represents a set of statements which share a scope, i.e. If one
|
||||||
@ -242,24 +249,24 @@ func (b Block) String() string {
|
|||||||
return fmt.Sprintf("{ %s }", strings.Join(strs, " "))
|
return fmt.Sprintf("{ %s }", strings.Join(strs, " "))
|
||||||
}
|
}
|
||||||
|
|
||||||
// Equal implements the Actual method
|
// LLVMVal implements the Actual interface method
|
||||||
func (b Block) Equal(e Actual) bool {
|
func (b Block) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
|
return llvm.Value{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (b Block) equal(e equaler) bool {
|
||||||
bb, ok := e.(Block)
|
bb, ok := e.(Block)
|
||||||
if !ok {
|
if !ok {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
for i := range b {
|
for i := range b {
|
||||||
if !b[i].Equal(bb[i]) {
|
if !b[i].equal(bb[i]) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
func (b Block) LLVMVal(builder llvm.Builder) llvm.Value {
|
|
||||||
return llvm.Value{}
|
|
||||||
}
|
|
||||||
|
|
||||||
////////////////////////////////////////////////////////////////////////////////
|
////////////////////////////////////////////////////////////////////////////////
|
||||||
|
|
||||||
type exprErr struct {
|
type exprErr struct {
|
||||||
|
@ -37,7 +37,7 @@ func TestSliceEnclosedToks(t *T) {
|
|||||||
func assertParse(t *T, in []lexer.Token, expExpr Expr, expOut []lexer.Token) {
|
func assertParse(t *T, in []lexer.Token, expExpr Expr, expOut []lexer.Token) {
|
||||||
expr, out, err := parse(in)
|
expr, out, err := parse(in)
|
||||||
require.Nil(t, err)
|
require.Nil(t, err)
|
||||||
assert.True(t, expExpr.Actual.Equal(expr.Actual), "expr:%v expExpr:%v", expr, expExpr)
|
assert.True(t, expExpr.equal(expr), "expr:%+v expExpr:%+v", expr, expExpr)
|
||||||
assert.Equal(t, expOut, out, "out:%v expOut:%v", out, expOut)
|
assert.Equal(t, expOut, out, "out:%v expOut:%v", out, expOut)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8,8 +8,6 @@ import (
|
|||||||
|
|
||||||
type addActual []Expr
|
type addActual []Expr
|
||||||
|
|
||||||
func (aa addActual) Equal(Actual) bool { return false }
|
|
||||||
|
|
||||||
func (aa addActual) LLVMVal(builder llvm.Builder) llvm.Value {
|
func (aa addActual) LLVMVal(builder llvm.Builder) llvm.Value {
|
||||||
a := builder.CreateLoad(aa[0].LLVMVal(builder), "")
|
a := builder.CreateLoad(aa[0].LLVMVal(builder), "")
|
||||||
for i := range aa[1:] {
|
for i := range aa[1:] {
|
||||||
|
Loading…
Reference in New Issue
Block a user