More unary expressions

This commit is contained in:
MrLetsplay 2024-04-09 13:57:17 +02:00
parent 45f5ea3398
commit 0236dfbb2d
Signed by: mr
SSH Key Fingerprint: SHA256:92jBH80vpXyaZHjaIl47pjRq+Yt7XGTArqQg1V7hSqg
7 changed files with 114 additions and 53 deletions

View File

@ -323,23 +323,35 @@ func (c *Compiler) compileExpressionWAT(expr Expression) (string, error) {
}
return wat + "call $" + fc.Function + "\n", nil
case Expression_Negate:
neg := expr.Value.(NegateExpression)
case Expression_Unary:
unary := expr.Value.(UnaryExpression)
exprType := expr.ValueType.Value.(PrimitiveType)
wat, err := c.compileExpressionWAT(neg.Value)
wat, err := c.compileExpressionWAT(unary.Value)
if err != nil {
return "", err
}
watType := getPrimitiveWATType(exprType)
if isSignedInt(exprType) || isUnsignedInt(exprType) {
return watType + ".const 0\n" + wat + watType + ".sub\n", nil
switch unary.Operation {
case UnaryOperation_Negate:
if isFloatingPoint(exprType) {
return wat + watType + ".neg\n", nil
} else {
return watType + ".const 0\n" + wat + watType + ".sub\n" + getTypeCast(exprType), nil
}
case UnaryOperation_Nop:
return wat, nil
case UnaryOperation_BitwiseNot:
if getBits(exprType) == 64 {
return wat + watType + ".const 0xFFFFFFFFFFFFFFFF\n" + watType + ".xor\n" + getTypeCast(exprType), nil
} else {
return wat + watType + ".const 0xFFFFFFFF\n" + watType + ".xor\n" + getTypeCast(exprType), nil
}
case UnaryOperation_LogicalNot:
return wat + "i32.eqz\n", nil
}
if isFloatingPoint(exprType) {
return watType + ".neg\n", nil
}
case Expression_Cast:
cast := expr.Value.(CastExpression)

View File

@ -6,3 +6,17 @@ u32 c(u32 n) {
}
return sum;
}
u64 fib(u64 i) {
u64 fibA = 0u64;
u64 fibB = 1u64;
while((i -= 1u64) > 0u64) {
u64 tmp = fibB;
fibB = fibA + fibB;
fibA = tmp;
}
return fibA;
}

View File

