Move compileAssignmentExpressionWAT into compileAssignmentUpdateExpressionWAT

This commit is contained in:
MrLetsplay 2024-11-23 19:18:38 +01:00
parent 9e39936842
commit d8a80de37c
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
2 changed files with 71 additions and 87 deletions

View File

@ -214,12 +214,9 @@ func castPrimitiveWAT(from PrimitiveType, to PrimitiveType) (Code, error) {
return code, nil
}
func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpression) (Code, error) {
lhs := assignment.Lhs
exprWAT, err := c.compileExpressionWAT(assignment.Value)
if err != nil {
return emptyCode(), err
func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, update bool, valueOrUpdateWAT Code, evaluateToOldValue bool) (Code, error) {
if !isValidLHS(lhs.Type) {
panic(fmt.Sprintf("invalid LHS type passed to compileAssignmentUpdateExpressionWAT(): %s", lhs.Type))
}
switch lhs.Type {
@ -227,10 +224,40 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
ref := lhs.Value.(VariableReferenceExpression)
local := strconv.Itoa(getLocal(c.CurrentBlock, ref.Variable).Index)
exprWAT.add("local.tee $" + local + " (;" + ref.Variable + ";)")
return exprWAT, nil
code := emptyCode()
// Load variable
if update || evaluateToOldValue {
exprWAT, err := c.compileExpressionWAT(lhs)
if err != nil {
return emptyCode(), err
}
code.addAll(exprWAT)
}
var tmpLocal Local
if update && evaluateToOldValue {
tmpLocal = Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, tmpLocal)
// dup old value
code.add("local.tee $" + strconv.Itoa(tmpLocal.Index))
code.add("local.get $" + strconv.Itoa(tmpLocal.Index))
}
code.addAll(valueOrUpdateWAT)
if evaluateToOldValue {
code.add("local.set $" + local + " (;" + ref.Variable + ";)")
} else {
code.add("local.tee $" + local + " (;" + ref.Variable + ";)")
}
return code, nil
case Expression_ArrayAccess:
array := lhs.Value.(ArrayAccessExpression)
elementType := array.Array.ValueType.Value.(ArrayType).ElementType
localArray := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType(), Position: unknownPosition()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localArray)
@ -238,7 +265,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
localIndex := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType(), Position: unknownPosition()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localIndex)
localElement := Local{Name: "", Type: *assignment.Value.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
localElement := Local{Name: "", Type: elementType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localElement)
arrayWAT, err := c.compileExpressionWAT(array.Array)
@ -270,6 +297,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
// Error if index < 0
wat.add(
"block",
"(;bounds check < 0;)",
"local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)",
c.getAddressWATType()+".const 0",
c.getAddressWATType()+".ge_s",
@ -281,6 +309,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
// Error if index >= array length
wat.add(
"block",
"(;bounds check >= array length;)",
"local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)",
"local.get $"+strconv.Itoa(localArray.Index)+" (;array base address;)",
"i32.load", // Load array length
@ -291,7 +320,6 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
)
}
elementType := array.Array.ValueType.Value.(ArrayType).ElementType
wat.add(
"local.get $"+strconv.Itoa(localIndex.Index)+" (;array index;)",
c.getAddressWATType()+".const "+strconv.Itoa(c.getTypeSizeBytes(elementType)),
@ -302,7 +330,7 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
c.getAddressWATType()+".add",
)
wat.addAll(exprWAT)
wat.addAll(valueOrUpdateWAT)
wat.add(
"local.tee $"+strconv.Itoa(localElement.Index),
@ -314,63 +342,6 @@ func (c *Compiler) compileAssignmentExpressionWAT(assignment AssignmentExpressio
case Expression_RawMemoryReference:
raw := lhs.Value.(RawMemoryReferenceExpression)
local := Local{Name: "", Type: *lhs.ValueType, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, local)
if raw.Type.Type != Type_Primitive {
panic("TODO") //TODO
}
addrWAT, err := c.compileExpressionWAT(raw.Address)
if err != nil {
return emptyCode(), err
}
// TODO: should leave a copy of the stored value on the stack
code := addrWAT.clone()
code.addAll(exprWAT)
code.add(
"local.tee $"+strconv.Itoa(local.Index),
c.getWATType(raw.Type)+".store",
"local.get $"+strconv.Itoa(local.Index),
)
return code, nil
}
panic("assignment expr not implemented")
}
func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, updateWAT Code, evaluateToOldValue bool) (Code, error) {
switch lhs.Type {
case Expression_VariableReference:
ref := lhs.Value.(VariableReferenceExpression)
local := strconv.Itoa(getLocal(c.CurrentBlock, ref.Variable).Index)
exprWAT, err := c.compileExpressionWAT(lhs)
if err != nil {
return emptyCode(), err
}
wat := exprWAT.clone()
if evaluateToOldValue {
wat.add("local.get $" + local + " (;" + ref.Variable + ";)")
}
wat.addAll(updateWAT)
if evaluateToOldValue {
wat.add("local.set $" + local + " (;" + ref.Variable + ";)")
} else {
wat.add("local.tee $" + local + " (;" + ref.Variable + ";)")
}
return wat, nil
case Expression_ArrayAccess:
panic("TODO") // TODO
case Expression_RawMemoryReference:
raw := lhs.Value.(RawMemoryReferenceExpression)
localAddress := Local{Name: "", Type: Type{Type: Type_Primitive, Value: c.getEffectiveAddressType()}, IsParameter: false, Index: len(c.CurrentFunction.Locals)}
c.CurrentFunction.Locals = append(c.CurrentFunction.Locals, localAddress)
@ -388,27 +359,29 @@ func (c *Compiler) compileAssignmentUpdateExpressionWAT(lhs Expression, updateWA
wat := addrWAT
// dup address
wat.add(
"local.tee $"+strconv.Itoa(localAddress.Index),
"local.get $"+strconv.Itoa(localAddress.Index),
)
if update {
// dup address
wat.add(
"local.tee $"+strconv.Itoa(localAddress.Index)+" (;address;)",
"local.get $"+strconv.Itoa(localAddress.Index)+" (;address;)",
)
wat.add(c.getWATType(raw.Type) + ".load")
if evaluateToOldValue {
wat.add("local.tee $" + strconv.Itoa(localValue.Index))
wat.add(c.getWATType(raw.Type) + ".load")
}
wat.addAll(updateWAT)
if evaluateToOldValue {
wat.add("local.tee $" + strconv.Itoa(localValue.Index) + " (;temp storage for value;)")
}
wat.addAll(valueOrUpdateWAT)
if !evaluateToOldValue {
wat.add("local.tee $" + strconv.Itoa(localValue.Index))
wat.add("local.tee $" + strconv.Itoa(localValue.Index) + " (;temp storage for value;)")
}
wat.add(
c.getWATType(raw.Type)+".store",
"local.get $"+strconv.Itoa(localValue.Index),
"local.get $"+strconv.Itoa(localValue.Index)+" (;temp storage for value;)",
)
return wat, nil
@ -424,10 +397,6 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) {
case Expression_Assignment:
ass := expr.Value.(AssignmentExpression)
if ass.Operation == Operation_Nop {
return c.compileAssignmentExpressionWAT(ass)
}
watRight, err := c.compileExpressionWAT(ass.Value)
if err != nil {
return emptyCode(), err
@ -436,7 +405,7 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) {
updateOp := c.compileOperationWAT(ass.Operation, ass.Lhs.ValueType.Value.(PrimitiveType))
watRight.addAll(updateOp)
return c.compileAssignmentUpdateExpressionWAT(ass.Lhs, watRight, false)
return c.compileAssignmentUpdateExpressionWAT(ass.Lhs, ass.Operation != Operation_Nop, watRight, false)
case Expression_Literal:
lit := expr.Value.(LiteralExpression)
switch lit.Literal.Type {
@ -600,7 +569,7 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (Code, error) {
updateWAT.add(valueType + ".sub")
}
return c.compileAssignmentUpdateExpressionWAT(unary.Value, updateWAT, unary.Operation == UnaryOperation_PostIncrement || unary.Operation == UnaryOperation_PostDecrement)
return c.compileAssignmentUpdateExpressionWAT(unary.Value, true, updateWAT, unary.Operation == UnaryOperation_PostIncrement || unary.Operation == UnaryOperation_PostDecrement)
}
case Expression_Cast:
cast := expr.Value.(CastExpression)
@ -721,6 +690,8 @@ func (c *Compiler) compileOperationWAT(operation Operation, operandType Primitiv
}
switch operation {
case Operation_Nop:
return emptyCode()
case Operation_Add:
op = getPrimitiveWATType(operandType) + ".add"
case Operation_Sub:
@ -768,7 +739,7 @@ func (c *Compiler) compileStatementWAT(stmt Statement, block *Block) (Code, erro
}
}
for _ = range numItems {
for range numItems {
wat.add("drop")
}

View File

@ -128,6 +128,10 @@ func (t PrimitiveType) String() string {
return getPrimitiveTypeName(t)
}
func (t ExpressionType) String() string {
return strconv.Itoa(int(t))
}
func getOperation(operator Operator) Operation {
switch operator {
case Operator_Greater:
@ -186,3 +190,12 @@ func isBooleanOperation(operation Operation) bool {
func isArithmeticOperation(operation Operation) bool {
return !isBooleanOperation(operation)
}
func isValidLHS(expressionType ExpressionType) bool {
switch expressionType {
case Expression_ArrayAccess, Expression_VariableReference, Expression_RawMemoryReference:
return true
default:
return false
}
}