@ -55,7 +55,7 @@ const (
type Operator uint32
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%="}
var Operators []string = []string{"=", ">", "<", "!", "+", "-", "*", "/", "%", "==", ">=", "<=", "!=", "+=", "-=", "*=", "/=", "%=", "++", "--", "~"}
const (
Operator_Equals Operator = iota
@ -76,6 +76,9 @@ const (
Operator_MultiplyEquals
Operator_DivideEquals
Operator_ModuloEquals
Operator_PlusPlus
Operator_MinusMinus
Operator_BitwiseNot
)
type LiteralType uint32

View File

@ -87,7 +87,7 @@ const (
Expression_Binary
Expression_Tuple
Expression_FunctionCall
Expression_Negate
Expression_Unary
Expression_ArrayAccess
Expression_RawMemoryReference
Expression_Cast
@ -125,11 +125,19 @@ const (
Operation_Less
Operation_GreaterEquals
Operation_LessEquals
Operation_LogicalNot
Operation_NotEquals
Operation_Equals
)
type UnaryOperation uint32
const (
UnaryOperation_Negate UnaryOperation = iota
UnaryOperation_Nop
UnaryOperation_BitwiseNot
UnaryOperation_LogicalNot
)
type BinaryExpression struct {
Operation Operation
Left Expression
@ -145,8 +153,9 @@ type FunctionCallExpression struct {
Parameters *Expression
}
type NegateExpression struct {
Value Expression
type UnaryExpression struct {
Operation UnaryOperation
Value Expression
}
type ArrayAccessExpression struct {
@ -594,27 +603,27 @@ func (p *Parser) tryUnaryExpression() (*Expression, error) {
return nil, nil
}
if token.Type == Type_Operator {
op := token.Value.(Operator)
if op == Operator_Minus || op == Operator_Plus {
pCopy.nextToken()
expr, err := pCopy.tryPrimaryExpression()
if err != nil {
return nil, err
}
if expr == nil {
return nil, nil
}
if op == Operator_Minus {
expr = &Expression{Type: Expression_Negate, Value: NegateExpression{Value: *expr}, Position: token.Position}
}
return expr, nil
}
op, err := pCopy.tryOperator(Operator_Minus, Operator_Plus, Operator_BitwiseNot, Operator_Not)
if err != nil {
return nil, err
}
if op != nil {
expr, err := pCopy.tryPrimaryExpression()
if err != nil {
return nil, err
}
if expr == nil {
return nil, nil
}
*p = pCopy
return &Expression{Type: Expression_Unary, Value: UnaryExpression{Operation: getUnaryOperation(*op), Value: *expr}, Position: token.Position}, nil
}
// TODO: pre-/postfix in-/decrement expr
return p.tryPrimaryExpression()
}
@ -647,7 +656,12 @@ func (p *Parser) tryBinaryExpression0(opFunc func() (*Expression, error), operat
return nil, p.error("expected expression")
}
left = &Expression{Type: Expression_Binary, Value: BinaryExpression{Operation: getOperation(*op), Left: *left, Right: *right}, Position: left.Position}
operation := getOperation(*op)
if operation == InvalidValue {
return nil, p.error("operator not allowed in binary expression")
}
left = &Expression{Type: Expression_Binary, Value: BinaryExpression{Operation: operation, Left: *left, Right: *right}, Position: left.Position}
}
}
@ -679,11 +693,7 @@ func (p *Parser) tryAssignmentExpression() (*Expression, error) {
return nil, err
}
if lhs == nil {
return nil, nil
}
if lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference {
if lhs == nil || (lhs.Type != Expression_VariableReference && lhs.Type != Expression_ArrayAccess && lhs.Type != Expression_RawMemoryReference) {
return p.tryBinaryExpression()
}

View File

@ -1,9 +1,6 @@
module alloc;
u64 alloc(u64 size) {
u64 ptr = 0x0u64;
raw(i32, ptr) = 0x03u32;
i32 sus = raw(i32, ptr);
return 0u64;
}

View File

@ -154,8 +154,6 @@ func getOperation(operator Operator) Operation {
return Operation_Greater
case Operator_Less:
return Operation_Less
case Operator_Not:
return Operation_LogicalNot
case Operator_Plus, Operator_PlusEquals:
return Operation_Add
case Operator_Minus, Operator_MinusEquals:
@ -179,9 +177,24 @@ func getOperation(operator Operator) Operation {
}
}
func getUnaryOperation(operator Operator) UnaryOperation {
switch operator {
case Operator_Minus:
return UnaryOperation_Negate
case Operator_Plus:
return UnaryOperation_Nop
case Operator_BitwiseNot:
return UnaryOperation_BitwiseNot
case Operator_Not:
return UnaryOperation_LogicalNot
default:
return InvalidValue
}
}
func isBooleanOperation(operation Operation) bool {
switch operation {
case Operation_Greater, Operation_Less, Operation_LogicalNot, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals:
case Operation_Greater, Operation_Less, Operation_Equals, Operation_GreaterEquals, Operation_LessEquals, Operation_NotEquals:
return true
default:
return false

View File

@ -156,7 +156,7 @@ func (v *Validator) getArithmeticResultType(expr *Expression, left PrimitiveType
return left, nil
}
return InvalidValue, v.createError(fmt.Sprintf("cannot use the types [%s, %s] in an arithmetic expression without an explicit cast", left, right), expr.Position) // TODO: include type names in error
return InvalidValue, v.createError(fmt.Sprintf("cannot use the types [%s, %s] in an arithmetic expression without an explicit cast", left, right), expr.Position)
}
func getLocal(block *Block, variable string) *Local {
@ -324,24 +324,36 @@ func (v *Validator) validatePotentiallyVoidExpression(expr *Expression) []error
}
}
// TODO: get function and validate using return type
expr.ValueType = calledFunc.ReturnType
expr.Value = fc
case Expression_Negate:
neg := expr.Value.(NegateExpression)
case Expression_Unary:
unary := expr.Value.(UnaryExpression)
valErrors := v.validateExpression(&neg.Value)
valErrors := v.validateExpression(&unary.Value)
if len(valErrors) != 0 {
errors = append(errors, valErrors...)
return errors
}
if neg.Value.ValueType.Type != Type_Primitive {
errors = append(errors, v.createError("cannot negate non-number types", expr.Position))
if unary.Value.ValueType.Type != Type_Primitive {
errors = append(errors, v.createError("cannot operate on non-primitive types", expr.Position))
} else {
primitive := unary.Value.ValueType.Value.(PrimitiveType)
if (unary.Operation == UnaryOperation_Negate || unary.Operation == UnaryOperation_Nop /* + sign */) && !isSignedInt(primitive) && !isFloatingPoint(primitive) {
errors = append(errors, v.createError("can only perform negation/unary plus on signed types", expr.Position))
}
if unary.Operation == UnaryOperation_LogicalNot && primitive != Primitive_Bool {
errors = append(errors, v.createError("cannot perform logical not on non-bool type", expr.Position))
}
if unary.Operation == UnaryOperation_BitwiseNot && !isUnsignedInt(primitive) && !isSignedInt(primitive) {
errors = append(errors, v.createError("cannot perform bitwise not on non-integer type", expr.Position))
}
}
expr.ValueType = neg.Value.ValueType
expr.Value = neg
expr.ValueType = unary.Value.ValueType
expr.Value = unary
case Expression_RawMemoryReference:
raw := expr.Value.(RawMemoryReferenceExpression)